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  * Copyright (c) 2016 by Delphix. All rights reserved.
36  */
37 
38 /*
39  * Standard headers.
40  */
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <signal.h>
44 #include <string.h>
45 #include <errno.h>
46 #include <ctype.h>
47 #include <setjmp.h>
48 #include <stdarg.h>
49 
50 /*
51  * UNIX headers.
52  */
53 #include <sys/ioctl.h>
54 #ifdef HAVE_SELECT
55 #ifdef HAVE_SYS_SELECT_H
56 #include <sys/select.h>
57 #endif
58 #include <sys/time.h>
59 #include <sys/types.h>
60 #endif
61 
62 /*
63  * Handle the different sources of terminal control string and size
64  * information. Note that if no terminal information database is available,
65  * ANSI VT100 control sequences are used.
66  */
67 #if defined(USE_TERMINFO) || defined(USE_TERMCAP)
68 /*
69  * Include curses.h or ncurses/curses.h depending on which is available.
70  */
71 #ifdef HAVE_CURSES_H
72 #include <curses.h>
73 #elif defined(HAVE_NCURSES_CURSES_H)
74 #include <ncurses/curses.h>
75 #endif
76 /*
77  * Include term.h where available.
78  */
79 #if defined(HAVE_TERM_H)
80 #include <term.h>
81 #elif defined(HAVE_NCURSES_TERM_H)
82 #include <ncurses/term.h>
83 #endif
84 /*
85  * When using termcap, include termcap.h on systems that have it.
86  * Otherwise assume that all prototypes are provided by curses.h.
87  */
88 #if defined(USE_TERMCAP) && defined(HAVE_TERMCAP_H)
89 #include <termcap.h>
90 #endif
91 
92 /*
93  * Under Solaris default Curses the output function that tputs takes is
94  * declared to have a char argument. On all other systems and on Solaris
95  * X/Open Curses (Issue 4, Version 2) it expects an int argument (using
96  * c89 or options -I /usr/xpg4/include -L /usr/xpg4/lib -R /usr/xpg4/lib
97  * selects XPG4v2 Curses on Solaris 2.6 and later).
98  *
99  * Similarly, under Mac OS X, the return value of the tputs output
100  * function is declared as void, whereas it is declared as int on
101  * other systems.
102  */
103 #if defined __sun && defined __SVR4 && !defined _XOPEN_CURSES
104 typedef int TputsRetType;
105 typedef char TputsArgType;              /* int tputs(char c, FILE *fp) */
106 #define TPUTS_RETURNS_VALUE 1
107 #elif defined(__APPLE__) && defined(__MACH__)
108 typedef void TputsRetType;
109 typedef int TputsArgType;               /* void tputs(int c, FILE *fp) */
110 #define TPUTS_RETURNS_VALUE 0
111 #else
112 typedef int TputsRetType;
113 typedef int TputsArgType;               /* int tputs(int c, FILE *fp) */
114 #define TPUTS_RETURNS_VALUE 1
115 #endif
116 
117 /*
118  * Use the above specifications to prototype our tputs callback function.
119  */
120 static TputsRetType gl_tputs_putchar(TputsArgType c);
121 
122 #endif  /* defined(USE_TERMINFO) || defined(USE_TERMCAP) */
123 
124 /*
125  * If the library is being compiled without filesystem access facilities,
126  * ensure that none of the action functions that normally do access the
127  * filesystem are bound by default, and that it they do get bound, that
128  * they don't do anything.
129  */
130 #if WITHOUT_FILE_SYSTEM
131 #define HIDE_FILE_SYSTEM
132 #endif
133 
134 /*
135  * POSIX headers.
136  */
137 #include <unistd.h>
138 #include <fcntl.h>
139 #include <termios.h>
140 
141 /*
142  * Provide typedefs for standard POSIX structures.
143  */
144 typedef struct sigaction SigAction;
145 typedef struct termios Termios;
146 
147 /*
148  * Which flag is used to select non-blocking I/O with fcntl()?
149  */
150 #undef NON_BLOCKING_FLAG
151 #if defined(O_NONBLOCK)
152 #define NON_BLOCKING_FLAG (O_NONBLOCK)
153 #elif defined(O_NDELAY)
154 #define NON_BLOCKING_FLAG (O_NDELAY)
155 #endif
156 
157 /*
158  * What value should we give errno if I/O blocks when it shouldn't.
159  */
160 #undef BLOCKED_ERRNO
161 #if defined(EAGAIN)
162 #define BLOCKED_ERRNO (EAGAIN)
163 #elif defined(EWOULDBLOCK)
164 #define BLOCKED_ERRNO (EWOULDBLOCK)
165 #elif defined(EIO)
166 #define BLOCKED_ERRNO (EIO)
167 #else
168 #define BLOCKED_ERRNO 0
169 #endif
170 
171 /*
172  * Local headers.
173  */
174 #ifndef WITHOUT_FILE_SYSTEM
175 #include "pathutil.h"
176 #endif
177 #include "libtecla.h"
178 #include "keytab.h"
179 #include "getline.h"
180 #include "ioutil.h"
181 #include "history.h"
182 #include "freelist.h"
183 #include "stringrp.h"
184 #include "chrqueue.h"
185 #include "cplmatch.h"
186 #ifndef WITHOUT_FILE_SYSTEM
187 #include "expand.h"
188 #endif
189 #include "errmsg.h"
190 
191 /*
192  * Enumerate the available editing styles.
193  */
194 typedef enum {
195   GL_EMACS_MODE,   /* Emacs style editing */
196   GL_VI_MODE,      /* Vi style editing */
197   GL_NO_EDITOR     /* Fall back to the basic OS-provided editing */
198 } GlEditor;
199 
200 /*
201  * Set the largest key-sequence that can be handled.
202  */
203 #define GL_KEY_MAX 64
204 
205 /*
206  * In vi mode, the following datatype is used to implement the
207  * undo command. It records a copy of the input line from before
208  * the command-mode action which edited the input line.
209  */
210 typedef struct {
211   char *line;        /* A historical copy of the input line */
212   int buff_curpos;   /* The historical location of the cursor in */
213                      /*  line[] when the line was modified. */
214   int ntotal;        /* The number of characters in line[] */
215   int saved;         /* True once a line has been saved after the */
216                      /*  last call to gl_interpret_char(). */
217 } ViUndo;
218 
219 /*
220  * In vi mode, the following datatype is used to record information
221  * needed by the vi-repeat-change command.
222  */
223 typedef struct {
224   KtAction action;           /* The last action function that made a */
225                              /*  change to the line. */
226   int count;                 /* The repeat count that was passed to the */
227                              /*  above command. */
228   int input_curpos;          /* Whenever vi command mode is entered, the */
229                              /*  the position at which it was first left */
230                              /*  is recorded here. */
231   int command_curpos;        /* Whenever vi command mode is entered, the */
232                              /*  the location of the cursor is recorded */
233                              /*  here. */
234   char input_char;           /* Commands that call gl_read_terminal() */
235                              /*  record the character here, so that it can */
236                              /*  used on repeating the function. */
237   int saved;                 /* True if a function has been saved since the */
238                              /*  last call to gl_interpret_char(). */
239   int active;                /* True while a function is being repeated. */
240 } ViRepeat;
241 
242 /*
243  * The following datatype is used to encapsulate information specific
244  * to vi mode.
245  */
246 typedef struct {
247   ViUndo undo;               /* Information needed to implement the vi */
248                              /*  undo command. */
249   ViRepeat repeat;           /* Information needed to implement the vi */
250                              /*  repeat command. */
251   int command;               /* True in vi command-mode */
252   int find_forward;          /* True if the last character search was in the */
253                              /*  forward direction. */
254   int find_onto;             /* True if the last character search left the */
255                              /*  on top of the located character, as opposed */
256                              /*  to just before or after it. */
257   char find_char;            /* The last character sought, or '\0' if no */
258                              /*  searches have been performed yet. */
259 } ViMode;
260 
261 #ifdef HAVE_SELECT
262 /*
263  * Define a type for recording a file-descriptor callback and its associated
264  * data.
265  */
266 typedef struct {
267   GlFdEventFn *fn;   /* The callback function */
268   void *data;        /* Anonymous data to pass to the callback function */
269 } GlFdHandler;
270 
271 /*
272  * A list of nodes of the following type is used to record file-activity
273  * event handlers, but only on systems that have the select() system call.
274  */
275 typedef struct GlFdNode GlFdNode;
276 struct GlFdNode {
277   GlFdNode *next;    /* The next in the list of nodes */
278   int fd;            /* The file descriptor being watched */
279   GlFdHandler rd;    /* The callback to call when fd is readable */
280   GlFdHandler wr;    /* The callback to call when fd is writable */
281   GlFdHandler ur;    /* The callback to call when fd has urgent data */
282 };
283 
284 /*
285  * Set the number of the above structures to allocate every time that
286  * the freelist of GlFdNode's becomes exhausted.
287  */
288 #define GLFD_FREELIST_BLOCKING 10
289 
290 
291 static int gl_call_fd_handler(GetLine *gl, GlFdHandler *gfh, int fd,
292 			      GlFdEvent event);
293 
294 static int gl_call_timeout_handler(GetLine *gl);
295 
296 #endif
297 
298 /*
299  * Each signal that gl_get_line() traps is described by a list node
300  * of the following type.
301  */
302 typedef struct GlSignalNode GlSignalNode;
303 struct GlSignalNode {
304   GlSignalNode *next;  /* The next signal in the list */
305   int signo;           /* The number of the signal */
306   sigset_t proc_mask;  /* A process mask which only includes signo */
307   SigAction original;  /* The signal disposition of the calling program */
308                        /*  for this signal. */
309   unsigned flags;      /* A bitwise union of GlSignalFlags enumerators */
310   GlAfterSignal after; /* What to do after the signal has been handled */
311   int errno_value;     /* What to set errno to */
312 };
313 
314 /*
315  * Set the number of the above structures to allocate every time that
316  * the freelist of GlSignalNode's becomes exhausted.
317  */
318 #define GLS_FREELIST_BLOCKING 30
319 
320 /*
321  * Completion handlers and their callback data are recorded in
322  * nodes of the following type.
323  */
324 typedef struct GlCplCallback GlCplCallback;
325 struct GlCplCallback {
326   CplMatchFn *fn;            /* The completion callback function */
327   void *data;                /* Arbitrary callback data */
328 };
329 
330 /*
331  * The following function is used as the default completion handler when
332  * the filesystem is to be hidden. It simply reports no completions.
333  */
334 #ifdef HIDE_FILE_SYSTEM
335 static CPL_MATCH_FN(gl_no_completions);
336 #endif
337 
338 /*
339  * Specify how many GlCplCallback nodes are added to the GlCplCallback freelist
340  * whenever it becomes exhausted.
341  */
342 #define GL_CPL_FREELIST_BLOCKING 10
343 
344 /*
345  * External action functions and their callback data are recorded in
346  * nodes of the following type.
347  */
348 typedef struct GlExternalAction GlExternalAction;
349 struct GlExternalAction {
350   GlActionFn *fn;          /* The function which implements the action */
351   void *data;              /* Arbitrary callback data */
352 };
353 
354 /*
355  * Specify how many GlExternalAction nodes are added to the
356  * GlExternalAction freelist whenever it becomes exhausted.
357  */
358 #define GL_EXT_ACT_FREELIST_BLOCKING 10
359 
360 /*
361  * Define the contents of the GetLine object.
362  * Note that the typedef for this object can be found in libtecla.h.
363  */
364 struct GetLine {
365   ErrMsg *err;               /* The error-reporting buffer */
366   GlHistory *glh;            /* The line-history buffer */
367   WordCompletion *cpl;       /* String completion resource object */
368   GlCplCallback cplfn;       /* The completion callback */
369 #ifndef WITHOUT_FILE_SYSTEM
370   ExpandFile *ef;            /* ~user/, $envvar and wildcard expansion */
371                              /*  resource object. */
372 #endif
373   StringGroup *capmem;       /* Memory for recording terminal capability */
374                              /*  strings. */
375   GlCharQueue *cq;           /* The terminal output character queue */
376   int input_fd;              /* The file descriptor to read on */
377   int output_fd;             /* The file descriptor to write to */
378   FILE *input_fp;            /* A stream wrapper around input_fd */
379   FILE *output_fp;           /* A stream wrapper around output_fd */
380   FILE *file_fp;             /* When input is being temporarily taken from */
381                              /*  a file, this is its file-pointer. Otherwise */
382                              /*  it is NULL. */
383   char *term;                /* The terminal type specified on the last call */
384                              /*  to gl_change_terminal(). */
385   int is_term;               /* True if stdin is a terminal */
386   GlWriteFn *flush_fn;       /* The function to call to write to the terminal */
387   GlIOMode io_mode;          /* The I/O mode established by gl_io_mode() */
388   int raw_mode;              /* True while the terminal is in raw mode */
389   GlPendingIO pending_io;    /* The type of I/O that is currently pending */
390   GlReturnStatus rtn_status; /* The reason why gl_get_line() returned */
391   int rtn_errno;             /* THe value of errno associated with rtn_status */
392   size_t linelen;            /* The max number of characters per line */
393   char *line;                /* A line-input buffer of allocated size */
394                              /*  linelen+2. The extra 2 characters are */
395                              /*  reserved for "\n\0". */
396   char *cutbuf;              /* A cut-buffer of the same size as line[] */
397   char *prompt;              /* The current prompt string */
398   int prompt_len;            /* The length of the prompt string */
399   int prompt_changed;        /* True after a callback changes the prompt */
400   int prompt_style;          /* How the prompt string is displayed */
401   FreeList *cpl_mem;         /* Memory for GlCplCallback objects */
402   FreeList *ext_act_mem;     /* Memory for GlExternalAction objects */
403   FreeList *sig_mem;         /* Memory for nodes of the signal list */
404   GlSignalNode *sigs;        /* The head of the list of signals */
405   int signals_masked;        /* True between calls to gl_mask_signals() and */
406                              /*  gl_unmask_signals() */
407   int signals_overriden;     /* True between calls to gl_override_signals() */
408                              /*  and gl_restore_signals() */
409   sigset_t all_signal_set;   /* The set of all signals that we are trapping */
410   sigset_t old_signal_set;   /* The set of blocked signals on entry to */
411                              /*  gl_get_line(). */
412   sigset_t use_signal_set;   /* The subset of all_signal_set to unblock */
413                              /*  while waiting for key-strokes */
414   Termios oldattr;           /* Saved terminal attributes. */
415   KeyTab *bindings;          /* A table of key-bindings */
416   int ntotal;                /* The number of characters in gl->line[] */
417   int buff_curpos;           /* The cursor position within gl->line[] */
418   int term_curpos;           /* The cursor position on the terminal */
419   int term_len;              /* The number of terminal characters used to */
420                              /*  display the current input line. */
421   int buff_mark;             /* A marker location in the buffer */
422   int insert_curpos;         /* The cursor position at start of insert */
423   int insert;                /* True in insert mode */
424   int number;                /* If >= 0, a numeric argument is being read */
425   int endline;               /* True to tell gl_get_input_line() to return */
426                              /*  the current contents of gl->line[] */
427   int displayed;             /* True if an input line is currently displayed */
428   int redisplay;             /* If true, the input line will be redrawn */
429                              /*  either after the current action function */
430                              /*  returns, or when gl_get_input_line() */
431                              /*  is next called. */
432   int postpone;              /* _gl_normal_io() sets this flag, to */
433                              /*  postpone any redisplays until */
434                              /*  is next called, to resume line editing. */
435   char keybuf[GL_KEY_MAX+1]; /* A buffer of currently unprocessed key presses */
436   int nbuf;                  /* The number of characters in keybuf[] */
437   int nread;                 /* The number of characters read from keybuf[] */
438   KtAction current_action;   /* The action function that is being invoked */
439   int current_count;         /* The repeat count passed to */
440                              /*  current_acction.fn() */
441   GlhLineID preload_id;      /* When not zero, this should be the ID of a */
442                              /*  line in the history buffer for potential */
443                              /*  recall. */
444   int preload_history;       /* If true, preload the above history line when */
445                              /*  gl_get_input_line() is next called. */
446   long keyseq_count;         /* The number of key sequences entered by the */
447                              /*  the user since new_GetLine() was called. */
448   long last_search;          /* The value of keyseq_count during the last */
449                              /*  history search operation. */
450   GlEditor editor;           /* The style of editing, (eg. vi or emacs) */
451   int silence_bell;          /* True if gl_ring_bell() should do nothing. */
452   int automatic_history;     /* True to automatically archive entered lines */
453                              /*  in the history list. */
454   ViMode vi;                 /* Parameters used when editing in vi mode */
455   const char *left;          /* The string that moves the cursor 1 character */
456                              /*  left. */
457   const char *right;         /* The string that moves the cursor 1 character */
458                              /*  right. */
459   const char *up;            /* The string that moves the cursor 1 character */
460                              /*  up. */
461   const char *down;          /* The string that moves the cursor 1 character */
462                              /*  down. */
463   const char *home;          /* The string that moves the cursor home */
464   const char *bol;           /* Move cursor to beginning of line */
465   const char *clear_eol;     /* The string that clears from the cursor to */
466                              /*  the end of the line. */
467   const char *clear_eod;     /* The string that clears from the cursor to */
468                              /*  the end of the display. */
469   const char *u_arrow;       /* The string returned by the up-arrow key */
470   const char *d_arrow;       /* The string returned by the down-arrow key */
471   const char *l_arrow;       /* The string returned by the left-arrow key */
472   const char *r_arrow;       /* The string returned by the right-arrow key */
473   const char *sound_bell;    /* The string needed to ring the terminal bell */
474   const char *bold;          /* Switch to the bold font */
475   const char *underline;     /* Underline subsequent characters */
476   const char *standout;      /* Turn on standout mode */
477   const char *dim;           /* Switch to a dim font */
478   const char *reverse;       /* Turn on reverse video */
479   const char *blink;         /* Switch to a blinking font */
480   const char *text_attr_off; /* Turn off all text attributes */
481   int nline;                 /* The height of the terminal in lines */
482   int ncolumn;               /* The width of the terminal in columns */
483 #ifdef USE_TERMCAP
484   char *tgetent_buf;         /* The buffer that is used by tgetent() to */
485                              /*  store a terminal description. */
486   char *tgetstr_buf;         /* The buffer that is used by tgetstr() to */
487                              /*  store terminal capabilities. */
488 #endif
489 #ifdef USE_TERMINFO
490   const char *left_n;        /* The parameter string that moves the cursor */
491                              /*  n characters left. */
492   const char *right_n;       /* The parameter string that moves the cursor */
493                              /*  n characters right. */
494 #endif
495   char *app_file;            /* The pathname of the application-specific */
496                              /*  .teclarc configuration file, or NULL. */
497   char *user_file;           /* The pathname of the user-specific */
498                              /*  .teclarc configuration file, or NULL. */
499   int configured;            /* True as soon as any teclarc configuration */
500                              /*  file has been read. */
501   int echo;                  /* True to display the line as it is being */
502                              /*  entered. If 0, only the prompt will be */
503                              /*  displayed, and the line will not be */
504                              /*  archived in the history list. */
505   int last_signal;           /* The last signal that was caught by */
506                              /*  the last call to gl_get_line(), or -1 */
507                              /*  if no signal has been caught yet. */
508 #ifdef HAVE_SELECT
509   FreeList *fd_node_mem;     /* A freelist of GlFdNode structures */
510   GlFdNode *fd_nodes;        /* The list of fd event descriptions */
511   fd_set rfds;               /* The set of fds to watch for readability */
512   fd_set wfds;               /* The set of fds to watch for writability */
513   fd_set ufds;               /* The set of fds to watch for urgent data */
514   int max_fd;                /* The maximum file-descriptor being watched */
515   struct {                   /* Inactivity timeout related data */
516     struct timeval dt;       /* The inactivity timeout when timer.fn() */
517                              /*  isn't 0 */
518     GlTimeoutFn *fn;         /* The application callback to call when */
519                              /*  the inactivity timer expires, or 0 if */
520                              /*  timeouts are not required. */
521     void *data;              /* Application provided data to be passed to */
522                              /*  timer.fn(). */
523   } timer;
524 #endif
525 };
526 
527 /*
528  * Define the max amount of space needed to store a termcap terminal
529  * description. Unfortunately this has to be done by guesswork, so
530  * there is the potential for buffer overflows if we guess too small.
531  * Fortunately termcap has been replaced by terminfo on most
532  * platforms, and with terminfo this isn't an issue. The value that I
533  * am using here is the conventional value, as recommended by certain
534  * web references.
535  */
536 #ifdef USE_TERMCAP
537 #define TERMCAP_BUF_SIZE 2048
538 #endif
539 
540 /*
541  * Set the size of the string segments used to store terminal capability
542  * strings.
543  */
544 #define CAPMEM_SEGMENT_SIZE 512
545 
546 /*
547  * If no terminal size information is available, substitute the
548  * following vt100 default sizes.
549  */
550 #define GL_DEF_NLINE 24
551 #define GL_DEF_NCOLUMN 80
552 
553 /*
554  * Enumerate the attributes needed to classify different types of
555  * signals. These attributes reflect the standard default
556  * characteristics of these signals (according to Richard Steven's
557  * Advanced Programming in the UNIX Environment). Note that these values
558  * are all powers of 2, so that they can be combined in a bitwise union.
559  */
560 typedef enum {
561   GLSA_TERM=1,   /* A signal that terminates processes */
562   GLSA_SUSP=2,   /* A signal that suspends processes */
563   GLSA_CONT=4,   /* A signal that is sent when suspended processes resume */
564   GLSA_IGN=8,    /* A signal that is ignored */
565   GLSA_CORE=16,  /* A signal that generates a core dump */
566   GLSA_HARD=32,  /* A signal generated by a hardware exception */
567   GLSA_SIZE=64   /* A signal indicating terminal size changes */
568 } GlSigAttr;
569 
570 /*
571  * List the signals that we need to catch. In general these are
572  * those that by default terminate or suspend the process, since
573  * in such cases we need to restore terminal settings.
574  */
575 static const struct GlDefSignal {
576   int signo;            /* The number of the signal */
577   unsigned flags;       /* A bitwise union of GlSignalFlags enumerators */
578   GlAfterSignal after;  /* What to do after the signal has been delivered */
579   int attr;             /* The default attributes of this signal, expressed */
580                         /* as a bitwise union of GlSigAttr enumerators */
581   int errno_value;      /* What to set errno to */
582 } gl_signal_list[] = {
583   {SIGABRT,   GLS_SUSPEND_INPUT,    GLS_ABORT, GLSA_TERM|GLSA_CORE, EINTR},
584   {SIGALRM,   GLS_RESTORE_ENV,   GLS_CONTINUE, GLSA_TERM,           0},
585   {SIGCONT,   GLS_RESTORE_ENV,   GLS_CONTINUE, GLSA_CONT|GLSA_IGN,  0},
586 #if defined(SIGHUP)
587 #ifdef ENOTTY
588   {SIGHUP,    GLS_SUSPEND_INPUT,    GLS_ABORT, GLSA_TERM,           ENOTTY},
589 #else
590   {SIGHUP,    GLS_SUSPEND_INPUT,    GLS_ABORT, GLSA_TERM,           EINTR},
591 #endif
592 #endif
593   {SIGINT,    GLS_SUSPEND_INPUT,    GLS_ABORT, GLSA_TERM,           EINTR},
594 #if defined(SIGPIPE)
595 #ifdef EPIPE
596   {SIGPIPE,   GLS_SUSPEND_INPUT,    GLS_ABORT, GLSA_TERM,           EPIPE},
597 #else
598   {SIGPIPE,   GLS_SUSPEND_INPUT,    GLS_ABORT, GLSA_TERM,           EINTR},
599 #endif
600 #endif
601 #ifdef SIGPOLL
602   {SIGPOLL,   GLS_SUSPEND_INPUT,    GLS_ABORT, GLSA_TERM,           EINTR},
603 #endif
604 #ifdef SIGPWR
605   {SIGPWR,    GLS_RESTORE_ENV,   GLS_CONTINUE, GLSA_IGN,            0},
606 #endif
607 #ifdef SIGQUIT
608   {SIGQUIT,   GLS_SUSPEND_INPUT,    GLS_ABORT, GLSA_TERM|GLSA_CORE, EINTR},
609 #endif
610   {SIGTERM,   GLS_SUSPEND_INPUT,    GLS_ABORT, GLSA_TERM,           EINTR},
611 #ifdef SIGTSTP
612   {SIGTSTP,   GLS_SUSPEND_INPUT, GLS_CONTINUE, GLSA_SUSP,           0},
613 #endif
614 #ifdef SIGTTIN
615   {SIGTTIN,   GLS_SUSPEND_INPUT, GLS_CONTINUE, GLSA_SUSP,           0},
616 #endif
617 #ifdef SIGTTOU
618   {SIGTTOU,   GLS_SUSPEND_INPUT, GLS_CONTINUE, GLSA_SUSP,           0},
619 #endif
620 #ifdef SIGUSR1
621   {SIGUSR1,   GLS_RESTORE_ENV,   GLS_CONTINUE, GLSA_TERM,           0},
622 #endif
623 #ifdef SIGUSR2
624   {SIGUSR2,   GLS_RESTORE_ENV,   GLS_CONTINUE, GLSA_TERM,           0},
625 #endif
626 #ifdef SIGVTALRM
627   {SIGVTALRM, GLS_RESTORE_ENV,   GLS_CONTINUE, GLSA_TERM,           0},
628 #endif
629 #ifdef SIGWINCH
630   {SIGWINCH,  GLS_RESTORE_ENV,   GLS_CONTINUE, GLSA_SIZE|GLSA_IGN,  0},
631 #endif
632 #ifdef SIGXCPU
633   {SIGXCPU,   GLS_RESTORE_ENV,   GLS_CONTINUE, GLSA_TERM|GLSA_CORE, 0},
634 #endif
635 #ifdef SIGXFSZ
636   {SIGXFSZ,   GLS_RESTORE_ENV,   GLS_CONTINUE, GLSA_TERM|GLSA_CORE, 0},
637 #endif
638 };
639 
640 /*
641  * Define file-scope variables for use in signal handlers.
642  */
643 static volatile sig_atomic_t gl_pending_signal = -1;
644 static sigjmp_buf gl_setjmp_buffer;
645 
646 static void gl_signal_handler(int signo);
647 
648 static int gl_check_caught_signal(GetLine *gl);
649 
650 /*
651  * Respond to an externally caught process suspension or
652  * termination signal.
653  */
654 static void gl_suspend_process(int signo, GetLine *gl, int ngl);
655 
656 /* Return the default attributes of a given signal */
657 
658 static int gl_classify_signal(int signo);
659 
660 /*
661  * Unfortunately both terminfo and termcap require one to use the tputs()
662  * function to output terminal control characters, and this function
663  * doesn't allow one to specify a file stream. As a result, the following
664  * file-scope variable is used to pass the current output file stream.
665  * This is bad, but there doesn't seem to be any alternative.
666  */
667 static GetLine *tputs_gl = NULL;
668 
669 /*
670  * Define a tab to be a string of 8 spaces.
671  */
672 #define TAB_WIDTH 8
673 
674 /*
675  * Lookup the current size of the terminal.
676  */
677 static void gl_query_size(GetLine *gl, int *ncolumn, int *nline);
678 
679 /*
680  * Getline calls this to temporarily override certain signal handlers
681  * of the calling program.
682  */
683 static int gl_override_signal_handlers(GetLine *gl);
684 
685 /*
686  * Getline calls this to restore the signal handlers of the calling
687  * program.
688  */
689 static int gl_restore_signal_handlers(GetLine *gl);
690 
691 /*
692  * Temporarily block the delivery of all signals that gl_get_line()
693  * is currently configured to trap.
694  */
695 static int gl_mask_signals(GetLine *gl, sigset_t *oldset);
696 
697 /*
698  * Restore the process signal mask that was overriden by a previous
699  * call to gl_mask_signals().
700  */
701 static int gl_unmask_signals(GetLine *gl, sigset_t *oldset);
702 
703 /*
704  * Unblock the signals that gl_get_line() has been configured to catch.
705  */
706 static int gl_catch_signals(GetLine *gl);
707 
708 /*
709  * Return the set of all trappable signals.
710  */
711 static void gl_list_trappable_signals(sigset_t *signals);
712 
713 /*
714  * Put the terminal into raw input mode, after saving the original
715  * terminal attributes in gl->oldattr.
716  */
717 static int gl_raw_terminal_mode(GetLine *gl);
718 
719 /*
720  * Restore the terminal attributes from gl->oldattr.
721  */
722 static int gl_restore_terminal_attributes(GetLine *gl);
723 
724 /*
725  * Switch to non-blocking I/O if possible.
726  */
727 static int gl_nonblocking_io(GetLine *gl, int fd);
728 
729 /*
730  * Switch to blocking I/O if possible.
731  */
732 static int gl_blocking_io(GetLine *gl, int fd);
733 
734 /*
735  * Read a line from the user in raw mode.
736  */
737 static int gl_get_input_line(GetLine *gl, const char *prompt,
738 			     const char *start_line, int start_pos);
739 
740 /*
741  * Query the user for a single character.
742  */
743 static int gl_get_query_char(GetLine *gl, const char *prompt, int defchar);
744 
745 /*
746  * Read input from a non-interactive input stream.
747  */
748 static int gl_read_stream_line(GetLine *gl);
749 
750 /*
751  * Read a single character from a non-interactive input stream.
752  */
753 static int gl_read_stream_char(GetLine *gl);
754 
755 /*
756  * Prepare to edit a new line.
757  */
758 static int gl_present_line(GetLine *gl, const char *prompt,
759 			   const char *start_line, int start_pos);
760 
761 /*
762  * Reset all line input parameters for a new input line.
763  */
764 static void gl_reset_input_line(GetLine *gl);
765 
766 /*
767  * Handle the receipt of the potential start of a new key-sequence from
768  * the user.
769  */
770 static int gl_interpret_char(GetLine *gl, char c);
771 
772 /*
773  * Bind a single control or meta character to an action.
774  */
775 static int gl_bind_control_char(GetLine *gl, KtBinder binder,
776 				char c, const char *action);
777 
778 /*
779  * Set up terminal-specific key bindings.
780  */
781 static int gl_bind_terminal_keys(GetLine *gl);
782 
783 /*
784  * Lookup terminal control string and size information.
785  */
786 static int gl_control_strings(GetLine *gl, const char *term);
787 
788 /*
789  * Wrappers around the terminfo and termcap functions that lookup
790  * strings in the terminal information databases.
791  */
792 #ifdef USE_TERMINFO
793 static const char *gl_tigetstr(GetLine *gl, const char *name);
794 #elif defined(USE_TERMCAP)
795 static const char *gl_tgetstr(GetLine *gl, const char *name, char **bufptr);
796 #endif
797 
798 /*
799  * Output a binary string directly to the terminal.
800  */
801 static int gl_print_raw_string(GetLine *gl, int buffered,
802 			       const char *string, int n);
803 
804 /*
805  * Print an informational message, starting and finishing on new lines.
806  * After the list of strings to be printed, the last argument MUST be
807  * GL_END_INFO.
808  */
809 static int gl_print_info(GetLine *gl, ...);
810 #define GL_END_INFO ((const char *)0)
811 
812 /*
813  * Start a newline and place the cursor at its start.
814  */
815 static int gl_start_newline(GetLine *gl, int buffered);
816 
817 /*
818  * Output a terminal control sequence.
819  */
820 static int gl_print_control_sequence(GetLine *gl, int nline,
821 				     const char *string);
822 
823 /*
824  * Output a character or string to the terminal after converting tabs
825  * to spaces and control characters to a caret followed by the modified
826  * character.
827  */
828 static int gl_print_char(GetLine *gl, char c, char pad);
829 static int gl_print_string(GetLine *gl, const char *string, char pad);
830 
831 /*
832  * Delete nc characters starting from the one under the cursor.
833  * Optionally copy the deleted characters to the cut buffer.
834  */
835 static int gl_delete_chars(GetLine *gl, int nc, int cut);
836 
837 /*
838  * Add a character to the line buffer at the current cursor position,
839  * inserting or overwriting according the current mode.
840  */
841 static int gl_add_char_to_line(GetLine *gl, char c);
842 
843 /*
844  * Insert/append a string to the line buffer and terminal at the current
845  * cursor position.
846  */
847 static int gl_add_string_to_line(GetLine *gl, const char *s);
848 
849 /*
850  * Record a new character in the input-line buffer.
851  */
852 static int gl_buffer_char(GetLine *gl, char c, int bufpos);
853 
854 /*
855  * Record a string in the input-line buffer.
856  */
857 static int gl_buffer_string(GetLine *gl, const char *s, int n, int bufpos);
858 
859 /*
860  * Make way to insert a string in the input-line buffer.
861  */
862 static int gl_make_gap_in_buffer(GetLine *gl, int start, int n);
863 
864 /*
865  * Remove characters from the input-line buffer, and move any characters
866  * that followed them to the start of the vacated space.
867  */
868 static void gl_remove_from_buffer(GetLine *gl, int start, int n);
869 
870 /*
871  * Terminate the input-line buffer after a specified number of characters.
872  */
873 static int gl_truncate_buffer(GetLine *gl, int n);
874 
875 /*
876  * Delete the displayed part of the input line that follows the current
877  * terminal cursor position.
878  */
879 static int gl_truncate_display(GetLine *gl);
880 
881 /*
882  * Accomodate changes to the contents of the input line buffer
883  * that weren't made by the above gl_*buffer functions.
884  */
885 static void gl_update_buffer(GetLine *gl);
886 
887 /*
888  * Read a single character from the terminal.
889  */
890 static int gl_read_terminal(GetLine *gl, int keep, char *c);
891 
892 /*
893  * Discard processed characters from the key-press lookahead buffer.
894  */
895 static void gl_discard_chars(GetLine *gl, int nused);
896 
897 /*
898  * Move the terminal cursor n positions to the left or right.
899  */
900 static int gl_terminal_move_cursor(GetLine *gl, int n);
901 
902 /*
903  * Move the terminal cursor to a given position.
904  */
905 static int gl_set_term_curpos(GetLine *gl, int term_curpos);
906 
907 /*
908  * Set the position of the cursor both in the line input buffer and on the
909  * terminal.
910  */
911 static int gl_place_cursor(GetLine *gl, int buff_curpos);
912 
913 /*
914  * How many characters are needed to write a number as an octal string?
915  */
916 static int gl_octal_width(unsigned num);
917 
918 /*
919  * Return the number of spaces needed to display a tab character at
920  * a given location of the terminal.
921  */
922 static int gl_displayed_tab_width(GetLine *gl, int term_curpos);
923 
924 /*
925  * Return the number of terminal characters needed to display a
926  * given raw character.
927  */
928 static int gl_displayed_char_width(GetLine *gl, char c, int term_curpos);
929 
930 /*
931  * Return the number of terminal characters needed to display a
932  * given substring.
933  */
934 static int gl_displayed_string_width(GetLine *gl, const char *string, int nc,
935 				     int term_curpos);
936 
937 /*
938  * Return non-zero if 'c' is to be considered part of a word.
939  */
940 static int gl_is_word_char(int c);
941 
942 /*
943  * Read a tecla configuration file.
944  */
945 static int _gl_read_config_file(GetLine *gl, const char *filename, KtBinder who);
946 
947 /*
948  * Read a tecla configuration string.
949  */
950 static int _gl_read_config_string(GetLine *gl, const char *buffer, KtBinder who);
951 
952 /*
953  * Define the callback function used by _gl_parse_config_line() to
954  * read the next character of a configuration stream.
955  */
956 #define GLC_GETC_FN(fn) int (fn)(void *stream)
957 typedef GLC_GETC_FN(GlcGetcFn);
958 
959 static GLC_GETC_FN(glc_file_getc);  /* Read from a file */
960 static GLC_GETC_FN(glc_buff_getc);  /* Read from a string */
961 
962 /*
963  * Parse a single configuration command line.
964  */
965 static int _gl_parse_config_line(GetLine *gl, void *stream, GlcGetcFn *getc_fn,
966 				 const char *origin, KtBinder who, int *lineno);
967 static int gl_report_config_error(GetLine *gl, const char *origin, int lineno,
968 				  const char *errmsg);
969 
970 /*
971  * Bind the actual arrow key bindings to match those of the symbolic
972  * arrow-key bindings.
973  */
974 static int _gl_bind_arrow_keys(GetLine *gl);
975 
976 /*
977  * Copy the binding of the specified symbolic arrow-key binding to
978  * the terminal specific, and default arrow-key key-sequences.
979  */
980 static int _gl_rebind_arrow_key(GetLine *gl, const char *name,
981 				const char *term_seq,
982 				const char *def_seq1,
983 				const char *def_seq2);
984 
985 /*
986  * After the gl_read_from_file() action has been used to tell gl_get_line()
987  * to temporarily read input from a file, gl_revert_input() arranges
988  * for input to be reverted to the input stream last registered with
989  * gl_change_terminal().
990  */
991 static void gl_revert_input(GetLine *gl);
992 
993 /*
994  * Flush unwritten characters to the terminal.
995  */
996 static int gl_flush_output(GetLine *gl);
997 
998 /*
999  * The callback through which all terminal output is routed.
1000  * This simply appends characters to a queue buffer, which is
1001  * subsequently flushed to the output channel by gl_flush_output().
1002  */
1003 static GL_WRITE_FN(gl_write_fn);
1004 
1005 /*
1006  * The callback function which the output character queue object
1007  * calls to transfer characters to the output channel.
1008  */
1009 static GL_WRITE_FN(gl_flush_terminal);
1010 
1011 /*
1012  * Enumerate the possible return statuses of gl_read_input().
1013  */
1014 typedef enum {
1015   GL_READ_OK,      /* A character was read successfully */
1016   GL_READ_ERROR,   /* A read-error occurred */
1017   GL_READ_BLOCKED, /* The read would have blocked the caller */
1018   GL_READ_EOF      /* The end of the current input file was reached */
1019 } GlReadStatus;
1020 
1021 static GlReadStatus gl_read_input(GetLine *gl, char *c);
1022 /*
1023  * Private functions of gl_read_input().
1024  */
1025 static int gl_event_handler(GetLine *gl, int fd);
1026 static int gl_read_unmasked(GetLine *gl, int fd, char *c);
1027 
1028 
1029 /*
1030  * A private function of gl_tty_signals().
1031  */
1032 static int gl_set_tty_signal(int signo, void (*handler)(int));
1033 
1034 /*
1035  * Change the editor style being emulated.
1036  */
1037 static int gl_change_editor(GetLine *gl, GlEditor editor);
1038 
1039 /*
1040  * Searching in a given direction, return the index of a given (or
1041  * read) character in the input line, or the character that precedes
1042  * it in the specified search direction. Return -1 if not found.
1043  */
1044 static int gl_find_char(GetLine *gl, int count, int forward, int onto, char c);
1045 
1046 /*
1047  * Return the buffer index of the nth word ending after the cursor.
1048  */
1049 static int gl_nth_word_end_forward(GetLine *gl, int n);
1050 
1051 /*
1052  * Return the buffer index of the nth word start after the cursor.
1053  */
1054 static int gl_nth_word_start_forward(GetLine *gl, int n);
1055 
1056 /*
1057  * Return the buffer index of the nth word start before the cursor.
1058  */
1059 static int gl_nth_word_start_backward(GetLine *gl, int n);
1060 
1061 /*
1062  * When called when vi command mode is enabled, this function saves the
1063  * current line and cursor position for potential restoration later
1064  * by the vi undo command.
1065  */
1066 static void gl_save_for_undo(GetLine *gl);
1067 
1068 /*
1069  * If in vi mode, switch to vi command mode.
1070  */
1071 static void gl_vi_command_mode(GetLine *gl);
1072 
1073 /*
1074  * In vi mode this is used to delete up to or onto a given or read
1075  * character in the input line. Also switch to insert mode if requested
1076  * after the deletion.
1077  */
1078 static int gl_delete_find(GetLine *gl, int count, char c, int forward,
1079 			  int onto, int change);
1080 
1081 /*
1082  * Copy the characters between the cursor and the count'th instance of
1083  * a specified (or read) character in the input line, into the cut buffer.
1084  */
1085 static int gl_copy_find(GetLine *gl, int count, char c, int forward, int onto);
1086 
1087 /*
1088  * Return the line index of the parenthesis that either matches the one under
1089  * the cursor, or not over a parenthesis character, the index of the next
1090  * close parenthesis. Return -1 if not found.
1091  */
1092 static int gl_index_of_matching_paren(GetLine *gl);
1093 
1094 /*
1095  * Replace a malloc'd string (or NULL), with another malloc'd copy of
1096  * a string (or NULL).
1097  */
1098 static int gl_record_string(char **sptr, const char *string);
1099 
1100 /*
1101  * Enumerate text display attributes as powers of two, suitable for
1102  * use in a bit-mask.
1103  */
1104 typedef enum {
1105   GL_TXT_STANDOUT=1,   /* Display text highlighted */
1106   GL_TXT_UNDERLINE=2,  /* Display text underlined */
1107   GL_TXT_REVERSE=4,    /* Display text with reverse video */
1108   GL_TXT_BLINK=8,      /* Display blinking text */
1109   GL_TXT_DIM=16,       /* Display text in a dim font */
1110   GL_TXT_BOLD=32       /* Display text using a bold font */
1111 } GlTextAttr;
1112 
1113 /*
1114  * Display the prompt regardless of the current visibility mode.
1115  */
1116 static int gl_display_prompt(GetLine *gl);
1117 
1118 /*
1119  * Return the number of characters used by the prompt on the terminal.
1120  */
1121 static int gl_displayed_prompt_width(GetLine *gl);
1122 
1123 /*
1124  * Prepare to return the current input line to the caller of gl_get_line().
1125  */
1126 static int gl_line_ended(GetLine *gl, int newline_char);
1127 
1128 /*
1129  * Arrange for the input line to be redisplayed when the current contents
1130  * of the output queue have been flushed.
1131  */
1132 static void gl_queue_redisplay(GetLine *gl);
1133 
1134 /*
1135  * Erase the displayed representation of the input line, without
1136  * touching the buffered copy.
1137  */
1138 static int gl_erase_line(GetLine *gl);
1139 
1140 /*
1141  * This function is called whenever the input line has been erased.
1142  */
1143 static void gl_line_erased(GetLine *gl);
1144 
1145 /*
1146  * Arrange for the current input line to be discarded.
1147  */
1148 void _gl_abandon_line(GetLine *gl);
1149 
1150 /*
1151  * The following are private internally callable versions of pertinent
1152  * public functions. Unlike their public wrapper functions, they don't
1153  * block signals while running, and assume that their arguments are valid.
1154  * They are designed to be called from places where signals are already
1155  * blocked, and where simple sanity checks have already been applied to
1156  * their arguments.
1157  */
1158 static char *_gl_get_line(GetLine *gl, const char *prompt,
1159 			  const char *start_line, int start_pos);
1160 static int _gl_query_char(GetLine *gl, const char *prompt, char defchar);
1161 static int _gl_read_char(GetLine *gl);
1162 static int _gl_update_size(GetLine *gl);
1163 /*
1164  * Redraw the current input line to account for a change in the terminal
1165  * size. Also install the new size in gl.
1166  */
1167 static int gl_handle_tty_resize(GetLine *gl, int ncolumn, int nline);
1168 
1169 static int _gl_change_terminal(GetLine *gl, FILE *input_fp, FILE *output_fp,
1170 			       const char *term);
1171 static int _gl_configure_getline(GetLine *gl, const char *app_string,
1172 				 const char *app_file, const char *user_file);
1173 static int _gl_save_history(GetLine *gl, const char *filename,
1174 			    const char *comment, int max_lines);
1175 static int _gl_load_history(GetLine *gl, const char *filename,
1176 			    const char *comment);
1177 static int _gl_watch_fd(GetLine *gl, int fd, GlFdEvent event,
1178 			GlFdEventFn *callback, void *data);
1179 static void _gl_terminal_size(GetLine *gl, int def_ncolumn, int def_nline,
1180 			      GlTerminalSize *size);
1181 static void _gl_replace_prompt(GetLine *gl, const char *prompt);
1182 static int _gl_trap_signal(GetLine *gl, int signo, unsigned flags,
1183 			   GlAfterSignal after, int errno_value);
1184 static int _gl_raw_io(GetLine *gl, int redisplay);
1185 static int _gl_normal_io(GetLine *gl);
1186 static int _gl_completion_action(GetLine *gl, void *data, CplMatchFn *match_fn,
1187 				 int list_only, const char *name,
1188 				 const char *keyseq);
1189 static int _gl_register_action(GetLine *gl, void *data, GlActionFn *fn,
1190 			       const char *name, const char *keyseq);
1191 static int _gl_io_mode(GetLine *gl, GlIOMode mode);
1192 static int _gl_set_term_size(GetLine *gl, int ncolumn, int nline);
1193 static int _gl_append_history(GetLine *gl, const char *line);
1194 
1195 /*
1196  * Reset the completion status and associated errno value in
1197  * gl->rtn_status and gl->rtn_errno.
1198  */
1199 static void gl_clear_status(GetLine *gl);
1200 
1201 /*
1202  * Record a completion status, unless a previous abnormal completion
1203  * status has already been recorded for the current call.
1204  */
1205 static void gl_record_status(GetLine *gl, GlReturnStatus rtn_status,
1206 			     int rtn_errno);
1207 
1208 /*
1209  * Set the maximum length of a line in a user's tecla configuration
1210  * file (not counting comments).
1211  */
1212 #define GL_CONF_BUFLEN 100
1213 
1214 /*
1215  * Set the maximum number of arguments supported by individual commands
1216  * in tecla configuration files.
1217  */
1218 #define GL_CONF_MAXARG 10
1219 
1220 /*
1221  * Prototype the available action functions.
1222  */
1223 static KT_KEY_FN(gl_user_interrupt);
1224 static KT_KEY_FN(gl_abort);
1225 static KT_KEY_FN(gl_suspend);
1226 static KT_KEY_FN(gl_stop_output);
1227 static KT_KEY_FN(gl_start_output);
1228 static KT_KEY_FN(gl_literal_next);
1229 static KT_KEY_FN(gl_cursor_left);
1230 static KT_KEY_FN(gl_cursor_right);
1231 static KT_KEY_FN(gl_insert_mode);
1232 static KT_KEY_FN(gl_beginning_of_line);
1233 static KT_KEY_FN(gl_end_of_line);
1234 static KT_KEY_FN(gl_delete_line);
1235 static KT_KEY_FN(gl_kill_line);
1236 static KT_KEY_FN(gl_forward_word);
1237 static KT_KEY_FN(gl_backward_word);
1238 static KT_KEY_FN(gl_forward_delete_char);
1239 static KT_KEY_FN(gl_backward_delete_char);
1240 static KT_KEY_FN(gl_forward_delete_word);
1241 static KT_KEY_FN(gl_backward_delete_word);
1242 static KT_KEY_FN(gl_delete_refind);
1243 static KT_KEY_FN(gl_delete_invert_refind);
1244 static KT_KEY_FN(gl_delete_to_column);
1245 static KT_KEY_FN(gl_delete_to_parenthesis);
1246 static KT_KEY_FN(gl_forward_delete_find);
1247 static KT_KEY_FN(gl_backward_delete_find);
1248 static KT_KEY_FN(gl_forward_delete_to);
1249 static KT_KEY_FN(gl_backward_delete_to);
1250 static KT_KEY_FN(gl_upcase_word);
1251 static KT_KEY_FN(gl_downcase_word);
1252 static KT_KEY_FN(gl_capitalize_word);
1253 static KT_KEY_FN(gl_redisplay);
1254 static KT_KEY_FN(gl_clear_screen);
1255 static KT_KEY_FN(gl_transpose_chars);
1256 static KT_KEY_FN(gl_set_mark);
1257 static KT_KEY_FN(gl_exchange_point_and_mark);
1258 static KT_KEY_FN(gl_kill_region);
1259 static KT_KEY_FN(gl_copy_region_as_kill);
1260 static KT_KEY_FN(gl_yank);
1261 static KT_KEY_FN(gl_up_history);
1262 static KT_KEY_FN(gl_down_history);
1263 static KT_KEY_FN(gl_history_search_backward);
1264 static KT_KEY_FN(gl_history_re_search_backward);
1265 static KT_KEY_FN(gl_history_search_forward);
1266 static KT_KEY_FN(gl_history_re_search_forward);
1267 static KT_KEY_FN(gl_complete_word);
1268 #ifndef HIDE_FILE_SYSTEM
1269 static KT_KEY_FN(gl_expand_filename);
1270 static KT_KEY_FN(gl_read_from_file);
1271 static KT_KEY_FN(gl_read_init_files);
1272 static KT_KEY_FN(gl_list_glob);
1273 #endif
1274 static KT_KEY_FN(gl_del_char_or_list_or_eof);
1275 static KT_KEY_FN(gl_list_or_eof);
1276 static KT_KEY_FN(gl_beginning_of_history);
1277 static KT_KEY_FN(gl_end_of_history);
1278 static KT_KEY_FN(gl_digit_argument);
1279 static KT_KEY_FN(gl_newline);
1280 static KT_KEY_FN(gl_repeat_history);
1281 static KT_KEY_FN(gl_vi_insert);
1282 static KT_KEY_FN(gl_vi_overwrite);
1283 static KT_KEY_FN(gl_change_case);
1284 static KT_KEY_FN(gl_vi_insert_at_bol);
1285 static KT_KEY_FN(gl_vi_append_at_eol);
1286 static KT_KEY_FN(gl_vi_append);
1287 static KT_KEY_FN(gl_backward_kill_line);
1288 static KT_KEY_FN(gl_goto_column);
1289 static KT_KEY_FN(gl_forward_to_word);
1290 static KT_KEY_FN(gl_vi_replace_char);
1291 static KT_KEY_FN(gl_vi_change_rest_of_line);
1292 static KT_KEY_FN(gl_vi_change_line);
1293 static KT_KEY_FN(gl_vi_change_to_bol);
1294 static KT_KEY_FN(gl_vi_change_refind);
1295 static KT_KEY_FN(gl_vi_change_invert_refind);
1296 static KT_KEY_FN(gl_vi_change_to_column);
1297 static KT_KEY_FN(gl_vi_change_to_parenthesis);
1298 static KT_KEY_FN(gl_vi_forward_change_word);
1299 static KT_KEY_FN(gl_vi_backward_change_word);
1300 static KT_KEY_FN(gl_vi_forward_change_find);
1301 static KT_KEY_FN(gl_vi_backward_change_find);
1302 static KT_KEY_FN(gl_vi_forward_change_to);
1303 static KT_KEY_FN(gl_vi_backward_change_to);
1304 static KT_KEY_FN(gl_vi_forward_change_char);
1305 static KT_KEY_FN(gl_vi_backward_change_char);
1306 static KT_KEY_FN(gl_forward_copy_char);
1307 static KT_KEY_FN(gl_backward_copy_char);
1308 static KT_KEY_FN(gl_forward_find_char);
1309 static KT_KEY_FN(gl_backward_find_char);
1310 static KT_KEY_FN(gl_forward_to_char);
1311 static KT_KEY_FN(gl_backward_to_char);
1312 static KT_KEY_FN(gl_repeat_find_char);
1313 static KT_KEY_FN(gl_invert_refind_char);
1314 static KT_KEY_FN(gl_append_yank);
1315 static KT_KEY_FN(gl_backward_copy_word);
1316 static KT_KEY_FN(gl_forward_copy_word);
1317 static KT_KEY_FN(gl_copy_to_bol);
1318 static KT_KEY_FN(gl_copy_refind);
1319 static KT_KEY_FN(gl_copy_invert_refind);
1320 static KT_KEY_FN(gl_copy_to_column);
1321 static KT_KEY_FN(gl_copy_to_parenthesis);
1322 static KT_KEY_FN(gl_copy_rest_of_line);
1323 static KT_KEY_FN(gl_copy_line);
1324 static KT_KEY_FN(gl_backward_copy_find);
1325 static KT_KEY_FN(gl_forward_copy_find);
1326 static KT_KEY_FN(gl_backward_copy_to);
1327 static KT_KEY_FN(gl_forward_copy_to);
1328 static KT_KEY_FN(gl_vi_undo);
1329 static KT_KEY_FN(gl_emacs_editing_mode);
1330 static KT_KEY_FN(gl_vi_editing_mode);
1331 static KT_KEY_FN(gl_ring_bell);
1332 static KT_KEY_FN(gl_vi_repeat_change);
1333 static KT_KEY_FN(gl_find_parenthesis);
1334 static KT_KEY_FN(gl_list_history);
1335 static KT_KEY_FN(gl_list_completions);
1336 static KT_KEY_FN(gl_run_external_action);
1337 
1338 /*
1339  * Name the available action functions.
1340  */
1341 static const struct {const char *name; KT_KEY_FN(*fn);} gl_actions[] = {
1342   {"user-interrupt",             gl_user_interrupt},
1343   {"abort",                      gl_abort},
1344   {"suspend",                    gl_suspend},
1345   {"stop-output",                gl_stop_output},
1346   {"start-output",               gl_start_output},
1347   {"literal-next",               gl_literal_next},
1348   {"cursor-right",               gl_cursor_right},
1349   {"cursor-left",                gl_cursor_left},
1350   {"insert-mode",                gl_insert_mode},
1351   {"beginning-of-line",          gl_beginning_of_line},
1352   {"end-of-line",                gl_end_of_line},
1353   {"delete-line",                gl_delete_line},
1354   {"kill-line",                  gl_kill_line},
1355   {"forward-word",               gl_forward_word},
1356   {"backward-word",              gl_backward_word},
1357   {"forward-delete-char",        gl_forward_delete_char},
1358   {"backward-delete-char",       gl_backward_delete_char},
1359   {"forward-delete-word",        gl_forward_delete_word},
1360   {"backward-delete-word",       gl_backward_delete_word},
1361   {"delete-refind",              gl_delete_refind},
1362   {"delete-invert-refind",       gl_delete_invert_refind},
1363   {"delete-to-column",           gl_delete_to_column},
1364   {"delete-to-parenthesis",      gl_delete_to_parenthesis},
1365   {"forward-delete-find",        gl_forward_delete_find},
1366   {"backward-delete-find",       gl_backward_delete_find},
1367   {"forward-delete-to",          gl_forward_delete_to},
1368   {"backward-delete-to",         gl_backward_delete_to},
1369   {"upcase-word",                gl_upcase_word},
1370   {"downcase-word",              gl_downcase_word},
1371   {"capitalize-word",            gl_capitalize_word},
1372   {"redisplay",                  gl_redisplay},
1373   {"clear-screen",               gl_clear_screen},
1374   {"transpose-chars",            gl_transpose_chars},
1375   {"set-mark",                   gl_set_mark},
1376   {"exchange-point-and-mark",    gl_exchange_point_and_mark},
1377   {"kill-region",                gl_kill_region},
1378   {"copy-region-as-kill",        gl_copy_region_as_kill},
1379   {"yank",                       gl_yank},
1380   {"up-history",                 gl_up_history},
1381   {"down-history",               gl_down_history},
1382   {"history-search-backward",    gl_history_search_backward},
1383   {"history-re-search-backward", gl_history_re_search_backward},
1384   {"history-search-forward",     gl_history_search_forward},
1385   {"history-re-search-forward",  gl_history_re_search_forward},
1386   {"complete-word",              gl_complete_word},
1387 #ifndef HIDE_FILE_SYSTEM
1388   {"expand-filename",            gl_expand_filename},
1389   {"read-from-file",             gl_read_from_file},
1390   {"read-init-files",            gl_read_init_files},
1391   {"list-glob",                  gl_list_glob},
1392 #endif
1393   {"del-char-or-list-or-eof",    gl_del_char_or_list_or_eof},
1394   {"beginning-of-history",       gl_beginning_of_history},
1395   {"end-of-history",             gl_end_of_history},
1396   {"digit-argument",             gl_digit_argument},
1397   {"newline",                    gl_newline},
1398   {"repeat-history",             gl_repeat_history},
1399   {"vi-insert",                  gl_vi_insert},
1400   {"vi-overwrite",               gl_vi_overwrite},
1401   {"vi-insert-at-bol",           gl_vi_insert_at_bol},
1402   {"vi-append-at-eol",           gl_vi_append_at_eol},
1403   {"vi-append",                  gl_vi_append},
1404   {"change-case",                gl_change_case},
1405   {"backward-kill-line",         gl_backward_kill_line},
1406   {"goto-column",                gl_goto_column},
1407   {"forward-to-word",            gl_forward_to_word},
1408   {"vi-replace-char",            gl_vi_replace_char},
1409   {"vi-change-rest-of-line",     gl_vi_change_rest_of_line},
1410   {"vi-change-line",             gl_vi_change_line},
1411   {"vi-change-to-bol",           gl_vi_change_to_bol},
1412   {"vi-change-refind",           gl_vi_change_refind},
1413   {"vi-change-invert-refind",    gl_vi_change_invert_refind},
1414   {"vi-change-to-column",        gl_vi_change_to_column},
1415   {"vi-change-to-parenthesis",   gl_vi_change_to_parenthesis},
1416   {"forward-copy-char",          gl_forward_copy_char},
1417   {"backward-copy-char",         gl_backward_copy_char},
1418   {"forward-find-char",          gl_forward_find_char},
1419   {"backward-find-char",         gl_backward_find_char},
1420   {"forward-to-char",            gl_forward_to_char},
1421   {"backward-to-char",           gl_backward_to_char},
1422   {"repeat-find-char",           gl_repeat_find_char},
1423   {"invert-refind-char",         gl_invert_refind_char},
1424   {"append-yank",                gl_append_yank},
1425   {"backward-copy-word",         gl_backward_copy_word},
1426   {"forward-copy-word",          gl_forward_copy_word},
1427   {"copy-to-bol",                gl_copy_to_bol},
1428   {"copy-refind",                gl_copy_refind},
1429   {"copy-invert-refind",         gl_copy_invert_refind},
1430   {"copy-to-column",             gl_copy_to_column},
1431   {"copy-to-parenthesis",        gl_copy_to_parenthesis},
1432   {"copy-rest-of-line",          gl_copy_rest_of_line},
1433   {"copy-line",                  gl_copy_line},
1434   {"backward-copy-find",         gl_backward_copy_find},
1435   {"forward-copy-find",          gl_forward_copy_find},
1436   {"backward-copy-to",           gl_backward_copy_to},
1437   {"forward-copy-to",            gl_forward_copy_to},
1438   {"list-or-eof",                gl_list_or_eof},
1439   {"vi-undo",                    gl_vi_undo},
1440   {"vi-backward-change-word",    gl_vi_backward_change_word},
1441   {"vi-forward-change-word",     gl_vi_forward_change_word},
1442   {"vi-backward-change-find",    gl_vi_backward_change_find},
1443   {"vi-forward-change-find",     gl_vi_forward_change_find},
1444   {"vi-backward-change-to",      gl_vi_backward_change_to},
1445   {"vi-forward-change-to",       gl_vi_forward_change_to},
1446   {"vi-backward-change-char",    gl_vi_backward_change_char},
1447   {"vi-forward-change-char",     gl_vi_forward_change_char},
1448   {"emacs-mode",                 gl_emacs_editing_mode},
1449   {"vi-mode",                    gl_vi_editing_mode},
1450   {"ring-bell",                  gl_ring_bell},
1451   {"vi-repeat-change",           gl_vi_repeat_change},
1452   {"find-parenthesis",           gl_find_parenthesis},
1453   {"list-history",               gl_list_history},
1454 };
1455 
1456 /*
1457  * Define the default key-bindings in emacs mode.
1458  */
1459 static const KtKeyBinding gl_emacs_bindings[] = {
1460   {"right",        "cursor-right"},
1461   {"^F",           "cursor-right"},
1462   {"left",         "cursor-left"},
1463   {"^B",           "cursor-left"},
1464   {"M-i",          "insert-mode"},
1465   {"M-I",          "insert-mode"},
1466   {"^A",           "beginning-of-line"},
1467   {"^E",           "end-of-line"},
1468   {"^U",           "delete-line"},
1469   {"^K",           "kill-line"},
1470   {"M-f",          "forward-word"},
1471   {"M-F",          "forward-word"},
1472   {"M-b",          "backward-word"},
1473   {"M-B",          "backward-word"},
1474   {"^D",           "del-char-or-list-or-eof"},
1475   {"^H",           "backward-delete-char"},
1476   {"^?",           "backward-delete-char"},
1477   {"M-d",          "forward-delete-word"},
1478   {"M-D",          "forward-delete-word"},
1479   {"M-^H",         "backward-delete-word"},
1480   {"M-^?",         "backward-delete-word"},
1481   {"M-u",          "upcase-word"},
1482   {"M-U",          "upcase-word"},
1483   {"M-l",          "downcase-word"},
1484   {"M-L",          "downcase-word"},
1485   {"M-c",          "capitalize-word"},
1486   {"M-C",          "capitalize-word"},
1487   {"^R",           "redisplay"},
1488   {"^L",           "clear-screen"},
1489   {"^T",           "transpose-chars"},
1490   {"^@",           "set-mark"},
1491   {"^X^X",         "exchange-point-and-mark"},
1492   {"^W",           "kill-region"},
1493   {"M-w",          "copy-region-as-kill"},
1494   {"M-W",          "copy-region-as-kill"},
1495   {"^Y",           "yank"},
1496   {"^P",           "up-history"},
1497   {"up",           "up-history"},
1498   {"^N",           "down-history"},
1499   {"down",         "down-history"},
1500   {"M-p",          "history-search-backward"},
1501   {"M-P",          "history-search-backward"},
1502   {"M-n",          "history-search-forward"},
1503   {"M-N",          "history-search-forward"},
1504   {"\t",           "complete-word"},
1505 #ifndef HIDE_FILE_SYSTEM
1506   {"^X*",          "expand-filename"},
1507   {"^X^F",         "read-from-file"},
1508   {"^X^R",         "read-init-files"},
1509   {"^Xg",          "list-glob"},
1510   {"^XG",          "list-glob"},
1511 #endif
1512   {"^Xh",          "list-history"},
1513   {"^XH",          "list-history"},
1514   {"M-<",          "beginning-of-history"},
1515   {"M->",          "end-of-history"},
1516   {"M-0",          "digit-argument"},
1517   {"M-1",          "digit-argument"},
1518   {"M-2",          "digit-argument"},
1519   {"M-3",          "digit-argument"},
1520   {"M-4",          "digit-argument"},
1521   {"M-5",          "digit-argument"},
1522   {"M-6",          "digit-argument"},
1523   {"M-7",          "digit-argument"},
1524   {"M-8",          "digit-argument"},
1525   {"M-9",          "digit-argument"},
1526   {"\r",           "newline"},
1527   {"\n",           "newline"},
1528   {"M-o",          "repeat-history"},
1529   {"M-C-v",        "vi-mode"},
1530 };
1531 
1532 /*
1533  * Define the default key-bindings in vi mode. Note that in vi-mode
1534  * meta-key bindings are command-mode bindings. For example M-i first
1535  * switches to command mode if not already in that mode, then moves
1536  * the cursor one position right, as in vi.
1537  */
1538 static const KtKeyBinding gl_vi_bindings[] = {
1539   {"^D",           "list-or-eof"},
1540 #ifndef HIDE_FILE_SYSTEM
1541   {"^G",           "list-glob"},
1542 #endif
1543   {"^H",           "backward-delete-char"},
1544   {"\t",           "complete-word"},
1545   {"\r",           "newline"},
1546   {"\n",           "newline"},
1547   {"^L",           "clear-screen"},
1548   {"^N",           "down-history"},
1549   {"^P",           "up-history"},
1550   {"^R",           "redisplay"},
1551   {"^U",           "backward-kill-line"},
1552   {"^W",           "backward-delete-word"},
1553 #ifndef HIDE_FILE_SYSTEM
1554   {"^X^F",         "read-from-file"},
1555   {"^X^R",         "read-init-files"},
1556   {"^X*",          "expand-filename"},
1557 #endif
1558   {"^?",           "backward-delete-char"},
1559   {"M- ",          "cursor-right"},
1560   {"M-$",          "end-of-line"},
1561 #ifndef HIDE_FILE_SYSTEM
1562   {"M-*",          "expand-filename"},
1563 #endif
1564   {"M-+",          "down-history"},
1565   {"M--",          "up-history"},
1566   {"M-<",          "beginning-of-history"},
1567   {"M->",          "end-of-history"},
1568   {"M-^",          "beginning-of-line"},
1569   {"M-;",          "repeat-find-char"},
1570   {"M-,",          "invert-refind-char"},
1571   {"M-|",          "goto-column"},
1572   {"M-~",          "change-case"},
1573   {"M-.",          "vi-repeat-change"},
1574   {"M-%",          "find-parenthesis"},
1575   {"M-0",          "digit-argument"},
1576   {"M-1",          "digit-argument"},
1577   {"M-2",          "digit-argument"},
1578   {"M-3",          "digit-argument"},
1579   {"M-4",          "digit-argument"},
1580   {"M-5",          "digit-argument"},
1581   {"M-6",          "digit-argument"},
1582   {"M-7",          "digit-argument"},
1583   {"M-8",          "digit-argument"},
1584   {"M-9",          "digit-argument"},
1585   {"M-a",          "vi-append"},
1586   {"M-A",          "vi-append-at-eol"},
1587   {"M-b",          "backward-word"},
1588   {"M-B",          "backward-word"},
1589   {"M-C",          "vi-change-rest-of-line"},
1590   {"M-cb",         "vi-backward-change-word"},
1591   {"M-cB",         "vi-backward-change-word"},
1592   {"M-cc",         "vi-change-line"},
1593   {"M-ce",         "vi-forward-change-word"},
1594   {"M-cE",         "vi-forward-change-word"},
1595   {"M-cw",         "vi-forward-change-word"},
1596   {"M-cW",         "vi-forward-change-word"},
1597   {"M-cF",         "vi-backward-change-find"},
1598   {"M-cf",         "vi-forward-change-find"},
1599   {"M-cT",         "vi-backward-change-to"},
1600   {"M-ct",         "vi-forward-change-to"},
1601   {"M-c;",         "vi-change-refind"},
1602   {"M-c,",         "vi-change-invert-refind"},
1603   {"M-ch",         "vi-backward-change-char"},
1604   {"M-c^H",        "vi-backward-change-char"},
1605   {"M-c^?",        "vi-backward-change-char"},
1606   {"M-cl",         "vi-forward-change-char"},
1607   {"M-c ",         "vi-forward-change-char"},
1608   {"M-c^",         "vi-change-to-bol"},
1609   {"M-c0",         "vi-change-to-bol"},
1610   {"M-c$",         "vi-change-rest-of-line"},
1611   {"M-c|",         "vi-change-to-column"},
1612   {"M-c%",         "vi-change-to-parenthesis"},
1613   {"M-dh",         "backward-delete-char"},
1614   {"M-d^H",        "backward-delete-char"},
1615   {"M-d^?",        "backward-delete-char"},
1616   {"M-dl",         "forward-delete-char"},
1617   {"M-d ",         "forward-delete-char"},
1618   {"M-dd",         "delete-line"},
1619   {"M-db",         "backward-delete-word"},
1620   {"M-dB",         "backward-delete-word"},
1621   {"M-de",         "forward-delete-word"},
1622   {"M-dE",         "forward-delete-word"},
1623   {"M-dw",         "forward-delete-word"},
1624   {"M-dW",         "forward-delete-word"},
1625   {"M-dF",         "backward-delete-find"},
1626   {"M-df",         "forward-delete-find"},
1627   {"M-dT",         "backward-delete-to"},
1628   {"M-dt",         "forward-delete-to"},
1629   {"M-d;",         "delete-refind"},
1630   {"M-d,",         "delete-invert-refind"},
1631   {"M-d^",         "backward-kill-line"},
1632   {"M-d0",         "backward-kill-line"},
1633   {"M-d$",         "kill-line"},
1634   {"M-D",          "kill-line"},
1635   {"M-d|",         "delete-to-column"},
1636   {"M-d%",         "delete-to-parenthesis"},
1637   {"M-e",          "forward-word"},
1638   {"M-E",          "forward-word"},
1639   {"M-f",          "forward-find-char"},
1640   {"M-F",          "backward-find-char"},
1641   {"M--",          "up-history"},
1642   {"M-h",          "cursor-left"},
1643   {"M-H",          "beginning-of-history"},
1644   {"M-i",          "vi-insert"},
1645   {"M-I",          "vi-insert-at-bol"},
1646   {"M-j",          "down-history"},
1647   {"M-J",          "history-search-forward"},
1648   {"M-k",          "up-history"},
1649   {"M-K",          "history-search-backward"},
1650   {"M-l",          "cursor-right"},
1651   {"M-L",          "end-of-history"},
1652   {"M-n",          "history-re-search-forward"},
1653   {"M-N",          "history-re-search-backward"},
1654   {"M-p",          "append-yank"},
1655   {"M-P",          "yank"},
1656   {"M-r",          "vi-replace-char"},
1657   {"M-R",          "vi-overwrite"},
1658   {"M-s",          "vi-forward-change-char"},
1659   {"M-S",          "vi-change-line"},
1660   {"M-t",          "forward-to-char"},
1661   {"M-T",          "backward-to-char"},
1662   {"M-u",          "vi-undo"},
1663   {"M-w",          "forward-to-word"},
1664   {"M-W",          "forward-to-word"},
1665   {"M-x",          "forward-delete-char"},
1666   {"M-X",          "backward-delete-char"},
1667   {"M-yh",         "backward-copy-char"},
1668   {"M-y^H",        "backward-copy-char"},
1669   {"M-y^?",        "backward-copy-char"},
1670   {"M-yl",         "forward-copy-char"},
1671   {"M-y ",         "forward-copy-char"},
1672   {"M-ye",         "forward-copy-word"},
1673   {"M-yE",         "forward-copy-word"},
1674   {"M-yw",         "forward-copy-word"},
1675   {"M-yW",         "forward-copy-word"},
1676   {"M-yb",         "backward-copy-word"},
1677   {"M-yB",         "backward-copy-word"},
1678   {"M-yf",         "forward-copy-find"},
1679   {"M-yF",         "backward-copy-find"},
1680   {"M-yt",         "forward-copy-to"},
1681   {"M-yT",         "backward-copy-to"},
1682   {"M-y;",         "copy-refind"},
1683   {"M-y,",         "copy-invert-refind"},
1684   {"M-y^",         "copy-to-bol"},
1685   {"M-y0",         "copy-to-bol"},
1686   {"M-y$",         "copy-rest-of-line"},
1687   {"M-yy",         "copy-line"},
1688   {"M-Y",          "copy-line"},
1689   {"M-y|",         "copy-to-column"},
1690   {"M-y%",         "copy-to-parenthesis"},
1691   {"M-^E",         "emacs-mode"},
1692   {"M-^H",         "cursor-left"},
1693   {"M-^?",         "cursor-left"},
1694   {"M-^L",         "clear-screen"},
1695   {"M-^N",         "down-history"},
1696   {"M-^P",         "up-history"},
1697   {"M-^R",         "redisplay"},
1698   {"M-^D",         "list-or-eof"},
1699   {"M-\r",         "newline"},
1700   {"M-\t",         "complete-word"},
1701   {"M-\n",         "newline"},
1702 #ifndef HIDE_FILE_SYSTEM
1703   {"M-^X^R",       "read-init-files"},
1704 #endif
1705   {"M-^Xh",        "list-history"},
1706   {"M-^XH",        "list-history"},
1707   {"down",         "down-history"},
1708   {"up",           "up-history"},
1709   {"left",         "cursor-left"},
1710   {"right",        "cursor-right"},
1711 };
1712 
1713 /*.......................................................................
1714  * Create a new GetLine object.
1715  *
1716  * Input:
1717  *  linelen  size_t    The maximum line length to allow for.
1718  *  histlen  size_t    The number of bytes to allocate for recording
1719  *                     a circular buffer of history lines.
1720  * Output:
1721  *  return  GetLine *  The new object, or NULL on error.
1722  */
new_GetLine(size_t linelen,size_t histlen)1723 GetLine *new_GetLine(size_t linelen, size_t histlen)
1724 {
1725   GetLine *gl;  /* The object to be returned */
1726   int i;
1727 /*
1728  * Check the arguments.
1729  */
1730   if(linelen < 10) {
1731     errno = ENOMEM;
1732     return NULL;
1733   };
1734 /*
1735  * Allocate the container.
1736  */
1737   gl = (GetLine *) malloc(sizeof(GetLine));
1738   if(!gl) {
1739     errno = ENOMEM;
1740     return NULL;
1741   };
1742 /*
1743  * Before attempting any operation that might fail, initialize the
1744  * container at least up to the point at which it can safely be passed
1745  * to del_GetLine().
1746  */
1747   gl->err = NULL;
1748   gl->glh = NULL;
1749   gl->cpl = NULL;
1750 #ifndef HIDE_FILE_SYSTEM
1751   gl->cplfn.fn = cpl_file_completions;
1752 #else
1753   gl->cplfn.fn = gl_no_completions;
1754 #endif
1755   gl->cplfn.data = NULL;
1756 #ifndef WITHOUT_FILE_SYSTEM
1757   gl->ef = NULL;
1758 #endif
1759   gl->capmem = NULL;
1760   gl->cq = NULL;
1761   gl->input_fd = -1;
1762   gl->output_fd = -1;
1763   gl->input_fp = NULL;
1764   gl->output_fp = NULL;
1765   gl->file_fp = NULL;
1766   gl->term = NULL;
1767   gl->is_term = 0;
1768   gl->flush_fn = gl_flush_terminal;
1769   gl->io_mode = GL_NORMAL_MODE;
1770   gl->raw_mode = 0;
1771   gl->pending_io = GLP_WRITE;  /* We will start by writing the prompt */
1772   gl_clear_status(gl);
1773   gl->linelen = linelen;
1774   gl->line = NULL;
1775   gl->cutbuf = NULL;
1776   gl->prompt = NULL;
1777   gl->prompt_len = 0;
1778   gl->prompt_changed = 0;
1779   gl->prompt_style = GL_LITERAL_PROMPT;
1780   gl->cpl_mem = NULL;
1781   gl->ext_act_mem = NULL;
1782   gl->sig_mem = NULL;
1783   gl->sigs = NULL;
1784   gl->signals_masked = 0;
1785   gl->signals_overriden = 0;
1786   sigemptyset(&gl->all_signal_set);
1787   sigemptyset(&gl->old_signal_set);
1788   sigemptyset(&gl->use_signal_set);
1789   gl->bindings = NULL;
1790   gl->ntotal = 0;
1791   gl->buff_curpos = 0;
1792   gl->term_curpos = 0;
1793   gl->term_len = 0;
1794   gl->buff_mark = 0;
1795   gl->insert_curpos = 0;
1796   gl->insert = 1;
1797   gl->number = -1;
1798   gl->endline = 1;
1799   gl->displayed = 0;
1800   gl->redisplay = 0;
1801   gl->postpone = 0;
1802   gl->keybuf[0]='\0';
1803   gl->nbuf = 0;
1804   gl->nread = 0;
1805   gl->current_action.fn = 0;
1806   gl->current_action.data = NULL;
1807   gl->current_count = 0;
1808   gl->preload_id = 0;
1809   gl->preload_history = 0;
1810   gl->keyseq_count = 0;
1811   gl->last_search = -1;
1812   gl->editor = GL_EMACS_MODE;
1813   gl->silence_bell = 0;
1814   gl->automatic_history = 1;
1815   gl->vi.undo.line = NULL;
1816   gl->vi.undo.buff_curpos = 0;
1817   gl->vi.undo.ntotal = 0;
1818   gl->vi.undo.saved = 0;
1819   gl->vi.repeat.action.fn = 0;
1820   gl->vi.repeat.action.data = 0;
1821   gl->vi.repeat.count = 0;
1822   gl->vi.repeat.input_curpos = 0;
1823   gl->vi.repeat.command_curpos = 0;
1824   gl->vi.repeat.input_char = '\0';
1825   gl->vi.repeat.saved = 0;
1826   gl->vi.repeat.active = 0;
1827   gl->vi.command = 0;
1828   gl->vi.find_forward = 0;
1829   gl->vi.find_onto = 0;
1830   gl->vi.find_char = '\0';
1831   gl->left = NULL;
1832   gl->right = NULL;
1833   gl->up = NULL;
1834   gl->down = NULL;
1835   gl->home = NULL;
1836   gl->bol = 0;
1837   gl->clear_eol = NULL;
1838   gl->clear_eod = NULL;
1839   gl->u_arrow = NULL;
1840   gl->d_arrow = NULL;
1841   gl->l_arrow = NULL;
1842   gl->r_arrow = NULL;
1843   gl->sound_bell = NULL;
1844   gl->bold = NULL;
1845   gl->underline = NULL;
1846   gl->standout = NULL;
1847   gl->dim = NULL;
1848   gl->reverse = NULL;
1849   gl->blink = NULL;
1850   gl->text_attr_off = NULL;
1851   gl->nline = 0;
1852   gl->ncolumn = 0;
1853 #ifdef USE_TERMINFO
1854   gl->left_n = NULL;
1855   gl->right_n = NULL;
1856 #elif defined(USE_TERMCAP)
1857   gl->tgetent_buf = NULL;
1858   gl->tgetstr_buf = NULL;
1859 #endif
1860   gl->app_file = NULL;
1861   gl->user_file = NULL;
1862   gl->configured = 0;
1863   gl->echo = 1;
1864   gl->last_signal = -1;
1865 #ifdef HAVE_SELECT
1866   gl->fd_node_mem = NULL;
1867   gl->fd_nodes = NULL;
1868   FD_ZERO(&gl->rfds);
1869   FD_ZERO(&gl->wfds);
1870   FD_ZERO(&gl->ufds);
1871   gl->max_fd = 0;
1872   gl->timer.dt.tv_sec = 0;
1873   gl->timer.dt.tv_usec = 0;
1874   gl->timer.fn = 0;
1875   gl->timer.data = NULL;
1876 #endif
1877 /*
1878  * Allocate an error reporting buffer.
1879  */
1880   gl->err = _new_ErrMsg();
1881   if(!gl->err)
1882     return del_GetLine(gl);
1883 /*
1884  * Allocate the history buffer.
1885  */
1886   gl->glh = _new_GlHistory(histlen);
1887   if(!gl->glh)
1888     return del_GetLine(gl);
1889 /*
1890  * Allocate the resource object for file-completion.
1891  */
1892   gl->cpl = new_WordCompletion();
1893   if(!gl->cpl)
1894     return del_GetLine(gl);
1895 /*
1896  * Allocate the resource object for file-completion.
1897  */
1898 #ifndef WITHOUT_FILE_SYSTEM
1899   gl->ef = new_ExpandFile();
1900   if(!gl->ef)
1901     return del_GetLine(gl);
1902 #endif
1903 /*
1904  * Allocate a string-segment memory allocator for use in storing terminal
1905  * capablity strings.
1906  */
1907   gl->capmem = _new_StringGroup(CAPMEM_SEGMENT_SIZE);
1908   if(!gl->capmem)
1909     return del_GetLine(gl);
1910 /*
1911  * Allocate the character queue that is used to buffer terminal output.
1912  */
1913   gl->cq = _new_GlCharQueue();
1914   if(!gl->cq)
1915     return del_GetLine(gl);
1916 /*
1917  * Allocate a line buffer, leaving 2 extra characters for the terminating
1918  * '\n' and '\0' characters
1919  */
1920   gl->line = (char *) malloc(linelen + 2);
1921   if(!gl->line) {
1922     errno = ENOMEM;
1923     return del_GetLine(gl);
1924   };
1925 /*
1926  * Start with an empty input line.
1927  */
1928   gl_truncate_buffer(gl, 0);
1929 /*
1930  * Allocate a cut buffer.
1931  */
1932   gl->cutbuf = (char *) malloc(linelen + 2);
1933   if(!gl->cutbuf) {
1934     errno = ENOMEM;
1935     return del_GetLine(gl);
1936   };
1937   gl->cutbuf[0] = '\0';
1938 /*
1939  * Allocate an initial empty prompt.
1940  */
1941   _gl_replace_prompt(gl, NULL);
1942   if(!gl->prompt) {
1943     errno = ENOMEM;
1944     return del_GetLine(gl);
1945   };
1946 /*
1947  * Allocate a vi undo buffer.
1948  */
1949   gl->vi.undo.line = (char *) malloc(linelen + 2);
1950   if(!gl->vi.undo.line) {
1951     errno = ENOMEM;
1952     return del_GetLine(gl);
1953   };
1954   gl->vi.undo.line[0] = '\0';
1955 /*
1956  * Allocate a freelist from which to allocate nodes for the list
1957  * of completion functions.
1958  */
1959   gl->cpl_mem = _new_FreeList(sizeof(GlCplCallback), GL_CPL_FREELIST_BLOCKING);
1960   if(!gl->cpl_mem)
1961     return del_GetLine(gl);
1962 /*
1963  * Allocate a freelist from which to allocate nodes for the list
1964  * of external action functions.
1965  */
1966   gl->ext_act_mem = _new_FreeList(sizeof(GlExternalAction),
1967 				  GL_EXT_ACT_FREELIST_BLOCKING);
1968   if(!gl->ext_act_mem)
1969     return del_GetLine(gl);
1970 /*
1971  * Allocate a freelist from which to allocate nodes for the list
1972  * of signals.
1973  */
1974   gl->sig_mem = _new_FreeList(sizeof(GlSignalNode), GLS_FREELIST_BLOCKING);
1975   if(!gl->sig_mem)
1976     return del_GetLine(gl);
1977 /*
1978  * Install initial dispositions for the default list of signals that
1979  * gl_get_line() traps.
1980  */
1981   for(i=0; i<sizeof(gl_signal_list)/sizeof(gl_signal_list[0]); i++) {
1982     const struct GlDefSignal *sig = gl_signal_list + i;
1983     if(_gl_trap_signal(gl, sig->signo, sig->flags, sig->after,
1984 		       sig->errno_value))
1985       return del_GetLine(gl);
1986   };
1987 /*
1988  * Allocate an empty table of key bindings.
1989  */
1990   gl->bindings = _new_KeyTab();
1991   if(!gl->bindings)
1992     return del_GetLine(gl);
1993 /*
1994  * Define the available actions that can be bound to key sequences.
1995  */
1996   for(i=0; i<sizeof(gl_actions)/sizeof(gl_actions[0]); i++) {
1997     if(_kt_set_action(gl->bindings, gl_actions[i].name, gl_actions[i].fn, NULL))
1998       return del_GetLine(gl);
1999   };
2000 /*
2001  * Set up the default bindings.
2002  */
2003   if(gl_change_editor(gl, gl->editor))
2004     return del_GetLine(gl);
2005 /*
2006  * Allocate termcap buffers.
2007  */
2008 #ifdef USE_TERMCAP
2009   gl->tgetent_buf = (char *) malloc(TERMCAP_BUF_SIZE);
2010   gl->tgetstr_buf = (char *) malloc(TERMCAP_BUF_SIZE);
2011   if(!gl->tgetent_buf || !gl->tgetstr_buf) {
2012     errno = ENOMEM;
2013     return del_GetLine(gl);
2014   };
2015 #endif
2016 /*
2017  * Set up for I/O assuming stdin and stdout.
2018  */
2019   if(_gl_change_terminal(gl, stdin, stdout, getenv("TERM")))
2020     return del_GetLine(gl);
2021 /*
2022  * Create a freelist for use in allocating GlFdNode list nodes.
2023  */
2024 #ifdef HAVE_SELECT
2025   gl->fd_node_mem = _new_FreeList(sizeof(GlFdNode), GLFD_FREELIST_BLOCKING);
2026   if(!gl->fd_node_mem)
2027     return del_GetLine(gl);
2028 #endif
2029 /*
2030  * We are done for now.
2031  */
2032   return gl;
2033 }
2034 
2035 /*.......................................................................
2036  * Delete a GetLine object.
2037  *
2038  * Input:
2039  *  gl     GetLine *  The object to be deleted.
2040  * Output:
2041  *  return GetLine *  The deleted object (always NULL).
2042  */
del_GetLine(GetLine * gl)2043 GetLine *del_GetLine(GetLine *gl)
2044 {
2045   if(gl) {
2046 /*
2047  * If the terminal is in raw server mode, reset it.
2048  */
2049     _gl_normal_io(gl);
2050 /*
2051  * Deallocate all objects contained by gl.
2052  */
2053     gl->err = _del_ErrMsg(gl->err);
2054     gl->glh = _del_GlHistory(gl->glh);
2055     gl->cpl = del_WordCompletion(gl->cpl);
2056 #ifndef WITHOUT_FILE_SYSTEM
2057     gl->ef = del_ExpandFile(gl->ef);
2058 #endif
2059     gl->capmem = _del_StringGroup(gl->capmem);
2060     gl->cq = _del_GlCharQueue(gl->cq);
2061     if(gl->file_fp)
2062       fclose(gl->file_fp);
2063     if(gl->term)
2064       free(gl->term);
2065     if(gl->line)
2066       free(gl->line);
2067     if(gl->cutbuf)
2068       free(gl->cutbuf);
2069     if(gl->prompt)
2070       free(gl->prompt);
2071     gl->cpl_mem = _del_FreeList(gl->cpl_mem, 1);
2072     gl->ext_act_mem = _del_FreeList(gl->ext_act_mem, 1);
2073     gl->sig_mem = _del_FreeList(gl->sig_mem, 1);
2074     gl->sigs = NULL;       /* Already freed by freeing sig_mem */
2075     gl->bindings = _del_KeyTab(gl->bindings);
2076     if(gl->vi.undo.line)
2077       free(gl->vi.undo.line);
2078 #ifdef USE_TERMCAP
2079     if(gl->tgetent_buf)
2080       free(gl->tgetent_buf);
2081     if(gl->tgetstr_buf)
2082       free(gl->tgetstr_buf);
2083 #endif
2084     if(gl->app_file)
2085       free(gl->app_file);
2086     if(gl->user_file)
2087       free(gl->user_file);
2088 #ifdef HAVE_SELECT
2089     gl->fd_node_mem = _del_FreeList(gl->fd_node_mem, 1);
2090     gl->fd_nodes = NULL;  /* Already freed by freeing gl->fd_node_mem */
2091 #endif
2092 /*
2093  * Delete the now empty container.
2094  */
2095     free(gl);
2096   };
2097   return NULL;
2098 }
2099 
2100 /*.......................................................................
2101  * Bind a control or meta character to an action.
2102  *
2103  * Input:
2104  *  gl         GetLine *  The resource object of this program.
2105  *  binder    KtBinder    The source of the binding.
2106  *  c             char    The control or meta character.
2107  *                        If this is '\0', the call is ignored.
2108  *  action  const char *  The action name to bind the key to.
2109  * Output:
2110  *  return         int    0 - OK.
2111  *                        1 - Error.
2112  */
gl_bind_control_char(GetLine * gl,KtBinder binder,char c,const char * action)2113 static int gl_bind_control_char(GetLine *gl, KtBinder binder, char c,
2114 				const char *action)
2115 {
2116   char keyseq[2];
2117 /*
2118  * Quietly reject binding to the NUL control character, since this
2119  * is an ambiguous prefix of all bindings.
2120  */
2121   if(c == '\0')
2122     return 0;
2123 /*
2124  * Making sure not to bind characters which aren't either control or
2125  * meta characters.
2126  */
2127   if(IS_CTRL_CHAR(c) || IS_META_CHAR(c)) {
2128     keyseq[0] = c;
2129     keyseq[1] = '\0';
2130   } else {
2131     return 0;
2132   };
2133 /*
2134  * Install the binding.
2135  */
2136   if(_kt_set_keybinding(gl->bindings, binder, keyseq, action)) {
2137     _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG);
2138     return 1;
2139   };
2140   return 0;
2141 }
2142 
2143 /*.......................................................................
2144  * Read a line from the user.
2145  *
2146  * Input:
2147  *  gl       GetLine *  A resource object returned by new_GetLine().
2148  *  prompt      char *  The prompt to prefix the line with.
2149  *  start_line  char *  The initial contents of the input line, or NULL
2150  *                      if it should start out empty.
2151  *  start_pos    int    If start_line isn't NULL, this specifies the
2152  *                      index of the character over which the cursor
2153  *                      should initially be positioned within the line.
2154  *                      If you just want it to follow the last character
2155  *                      of the line, send -1.
2156  * Output:
2157  *  return      char *  An internal buffer containing the input line, or
2158  *                      NULL at the end of input. If the line fitted in
2159  *                      the buffer there will be a '\n' newline character
2160  *                      before the terminating '\0'. If it was truncated
2161  *                      there will be no newline character, and the remains
2162  *                      of the line should be retrieved via further calls
2163  *                      to this function.
2164  */
gl_get_line(GetLine * gl,const char * prompt,const char * start_line,int start_pos)2165 char *gl_get_line(GetLine *gl, const char *prompt,
2166 		  const char *start_line, int start_pos)
2167 {
2168   char *retval;   /* The return value of _gl_get_line() */
2169 /*
2170  * Check the arguments.
2171  */
2172   if(!gl) {
2173     errno = EINVAL;
2174     return NULL;
2175   };
2176 /*
2177  * Temporarily block all of the signals that we have been asked to trap.
2178  */
2179   if(gl_mask_signals(gl, &gl->old_signal_set))
2180     return NULL;
2181 /*
2182  * Perform the command-line editing task.
2183  */
2184   retval = _gl_get_line(gl, prompt, start_line, start_pos);
2185 /*
2186  * Restore the process signal mask to how it was when this function was
2187  * first called.
2188  */
2189   gl_unmask_signals(gl, &gl->old_signal_set);
2190   return retval;
2191 }
2192 
2193 
2194 /*.......................................................................
2195  * This is the main body of the public function gl_get_line().
2196  */
_gl_get_line(GetLine * gl,const char * prompt,const char * start_line,int start_pos)2197 static char *_gl_get_line(GetLine *gl, const char *prompt,
2198 			  const char *start_line, int start_pos)
2199 {
2200   int waserr = 0;    /* True if an error occurs */
2201 /*
2202  * Assume that this call will successfully complete the input
2203  * line until proven otherwise.
2204  */
2205   gl_clear_status(gl);
2206 /*
2207  * If this is the first call to this function since new_GetLine(),
2208  * complete any postponed configuration.
2209  */
2210   if(!gl->configured) {
2211     (void) _gl_configure_getline(gl, NULL, NULL, TECLA_CONFIG_FILE);
2212     gl->configured = 1;
2213   };
2214 /*
2215  * Before installing our signal handler functions, record the fact
2216  * that there are no pending signals.
2217  */
2218   gl_pending_signal = -1;
2219 /*
2220  * Temporarily override the signal handlers of the calling program,
2221  * so that we can intercept signals that would leave the terminal
2222  * in a bad state.
2223  */
2224   waserr = gl_override_signal_handlers(gl);
2225 /*
2226  * After recording the current terminal settings, switch the terminal
2227  * into raw input mode.
2228  */
2229   waserr = waserr || _gl_raw_io(gl, 1);
2230 /*
2231  * Attempt to read the line. This will require more than one attempt if
2232  * either a current temporary input file is opened by gl_get_input_line()
2233  * or the end of a temporary input file is reached by gl_read_stream_line().
2234  */
2235   while(!waserr) {
2236 /*
2237  * Read a line from a non-interactive stream?
2238  */
2239     if(gl->file_fp || !gl->is_term) {
2240       if(gl_read_stream_line(gl)==0) {
2241 	break;
2242       } else if(gl->file_fp) {
2243 	gl_revert_input(gl);
2244 	gl_record_status(gl, GLR_NEWLINE, 0);
2245       } else {
2246 	waserr = 1;
2247 	break;
2248       };
2249     };
2250 /*
2251  * Read from the terminal? Note that the above if() block may have
2252  * changed gl->file_fp, so it is necessary to retest it here, rather
2253  * than using an else statement.
2254  */
2255     if(!gl->file_fp && gl->is_term) {
2256       if(gl_get_input_line(gl, prompt, start_line, start_pos))
2257 	waserr = 1;
2258       else
2259 	break;
2260     };
2261   };
2262 /*
2263  * If an error occurred, but gl->rtn_status is still set to
2264  * GLR_NEWLINE, change the status to GLR_ERROR. Otherwise
2265  * leave it at whatever specific value was assigned by the function
2266  * that aborted input. This means that only functions that trap
2267  * non-generic errors have to remember to update gl->rtn_status
2268  * themselves.
2269  */
2270   if(waserr && gl->rtn_status == GLR_NEWLINE)
2271     gl_record_status(gl, GLR_ERROR, errno);
2272 /*
2273  * Restore terminal settings.
2274  */
2275   if(gl->io_mode != GL_SERVER_MODE)
2276     _gl_normal_io(gl);
2277 /*
2278  * Restore the signal handlers.
2279  */
2280   gl_restore_signal_handlers(gl);
2281 /*
2282  * If gl_get_line() gets aborted early, the errno value associated
2283  * with the event that caused this to happen is recorded in
2284  * gl->rtn_errno. Since errno may have been overwritten by cleanup
2285  * functions after this, restore its value to the value that it had
2286  * when the error condition occured, so that the caller can examine it
2287  * to find out what happened.
2288  */
2289   errno = gl->rtn_errno;
2290 /*
2291  * Check the completion status to see how to return.
2292  */
2293   switch(gl->rtn_status) {
2294   case GLR_NEWLINE:    /* Success */
2295     return gl->line;
2296   case GLR_BLOCKED:    /* These events abort the current input line, */
2297   case GLR_SIGNAL:     /*  when in normal blocking I/O mode, but only */
2298   case GLR_TIMEOUT:    /*  temporarily pause line editing when in */
2299   case GLR_FDABORT:    /*  non-blocking server I/O mode. */
2300     if(gl->io_mode != GL_SERVER_MODE)
2301       _gl_abandon_line(gl);
2302     return NULL;
2303   case GLR_ERROR:      /* Unrecoverable errors abort the input line, */
2304   case GLR_EOF:        /*  regardless of the I/O mode. */
2305   default:
2306     _gl_abandon_line(gl);
2307     return NULL;
2308   };
2309 }
2310 
2311 /*.......................................................................
2312  * Read a single character from the user.
2313  *
2314  * Input:
2315  *  gl       GetLine *  A resource object returned by new_GetLine().
2316  *  prompt      char *  The prompt to prefix the line with, or NULL if
2317  *                      no prompt is required.
2318  *  defchar     char    The character to substitute if the
2319  *                      user simply hits return, or '\n' if you don't
2320  *                      need to substitute anything.
2321  * Output:
2322  *  return       int    The character that was read, or EOF if the read
2323  *                      had to be aborted (in which case you can call
2324  *                      gl_return_status() to find out why).
2325  */
gl_query_char(GetLine * gl,const char * prompt,char defchar)2326 int gl_query_char(GetLine *gl, const char *prompt, char defchar)
2327 {
2328   int retval;   /* The return value of _gl_query_char() */
2329 /*
2330  * Check the arguments.
2331  */
2332   if(!gl) {
2333     errno = EINVAL;
2334     return EOF;
2335   };
2336 /*
2337  * Temporarily block all of the signals that we have been asked to trap.
2338  */
2339   if(gl_mask_signals(gl, &gl->old_signal_set))
2340     return EOF;
2341 /*
2342  * Perform the character reading task.
2343  */
2344   retval = _gl_query_char(gl, prompt, defchar);
2345 /*
2346  * Restore the process signal mask to how it was when this function was
2347  * first called.
2348  */
2349   gl_unmask_signals(gl, &gl->old_signal_set);
2350   return retval;
2351 }
2352 
2353 /*.......................................................................
2354  * This is the main body of the public function gl_query_char().
2355  */
_gl_query_char(GetLine * gl,const char * prompt,char defchar)2356 static int _gl_query_char(GetLine *gl, const char *prompt, char defchar)
2357 {
2358   int c = EOF;       /* The character to be returned */
2359   int waserr = 0;    /* True if an error occurs */
2360 /*
2361  * Assume that this call will successfully complete the input operation
2362  * until proven otherwise.
2363  */
2364   gl_clear_status(gl);
2365 /*
2366  * If this is the first call to this function or gl_get_line(),
2367  * since new_GetLine(), complete any postponed configuration.
2368  */
2369   if(!gl->configured) {
2370     (void) _gl_configure_getline(gl, NULL, NULL, TECLA_CONFIG_FILE);
2371     gl->configured = 1;
2372   };
2373 /*
2374  * Before installing our signal handler functions, record the fact
2375  * that there are no pending signals.
2376  */
2377   gl_pending_signal = -1;
2378 /*
2379  * Temporarily override the signal handlers of the calling program,
2380  * so that we can intercept signals that would leave the terminal
2381  * in a bad state.
2382  */
2383   waserr = gl_override_signal_handlers(gl);
2384 /*
2385  * After recording the current terminal settings, switch the terminal
2386  * into raw input mode without redisplaying any partially entered
2387  * input line.
2388  */
2389   waserr = waserr || _gl_raw_io(gl, 0);
2390 /*
2391  * Attempt to read the line. This will require more than one attempt if
2392  * either a current temporary input file is opened by gl_get_input_line()
2393  * or the end of a temporary input file is reached by gl_read_stream_line().
2394  */
2395   while(!waserr) {
2396 /*
2397  * Read a line from a non-interactive stream?
2398  */
2399     if(gl->file_fp || !gl->is_term) {
2400       c = gl_read_stream_char(gl);
2401       if(c != EOF) {            /* Success? */
2402 	if(c=='\n') c = defchar;
2403 	break;
2404       } else if(gl->file_fp) {  /* End of temporary input file? */
2405 	gl_revert_input(gl);
2406 	gl_record_status(gl, GLR_NEWLINE, 0);
2407       } else {                  /* An error? */
2408 	waserr = 1;
2409 	break;
2410       };
2411     };
2412 /*
2413  * Read from the terminal? Note that the above if() block may have
2414  * changed gl->file_fp, so it is necessary to retest it here, rather
2415  * than using an else statement.
2416  */
2417     if(!gl->file_fp && gl->is_term) {
2418       c = gl_get_query_char(gl, prompt, defchar);
2419       if(c==EOF)
2420 	waserr = 1;
2421       else
2422 	break;
2423     };
2424   };
2425 /*
2426  * If an error occurred, but gl->rtn_status is still set to
2427  * GLR_NEWLINE, change the status to GLR_ERROR. Otherwise
2428  * leave it at whatever specific value was assigned by the function
2429  * that aborted input. This means that only functions that trap
2430  * non-generic errors have to remember to update gl->rtn_status
2431  * themselves.
2432  */
2433   if(waserr && gl->rtn_status == GLR_NEWLINE)
2434     gl_record_status(gl, GLR_ERROR, errno);
2435 /*
2436  * Restore terminal settings.
2437  */
2438   if(gl->io_mode != GL_SERVER_MODE)
2439     _gl_normal_io(gl);
2440 /*
2441  * Restore the signal handlers.
2442  */
2443   gl_restore_signal_handlers(gl);
2444 /*
2445  * If this function gets aborted early, the errno value associated
2446  * with the event that caused this to happen is recorded in
2447  * gl->rtn_errno. Since errno may have been overwritten by cleanup
2448  * functions after this, restore its value to the value that it had
2449  * when the error condition occured, so that the caller can examine it
2450  * to find out what happened.
2451  */
2452   errno = gl->rtn_errno;
2453 /*
2454  * Error conditions are signalled to the caller, by setting the returned
2455  * character to EOF.
2456  */
2457   if(gl->rtn_status != GLR_NEWLINE)
2458     c = EOF;
2459 /*
2460  * In this mode, every character that is read is a completed
2461  * transaction, just like reading a completed input line, so prepare
2462  * for the next input line or character.
2463  */
2464   _gl_abandon_line(gl);
2465 /*
2466  * Return the acquired character.
2467  */
2468   return c;
2469 }
2470 
2471 /*.......................................................................
2472  * Record of the signal handlers of the calling program, so that they
2473  * can be restored later.
2474  *
2475  * Input:
2476  *  gl    GetLine *   The resource object of this library.
2477  * Output:
2478  *  return    int     0 - OK.
2479  *                    1 - Error.
2480  */
gl_override_signal_handlers(GetLine * gl)2481 static int gl_override_signal_handlers(GetLine *gl)
2482 {
2483   GlSignalNode *sig;   /* A node in the list of signals to be caught */
2484 /*
2485  * Set up our signal handler.
2486  */
2487   SigAction act;
2488   act.sa_handler = gl_signal_handler;
2489   memcpy(&act.sa_mask, &gl->all_signal_set, sizeof(sigset_t));
2490   act.sa_flags = 0;
2491 /*
2492  * Get the subset of the signals that we are supposed to trap that
2493  * should actually be trapped.
2494  */
2495   sigemptyset(&gl->use_signal_set);
2496   for(sig=gl->sigs; sig; sig=sig->next) {
2497 /*
2498  * Trap this signal? If it is blocked by the calling program and we
2499  * haven't been told to unblock it, don't arrange to trap this signal.
2500  */
2501     if(sig->flags & GLS_UNBLOCK_SIG ||
2502        !sigismember(&gl->old_signal_set, sig->signo)) {
2503       if(sigaddset(&gl->use_signal_set, sig->signo) == -1) {
2504 	_err_record_msg(gl->err, "sigaddset error", END_ERR_MSG);
2505 	return 1;
2506       };
2507     };
2508   };
2509 /*
2510  * Override the actions of the signals that we are trapping.
2511  */
2512   for(sig=gl->sigs; sig; sig=sig->next) {
2513     if(sigismember(&gl->use_signal_set, sig->signo)) {
2514       sigdelset(&act.sa_mask, sig->signo);
2515       if(sigaction(sig->signo, &act, &sig->original)) {
2516 	_err_record_msg(gl->err, "sigaction error", END_ERR_MSG);
2517 	return 1;
2518       };
2519       sigaddset(&act.sa_mask, sig->signo);
2520     };
2521   };
2522 /*
2523  * Record the fact that the application's signal handlers have now
2524  * been overriden.
2525  */
2526   gl->signals_overriden = 1;
2527 /*
2528  * Just in case a SIGWINCH signal was sent to the process while our
2529  * SIGWINCH signal handler wasn't in place, check to see if the terminal
2530  * size needs updating.
2531  */
2532   if(_gl_update_size(gl))
2533     return 1;
2534   return 0;
2535 }
2536 
2537 /*.......................................................................
2538  * Restore the signal handlers of the calling program.
2539  *
2540  * Input:
2541  *  gl     GetLine *  The resource object of this library.
2542  * Output:
2543  *  return     int    0 - OK.
2544  *                    1 - Error.
2545  */
gl_restore_signal_handlers(GetLine * gl)2546 static int gl_restore_signal_handlers(GetLine *gl)
2547 {
2548   GlSignalNode *sig;   /* A node in the list of signals to be caught */
2549 /*
2550  * Restore application signal handlers that were overriden
2551  * by gl_override_signal_handlers().
2552  */
2553   for(sig=gl->sigs; sig; sig=sig->next) {
2554     if(sigismember(&gl->use_signal_set, sig->signo) &&
2555        sigaction(sig->signo, &sig->original, NULL)) {
2556       _err_record_msg(gl->err, "sigaction error", END_ERR_MSG);
2557       return 1;
2558     };
2559   };
2560 /*
2561  * Record the fact that the application's signal handlers have now
2562  * been restored.
2563  */
2564   gl->signals_overriden = 0;
2565   return 0;
2566 }
2567 
2568 /*.......................................................................
2569  * This signal handler simply records the fact that a given signal was
2570  * caught in the file-scope gl_pending_signal variable.
2571  */
gl_signal_handler(int signo)2572 static void gl_signal_handler(int signo)
2573 {
2574   gl_pending_signal = signo;
2575   siglongjmp(gl_setjmp_buffer, 1);
2576 }
2577 
2578 /*.......................................................................
2579  * Switch the terminal into raw mode after storing the previous terminal
2580  * settings in gl->attributes.
2581  *
2582  * Input:
2583  *  gl     GetLine *   The resource object of this program.
2584  * Output:
2585  *  return     int     0 - OK.
2586  *                     1 - Error.
2587  */
gl_raw_terminal_mode(GetLine * gl)2588 static int gl_raw_terminal_mode(GetLine *gl)
2589 {
2590   Termios newattr;   /* The new terminal attributes */
2591 /*
2592  * If the terminal is already in raw mode, do nothing.
2593  */
2594   if(gl->raw_mode)
2595     return 0;
2596 /*
2597  * Record the current terminal attributes.
2598  */
2599   if(tcgetattr(gl->input_fd, &gl->oldattr)) {
2600     _err_record_msg(gl->err, "tcgetattr error", END_ERR_MSG);
2601     return 1;
2602   };
2603 /*
2604  * This function shouldn't do anything but record the current terminal
2605  * attritubes if editing has been disabled.
2606  */
2607   if(gl->editor == GL_NO_EDITOR)
2608     return 0;
2609 /*
2610  * Modify the existing attributes.
2611  */
2612   newattr = gl->oldattr;
2613 /*
2614  * Turn off local echo, canonical input mode and extended input processing.
2615  */
2616   newattr.c_lflag &= ~(ECHO | ICANON | IEXTEN);
2617 /*
2618  * Don't translate carriage return to newline, turn off input parity
2619  * checking, don't strip off 8th bit, turn off output flow control.
2620  */
2621   newattr.c_iflag &= ~(ICRNL | INPCK | ISTRIP);
2622 /*
2623  * Clear size bits, turn off parity checking, and allow 8-bit characters.
2624  */
2625   newattr.c_cflag &= ~(CSIZE | PARENB);
2626   newattr.c_cflag |= CS8;
2627 /*
2628  * Turn off output processing.
2629  */
2630   newattr.c_oflag &= ~(OPOST);
2631 /*
2632  * Request one byte at a time, without waiting.
2633  */
2634   newattr.c_cc[VMIN] = gl->io_mode==GL_SERVER_MODE ? 0:1;
2635   newattr.c_cc[VTIME] = 0;
2636 /*
2637  * Install the new terminal modes.
2638  */
2639   while(tcsetattr(gl->input_fd, TCSADRAIN, &newattr)) {
2640     if(errno != EINTR) {
2641       _err_record_msg(gl->err, "tcsetattr error", END_ERR_MSG);
2642       return 1;
2643     };
2644   };
2645 /*
2646  * Record the new terminal mode.
2647  */
2648   gl->raw_mode = 1;
2649   return 0;
2650 }
2651 
2652 /*.......................................................................
2653  * Restore the terminal attributes recorded in gl->oldattr.
2654  *
2655  * Input:
2656  *  gl     GetLine *   The resource object of this library.
2657  * Output:
2658  *  return     int     0 - OK.
2659  *                     1 - Error.
2660  */
gl_restore_terminal_attributes(GetLine * gl)2661 static int gl_restore_terminal_attributes(GetLine *gl)
2662 {
2663   int waserr = 0;
2664 /*
2665  * If not in raw mode, do nothing.
2666  */
2667   if(!gl->raw_mode)
2668     return 0;
2669 /*
2670  * Before changing the terminal attributes, make sure that all output
2671  * has been passed to the terminal.
2672  */
2673   if(gl_flush_output(gl))
2674     waserr = 1;
2675 /*
2676  * Reset the terminal attributes to the values that they had on
2677  * entry to gl_get_line().
2678  */
2679   while(tcsetattr(gl->input_fd, TCSADRAIN, &gl->oldattr)) {
2680     if(errno != EINTR) {
2681       _err_record_msg(gl->err, "tcsetattr error", END_ERR_MSG);
2682       waserr = 1;
2683       break;
2684     };
2685   };
2686 /*
2687  * Record the new terminal mode.
2688  */
2689   gl->raw_mode = 0;
2690   return waserr;
2691 }
2692 
2693 /*.......................................................................
2694  * Switch the terminal file descriptor to use non-blocking I/O.
2695  *
2696  * Input:
2697  *  gl         GetLine *  The resource object of gl_get_line().
2698  *  fd             int    The file descriptor to make non-blocking.
2699  */
gl_nonblocking_io(GetLine * gl,int fd)2700 static int gl_nonblocking_io(GetLine *gl, int fd)
2701 {
2702   int fcntl_flags;   /* The new file-descriptor control flags */
2703 /*
2704  * Is non-blocking I/O supported on this system?  Note that even
2705  * without non-blocking I/O, the terminal will probably still act as
2706  * though it was non-blocking, because we also set the terminal
2707  * attributes to return immediately if no input is available and we
2708  * use select() to wait to be able to write. If select() also isn't
2709  * available, then input will probably remain fine, but output could
2710  * block, depending on the behaviour of the terminal driver.
2711  */
2712 #if defined(NON_BLOCKING_FLAG)
2713 /*
2714  * Query the current file-control flags, and add the
2715  * non-blocking I/O flag.
2716  */
2717   fcntl_flags = fcntl(fd, F_GETFL) | NON_BLOCKING_FLAG;
2718 /*
2719  * Install the new control flags.
2720  */
2721   if(fcntl(fd, F_SETFL, fcntl_flags) == -1) {
2722     _err_record_msg(gl->err, "fcntl error", END_ERR_MSG);
2723     return 1;
2724   };
2725 #endif
2726   return 0;
2727 }
2728 
2729 /*.......................................................................
2730  * Switch to blocking terminal I/O.
2731  *
2732  * Input:
2733  *  gl         GetLine *  The resource object of gl_get_line().
2734  *  fd             int    The file descriptor to make blocking.
2735  */
gl_blocking_io(GetLine * gl,int fd)2736 static int gl_blocking_io(GetLine *gl, int fd)
2737 {
2738   int fcntl_flags;   /* The new file-descriptor control flags */
2739 /*
2740  * Is non-blocking I/O implemented on this system?
2741  */
2742 #if defined(NON_BLOCKING_FLAG)
2743 /*
2744  * Query the current file control flags and remove the non-blocking
2745  * I/O flag.
2746  */
2747   fcntl_flags = fcntl(fd, F_GETFL) & ~NON_BLOCKING_FLAG;
2748 /*
2749  * Install the modified control flags.
2750  */
2751   if(fcntl(fd, F_SETFL, fcntl_flags) == -1) {
2752     _err_record_msg(gl->err, "fcntl error", END_ERR_MSG);
2753     return 1;
2754   };
2755 #endif
2756   return 0;
2757 }
2758 
2759 /*.......................................................................
2760  * Read a new input line from the user.
2761  *
2762  * Input:
2763  *  gl         GetLine *  The resource object of this library.
2764  *  prompt        char *  The prompt to prefix the line with, or NULL to
2765  *                        use the same prompt that was used by the previous
2766  *                        line.
2767  *  start_line    char *  The initial contents of the input line, or NULL
2768  *                        if it should start out empty.
2769  *  start_pos      int    If start_line isn't NULL, this specifies the
2770  *                        index of the character over which the cursor
2771  *                        should initially be positioned within the line.
2772  *                        If you just want it to follow the last character
2773  *                        of the line, send -1.
2774  * Output:
2775  *  return    int    0 - OK.
2776  *                   1 - Error.
2777  */
gl_get_input_line(GetLine * gl,const char * prompt,const char * start_line,int start_pos)2778 static int gl_get_input_line(GetLine *gl, const char *prompt,
2779 			     const char *start_line, int start_pos)
2780 {
2781   char c;               /* The character being read */
2782 /*
2783  * Flush any pending output to the terminal.
2784  */
2785   if(_glq_char_count(gl->cq) > 0 && gl_flush_output(gl))
2786     return 1;
2787 /*
2788  * Are we starting a new line?
2789  */
2790   if(gl->endline) {
2791 /*
2792  * Delete any incompletely enterred line.
2793  */
2794     if(gl_erase_line(gl))
2795       return 1;
2796 /*
2797  * Display the new line to be edited.
2798  */
2799     if(gl_present_line(gl, prompt, start_line, start_pos))
2800       return 1;
2801   };
2802 /*
2803  * Read one character at a time.
2804  */
2805   while(gl_read_terminal(gl, 1, &c) == 0) {
2806 /*
2807  * Increment the count of the number of key sequences entered.
2808  */
2809     gl->keyseq_count++;
2810 /*
2811  * Interpret the character either as the start of a new key-sequence,
2812  * as a continuation of a repeat count, or as a printable character
2813  * to be added to the line.
2814  */
2815     if(gl_interpret_char(gl, c))
2816       break;
2817 /*
2818  * If we just ran an action function which temporarily asked for
2819  * input to be taken from a file, abort this call.
2820  */
2821     if(gl->file_fp)
2822       return 0;
2823 /*
2824  * Has the line been completed?
2825  */
2826     if(gl->endline)
2827       return gl_line_ended(gl, c);
2828   };
2829 /*
2830  * To get here, gl_read_terminal() must have returned non-zero. See
2831  * whether a signal was caught that requested that the current line
2832  * be returned.
2833  */
2834   if(gl->endline)
2835     return gl_line_ended(gl, '\n');
2836 /*
2837  * If I/O blocked while attempting to get the latest character
2838  * of the key sequence, rewind the key buffer to allow interpretation of
2839  * the current key sequence to be restarted on the next call to this
2840  * function.
2841  */
2842   if(gl->rtn_status == GLR_BLOCKED && gl->pending_io == GLP_READ)
2843     gl->nread = 0;
2844   return 1;
2845 }
2846 
2847 /*.......................................................................
2848  * This is the private function of gl_query_char() that handles
2849  * prompting the user, reading a character from the terminal, and
2850  * displaying what the user entered.
2851  *
2852  * Input:
2853  *  gl         GetLine *  The resource object of this library.
2854  *  prompt        char *  The prompt to prefix the line with.
2855  *  defchar       char    The character to substitute if the
2856  *                        user simply hits return, or '\n' if you don't
2857  *                        need to substitute anything.
2858  * Output:
2859  *  return         int    The character that was read, or EOF if something
2860  *                        prevented a character from being read.
2861  */
gl_get_query_char(GetLine * gl,const char * prompt,int defchar)2862 static int gl_get_query_char(GetLine *gl, const char *prompt, int defchar)
2863 {
2864   char c;               /* The character being read */
2865   int retval;           /* The return value of this function */
2866 /*
2867  * Flush any pending output to the terminal.
2868  */
2869   if(_glq_char_count(gl->cq) > 0 && gl_flush_output(gl))
2870     return EOF;
2871 /*
2872  * Delete any incompletely entered line.
2873  */
2874   if(gl_erase_line(gl))
2875     return EOF;
2876 /*
2877  * Reset the line input parameters and display the prompt, if any.
2878  */
2879   if(gl_present_line(gl, prompt, NULL, 0))
2880     return EOF;
2881 /*
2882  * Read one character.
2883  */
2884   if(gl_read_terminal(gl, 1, &c) == 0) {
2885 /*
2886  * In this mode, count each character as being a new key-sequence.
2887  */
2888     gl->keyseq_count++;
2889 /*
2890  * Delete the character that was read, from the key-press buffer.
2891  */
2892     gl_discard_chars(gl, gl->nread);
2893 /*
2894  * Convert carriage returns to newlines.
2895  */
2896     if(c == '\r')
2897       c = '\n';
2898 /*
2899  * If the user just hit return, subsitute the default character.
2900  */
2901     if(c == '\n')
2902       c = defchar;
2903 /*
2904  * Display the entered character to the right of the prompt.
2905  */
2906     if(c!='\n') {
2907       if(gl_end_of_line(gl, 1, NULL)==0)
2908 	gl_print_char(gl, c, ' ');
2909     };
2910 /*
2911  * Record the return character, and mark the call as successful.
2912  */
2913     retval = c;
2914     gl_record_status(gl, GLR_NEWLINE, 0);
2915 /*
2916  * Was a signal caught whose disposition is to cause the current input
2917  * line to be returned? If so return a newline character.
2918  */
2919   } else if(gl->endline) {
2920     retval = '\n';
2921     gl_record_status(gl, GLR_NEWLINE, 0);
2922   } else {
2923     retval = EOF;
2924   };
2925 /*
2926  * Start a new line.
2927  */
2928   if(gl_start_newline(gl, 1))
2929     return EOF;
2930 /*
2931  * Attempt to flush any pending output.
2932  */
2933   (void) gl_flush_output(gl);
2934 /*
2935  * Return either the character that was read, or EOF if an error occurred.
2936  */
2937   return retval;
2938 }
2939 
2940 /*.......................................................................
2941  * Add a character to the line buffer at the current cursor position,
2942  * inserting or overwriting according the current mode.
2943  *
2944  * Input:
2945  *  gl   GetLine *   The resource object of this library.
2946  *  c       char     The character to be added.
2947  * Output:
2948  *  return   int     0 - OK.
2949  *                   1 - Insufficient room.
2950  */
gl_add_char_to_line(GetLine * gl,char c)2951 static int gl_add_char_to_line(GetLine *gl, char c)
2952 {
2953 /*
2954  * Keep a record of the current cursor position.
2955  */
2956   int buff_curpos = gl->buff_curpos;
2957   int term_curpos = gl->term_curpos;
2958 /*
2959  * Work out the displayed width of the new character.
2960  */
2961   int width = gl_displayed_char_width(gl, c, term_curpos);
2962 /*
2963  * If we are in insert mode, or at the end of the line,
2964  * check that we can accomodate a new character in the buffer.
2965  * If not, simply return, leaving it up to the calling program
2966  * to check for the absence of a newline character.
2967  */
2968   if((gl->insert || buff_curpos >= gl->ntotal) && gl->ntotal >= gl->linelen)
2969     return 0;
2970 /*
2971  * Are we adding characters to the line (ie. inserting or appending)?
2972  */
2973   if(gl->insert || buff_curpos >= gl->ntotal) {
2974 /*
2975  * If inserting, make room for the new character.
2976  */
2977     if(buff_curpos < gl->ntotal)
2978       gl_make_gap_in_buffer(gl, buff_curpos, 1);
2979 /*
2980  * Copy the character into the buffer.
2981  */
2982     gl_buffer_char(gl, c, buff_curpos);
2983     gl->buff_curpos++;
2984 /*
2985  * Redraw the line from the cursor position to the end of the line,
2986  * and move the cursor to just after the added character.
2987  */
2988     if(gl_print_string(gl, gl->line + buff_curpos, '\0') ||
2989        gl_set_term_curpos(gl, term_curpos + width))
2990       return 1;
2991 /*
2992  * Are we overwriting an existing character?
2993  */
2994   } else {
2995 /*
2996  * Get the width of the character being overwritten.
2997  */
2998     int old_width = gl_displayed_char_width(gl, gl->line[buff_curpos],
2999 					    term_curpos);
3000 /*
3001  * Overwrite the character in the buffer.
3002  */
3003     gl_buffer_char(gl, c, buff_curpos);
3004 /*
3005  * If we are replacing with a narrower character, we need to
3006  * redraw the terminal string to the end of the line, then
3007  * overwrite the trailing old_width - width characters
3008  * with spaces.
3009  */
3010     if(old_width > width) {
3011       if(gl_print_string(gl, gl->line + buff_curpos, '\0'))
3012 	return 1;
3013 /*
3014  * Clear to the end of the terminal.
3015  */
3016       if(gl_truncate_display(gl))
3017 	return 1;
3018 /*
3019  * Move the cursor to the end of the new character.
3020  */
3021       if(gl_set_term_curpos(gl, term_curpos + width))
3022 	return 1;
3023       gl->buff_curpos++;
3024 /*
3025  * If we are replacing with a wider character, then we will be
3026  * inserting new characters, and thus extending the line.
3027  */
3028     } else if(width > old_width) {
3029 /*
3030  * Redraw the line from the cursor position to the end of the line,
3031  * and move the cursor to just after the added character.
3032  */
3033       if(gl_print_string(gl, gl->line + buff_curpos, '\0') ||
3034 	 gl_set_term_curpos(gl, term_curpos + width))
3035 	return 1;
3036       gl->buff_curpos++;
3037 /*
3038  * The original and replacement characters have the same width,
3039  * so simply overwrite.
3040  */
3041     } else {
3042 /*
3043  * Copy the character into the buffer.
3044  */
3045       gl_buffer_char(gl, c, buff_curpos);
3046       gl->buff_curpos++;
3047 /*
3048  * Overwrite the original character.
3049  */
3050       if(gl_print_char(gl, c, gl->line[gl->buff_curpos]))
3051 	return 1;
3052     };
3053   };
3054   return 0;
3055 }
3056 
3057 /*.......................................................................
3058  * Insert/append a string to the line buffer and terminal at the current
3059  * cursor position.
3060  *
3061  * Input:
3062  *  gl   GetLine *   The resource object of this library.
3063  *  s       char *   The string to be added.
3064  * Output:
3065  *  return   int     0 - OK.
3066  *                   1 - Insufficient room.
3067  */
gl_add_string_to_line(GetLine * gl,const char * s)3068 static int gl_add_string_to_line(GetLine *gl, const char *s)
3069 {
3070   int buff_slen;   /* The length of the string being added to line[] */
3071   int term_slen;   /* The length of the string being written to the terminal */
3072   int buff_curpos; /* The original value of gl->buff_curpos */
3073   int term_curpos; /* The original value of gl->term_curpos */
3074 /*
3075  * Keep a record of the current cursor position.
3076  */
3077   buff_curpos = gl->buff_curpos;
3078   term_curpos = gl->term_curpos;
3079 /*
3080  * How long is the string to be added?
3081  */
3082   buff_slen = strlen(s);
3083   term_slen = gl_displayed_string_width(gl, s, buff_slen, term_curpos);
3084 /*
3085  * Check that we can accomodate the string in the buffer.
3086  * If not, simply return, leaving it up to the calling program
3087  * to check for the absence of a newline character.
3088  */
3089   if(gl->ntotal + buff_slen > gl->linelen)
3090     return 0;
3091 /*
3092  * Move the characters that follow the cursor in the buffer by
3093  * buff_slen characters to the right.
3094  */
3095   if(gl->ntotal > gl->buff_curpos)
3096     gl_make_gap_in_buffer(gl, gl->buff_curpos, buff_slen);
3097 /*
3098  * Copy the string into the buffer.
3099  */
3100   gl_buffer_string(gl, s, buff_slen, gl->buff_curpos);
3101   gl->buff_curpos += buff_slen;
3102 /*
3103  * Write the modified part of the line to the terminal, then move
3104  * the terminal cursor to the end of the displayed input string.
3105  */
3106   if(gl_print_string(gl, gl->line + buff_curpos, '\0') ||
3107      gl_set_term_curpos(gl, term_curpos + term_slen))
3108     return 1;
3109   return 0;
3110 }
3111 
3112 /*.......................................................................
3113  * Read a single character from the terminal.
3114  *
3115  * Input:
3116  *  gl    GetLine *   The resource object of this library.
3117  *  keep      int     If true, the returned character will be kept in
3118  *                    the input buffer, for potential replays. It should
3119  *                    subsequently be removed from the buffer when the
3120  *                    key sequence that it belongs to has been fully
3121  *                    processed, by calling gl_discard_chars().
3122  * Input/Output:
3123  *  c        char *   The character that is read, is assigned to *c.
3124  * Output:
3125  *  return    int     0 - OK.
3126  *                    1 - Either an I/O error occurred, or a signal was
3127  *                        caught who's disposition is to abort gl_get_line()
3128  *                        or to have gl_get_line() return the current line
3129  *                        as though the user had pressed return. In the
3130  *                        latter case gl->endline will be non-zero.
3131  */
gl_read_terminal(GetLine * gl,int keep,char * c)3132 static int gl_read_terminal(GetLine *gl, int keep, char *c)
3133 {
3134 /*
3135  * Before waiting for a new character to be input, flush unwritten
3136  * characters to the terminal.
3137  */
3138   if(gl_flush_output(gl))
3139     return 1;
3140 /*
3141  * Record the fact that we are about to read from the terminal.
3142  */
3143   gl->pending_io = GLP_READ;
3144 /*
3145  * If there is already an unread character in the buffer,
3146  * return it.
3147  */
3148   if(gl->nread < gl->nbuf) {
3149     *c = gl->keybuf[gl->nread];
3150 /*
3151  * Retain the character in the key buffer, but mark it as having been read?
3152  */
3153     if(keep) {
3154       gl->nread++;
3155 /*
3156  * Completely remove the character from the key buffer?
3157  */
3158     } else {
3159       memmove(gl->keybuf + gl->nread, gl->keybuf + gl->nread + 1,
3160 	      gl->nbuf - gl->nread - 1);
3161     };
3162     return 0;
3163   };
3164 /*
3165  * Make sure that there is space in the key buffer for one more character.
3166  * This should always be true if gl_interpret_char() is called for each
3167  * new character added, since it will clear the buffer once it has recognized
3168  * or rejected a key sequence.
3169  */
3170   if(gl->nbuf + 1 > GL_KEY_MAX) {
3171     gl_print_info(gl, "gl_read_terminal: Buffer overflow avoided.",
3172 		  GL_END_INFO);
3173     errno = EIO;
3174     return 1;
3175   };
3176 /*
3177  * Read one character from the terminal.
3178  */
3179   switch(gl_read_input(gl, c)) {
3180   case GL_READ_OK:
3181     break;
3182   case GL_READ_BLOCKED:
3183     gl_record_status(gl, GLR_BLOCKED, BLOCKED_ERRNO);
3184     return 1;
3185     break;
3186   default:
3187     return 1;
3188     break;
3189   };
3190 /*
3191  * Append the character to the key buffer?
3192  */
3193   if(keep) {
3194     gl->keybuf[gl->nbuf] = *c;
3195     gl->nread = ++gl->nbuf;
3196   };
3197   return 0;
3198 }
3199 
3200 /*.......................................................................
3201  * Read one or more keypresses from the terminal of an input stream.
3202  *
3203  * Input:
3204  *  gl           GetLine *  The resource object of this module.
3205  *  c               char *  The character that was read is assigned to *c.
3206  * Output:
3207  *  return  GlReadStatus    The completion status of the read operation.
3208  */
gl_read_input(GetLine * gl,char * c)3209 static GlReadStatus gl_read_input(GetLine *gl, char *c)
3210 {
3211 /*
3212  * We may have to repeat the read if window change signals are received.
3213  */
3214   for(;;) {
3215 /*
3216  * Which file descriptor should we read from? Mark this volatile, so
3217  * that siglongjmp() can't clobber it.
3218  */
3219     volatile int fd = gl->file_fp ? fileno(gl->file_fp) : gl->input_fd;
3220 /*
3221  * If the endline flag becomes set, don't wait for another character.
3222  */
3223     if(gl->endline)
3224       return GL_READ_ERROR;
3225 /*
3226  * Since the code in this function can block, trap signals.
3227  */
3228     if(sigsetjmp(gl_setjmp_buffer, 1)==0) {
3229 /*
3230  * Handle the different I/O modes.
3231  */
3232       switch(gl->io_mode) {
3233 /*
3234  * In normal I/O mode, we call the event handler before attempting
3235  * to read, since read() blocks.
3236  */
3237       case GL_NORMAL_MODE:
3238 	if(gl_event_handler(gl, fd))
3239 	  return GL_READ_ERROR;
3240 	return gl_read_unmasked(gl, fd, c);  /* Read one character */
3241 	break;
3242 /*
3243  * In non-blocking server I/O mode, we attempt to read a character,
3244  * and only if this fails, call the event handler to wait for a any
3245  * user-configured timeout and any other user-configured events.  In
3246  * addition, we turn off the fcntl() non-blocking flag when reading
3247  * from the terminal, to work around a bug in Solaris. We can do this
3248  * without causing the read() to block, because when in non-blocking
3249  * server-I/O mode, gl_raw_io() sets the VMIN terminal attribute to 0,
3250  * which tells the terminal driver to return immediately if no
3251  * characters are available to be read.
3252  */
3253       case GL_SERVER_MODE:
3254 	{
3255 	  GlReadStatus status;        /* The return status */
3256 	  if(isatty(fd))              /* If we reading from a terminal, */
3257 	     gl_blocking_io(gl, fd);  /* switch to blocking I/O */
3258 	  status = gl_read_unmasked(gl, fd, c); /* Try reading */
3259 	  if(status == GL_READ_BLOCKED) {       /* Nothing readable yet */
3260 	    if(gl_event_handler(gl, fd))        /* Wait for input */
3261 	      status = GL_READ_ERROR;
3262 	    else
3263 	      status = gl_read_unmasked(gl, fd, c); /* Try reading again */
3264 	  };
3265 	  gl_nonblocking_io(gl, fd); /* Restore non-blocking I/O */
3266 	  return status;
3267 	};
3268 	break;
3269       };
3270     };
3271 /*
3272  * To get here, one of the signals that we are trapping must have
3273  * been received. Note that by using sigsetjmp() instead of setjmp()
3274  * the signal mask that was blocking these signals will have been
3275  * reinstated, so we can be sure that no more of these signals will
3276  * be received until we explicitly unblock them again.
3277  *
3278  * First, if non-blocking I/O was temporarily disabled, reinstate it.
3279  */
3280     if(gl->io_mode == GL_SERVER_MODE)
3281       gl_nonblocking_io(gl, fd);
3282 /*
3283  * Now respond to the signal that was caught.
3284  */
3285     if(gl_check_caught_signal(gl))
3286       return GL_READ_ERROR;
3287   };
3288 }
3289 
3290 /*.......................................................................
3291  * This is a private function of gl_read_input(), which unblocks signals
3292  * temporarily while it reads a single character from the specified file
3293  * descriptor.
3294  *
3295  * Input:
3296  *  gl          GetLine *  The resource object of this module.
3297  *  fd              int    The file descriptor to read from.
3298  *  c              char *  The character that was read is assigned to *c.
3299  * Output:
3300  *  return GlReadStatus    The completion status of the read.
3301  */
gl_read_unmasked(GetLine * gl,int fd,char * c)3302 static int gl_read_unmasked(GetLine *gl, int fd, char *c)
3303 {
3304   int nread;  /* The return value of read() */
3305 /*
3306  * Unblock the signals that we are trapping, while waiting for I/O.
3307  */
3308   gl_catch_signals(gl);
3309 /*
3310  * Attempt to read one character from the terminal, restarting the read
3311  * if any signals that we aren't trapping, are received.
3312  */
3313   do {
3314     errno = 0;
3315     nread = read(fd, c, 1);
3316   } while(nread < 0 && errno==EINTR);
3317 /*
3318  * Block all of the signals that we are trapping.
3319  */
3320   gl_mask_signals(gl, NULL);
3321 /*
3322  * Check the completion status of the read.
3323  */
3324   switch(nread) {
3325   case 1:
3326     return GL_READ_OK;
3327   case 0:
3328     return (errno != 0 || isatty(fd)) ? GL_READ_BLOCKED : GL_READ_EOF;
3329   default:
3330     return GL_READ_ERROR;
3331   };
3332 }
3333 
3334 /*.......................................................................
3335  * Remove a specified number of characters from the start of the
3336  * key-press lookahead buffer, gl->keybuf[], and arrange for the next
3337  * read to start from the character at the start of the shifted buffer.
3338  *
3339  * Input:
3340  *  gl      GetLine *  The resource object of this module.
3341  *  nused       int    The number of characters to discard from the start
3342  *                     of the buffer.
3343  */
gl_discard_chars(GetLine * gl,int nused)3344 static void gl_discard_chars(GetLine *gl, int nused)
3345 {
3346   int nkeep = gl->nbuf - nused;
3347   if(nkeep > 0) {
3348     memmove(gl->keybuf, gl->keybuf + nused, nkeep);
3349     gl->nbuf = nkeep;
3350     gl->nread = 0;
3351   } else {
3352     gl->nbuf = gl->nread = 0;
3353   };
3354 }
3355 
3356 /*.......................................................................
3357  * This function is called to handle signals caught between calls to
3358  * sigsetjmp() and siglongjmp().
3359  *
3360  * Input:
3361  *  gl      GetLine *   The resource object of this library.
3362  * Output:
3363  *  return      int     0 - Signal handled internally.
3364  *                      1 - Signal requires gl_get_line() to abort.
3365  */
gl_check_caught_signal(GetLine * gl)3366 static int gl_check_caught_signal(GetLine *gl)
3367 {
3368   GlSignalNode *sig;      /* The signal disposition */
3369   SigAction keep_action;  /* The signal disposition of tecla signal handlers */
3370   unsigned flags;         /* The signal processing flags to use */
3371   int signo;              /* The signal to be handled */
3372 /*
3373  * Was no signal caught?
3374  */
3375   if(gl_pending_signal == -1)
3376     return 0;
3377 /*
3378  * Get the signal to be handled.
3379  */
3380   signo = gl_pending_signal;
3381 /*
3382  * Mark the signal as handled. Note that at this point, all of
3383  * the signals that we are trapping are blocked from delivery.
3384  */
3385   gl_pending_signal = -1;
3386 /*
3387  * Record the signal that was caught, so that the user can query it later.
3388  */
3389   gl->last_signal = signo;
3390 /*
3391  * In non-blocking server mode, the application is responsible for
3392  * responding to terminal signals, and we don't want gl_get_line()s
3393  * normal signal handling to clash with this, so whenever a signal
3394  * is caught, we arrange for gl_get_line() to abort and requeue the
3395  * signal while signals are still blocked. If the application
3396  * had the signal unblocked when gl_get_line() was called, the signal
3397  * will be delivered again as soon as gl_get_line() restores the
3398  * process signal mask, just before returning to the application.
3399  * Note that the caller of this function should set gl->pending_io
3400  * to the appropriate choice of GLP_READ and GLP_WRITE, before returning.
3401  */
3402   if(gl->io_mode==GL_SERVER_MODE) {
3403     gl_record_status(gl, GLR_SIGNAL, EINTR);
3404     raise(signo);
3405     return 1;
3406   };
3407 /*
3408  * Lookup the requested disposition of this signal.
3409  */
3410   for(sig=gl->sigs; sig && sig->signo != signo; sig=sig->next)
3411     ;
3412   if(!sig)
3413     return 0;
3414 /*
3415  * Get the signal response flags for this signal.
3416  */
3417   flags = sig->flags;
3418 /*
3419  * Did we receive a terminal size signal?
3420  */
3421 #ifdef SIGWINCH
3422   if(signo == SIGWINCH && _gl_update_size(gl))
3423     return 1;
3424 #endif
3425 /*
3426  * Start a fresh line?
3427  */
3428   if(flags & GLS_RESTORE_LINE) {
3429     if(gl_start_newline(gl, 0))
3430       return 1;
3431   };
3432 /*
3433  * Restore terminal settings to how they were before gl_get_line() was
3434  * called?
3435  */
3436   if(flags & GLS_RESTORE_TTY)
3437     gl_restore_terminal_attributes(gl);
3438 /*
3439  * Restore signal handlers to how they were before gl_get_line() was
3440  * called? If this hasn't been requested, only reinstate the signal
3441  * handler of the signal that we are handling.
3442  */
3443   if(flags & GLS_RESTORE_SIG) {
3444     gl_restore_signal_handlers(gl);
3445     gl_unmask_signals(gl, &gl->old_signal_set);
3446   } else {
3447     (void) sigaction(sig->signo, &sig->original, &keep_action);
3448     (void) sigprocmask(SIG_UNBLOCK, &sig->proc_mask, NULL);
3449   };
3450 /*
3451  * Forward the signal to the application's signal handler.
3452  */
3453   if(!(flags & GLS_DONT_FORWARD))
3454     raise(signo);
3455 /*
3456  * Reinstate our signal handlers.
3457  */
3458   if(flags & GLS_RESTORE_SIG) {
3459     gl_mask_signals(gl, NULL);
3460     gl_override_signal_handlers(gl);
3461   } else {
3462     (void) sigaction(sig->signo, &keep_action, NULL);
3463     (void) sigprocmask(SIG_BLOCK, &sig->proc_mask, NULL);
3464   };
3465 /*
3466  * Do we need to reinstate our terminal settings?
3467  */
3468   if(flags & GLS_RESTORE_TTY)
3469     gl_raw_terminal_mode(gl);
3470 /*
3471  * Redraw the line?
3472  */
3473   if(flags & GLS_REDRAW_LINE)
3474     gl_queue_redisplay(gl);
3475 /*
3476  * What next?
3477  */
3478   switch(sig->after) {
3479   case GLS_RETURN:
3480     gl_newline(gl, 1, NULL);
3481     return gl_flush_output(gl);
3482     break;
3483   case GLS_ABORT:
3484     gl_record_status(gl, GLR_SIGNAL, sig->errno_value);
3485     return 1;
3486     break;
3487   case GLS_CONTINUE:
3488     return gl_flush_output(gl);
3489     break;
3490   };
3491   return 0;
3492 }
3493 
3494 /*.......................................................................
3495  * Get pertinent terminal control strings and the initial terminal size.
3496  *
3497  * Input:
3498  *  gl     GetLine *  The resource object of this library.
3499  *  term      char *  The type of the terminal.
3500  * Output:
3501  *  return     int    0 - OK.
3502  *                    1 - Error.
3503  */
gl_control_strings(GetLine * gl,const char * term)3504 static int gl_control_strings(GetLine *gl, const char *term)
3505 {
3506   int bad_term = 0;   /* True if term is unusable */
3507 /*
3508  * Discard any existing control strings from a previous terminal.
3509  */
3510   gl->left = NULL;
3511   gl->right = NULL;
3512   gl->up = NULL;
3513   gl->down = NULL;
3514   gl->home = NULL;
3515   gl->bol = 0;
3516   gl->clear_eol = NULL;
3517   gl->clear_eod = NULL;
3518   gl->u_arrow = NULL;
3519   gl->d_arrow = NULL;
3520   gl->l_arrow = NULL;
3521   gl->r_arrow = NULL;
3522   gl->sound_bell = NULL;
3523   gl->bold = NULL;
3524   gl->underline = NULL;
3525   gl->standout = NULL;
3526   gl->dim = NULL;
3527   gl->reverse = NULL;
3528   gl->blink = NULL;
3529   gl->text_attr_off = NULL;
3530   gl->nline = 0;
3531   gl->ncolumn = 0;
3532 #ifdef USE_TERMINFO
3533   gl->left_n = NULL;
3534   gl->right_n = NULL;
3535 #endif
3536 /*
3537  * If possible lookup the information in a terminal information
3538  * database.
3539  */
3540 #ifdef USE_TERMINFO
3541   {
3542     int errret;
3543     if(!term || setupterm((char *)term, gl->input_fd, &errret) == ERR) {
3544       bad_term = 1;
3545     } else {
3546       _clr_StringGroup(gl->capmem);
3547       gl->left = gl_tigetstr(gl, "cub1");
3548       gl->right = gl_tigetstr(gl, "cuf1");
3549       gl->up = gl_tigetstr(gl, "cuu1");
3550       gl->down = gl_tigetstr(gl, "cud1");
3551       gl->home = gl_tigetstr(gl, "home");
3552       gl->clear_eol = gl_tigetstr(gl, "el");
3553       gl->clear_eod = gl_tigetstr(gl, "ed");
3554       gl->u_arrow = gl_tigetstr(gl, "kcuu1");
3555       gl->d_arrow = gl_tigetstr(gl, "kcud1");
3556       gl->l_arrow = gl_tigetstr(gl, "kcub1");
3557       gl->r_arrow = gl_tigetstr(gl, "kcuf1");
3558       gl->left_n = gl_tigetstr(gl, "cub");
3559       gl->right_n = gl_tigetstr(gl, "cuf");
3560       gl->sound_bell = gl_tigetstr(gl, "bel");
3561       gl->bold = gl_tigetstr(gl, "bold");
3562       gl->underline = gl_tigetstr(gl, "smul");
3563       gl->standout = gl_tigetstr(gl, "smso");
3564       gl->dim = gl_tigetstr(gl, "dim");
3565       gl->reverse = gl_tigetstr(gl, "rev");
3566       gl->blink = gl_tigetstr(gl, "blink");
3567       gl->text_attr_off = gl_tigetstr(gl, "sgr0");
3568     };
3569   };
3570 #elif defined(USE_TERMCAP)
3571   if(!term || tgetent(gl->tgetent_buf, (char *)term) < 0) {
3572     bad_term = 1;
3573   } else {
3574     char *tgetstr_buf_ptr = gl->tgetstr_buf;
3575     _clr_StringGroup(gl->capmem);
3576     gl->left = gl_tgetstr(gl, "le", &tgetstr_buf_ptr);
3577     gl->right = gl_tgetstr(gl, "nd", &tgetstr_buf_ptr);
3578     gl->up = gl_tgetstr(gl, "up", &tgetstr_buf_ptr);
3579     gl->down = gl_tgetstr(gl, "do", &tgetstr_buf_ptr);
3580     gl->home = gl_tgetstr(gl, "ho", &tgetstr_buf_ptr);
3581     gl->clear_eol = gl_tgetstr(gl, "ce", &tgetstr_buf_ptr);
3582     gl->clear_eod = gl_tgetstr(gl, "cd", &tgetstr_buf_ptr);
3583     gl->u_arrow = gl_tgetstr(gl, "ku", &tgetstr_buf_ptr);
3584     gl->d_arrow = gl_tgetstr(gl, "kd", &tgetstr_buf_ptr);
3585     gl->l_arrow = gl_tgetstr(gl, "kl", &tgetstr_buf_ptr);
3586     gl->r_arrow = gl_tgetstr(gl, "kr", &tgetstr_buf_ptr);
3587     gl->sound_bell = gl_tgetstr(gl, "bl", &tgetstr_buf_ptr);
3588     gl->bold = gl_tgetstr(gl, "md", &tgetstr_buf_ptr);
3589     gl->underline = gl_tgetstr(gl, "us", &tgetstr_buf_ptr);
3590     gl->standout = gl_tgetstr(gl, "so", &tgetstr_buf_ptr);
3591     gl->dim = gl_tgetstr(gl, "mh", &tgetstr_buf_ptr);
3592     gl->reverse = gl_tgetstr(gl, "mr", &tgetstr_buf_ptr);
3593     gl->blink = gl_tgetstr(gl, "mb", &tgetstr_buf_ptr);
3594     gl->text_attr_off = gl_tgetstr(gl, "me", &tgetstr_buf_ptr);
3595   };
3596 #endif
3597 /*
3598  * Report term being unusable.
3599  */
3600   if(bad_term) {
3601     gl_print_info(gl, "Bad terminal type: \"", term ? term : "(null)",
3602 		  "\". Will assume vt100.", GL_END_INFO);
3603   };
3604 /*
3605  * Fill in missing information with ANSI VT100 strings.
3606  */
3607   if(!gl->left)
3608     gl->left = "\b";    /* ^H */
3609   if(!gl->right)
3610     gl->right = GL_ESC_STR "[C";
3611   if(!gl->up)
3612     gl->up = GL_ESC_STR "[A";
3613   if(!gl->down)
3614     gl->down = "\n";
3615   if(!gl->home)
3616     gl->home = GL_ESC_STR "[H";
3617   if(!gl->bol)
3618     gl->bol = "\r";
3619   if(!gl->clear_eol)
3620     gl->clear_eol = GL_ESC_STR "[K";
3621   if(!gl->clear_eod)
3622     gl->clear_eod = GL_ESC_STR "[J";
3623   if(!gl->u_arrow)
3624     gl->u_arrow = GL_ESC_STR "[A";
3625   if(!gl->d_arrow)
3626     gl->d_arrow = GL_ESC_STR "[B";
3627   if(!gl->l_arrow)
3628     gl->l_arrow = GL_ESC_STR "[D";
3629   if(!gl->r_arrow)
3630     gl->r_arrow = GL_ESC_STR "[C";
3631   if(!gl->sound_bell)
3632     gl->sound_bell = "\a";
3633   if(!gl->bold)
3634     gl->bold = GL_ESC_STR "[1m";
3635   if(!gl->underline)
3636     gl->underline = GL_ESC_STR "[4m";
3637   if(!gl->standout)
3638     gl->standout = GL_ESC_STR "[1;7m";
3639   if(!gl->dim)
3640     gl->dim = "";  /* Not available */
3641   if(!gl->reverse)
3642     gl->reverse = GL_ESC_STR "[7m";
3643   if(!gl->blink)
3644     gl->blink = GL_ESC_STR "[5m";
3645   if(!gl->text_attr_off)
3646     gl->text_attr_off = GL_ESC_STR "[m";
3647 /*
3648  * Find out the current terminal size.
3649  */
3650   (void) _gl_terminal_size(gl, GL_DEF_NCOLUMN, GL_DEF_NLINE, NULL);
3651   return 0;
3652 }
3653 
3654 #ifdef USE_TERMINFO
3655 /*.......................................................................
3656  * This is a private function of gl_control_strings() used to look up
3657  * a termninal capability string from the terminfo database and make
3658  * a private copy of it.
3659  *
3660  * Input:
3661  *  gl         GetLine *  The resource object of gl_get_line().
3662  *  name    const char *  The name of the terminfo string to look up.
3663  * Output:
3664  *  return  const char *  The local copy of the capability, or NULL
3665  *                        if not available.
3666  */
gl_tigetstr(GetLine * gl,const char * name)3667 static const char *gl_tigetstr(GetLine *gl, const char *name)
3668 {
3669   const char *value = tigetstr((char *)name);
3670   if(!value || value == (char *) -1)
3671     return NULL;
3672   return _sg_store_string(gl->capmem, value, 0);
3673 }
3674 #elif defined(USE_TERMCAP)
3675 /*.......................................................................
3676  * This is a private function of gl_control_strings() used to look up
3677  * a termninal capability string from the termcap database and make
3678  * a private copy of it. Note that some emulations of tgetstr(), such
3679  * as that used by Solaris, ignores the buffer pointer that is past to
3680  * it, so we can't assume that a private copy has been made that won't
3681  * be trashed by another call to gl_control_strings() by another
3682  * GetLine object. So we make what may be a redundant private copy
3683  * of the string in gl->capmem.
3684  *
3685  * Input:
3686  *  gl         GetLine *  The resource object of gl_get_line().
3687  *  name    const char *  The name of the terminfo string to look up.
3688  * Input/Output:
3689  *  bufptr        char ** On input *bufptr points to the location in
3690  *                        gl->tgetstr_buf at which to record the
3691  *                        capability string. On output *bufptr is
3692  *                        incremented over the stored string.
3693  * Output:
3694  *  return  const char *  The local copy of the capability, or NULL
3695  *                        on error.
3696  */
gl_tgetstr(GetLine * gl,const char * name,char ** bufptr)3697 static const char *gl_tgetstr(GetLine *gl, const char *name, char **bufptr)
3698 {
3699   const char *value = tgetstr((char *)name, bufptr);
3700   if(!value || value == (char *) -1)
3701     return NULL;
3702   return _sg_store_string(gl->capmem, value, 0);
3703 }
3704 #endif
3705 
3706 /*.......................................................................
3707  * This is an action function that implements a user interrupt (eg. ^C).
3708  */
KT_KEY_FN(gl_user_interrupt)3709 static KT_KEY_FN(gl_user_interrupt)
3710 {
3711   raise(SIGINT);
3712   return 1;
3713 }
3714 
3715 /*.......................................................................
3716  * This is an action function that implements the abort signal.
3717  */
KT_KEY_FN(gl_abort)3718 static KT_KEY_FN(gl_abort)
3719 {
3720   raise(SIGABRT);
3721   return 1;
3722 }
3723 
3724 /*.......................................................................
3725  * This is an action function that sends a suspend signal (eg. ^Z) to the
3726  * the parent process.
3727  */
KT_KEY_FN(gl_suspend)3728 static KT_KEY_FN(gl_suspend)
3729 {
3730   raise(SIGTSTP);
3731   return 0;
3732 }
3733 
3734 /*.......................................................................
3735  * This is an action function that halts output to the terminal.
3736  */
KT_KEY_FN(gl_stop_output)3737 static KT_KEY_FN(gl_stop_output)
3738 {
3739   tcflow(gl->output_fd, TCOOFF);
3740   return 0;
3741 }
3742 
3743 /*.......................................................................
3744  * This is an action function that resumes halted terminal output.
3745  */
KT_KEY_FN(gl_start_output)3746 static KT_KEY_FN(gl_start_output)
3747 {
3748   tcflow(gl->output_fd, TCOON);
3749   return 0;
3750 }
3751 
3752 /*.......................................................................
3753  * This is an action function that allows the next character to be accepted
3754  * without any interpretation as a special character.
3755  */
KT_KEY_FN(gl_literal_next)3756 static KT_KEY_FN(gl_literal_next)
3757 {
3758   char c;   /* The character to be added to the line */
3759   int i;
3760 /*
3761  * Get the character to be inserted literally.
3762  */
3763   if(gl_read_terminal(gl, 1, &c))
3764     return 1;
3765 /*
3766  * Add the character to the line 'count' times.
3767  */
3768   for(i=0; i<count; i++)
3769     gl_add_char_to_line(gl, c);
3770   return 0;
3771 }
3772 
3773 /*.......................................................................
3774  * Return the width of a tab character at a given position when
3775  * displayed at a given position on the terminal. This is needed
3776  * because the width of tab characters depends on where they are,
3777  * relative to the preceding tab stops.
3778  *
3779  * Input:
3780  *  gl       GetLine *  The resource object of this library.
3781  *  term_curpos  int    The destination terminal location of the character.
3782  * Output:
3783  *  return       int    The number of terminal charaters needed.
3784  */
gl_displayed_tab_width(GetLine * gl,int term_curpos)3785 static int gl_displayed_tab_width(GetLine *gl, int term_curpos)
3786 {
3787   return TAB_WIDTH - ((term_curpos % gl->ncolumn) % TAB_WIDTH);
3788 }
3789 
3790 /*.......................................................................
3791  * Return the number of characters needed to display a given character
3792  * on the screen. Tab characters require eight spaces, and control
3793  * characters are represented by a caret followed by the modified
3794  * character.
3795  *
3796  * Input:
3797  *  gl       GetLine *  The resource object of this library.
3798  *  c           char    The character to be displayed.
3799  *  term_curpos  int    The destination terminal location of the character.
3800  *                      This is needed because the width of tab characters
3801  *                      depends on where they are, relative to the
3802  *                      preceding tab stops.
3803  * Output:
3804  *  return       int    The number of terminal charaters needed.
3805  */
gl_displayed_char_width(GetLine * gl,char c,int term_curpos)3806 static int gl_displayed_char_width(GetLine *gl, char c, int term_curpos)
3807 {
3808   if(c=='\t')
3809     return gl_displayed_tab_width(gl, term_curpos);
3810   if(IS_CTRL_CHAR(c))
3811     return 2;
3812   if(!isprint((int)(unsigned char) c))
3813     return gl_octal_width((int)(unsigned char)c) + 1;
3814   return 1;
3815 }
3816 
3817 
3818 /*.......................................................................
3819  * Work out the length of given string of characters on the terminal.
3820  *
3821  * Input:
3822  *  gl       GetLine *  The resource object of this library.
3823  *  string      char *  The string to be measured.
3824  *  nc           int    The number of characters to be measured, or -1
3825  *                      to measure the whole string.
3826  *  term_curpos  int    The destination terminal location of the character.
3827  *                      This is needed because the width of tab characters
3828  *                      depends on where they are, relative to the
3829  *                      preceding tab stops.
3830  * Output:
3831  *  return       int    The number of displayed characters.
3832  */
gl_displayed_string_width(GetLine * gl,const char * string,int nc,int term_curpos)3833 static int gl_displayed_string_width(GetLine *gl, const char *string, int nc,
3834 				     int term_curpos)
3835 {
3836   int slen = 0;   /* The displayed number of characters */
3837   int i;
3838 /*
3839  * How many characters are to be measured?
3840  */
3841   if(nc < 0)
3842     nc = strlen(string);
3843 /*
3844  * Add up the length of the displayed string.
3845  */
3846   for(i=0; i<nc; i++)
3847     slen += gl_displayed_char_width(gl, string[i], term_curpos + slen);
3848   return slen;
3849 }
3850 
3851 /*.......................................................................
3852  * Write a string verbatim to the current terminal or output stream.
3853  *
3854  * Note that when async-signal safety is required, the 'buffered'
3855  * argument must be 0, and n must not be -1.
3856  *
3857  * Input:
3858  *  gl         GetLine *  The resource object of the gl_get_line().
3859  *  buffered       int    If true, used buffered I/O when writing to
3860  *                        the terminal. Otherwise use async-signal-safe
3861  *                        unbuffered I/O.
3862  *  string  const char *  The string to be written (this need not be
3863  *                        '\0' terminated unless n<0).
3864  *  n              int    The number of characters to write from the
3865  *                        prefix of string[], or -1 to request that
3866  *                        gl_print_raw_string() use strlen() to figure
3867  *                        out the length.
3868  * Output:
3869  *  return         int    0 - OK.
3870  *                        1 - Error.
3871  */
gl_print_raw_string(GetLine * gl,int buffered,const char * string,int n)3872 static int gl_print_raw_string(GetLine *gl, int buffered,
3873 			       const char *string, int n)
3874 {
3875   GlWriteFn *write_fn = buffered ? gl_write_fn : gl->flush_fn;
3876 /*
3877  * Only display output when echoing is turned on.
3878  */
3879   if(gl->echo) {
3880     int ndone = 0;   /* The number of characters written so far */
3881 /*
3882  * When using un-buffered I/O, flush pending output first.
3883  */
3884     if(!buffered) {
3885       if(gl_flush_output(gl))
3886 	return 1;
3887     };
3888 /*
3889  * If no length has been provided, measure the length of the string.
3890  */
3891     if(n < 0)
3892       n = strlen(string);
3893 /*
3894  * Write the string.
3895  */
3896     if(write_fn(gl, string + ndone, n-ndone) != n)
3897       return 1;
3898   };
3899   return 0;
3900 }
3901 
3902 /*.......................................................................
3903  * Output a terminal control sequence. When using terminfo,
3904  * this must be a sequence returned by tgetstr() or tigetstr()
3905  * respectively.
3906  *
3907  * Input:
3908  *  gl     GetLine *   The resource object of this library.
3909  *  nline      int     The number of lines affected by the operation,
3910  *                     or 1 if not relevant.
3911  *  string    char *   The control sequence to be sent.
3912  * Output:
3913  *  return     int     0 - OK.
3914  *                     1 - Error.
3915  */
gl_print_control_sequence(GetLine * gl,int nline,const char * string)3916 static int gl_print_control_sequence(GetLine *gl, int nline, const char *string)
3917 {
3918   int waserr = 0;   /* True if an error occurs */
3919 /*
3920  * Only write characters to the terminal when echoing is enabled.
3921  */
3922   if(gl->echo) {
3923 #if defined(USE_TERMINFO) || defined(USE_TERMCAP)
3924     tputs_gl = gl;
3925     errno = 0;
3926     tputs((char *)string, nline, gl_tputs_putchar);
3927     waserr = errno != 0;
3928 #else
3929     waserr = gl_print_raw_string(gl, 1, string, -1);
3930 #endif
3931   };
3932   return waserr;
3933 }
3934 
3935 #if defined(USE_TERMINFO) || defined(USE_TERMCAP)
3936 /*.......................................................................
3937  * The following callback function is called by tputs() to output a raw
3938  * control character to the terminal.
3939  */
gl_tputs_putchar(TputsArgType c)3940 static TputsRetType gl_tputs_putchar(TputsArgType c)
3941 {
3942   char ch = c;
3943 #if TPUTS_RETURNS_VALUE
3944   return gl_print_raw_string(tputs_gl, 1, &ch, 1);
3945 #else
3946   (void) gl_print_raw_string(tputs_gl, 1, &ch, 1);
3947 #endif
3948 }
3949 #endif
3950 
3951 /*.......................................................................
3952  * Move the terminal cursor n characters to the left or right.
3953  *
3954  * Input:
3955  *  gl     GetLine *   The resource object of this program.
3956  *  n          int     number of positions to the right (> 0) or left (< 0).
3957  * Output:
3958  *  return     int     0 - OK.
3959  *                     1 - Error.
3960  */
gl_terminal_move_cursor(GetLine * gl,int n)3961 static int gl_terminal_move_cursor(GetLine *gl, int n)
3962 {
3963   int cur_row, cur_col; /* The current terminal row and column index of */
3964                         /*  the cursor wrt the start of the input line. */
3965   int new_row, new_col; /* The target terminal row and column index of */
3966                         /*  the cursor wrt the start of the input line. */
3967 /*
3968  * Do nothing if the input line isn't currently displayed. In this
3969  * case, the cursor will be moved to the right place when the line
3970  * is next redisplayed.
3971  */
3972   if(!gl->displayed)
3973     return 0;
3974 /*
3975  * How far can we move left?
3976  */
3977   if(gl->term_curpos + n < 0)
3978     n = gl->term_curpos;
3979 /*
3980  * Break down the current and target cursor locations into rows and columns.
3981  */
3982   cur_row = gl->term_curpos / gl->ncolumn;
3983   cur_col = gl->term_curpos % gl->ncolumn;
3984   new_row = (gl->term_curpos + n) / gl->ncolumn;
3985   new_col = (gl->term_curpos + n) % gl->ncolumn;
3986 /*
3987  * Move down to the next line.
3988  */
3989   for(; cur_row < new_row; cur_row++) {
3990     if(gl_print_control_sequence(gl, 1, gl->down))
3991       return 1;
3992   };
3993 /*
3994  * Move up to the previous line.
3995  */
3996   for(; cur_row > new_row; cur_row--) {
3997     if(gl_print_control_sequence(gl, 1, gl->up))
3998       return 1;
3999   };
4000 /*
4001  * Move to the right within the target line?
4002  */
4003   if(cur_col < new_col) {
4004 #ifdef USE_TERMINFO
4005 /*
4006  * Use a parameterized control sequence if it generates less control
4007  * characters (guess based on ANSI terminal termcap entry).
4008  */
4009     if(gl->right_n != NULL && new_col - cur_col > 1) {
4010       if(gl_print_control_sequence(gl, 1, tparm((char *)gl->right_n,
4011            (long)(new_col - cur_col), 0l, 0l, 0l, 0l, 0l, 0l, 0l, 0l)))
4012 	return 1;
4013     } else
4014 #endif
4015     {
4016       for(; cur_col < new_col; cur_col++) {
4017         if(gl_print_control_sequence(gl, 1, gl->right))
4018           return 1;
4019       };
4020     };
4021 /*
4022  * Move to the left within the target line?
4023  */
4024   } else if(cur_col > new_col) {
4025 #ifdef USE_TERMINFO
4026 /*
4027  * Use a parameterized control sequence if it generates less control
4028  * characters (guess based on ANSI terminal termcap entry).
4029  */
4030     if(gl->left_n != NULL && cur_col - new_col > 3) {
4031       if(gl_print_control_sequence(gl, 1, tparm((char *)gl->left_n,
4032            (long)(cur_col - new_col), 0l, 0l, 0l, 0l, 0l, 0l, 0l, 0l)))
4033 	return 1;
4034     } else
4035 #endif
4036     {
4037       for(; cur_col > new_col; cur_col--) {
4038         if(gl_print_control_sequence(gl, 1, gl->left))
4039           return 1;
4040       };
4041     };
4042   }
4043 /*
4044  * Update the recorded position of the terminal cursor.
4045  */
4046   gl->term_curpos += n;
4047   return 0;
4048 }
4049 
4050 /*.......................................................................
4051  * Write a character to the terminal after expanding tabs and control
4052  * characters to their multi-character representations.
4053  *
4054  * Input:
4055  *  gl    GetLine *   The resource object of this program.
4056  *  c        char     The character to be output.
4057  *  pad      char     Many terminals have the irritating feature that
4058  *                    when one writes a character in the last column of
4059  *                    of the terminal, the cursor isn't wrapped to the
4060  *                    start of the next line until one more character
4061  *                    is written. Some terminals don't do this, so
4062  *                    after such a write, we don't know where the
4063  *                    terminal is unless we output an extra character.
4064  *                    This argument specifies the character to write.
4065  *                    If at the end of the input line send '\0' or a
4066  *                    space, and a space will be written. Otherwise,
4067  *                    pass the next character in the input line
4068  *                    following the one being written.
4069  * Output:
4070  *  return    int     0 - OK.
4071  */
gl_print_char(GetLine * gl,char c,char pad)4072 static int gl_print_char(GetLine *gl, char c, char pad)
4073 {
4074   char string[TAB_WIDTH + 4]; /* A work area for composing compound strings */
4075   int nchar;                  /* The number of terminal characters */
4076   int i;
4077 /*
4078  * Check for special characters.
4079  */
4080   if(c == '\t') {
4081 /*
4082  * How many spaces do we need to represent a tab at the current terminal
4083  * column?
4084  */
4085     nchar = gl_displayed_tab_width(gl, gl->term_curpos);
4086 /*
4087  * Compose the tab string.
4088  */
4089     for(i=0; i<nchar; i++)
4090       string[i] = ' ';
4091   } else if(IS_CTRL_CHAR(c)) {
4092     string[0] = '^';
4093     string[1] = CTRL_TO_CHAR(c);
4094     nchar = 2;
4095   } else if(!isprint((int)(unsigned char) c)) {
4096     snprintf(string, sizeof(string), "\\%o", (int)(unsigned char)c);
4097     nchar = strlen(string);
4098   } else {
4099     string[0] = c;
4100     nchar = 1;
4101   };
4102 /*
4103  * Terminate the string.
4104  */
4105   string[nchar] = '\0';
4106 /*
4107  * Write the string to the terminal.
4108  */
4109   if(gl_print_raw_string(gl, 1, string, -1))
4110     return 1;
4111 /*
4112  * Except for one exception to be described in a moment, the cursor should
4113  * now have been positioned after the character that was just output.
4114  */
4115   gl->term_curpos += nchar;
4116 /*
4117  * Keep a record of the number of characters in the terminal version
4118  * of the input line.
4119  */
4120   if(gl->term_curpos > gl->term_len)
4121     gl->term_len = gl->term_curpos;
4122 /*
4123  * If the new character ended exactly at the end of a line,
4124  * most terminals won't move the cursor onto the next line until we
4125  * have written a character on the next line, so append an extra
4126  * space then move the cursor back.
4127  */
4128   if(gl->term_curpos % gl->ncolumn == 0) {
4129     int term_curpos = gl->term_curpos;
4130     if(gl_print_char(gl, pad ? pad : ' ', ' ') ||
4131        gl_set_term_curpos(gl, term_curpos))
4132       return 1;
4133   };
4134   return 0;
4135 }
4136 
4137 /*.......................................................................
4138  * Write a string to the terminal after expanding tabs and control
4139  * characters to their multi-character representations.
4140  *
4141  * Input:
4142  *  gl    GetLine *   The resource object of this program.
4143  *  string   char *   The string to be output.
4144  *  pad      char     Many terminals have the irritating feature that
4145  *                    when one writes a character in the last column of
4146  *                    of the terminal, the cursor isn't wrapped to the
4147  *                    start of the next line until one more character
4148  *                    is written. Some terminals don't do this, so
4149  *                    after such a write, we don't know where the
4150  *                    terminal is unless we output an extra character.
4151  *                    This argument specifies the character to write.
4152  *                    If at the end of the input line send '\0' or a
4153  *                    space, and a space will be written. Otherwise,
4154  *                    pass the next character in the input line
4155  *                    following the one being written.
4156  * Output:
4157  *  return    int     0 - OK.
4158  */
gl_print_string(GetLine * gl,const char * string,char pad)4159 static int gl_print_string(GetLine *gl, const char *string, char pad)
4160 {
4161   const char *cptr;   /* A pointer into string[] */
4162   for(cptr=string; *cptr; cptr++) {
4163     char nextc = cptr[1];
4164     if(gl_print_char(gl, *cptr, nextc ? nextc : pad))
4165       return 1;
4166   };
4167   return 0;
4168 }
4169 
4170 /*.......................................................................
4171  * Move the terminal cursor position.
4172  *
4173  * Input:
4174  *  gl      GetLine *  The resource object of this library.
4175  *  term_curpos int    The destination terminal cursor position.
4176  * Output:
4177  *  return      int    0 - OK.
4178  *                     1 - Error.
4179  */
gl_set_term_curpos(GetLine * gl,int term_curpos)4180 static int gl_set_term_curpos(GetLine *gl, int term_curpos)
4181 {
4182   return gl_terminal_move_cursor(gl, term_curpos - gl->term_curpos);
4183 }
4184 
4185 /*.......................................................................
4186  * This is an action function that moves the buffer cursor one character
4187  * left, and updates the terminal cursor to match.
4188  */
KT_KEY_FN(gl_cursor_left)4189 static KT_KEY_FN(gl_cursor_left)
4190 {
4191   return gl_place_cursor(gl, gl->buff_curpos - count);
4192 }
4193 
4194 /*.......................................................................
4195  * This is an action function that moves the buffer cursor one character
4196  * right, and updates the terminal cursor to match.
4197  */
KT_KEY_FN(gl_cursor_right)4198 static KT_KEY_FN(gl_cursor_right)
4199 {
4200   return gl_place_cursor(gl, gl->buff_curpos + count);
4201 }
4202 
4203 /*.......................................................................
4204  * This is an action function that toggles between overwrite and insert
4205  * mode.
4206  */
KT_KEY_FN(gl_insert_mode)4207 static KT_KEY_FN(gl_insert_mode)
4208 {
4209   gl->insert = !gl->insert;
4210   return 0;
4211 }
4212 
4213 /*.......................................................................
4214  * This is an action function which moves the cursor to the beginning of
4215  * the line.
4216  */
KT_KEY_FN(gl_beginning_of_line)4217 static KT_KEY_FN(gl_beginning_of_line)
4218 {
4219   return gl_place_cursor(gl, 0);
4220 }
4221 
4222 /*.......................................................................
4223  * This is an action function which moves the cursor to the end of
4224  * the line.
4225  */
KT_KEY_FN(gl_end_of_line)4226 static KT_KEY_FN(gl_end_of_line)
4227 {
4228   return gl_place_cursor(gl, gl->ntotal);
4229 }
4230 
4231 /*.......................................................................
4232  * This is an action function which deletes the entire contents of the
4233  * current line.
4234  */
KT_KEY_FN(gl_delete_line)4235 static KT_KEY_FN(gl_delete_line)
4236 {
4237 /*
4238  * If in vi command mode, preserve the current line for potential
4239  * use by vi-undo.
4240  */
4241   gl_save_for_undo(gl);
4242 /*
4243  * Copy the contents of the line to the cut buffer.
4244  */
4245   strlcpy(gl->cutbuf, gl->line, gl->linelen);
4246 /*
4247  * Clear the buffer.
4248  */
4249   gl_truncate_buffer(gl, 0);
4250 /*
4251  * Move the terminal cursor to just after the prompt.
4252  */
4253   if(gl_place_cursor(gl, 0))
4254     return 1;
4255 /*
4256  * Clear from the end of the prompt to the end of the terminal.
4257  */
4258   if(gl_truncate_display(gl))
4259     return 1;
4260   return 0;
4261 }
4262 
4263 /*.......................................................................
4264  * This is an action function which deletes all characters between the
4265  * current cursor position and the end of the line.
4266  */
KT_KEY_FN(gl_kill_line)4267 static KT_KEY_FN(gl_kill_line)
4268 {
4269 /*
4270  * If in vi command mode, preserve the current line for potential
4271  * use by vi-undo.
4272  */
4273   gl_save_for_undo(gl);
4274 /*
4275  * Copy the part of the line that is about to be deleted to the cut buffer.
4276  */
4277   strlcpy(gl->cutbuf, gl->line + gl->buff_curpos, gl->linelen);
4278 /*
4279  * Terminate the buffered line at the current cursor position.
4280  */
4281   gl_truncate_buffer(gl, gl->buff_curpos);
4282 /*
4283  * Clear the part of the line that follows the cursor.
4284  */
4285   if(gl_truncate_display(gl))
4286     return 1;
4287 /*
4288  * Explicitly reset the cursor position to allow vi command mode
4289  * constraints on its position to be set.
4290  */
4291   return gl_place_cursor(gl, gl->buff_curpos);
4292 }
4293 
4294 /*.......................................................................
4295  * This is an action function which deletes all characters between the
4296  * start of the line and the current cursor position.
4297  */
KT_KEY_FN(gl_backward_kill_line)4298 static KT_KEY_FN(gl_backward_kill_line)
4299 {
4300 /*
4301  * How many characters are to be deleted from before the cursor?
4302  */
4303   int nc = gl->buff_curpos - gl->insert_curpos;
4304   if (!nc)
4305     return 0;
4306 /*
4307  * Move the cursor to the start of the line, or in vi input mode,
4308  * the start of the sub-line at which insertion started, and delete
4309  * up to the old cursor position.
4310  */
4311   return gl_place_cursor(gl, gl->insert_curpos) ||
4312          gl_delete_chars(gl, nc, gl->editor == GL_EMACS_MODE || gl->vi.command);
4313 }
4314 
4315 /*.......................................................................
4316  * This is an action function which moves the cursor forward by a word.
4317  */
KT_KEY_FN(gl_forward_word)4318 static KT_KEY_FN(gl_forward_word)
4319 {
4320   return gl_place_cursor(gl, gl_nth_word_end_forward(gl, count) +
4321 			 (gl->editor==GL_EMACS_MODE));
4322 }
4323 
4324 /*.......................................................................
4325  * This is an action function which moves the cursor forward to the start
4326  * of the next word.
4327  */
KT_KEY_FN(gl_forward_to_word)4328 static KT_KEY_FN(gl_forward_to_word)
4329 {
4330   return gl_place_cursor(gl, gl_nth_word_start_forward(gl, count));
4331 }
4332 
4333 /*.......................................................................
4334  * This is an action function which moves the cursor backward by a word.
4335  */
KT_KEY_FN(gl_backward_word)4336 static KT_KEY_FN(gl_backward_word)
4337 {
4338   return gl_place_cursor(gl, gl_nth_word_start_backward(gl, count));
4339 }
4340 
4341 /*.......................................................................
4342  * Delete one or more characters, starting with the one under the cursor.
4343  *
4344  * Input:
4345  *  gl     GetLine *  The resource object of this library.
4346  *  nc         int    The number of characters to delete.
4347  *  cut        int    If true, copy the characters to the cut buffer.
4348  * Output:
4349  *  return     int    0 - OK.
4350  *                    1 - Error.
4351  */
gl_delete_chars(GetLine * gl,int nc,int cut)4352 static int gl_delete_chars(GetLine *gl, int nc, int cut)
4353 {
4354 /*
4355  * If in vi command mode, preserve the current line for potential
4356  * use by vi-undo.
4357  */
4358   gl_save_for_undo(gl);
4359 /*
4360  * If there are fewer than nc characters following the cursor, limit
4361  * nc to the number available.
4362  */
4363   if(gl->buff_curpos + nc > gl->ntotal)
4364     nc = gl->ntotal - gl->buff_curpos;
4365 /*
4366  * Copy the about to be deleted region to the cut buffer.
4367  */
4368   if(cut) {
4369     memcpy(gl->cutbuf, gl->line + gl->buff_curpos, nc);
4370     gl->cutbuf[nc] = '\0';
4371   }
4372 /*
4373  * Nothing to delete?
4374  */
4375   if(nc <= 0)
4376     return 0;
4377 /*
4378  * In vi overwrite mode, restore any previously overwritten characters
4379  * from the undo buffer.
4380  */
4381   if(gl->editor == GL_VI_MODE && !gl->vi.command && !gl->insert) {
4382 /*
4383  * How many of the characters being deleted can be restored from the
4384  * undo buffer?
4385  */
4386     int nrestore = gl->buff_curpos + nc <= gl->vi.undo.ntotal ?
4387       nc : gl->vi.undo.ntotal - gl->buff_curpos;
4388 /*
4389  * Restore any available characters.
4390  */
4391     if(nrestore > 0) {
4392       gl_buffer_string(gl, gl->vi.undo.line + gl->buff_curpos, nrestore,
4393 		       gl->buff_curpos);
4394     };
4395 /*
4396  * If their were insufficient characters in the undo buffer, then this
4397  * implies that we are deleting from the end of the line, so we need
4398  * to terminate the line either where the undo buffer ran out, or if
4399  * we are deleting from beyond the end of the undo buffer, at the current
4400  * cursor position.
4401  */
4402     if(nc != nrestore) {
4403       gl_truncate_buffer(gl, (gl->vi.undo.ntotal > gl->buff_curpos) ?
4404 			 gl->vi.undo.ntotal : gl->buff_curpos);
4405     };
4406   } else {
4407 /*
4408  * Copy the remaining part of the line back over the deleted characters.
4409  */
4410     gl_remove_from_buffer(gl, gl->buff_curpos, nc);
4411   };
4412 /*
4413  * Redraw the remaining characters following the cursor.
4414  */
4415   if(gl_print_string(gl, gl->line + gl->buff_curpos, '\0'))
4416     return 1;
4417 /*
4418  * Clear to the end of the terminal.
4419  */
4420   if(gl_truncate_display(gl))
4421     return 1;
4422 /*
4423  * Place the cursor at the start of where the deletion was performed.
4424  */
4425   return gl_place_cursor(gl, gl->buff_curpos);
4426 }
4427 
4428 /*.......................................................................
4429  * This is an action function which deletes character(s) under the
4430  * cursor without moving the cursor.
4431  */
KT_KEY_FN(gl_forward_delete_char)4432 static KT_KEY_FN(gl_forward_delete_char)
4433 {
4434 /*
4435  * Delete 'count' characters.
4436  */
4437   return gl_delete_chars(gl, count, gl->vi.command);
4438 }
4439 
4440 /*.......................................................................
4441  * This is an action function which deletes character(s) under the
4442  * cursor and moves the cursor back one character.
4443  */
KT_KEY_FN(gl_backward_delete_char)4444 static KT_KEY_FN(gl_backward_delete_char)
4445 {
4446 /*
4447  * Restrict the deletion count to the number of characters that
4448  * precede the insertion point.
4449  */
4450   if(count > gl->buff_curpos - gl->insert_curpos)
4451     count = gl->buff_curpos - gl->insert_curpos;
4452 /*
4453  * If in vi command mode, preserve the current line for potential
4454  * use by vi-undo.
4455  */
4456   gl_save_for_undo(gl);
4457   return gl_cursor_left(gl, count, NULL) ||
4458     gl_delete_chars(gl, count, gl->vi.command);
4459 }
4460 
4461 /*.......................................................................
4462  * Starting from the cursor position delete to the specified column.
4463  */
KT_KEY_FN(gl_delete_to_column)4464 static KT_KEY_FN(gl_delete_to_column)
4465 {
4466   if (--count >= gl->buff_curpos)
4467     return gl_forward_delete_char(gl, count - gl->buff_curpos, NULL);
4468   else
4469     return gl_backward_delete_char(gl, gl->buff_curpos - count, NULL);
4470 }
4471 
4472 /*.......................................................................
4473  * Starting from the cursor position delete characters to a matching
4474  * parenthesis.
4475  */
KT_KEY_FN(gl_delete_to_parenthesis)4476 static KT_KEY_FN(gl_delete_to_parenthesis)
4477 {
4478   int curpos = gl_index_of_matching_paren(gl);
4479   if(curpos >= 0) {
4480     gl_save_for_undo(gl);
4481     if(curpos >= gl->buff_curpos)
4482       return gl_forward_delete_char(gl, curpos - gl->buff_curpos + 1, NULL);
4483     else
4484       return gl_backward_delete_char(gl, ++gl->buff_curpos - curpos + 1, NULL);
4485   };
4486   return 0;
4487 }
4488 
4489 /*.......................................................................
4490  * This is an action function which deletes from the cursor to the end
4491  * of the word that the cursor is either in or precedes.
4492  */
KT_KEY_FN(gl_forward_delete_word)4493 static KT_KEY_FN(gl_forward_delete_word)
4494 {
4495 /*
4496  * If in vi command mode, preserve the current line for potential
4497  * use by vi-undo.
4498  */
4499   gl_save_for_undo(gl);
4500 /*
4501  * In emacs mode delete to the end of the word. In vi mode delete to the
4502  * start of the net word.
4503  */
4504   if(gl->editor == GL_EMACS_MODE) {
4505     return gl_delete_chars(gl,
4506 		gl_nth_word_end_forward(gl,count) - gl->buff_curpos + 1, 1);
4507   } else {
4508     return gl_delete_chars(gl,
4509 		gl_nth_word_start_forward(gl,count) - gl->buff_curpos,
4510 		gl->vi.command);
4511   };
4512 }
4513 
4514 /*.......................................................................
4515  * This is an action function which deletes the word that precedes the
4516  * cursor.
4517  */
KT_KEY_FN(gl_backward_delete_word)4518 static KT_KEY_FN(gl_backward_delete_word)
4519 {
4520 /*
4521  * Keep a record of the current cursor position.
4522  */
4523   int buff_curpos = gl->buff_curpos;
4524 /*
4525  * If in vi command mode, preserve the current line for potential
4526  * use by vi-undo.
4527  */
4528   gl_save_for_undo(gl);
4529 /*
4530  * Move back 'count' words.
4531  */
4532   if(gl_backward_word(gl, count, NULL))
4533     return 1;
4534 /*
4535  * Delete from the new cursor position to the original one.
4536  */
4537   return gl_delete_chars(gl, buff_curpos - gl->buff_curpos,
4538   			 gl->editor == GL_EMACS_MODE || gl->vi.command);
4539 }
4540 
4541 /*.......................................................................
4542  * Searching in a given direction, delete to the count'th
4543  * instance of a specified or queried character, in the input line.
4544  *
4545  * Input:
4546  *  gl       GetLine *  The getline resource object.
4547  *  count        int    The number of times to search.
4548  *  c           char    The character to be searched for, or '\0' if
4549  *                      the character should be read from the user.
4550  *  forward      int    True if searching forward.
4551  *  onto         int    True if the search should end on top of the
4552  *                      character, false if the search should stop
4553  *                      one character before the character in the
4554  *                      specified search direction.
4555  *  change       int    If true, this function is being called upon
4556  *                      to do a vi change command, in which case the
4557  *                      user will be left in insert mode after the
4558  *                      deletion.
4559  * Output:
4560  *  return       int    0 - OK.
4561  *                      1 - Error.
4562  */
gl_delete_find(GetLine * gl,int count,char c,int forward,int onto,int change)4563 static int gl_delete_find(GetLine *gl, int count, char c, int forward,
4564 			  int onto, int change)
4565 {
4566 /*
4567  * Search for the character, and abort the deletion if not found.
4568  */
4569   int pos = gl_find_char(gl, count, forward, onto, c);
4570   if(pos < 0)
4571     return 0;
4572 /*
4573  * If in vi command mode, preserve the current line for potential
4574  * use by vi-undo.
4575  */
4576   gl_save_for_undo(gl);
4577 /*
4578  * Allow the cursor to be at the end of the line if this is a change
4579  * command.
4580  */
4581   if(change)
4582     gl->vi.command = 0;
4583 /*
4584  * Delete the appropriate span of characters.
4585  */
4586   if(forward) {
4587     if(gl_delete_chars(gl, pos - gl->buff_curpos + 1, 1))
4588       return 1;
4589   } else {
4590     int buff_curpos = gl->buff_curpos;
4591     if(gl_place_cursor(gl, pos) ||
4592        gl_delete_chars(gl, buff_curpos - gl->buff_curpos, 1))
4593       return 1;
4594   };
4595 /*
4596  * If this is a change operation, switch the insert mode.
4597  */
4598   if(change && gl_vi_insert(gl, 0, NULL))
4599     return 1;
4600   return 0;
4601 }
4602 
4603 /*.......................................................................
4604  * This is an action function which deletes forward from the cursor up to and
4605  * including a specified character.
4606  */
KT_KEY_FN(gl_forward_delete_find)4607 static KT_KEY_FN(gl_forward_delete_find)
4608 {
4609   return gl_delete_find(gl, count, '\0', 1, 1, 0);
4610 }
4611 
4612 /*.......................................................................
4613  * This is an action function which deletes backward from the cursor back to
4614  * and including a specified character.
4615  */
KT_KEY_FN(gl_backward_delete_find)4616 static KT_KEY_FN(gl_backward_delete_find)
4617 {
4618   return gl_delete_find(gl, count, '\0', 0, 1, 0);
4619 }
4620 
4621 /*.......................................................................
4622  * This is an action function which deletes forward from the cursor up to but
4623  * not including a specified character.
4624  */
KT_KEY_FN(gl_forward_delete_to)4625 static KT_KEY_FN(gl_forward_delete_to)
4626 {
4627   return gl_delete_find(gl, count, '\0', 1, 0, 0);
4628 }
4629 
4630 /*.......................................................................
4631  * This is an action function which deletes backward from the cursor back to
4632  * but not including a specified character.
4633  */
KT_KEY_FN(gl_backward_delete_to)4634 static KT_KEY_FN(gl_backward_delete_to)
4635 {
4636   return gl_delete_find(gl, count, '\0', 0, 0, 0);
4637 }
4638 
4639 /*.......................................................................
4640  * This is an action function which deletes to a character specified by a
4641  * previous search.
4642  */
KT_KEY_FN(gl_delete_refind)4643 static KT_KEY_FN(gl_delete_refind)
4644 {
4645   return gl_delete_find(gl, count, gl->vi.find_char, gl->vi.find_forward,
4646 			gl->vi.find_onto, 0);
4647 }
4648 
4649 /*.......................................................................
4650  * This is an action function which deletes to a character specified by a
4651  * previous search, but in the opposite direction.
4652  */
KT_KEY_FN(gl_delete_invert_refind)4653 static KT_KEY_FN(gl_delete_invert_refind)
4654 {
4655   return gl_delete_find(gl, count, gl->vi.find_char,
4656 			!gl->vi.find_forward, gl->vi.find_onto, 0);
4657 }
4658 
4659 /*.......................................................................
4660  * This is an action function which converts the characters in the word
4661  * following the cursor to upper case.
4662  */
KT_KEY_FN(gl_upcase_word)4663 static KT_KEY_FN(gl_upcase_word)
4664 {
4665 /*
4666  * Locate the count'th word ending after the cursor.
4667  */
4668   int last = gl_nth_word_end_forward(gl, count);
4669 /*
4670  * If in vi command mode, preserve the current line for potential
4671  * use by vi-undo.
4672  */
4673   gl_save_for_undo(gl);
4674 /*
4675  * Upcase characters from the current cursor position to 'last'.
4676  */
4677   while(gl->buff_curpos <= last) {
4678     char *cptr = gl->line + gl->buff_curpos;
4679 /*
4680  * Convert the character to upper case?
4681  */
4682     if(islower((int)(unsigned char) *cptr))
4683       gl_buffer_char(gl, toupper((int) *cptr), gl->buff_curpos);
4684     gl->buff_curpos++;
4685 /*
4686  * Write the possibly modified character back. Note that for non-modified
4687  * characters we want to do this as well, so as to advance the cursor.
4688  */
4689     if(gl_print_char(gl, *cptr, cptr[1]))
4690       return 1;
4691   };
4692   return gl_place_cursor(gl, gl->buff_curpos);	/* bounds check */
4693 }
4694 
4695 /*.......................................................................
4696  * This is an action function which converts the characters in the word
4697  * following the cursor to lower case.
4698  */
KT_KEY_FN(gl_downcase_word)4699 static KT_KEY_FN(gl_downcase_word)
4700 {
4701 /*
4702  * Locate the count'th word ending after the cursor.
4703  */
4704   int last = gl_nth_word_end_forward(gl, count);
4705 /*
4706  * If in vi command mode, preserve the current line for potential
4707  * use by vi-undo.
4708  */
4709   gl_save_for_undo(gl);
4710 /*
4711  * Upcase characters from the current cursor position to 'last'.
4712  */
4713   while(gl->buff_curpos <= last) {
4714     char *cptr = gl->line + gl->buff_curpos;
4715 /*
4716  * Convert the character to upper case?
4717  */
4718     if(isupper((int)(unsigned char) *cptr))
4719       gl_buffer_char(gl, tolower((int) *cptr), gl->buff_curpos);
4720     gl->buff_curpos++;
4721 /*
4722  * Write the possibly modified character back. Note that for non-modified
4723  * characters we want to do this as well, so as to advance the cursor.
4724  */
4725     if(gl_print_char(gl, *cptr, cptr[1]))
4726       return 1;
4727   };
4728   return gl_place_cursor(gl, gl->buff_curpos);	/* bounds check */
4729 }
4730 
4731 /*.......................................................................
4732  * This is an action function which converts the first character of the
4733  * following word to upper case, in order to capitalize the word, and
4734  * leaves the cursor at the end of the word.
4735  */
KT_KEY_FN(gl_capitalize_word)4736 static KT_KEY_FN(gl_capitalize_word)
4737 {
4738   char *cptr;   /* &gl->line[gl->buff_curpos] */
4739   int first;    /* True for the first letter of the word */
4740   int i;
4741 /*
4742  * Keep a record of the current insert mode and the cursor position.
4743  */
4744   int insert = gl->insert;
4745 /*
4746  * If in vi command mode, preserve the current line for potential
4747  * use by vi-undo.
4748  */
4749   gl_save_for_undo(gl);
4750 /*
4751  * We want to overwrite the modified word.
4752  */
4753   gl->insert = 0;
4754 /*
4755  * Capitalize 'count' words.
4756  */
4757   for(i=0; i<count && gl->buff_curpos < gl->ntotal; i++) {
4758     int pos = gl->buff_curpos;
4759 /*
4760  * If we are not already within a word, skip to the start of the word.
4761  */
4762     for(cptr = gl->line + pos ; pos<gl->ntotal && !gl_is_word_char((int) *cptr);
4763 	pos++, cptr++)
4764       ;
4765 /*
4766  * Move the cursor to the new position.
4767  */
4768     if(gl_place_cursor(gl, pos))
4769       return 1;
4770 /*
4771  * While searching for the end of the word, change lower case letters
4772  * to upper case.
4773  */
4774     for(first=1; gl->buff_curpos<gl->ntotal && gl_is_word_char((int) *cptr);
4775 	gl->buff_curpos++, cptr++) {
4776 /*
4777  * Convert the character to upper case?
4778  */
4779       if(first) {
4780 	if(islower((int)(unsigned char) *cptr))
4781 	  gl_buffer_char(gl, toupper((int) *cptr), cptr - gl->line);
4782       } else {
4783 	if(isupper((int)(unsigned char) *cptr))
4784 	  gl_buffer_char(gl, tolower((int) *cptr), cptr - gl->line);
4785       };
4786       first = 0;
4787 /*
4788  * Write the possibly modified character back. Note that for non-modified
4789  * characters we want to do this as well, so as to advance the cursor.
4790  */
4791       if(gl_print_char(gl, *cptr, cptr[1]))
4792 	return 1;
4793     };
4794   };
4795 /*
4796  * Restore the insertion mode.
4797  */
4798   gl->insert = insert;
4799   return gl_place_cursor(gl, gl->buff_curpos);	/* bounds check */
4800 }
4801 
4802 /*.......................................................................
4803  * This is an action function which redraws the current line.
4804  */
KT_KEY_FN(gl_redisplay)4805 static KT_KEY_FN(gl_redisplay)
4806 {
4807 /*
4808  * Keep a record of the current cursor position.
4809  */
4810   int buff_curpos = gl->buff_curpos;
4811 /*
4812  * Do nothing if there is no line to be redisplayed.
4813  */
4814   if(gl->endline)
4815     return 0;
4816 /*
4817  * Erase the current input line.
4818  */
4819   if(gl_erase_line(gl))
4820     return 1;
4821 /*
4822  * Display the current prompt.
4823  */
4824   if(gl_display_prompt(gl))
4825     return 1;
4826 /*
4827  * Render the part of the line that the user has typed in so far.
4828  */
4829   if(gl_print_string(gl, gl->line, '\0'))
4830     return 1;
4831 /*
4832  * Restore the cursor position.
4833  */
4834   if(gl_place_cursor(gl, buff_curpos))
4835     return 1;
4836 /*
4837  * Mark the redisplay operation as having been completed.
4838  */
4839   gl->redisplay = 0;
4840 /*
4841  * Flush the redisplayed line to the terminal.
4842  */
4843   return gl_flush_output(gl);
4844 }
4845 
4846 /*.......................................................................
4847  * This is an action function which clears the display and redraws the
4848  * input line from the home position.
4849  */
KT_KEY_FN(gl_clear_screen)4850 static KT_KEY_FN(gl_clear_screen)
4851 {
4852 /*
4853  * Home the cursor and clear from there to the end of the display.
4854  */
4855   if(gl_print_control_sequence(gl, gl->nline, gl->home) ||
4856      gl_print_control_sequence(gl, gl->nline, gl->clear_eod))
4857     return 1;
4858 /*
4859  * The input line is no longer displayed.
4860  */
4861   gl_line_erased(gl);
4862 /*
4863  * Arrange for the input line to be redisplayed.
4864  */
4865   gl_queue_redisplay(gl);
4866   return 0;
4867 }
4868 
4869 /*.......................................................................
4870  * This is an action function which swaps the character under the cursor
4871  * with the character to the left of the cursor.
4872  */
KT_KEY_FN(gl_transpose_chars)4873 static KT_KEY_FN(gl_transpose_chars)
4874 {
4875   char from[3];     /* The original string of 2 characters */
4876   char swap[3];     /* The swapped string of two characters */
4877 /*
4878  * If we are at the beginning or end of the line, there aren't two
4879  * characters to swap.
4880  */
4881   if(gl->buff_curpos < 1 || gl->buff_curpos >= gl->ntotal)
4882     return 0;
4883 /*
4884  * If in vi command mode, preserve the current line for potential
4885  * use by vi-undo.
4886  */
4887   gl_save_for_undo(gl);
4888 /*
4889  * Get the original and swapped strings of the two characters.
4890  */
4891   from[0] = gl->line[gl->buff_curpos - 1];
4892   from[1] = gl->line[gl->buff_curpos];
4893   from[2] = '\0';
4894   swap[0] = gl->line[gl->buff_curpos];
4895   swap[1] = gl->line[gl->buff_curpos - 1];
4896   swap[2] = '\0';
4897 /*
4898  * Move the cursor to the start of the two characters.
4899  */
4900   if(gl_place_cursor(gl, gl->buff_curpos-1))
4901     return 1;
4902 /*
4903  * Swap the two characters in the buffer.
4904  */
4905   gl_buffer_char(gl, swap[0], gl->buff_curpos);
4906   gl_buffer_char(gl, swap[1], gl->buff_curpos+1);
4907 /*
4908  * If the sum of the displayed width of the two characters
4909  * in their current and final positions is the same, swapping can
4910  * be done by just overwriting with the two swapped characters.
4911  */
4912   if(gl_displayed_string_width(gl, from, -1, gl->term_curpos) ==
4913      gl_displayed_string_width(gl, swap, -1, gl->term_curpos)) {
4914     int insert = gl->insert;
4915     gl->insert = 0;
4916     if(gl_print_char(gl, swap[0], swap[1]) ||
4917        gl_print_char(gl, swap[1], gl->line[gl->buff_curpos+2]))
4918       return 1;
4919     gl->insert = insert;
4920 /*
4921  * If the swapped substring has a different displayed size, we need to
4922  * redraw everything after the first of the characters.
4923  */
4924   } else {
4925     if(gl_print_string(gl, gl->line + gl->buff_curpos, '\0') ||
4926        gl_truncate_display(gl))
4927       return 1;
4928   };
4929 /*
4930  * Advance the cursor to the character after the swapped pair.
4931  */
4932   return gl_place_cursor(gl, gl->buff_curpos + 2);
4933 }
4934 
4935 /*.......................................................................
4936  * This is an action function which sets a mark at the current cursor
4937  * location.
4938  */
KT_KEY_FN(gl_set_mark)4939 static KT_KEY_FN(gl_set_mark)
4940 {
4941   gl->buff_mark = gl->buff_curpos;
4942   return 0;
4943 }
4944 
4945 /*.......................................................................
4946  * This is an action function which swaps the mark location for the
4947  * cursor location.
4948  */
KT_KEY_FN(gl_exchange_point_and_mark)4949 static KT_KEY_FN(gl_exchange_point_and_mark)
4950 {
4951 /*
4952  * Get the old mark position, and limit to the extent of the input
4953  * line.
4954  */
4955   int old_mark = gl->buff_mark <= gl->ntotal ? gl->buff_mark : gl->ntotal;
4956 /*
4957  * Make the current cursor position the new mark.
4958  */
4959   gl->buff_mark = gl->buff_curpos;
4960 /*
4961  * Move the cursor to the old mark position.
4962  */
4963   return gl_place_cursor(gl, old_mark);
4964 }
4965 
4966 /*.......................................................................
4967  * This is an action function which deletes the characters between the
4968  * mark and the cursor, recording them in gl->cutbuf for later pasting.
4969  */
KT_KEY_FN(gl_kill_region)4970 static KT_KEY_FN(gl_kill_region)
4971 {
4972 /*
4973  * If in vi command mode, preserve the current line for potential
4974  * use by vi-undo.
4975  */
4976   gl_save_for_undo(gl);
4977 /*
4978  * Limit the mark to be within the line.
4979  */
4980   if(gl->buff_mark > gl->ntotal)
4981     gl->buff_mark = gl->ntotal;
4982 /*
4983  * If there are no characters between the cursor and the mark, simply clear
4984  * the cut buffer.
4985  */
4986   if(gl->buff_mark == gl->buff_curpos) {
4987     gl->cutbuf[0] = '\0';
4988     return 0;
4989   };
4990 /*
4991  * If the mark is before the cursor, swap the cursor and the mark.
4992  */
4993   if(gl->buff_mark < gl->buff_curpos && gl_exchange_point_and_mark(gl,1,NULL))
4994     return 1;
4995 /*
4996  * Delete the characters.
4997  */
4998   if(gl_delete_chars(gl, gl->buff_mark - gl->buff_curpos, 1))
4999     return 1;
5000 /*
5001  * Make the mark the same as the cursor position.
5002  */
5003   gl->buff_mark = gl->buff_curpos;
5004   return 0;
5005 }
5006 
5007 /*.......................................................................
5008  * This is an action function which records the characters between the
5009  * mark and the cursor, in gl->cutbuf for later pasting.
5010  */
KT_KEY_FN(gl_copy_region_as_kill)5011 static KT_KEY_FN(gl_copy_region_as_kill)
5012 {
5013   int ca, cb;  /* The indexes of the first and last characters in the region */
5014   int mark;    /* The position of the mark */
5015 /*
5016  * Get the position of the mark, limiting it to lie within the line.
5017  */
5018   mark = gl->buff_mark > gl->ntotal ? gl->ntotal : gl->buff_mark;
5019 /*
5020  * If there are no characters between the cursor and the mark, clear
5021  * the cut buffer.
5022  */
5023   if(mark == gl->buff_curpos) {
5024     gl->cutbuf[0] = '\0';
5025     return 0;
5026   };
5027 /*
5028  * Get the line indexes of the first and last characters in the region.
5029  */
5030   if(mark < gl->buff_curpos) {
5031     ca = mark;
5032     cb = gl->buff_curpos - 1;
5033   } else {
5034     ca = gl->buff_curpos;
5035     cb = mark - 1;
5036   };
5037 /*
5038  * Copy the region to the cut buffer.
5039  */
5040   memcpy(gl->cutbuf, gl->line + ca, cb + 1 - ca);
5041   gl->cutbuf[cb + 1 - ca] = '\0';
5042   return 0;
5043 }
5044 
5045 /*.......................................................................
5046  * This is an action function which inserts the contents of the cut
5047  * buffer at the current cursor location.
5048  */
KT_KEY_FN(gl_yank)5049 static KT_KEY_FN(gl_yank)
5050 {
5051   int i;
5052 /*
5053  * Set the mark at the current location.
5054  */
5055   gl->buff_mark = gl->buff_curpos;
5056 /*
5057  * Do nothing else if the cut buffer is empty.
5058  */
5059   if(gl->cutbuf[0] == '\0')
5060     return gl_ring_bell(gl, 1, NULL);
5061 /*
5062  * If in vi command mode, preserve the current line for potential
5063  * use by vi-undo.
5064  */
5065   gl_save_for_undo(gl);
5066 /*
5067  * Insert the string count times.
5068  */
5069   for(i=0; i<count; i++) {
5070     if(gl_add_string_to_line(gl, gl->cutbuf))
5071       return 1;
5072   };
5073 /*
5074  * gl_add_string_to_line() leaves the cursor after the last character that
5075  * was pasted, whereas vi leaves the cursor over the last character pasted.
5076  */
5077   if(gl->editor == GL_VI_MODE && gl_cursor_left(gl, 1, NULL))
5078     return 1;
5079   return 0;
5080 }
5081 
5082 /*.......................................................................
5083  * This is an action function which inserts the contents of the cut
5084  * buffer one character beyond the current cursor location.
5085  */
KT_KEY_FN(gl_append_yank)5086 static KT_KEY_FN(gl_append_yank)
5087 {
5088   int was_command = gl->vi.command;
5089   int i;
5090 /*
5091  * If the cut buffer is empty, ring the terminal bell.
5092  */
5093   if(gl->cutbuf[0] == '\0')
5094     return gl_ring_bell(gl, 1, NULL);
5095 /*
5096  * Set the mark at the current location + 1.
5097  */
5098   gl->buff_mark = gl->buff_curpos + 1;
5099 /*
5100  * If in vi command mode, preserve the current line for potential
5101  * use by vi-undo.
5102  */
5103   gl_save_for_undo(gl);
5104 /*
5105  * Arrange to paste the text in insert mode after the current character.
5106  */
5107   if(gl_vi_append(gl, 0, NULL))
5108     return 1;
5109 /*
5110  * Insert the string count times.
5111  */
5112   for(i=0; i<count; i++) {
5113     if(gl_add_string_to_line(gl, gl->cutbuf))
5114       return 1;
5115   };
5116 /*
5117  * Switch back to command mode if necessary.
5118  */
5119   if(was_command)
5120     gl_vi_command_mode(gl);
5121   return 0;
5122 }
5123 
5124 /*.......................................................................
5125  * Attempt to ask the terminal for its current size. On systems that
5126  * don't support the TIOCWINSZ ioctl() for querying the terminal size,
5127  * the current values of gl->ncolumn and gl->nrow are returned.
5128  *
5129  * Input:
5130  *  gl     GetLine *  The resource object of gl_get_line().
5131  * Input/Output:
5132  *  ncolumn    int *  The number of columns will be assigned to *ncolumn.
5133  *  nline      int *  The number of lines will be assigned to *nline.
5134  */
gl_query_size(GetLine * gl,int * ncolumn,int * nline)5135 static void gl_query_size(GetLine *gl, int *ncolumn, int *nline)
5136 {
5137 #ifdef TIOCGWINSZ
5138 /*
5139  * Query the new terminal window size. Ignore invalid responses.
5140  */
5141   struct winsize size;
5142   if(ioctl(gl->output_fd, TIOCGWINSZ, &size) == 0 &&
5143      size.ws_row > 0 && size.ws_col > 0) {
5144     *ncolumn = size.ws_col;
5145     *nline = size.ws_row;
5146     return;
5147   };
5148 #endif
5149 /*
5150  * Return the existing values.
5151  */
5152   *ncolumn = gl->ncolumn;
5153   *nline = gl->nline;
5154   return;
5155 }
5156 
5157 /*.......................................................................
5158  * Query the size of the terminal, and if it has changed, redraw the
5159  * current input line accordingly.
5160  *
5161  * Input:
5162  *  gl     GetLine *  The resource object of gl_get_line().
5163  * Output:
5164  *  return     int    0 - OK.
5165  *                    1 - Error.
5166  */
_gl_update_size(GetLine * gl)5167 static int _gl_update_size(GetLine *gl)
5168 {
5169   int ncolumn, nline;    /* The new size of the terminal */
5170 /*
5171  * Query the new terminal window size.
5172  */
5173   gl_query_size(gl, &ncolumn, &nline);
5174 /*
5175  * Update gl and the displayed line to fit the new dimensions.
5176  */
5177   return gl_handle_tty_resize(gl, ncolumn, nline);
5178 }
5179 
5180 /*.......................................................................
5181  * Redraw the current input line to account for a change in the terminal
5182  * size. Also install the new size in gl.
5183  *
5184  * Input:
5185  *  gl     GetLine *  The resource object of gl_get_line().
5186  *  ncolumn    int    The new number of columns.
5187  *  nline      int    The new number of lines.
5188  * Output:
5189  *  return     int    0 - OK.
5190  *                    1 - Error.
5191  */
gl_handle_tty_resize(GetLine * gl,int ncolumn,int nline)5192 static int gl_handle_tty_resize(GetLine *gl, int ncolumn, int nline)
5193 {
5194 /*
5195  * If the input device isn't a terminal, just record the new size.
5196  */
5197   if(!gl->is_term) {
5198     gl->nline = nline;
5199     gl->ncolumn = ncolumn;
5200 /*
5201  * Has the size actually changed?
5202  */
5203   } else if(ncolumn != gl->ncolumn || nline != gl->nline) {
5204 /*
5205  * If we are currently editing a line, erase it.
5206  */
5207     if(gl_erase_line(gl))
5208       return 1;
5209 /*
5210  * Update the recorded window size.
5211  */
5212     gl->nline = nline;
5213     gl->ncolumn = ncolumn;
5214 /*
5215  * Arrange for the input line to be redrawn before the next character
5216  * is read from the terminal.
5217  */
5218     gl_queue_redisplay(gl);
5219   };
5220   return 0;
5221 }
5222 
5223 /*.......................................................................
5224  * This is the action function that recalls the previous line in the
5225  * history buffer.
5226  */
KT_KEY_FN(gl_up_history)5227 static KT_KEY_FN(gl_up_history)
5228 {
5229 /*
5230  * In vi mode, switch to command mode, since the user is very
5231  * likely to want to move around newly recalled lines.
5232  */
5233   gl_vi_command_mode(gl);
5234 /*
5235  * Forget any previous recall session.
5236  */
5237   gl->preload_id = 0;
5238 /*
5239  * Record the key sequence number of this search action.
5240  */
5241   gl->last_search = gl->keyseq_count;
5242 /*
5243  * We don't want a search prefix for this function.
5244  */
5245   if(_glh_search_prefix(gl->glh, gl->line, 0)) {
5246     _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
5247     return 1;
5248   };
5249 /*
5250  * Recall the count'th next older line in the history list. If the first one
5251  * fails we can return since nothing has changed, otherwise we must continue
5252  * and update the line state.
5253  */
5254   if(_glh_find_backwards(gl->glh, gl->line, gl->linelen+1) == NULL)
5255     return 0;
5256   while(--count && _glh_find_backwards(gl->glh, gl->line, gl->linelen+1))
5257     ;
5258 /*
5259  * Accomodate the new contents of gl->line[].
5260  */
5261   gl_update_buffer(gl);
5262 /*
5263  * Arrange to have the cursor placed at the end of the new line.
5264  */
5265   gl->buff_curpos = gl->ntotal;
5266 /*
5267  * Erase and display the new line.
5268  */
5269   gl_queue_redisplay(gl);
5270   return 0;
5271 }
5272 
5273 /*.......................................................................
5274  * This is the action function that recalls the next line in the
5275  * history buffer.
5276  */
KT_KEY_FN(gl_down_history)5277 static KT_KEY_FN(gl_down_history)
5278 {
5279 /*
5280  * In vi mode, switch to command mode, since the user is very
5281  * likely to want to move around newly recalled lines.
5282  */
5283   gl_vi_command_mode(gl);
5284 /*
5285  * Record the key sequence number of this search action.
5286  */
5287   gl->last_search = gl->keyseq_count;
5288 /*
5289  * If no search is currently in progress continue a previous recall
5290  * session from a previous entered line if possible.
5291  */
5292   if(_glh_line_id(gl->glh, 0) == 0 && gl->preload_id) {
5293     _glh_recall_line(gl->glh, gl->preload_id, gl->line, gl->linelen+1);
5294     gl->preload_id = 0;
5295   } else {
5296 /*
5297  * We don't want a search prefix for this function.
5298  */
5299     if(_glh_search_prefix(gl->glh, gl->line, 0)) {
5300       _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
5301       return 1;
5302     };
5303 /*
5304  * Recall the count'th next newer line in the history list. If the first one
5305  * fails we can return since nothing has changed otherwise we must continue
5306  * and update the line state.
5307  */
5308     if(_glh_find_forwards(gl->glh, gl->line, gl->linelen+1) == NULL)
5309       return 0;
5310     while(--count && _glh_find_forwards(gl->glh, gl->line, gl->linelen+1))
5311       ;
5312   };
5313 /*
5314  * Accomodate the new contents of gl->line[].
5315  */
5316   gl_update_buffer(gl);
5317 /*
5318  * Arrange to have the cursor placed at the end of the new line.
5319  */
5320   gl->buff_curpos = gl->ntotal;
5321 /*
5322  * Erase and display the new line.
5323  */
5324   gl_queue_redisplay(gl);
5325   return 0;
5326 }
5327 
5328 /*.......................................................................
5329  * This is the action function that recalls the previous line in the
5330  * history buffer whos prefix matches the characters that currently
5331  * precede the cursor. By setting count=-1, this can be used internally
5332  * to force searching for the prefix used in the last search.
5333  */
KT_KEY_FN(gl_history_search_backward)5334 static KT_KEY_FN(gl_history_search_backward)
5335 {
5336 /*
5337  * In vi mode, switch to command mode, since the user is very
5338  * likely to want to move around newly recalled lines.
5339  */
5340   gl_vi_command_mode(gl);
5341 /*
5342  * Forget any previous recall session.
5343  */
5344   gl->preload_id = 0;
5345 /*
5346  * Record the key sequence number of this search action.
5347  */
5348   gl->last_search = gl->keyseq_count;
5349 /*
5350  * If a prefix search isn't already in progress, replace the search
5351  * prefix to the string that precedes the cursor. In vi command mode
5352  * include the character that is under the cursor in the string.  If
5353  * count<0 keep the previous search prefix regardless, so as to force
5354  * a repeat search even if the last command wasn't a history command.
5355  */
5356   if(count >= 0 && !_glh_search_active(gl->glh) &&
5357      _glh_search_prefix(gl->glh, gl->line, gl->buff_curpos +
5358 			(gl->editor==GL_VI_MODE && gl->ntotal>0))) {
5359     _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
5360     return 1;
5361   };
5362 /*
5363  * Search backwards for a match to the part of the line which precedes the
5364  * cursor.
5365  */
5366   if(_glh_find_backwards(gl->glh, gl->line, gl->linelen+1) == NULL)
5367     return 0;
5368 /*
5369  * Accomodate the new contents of gl->line[].
5370  */
5371   gl_update_buffer(gl);
5372 /*
5373  * Arrange to have the cursor placed at the end of the new line.
5374  */
5375   gl->buff_curpos = gl->ntotal;
5376 /*
5377  * Erase and display the new line.
5378  */
5379   gl_queue_redisplay(gl);
5380   return 0;
5381 }
5382 
5383 /*.......................................................................
5384  * This is the action function that recalls the previous line in the
5385  * history buffer who's prefix matches that specified in an earlier call
5386  * to gl_history_search_backward() or gl_history_search_forward().
5387  */
KT_KEY_FN(gl_history_re_search_backward)5388 static KT_KEY_FN(gl_history_re_search_backward)
5389 {
5390   return gl_history_search_backward(gl, -1, NULL);
5391 }
5392 
5393 /*.......................................................................
5394  * This is the action function that recalls the next line in the
5395  * history buffer who's prefix matches that specified in the earlier call
5396  * to gl_history_search_backward) which started the history search.
5397  * By setting count=-1, this can be used internally to force searching
5398  * for the prefix used in the last search.
5399  */
KT_KEY_FN(gl_history_search_forward)5400 static KT_KEY_FN(gl_history_search_forward)
5401 {
5402 /*
5403  * In vi mode, switch to command mode, since the user is very
5404  * likely to want to move around newly recalled lines.
5405  */
5406   gl_vi_command_mode(gl);
5407 /*
5408  * Record the key sequence number of this search action.
5409  */
5410   gl->last_search = gl->keyseq_count;
5411 /*
5412  * If a prefix search isn't already in progress, replace the search
5413  * prefix to the string that precedes the cursor. In vi command mode
5414  * include the character that is under the cursor in the string.  If
5415  * count<0 keep the previous search prefix regardless, so as to force
5416  * a repeat search even if the last command wasn't a history command.
5417  */
5418   if(count >= 0 && !_glh_search_active(gl->glh) &&
5419      _glh_search_prefix(gl->glh, gl->line, gl->buff_curpos +
5420 			(gl->editor==GL_VI_MODE && gl->ntotal>0))) {
5421     _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
5422     return 1;
5423   };
5424 /*
5425  * Search forwards for the next matching line.
5426  */
5427   if(_glh_find_forwards(gl->glh, gl->line, gl->linelen+1) == NULL)
5428     return 0;
5429 /*
5430  * Accomodate the new contents of gl->line[].
5431  */
5432   gl_update_buffer(gl);
5433 /*
5434  * Arrange for the cursor to be placed at the end of the new line.
5435  */
5436   gl->buff_curpos = gl->ntotal;
5437 /*
5438  * Erase and display the new line.
5439  */
5440   gl_queue_redisplay(gl);
5441   return 0;
5442 }
5443 
5444 /*.......................................................................
5445  * This is the action function that recalls the next line in the
5446  * history buffer who's prefix matches that specified in an earlier call
5447  * to gl_history_search_backward() or gl_history_search_forward().
5448  */
KT_KEY_FN(gl_history_re_search_forward)5449 static KT_KEY_FN(gl_history_re_search_forward)
5450 {
5451   return gl_history_search_forward(gl, -1, NULL);
5452 }
5453 
5454 #ifdef HIDE_FILE_SYSTEM
5455 /*.......................................................................
5456  * The following function is used as the default completion handler when
5457  * the filesystem is to be hidden. It simply reports no completions.
5458  */
CPL_MATCH_FN(gl_no_completions)5459 static CPL_MATCH_FN(gl_no_completions)
5460 {
5461   return 0;
5462 }
5463 #endif
5464 
5465 /*.......................................................................
5466  * This is the tab completion function that completes the filename that
5467  * precedes the cursor position. Its callback data argument must be a
5468  * pointer to a GlCplCallback containing the completion callback function
5469  * and its callback data, or NULL to use the builtin filename completer.
5470  */
KT_KEY_FN(gl_complete_word)5471 static KT_KEY_FN(gl_complete_word)
5472 {
5473   CplMatches *matches;    /* The possible completions */
5474   int suffix_len;         /* The length of the completion extension */
5475   int cont_len;           /* The length of any continuation suffix */
5476   int nextra;             /* The number of characters being added to the */
5477                           /*  total length of the line. */
5478   int buff_pos;           /* The buffer index at which the completion is */
5479                           /*  to be inserted. */
5480   int waserr = 0;         /* True after errors */
5481 /*
5482  * Get the container of the completion callback and its callback data.
5483  */
5484   GlCplCallback *cb = data ? (GlCplCallback *) data : &gl->cplfn;
5485 /*
5486  * In vi command mode, switch to append mode so that the character under
5487  * the cursor is included in the completion (otherwise people can't
5488  * complete at the end of the line).
5489  */
5490   if(gl->vi.command && gl_vi_append(gl, 0, NULL))
5491     return 1;
5492 /*
5493  * Get the cursor position at which the completion is to be inserted.
5494  */
5495   buff_pos = gl->buff_curpos;
5496 /*
5497  * Perform the completion.
5498  */
5499   matches = cpl_complete_word(gl->cpl, gl->line, gl->buff_curpos, cb->data,
5500 			      cb->fn);
5501 /*
5502  * No matching completions?
5503  */
5504   if(!matches) {
5505     waserr = gl_print_info(gl, cpl_last_error(gl->cpl), GL_END_INFO);
5506 /*
5507  * Are there any completions?
5508  */
5509   } else if(matches->nmatch >= 1) {
5510 /*
5511  * If there any ambiguous matches, report them, starting on a new line.
5512  */
5513     if(matches->nmatch > 1 && gl->echo) {
5514       if(_gl_normal_io(gl) ||
5515 	 _cpl_output_completions(matches, gl_write_fn, gl, gl->ncolumn))
5516 	waserr = 1;
5517     };
5518 /*
5519  * Get the length of the suffix and any continuation suffix to add to it.
5520  */
5521     suffix_len = strlen(matches->suffix);
5522     cont_len = strlen(matches->cont_suffix);
5523 /*
5524  * If there is an unambiguous match, and the continuation suffix ends in
5525  * a newline, strip that newline and arrange to have getline return
5526  * after this action function returns.
5527  */
5528     if(matches->nmatch==1 && cont_len > 0 &&
5529        matches->cont_suffix[cont_len - 1] == '\n') {
5530       cont_len--;
5531       if(gl_newline(gl, 1, NULL))
5532 	waserr = 1;
5533     };
5534 /*
5535  * Work out the number of characters that are to be added.
5536  */
5537     nextra = suffix_len + cont_len;
5538 /*
5539  * Is there anything to be added?
5540  */
5541     if(!waserr && nextra) {
5542 /*
5543  * Will there be space for the expansion in the line buffer?
5544  */
5545       if(gl->ntotal + nextra < gl->linelen) {
5546 /*
5547  * Make room to insert the filename extension.
5548  */
5549 	gl_make_gap_in_buffer(gl, gl->buff_curpos, nextra);
5550 /*
5551  * Insert the filename extension.
5552  */
5553 	gl_buffer_string(gl, matches->suffix, suffix_len, gl->buff_curpos);
5554 /*
5555  * Add the terminating characters.
5556  */
5557 	gl_buffer_string(gl, matches->cont_suffix, cont_len,
5558 			 gl->buff_curpos + suffix_len);
5559 /*
5560  * Place the cursor position at the end of the completion.
5561  */
5562 	gl->buff_curpos += nextra;
5563 /*
5564  * If we don't have to redisplay the whole line, redisplay the part
5565  * of the line which follows the original cursor position, and place
5566  * the cursor at the end of the completion.
5567  */
5568 	if(gl->displayed) {
5569 	  if(gl_truncate_display(gl) ||
5570 	     gl_print_string(gl, gl->line + buff_pos, '\0') ||
5571 	     gl_place_cursor(gl, gl->buff_curpos))
5572 	    waserr = 1;
5573 	};
5574       } else {
5575 	(void) gl_print_info(gl,
5576 			     "Insufficient room in line for file completion.",
5577 			     GL_END_INFO);
5578 	waserr = 1;
5579       };
5580     };
5581   };
5582 /*
5583  * If any output had to be written to the terminal, then editing will
5584  * have been suspended, make sure that we are back in raw line editing
5585  * mode before returning.
5586  */
5587   if(_gl_raw_io(gl, 1))
5588     waserr = 1;
5589   return 0;
5590 }
5591 
5592 #ifndef HIDE_FILE_SYSTEM
5593 /*.......................................................................
5594  * This is the function that expands the filename that precedes the
5595  * cursor position. It expands ~user/ expressions, $envvar expressions,
5596  * and wildcards.
5597  */
KT_KEY_FN(gl_expand_filename)5598 static KT_KEY_FN(gl_expand_filename)
5599 {
5600   char *start_path;      /* The pointer to the start of the pathname in */
5601                          /*  gl->line[]. */
5602   FileExpansion *result; /* The results of the filename expansion */
5603   int pathlen;           /* The length of the pathname being expanded */
5604   int length;            /* The number of characters needed to display the */
5605                          /*  expanded files. */
5606   int nextra;            /* The number of characters to be added */
5607   int i,j;
5608 /*
5609  * In vi command mode, switch to append mode so that the character under
5610  * the cursor is included in the completion (otherwise people can't
5611  * complete at the end of the line).
5612  */
5613   if(gl->vi.command && gl_vi_append(gl, 0, NULL))
5614     return 1;
5615 /*
5616  * Locate the start of the filename that precedes the cursor position.
5617  */
5618   start_path = _pu_start_of_path(gl->line, gl->buff_curpos);
5619   if(!start_path)
5620     return 1;
5621 /*
5622  * Get the length of the string that is to be expanded.
5623  */
5624   pathlen = gl->buff_curpos - (start_path - gl->line);
5625 /*
5626  * Attempt to expand it.
5627  */
5628   result = ef_expand_file(gl->ef, start_path, pathlen);
5629 /*
5630  * If there was an error, report the error on a new line.
5631  */
5632   if(!result)
5633     return gl_print_info(gl, ef_last_error(gl->ef), GL_END_INFO);
5634 /*
5635  * If no files matched, report this as well.
5636  */
5637   if(result->nfile == 0 || !result->exists)
5638     return gl_print_info(gl, "No files match.", GL_END_INFO);
5639 /*
5640  * If in vi command mode, preserve the current line for potential use by
5641  * vi-undo.
5642  */
5643   gl_save_for_undo(gl);
5644 /*
5645  * Work out how much space we will need to display all of the matching
5646  * filenames, taking account of the space that we need to place between
5647  * them, and the number of additional '\' characters needed to escape
5648  * spaces, tabs and backslash characters in the individual filenames.
5649  */
5650   length = 0;
5651   for(i=0; i<result->nfile; i++) {
5652     char *file = result->files[i];
5653     while(*file) {
5654       int c = *file++;
5655       switch(c) {
5656       case ' ': case '\t': case '\\': case '*': case '?': case '[':
5657 	length++;  /* Count extra backslash characters */
5658       };
5659       length++;    /* Count the character itself */
5660     };
5661     length++;      /* Count the space that follows each filename */
5662   };
5663 /*
5664  * Work out the number of characters that are to be added.
5665  */
5666   nextra = length - pathlen;
5667 /*
5668  * Will there be space for the expansion in the line buffer?
5669  */
5670   if(gl->ntotal + nextra >= gl->linelen) {
5671     return gl_print_info(gl, "Insufficient room in line for file expansion.",
5672 			 GL_END_INFO);
5673   } else {
5674 /*
5675  * Do we need to move the part of the line that followed the unexpanded
5676  * filename?
5677  */
5678     if(nextra > 0) {
5679       gl_make_gap_in_buffer(gl, gl->buff_curpos, nextra);
5680     } else if(nextra < 0) {
5681       gl->buff_curpos += nextra;
5682       gl_remove_from_buffer(gl, gl->buff_curpos, -nextra);
5683     };
5684 /*
5685  * Insert the filenames, separated by spaces, and with internal spaces,
5686  * tabs and backslashes escaped with backslashes.
5687  */
5688     for(i=0,j=start_path - gl->line; i<result->nfile; i++) {
5689       char *file = result->files[i];
5690       while(*file) {
5691 	int c = *file++;
5692 	switch(c) {
5693 	case ' ': case '\t': case '\\': case '*': case '?': case '[':
5694 	  gl_buffer_char(gl, '\\', j++);
5695 	};
5696 	gl_buffer_char(gl, c, j++);
5697       };
5698       gl_buffer_char(gl, ' ', j++);
5699     };
5700   };
5701 /*
5702  * Redisplay the part of the line which follows the start of
5703  * the original filename.
5704  */
5705   if(gl_place_cursor(gl, start_path - gl->line) ||
5706      gl_truncate_display(gl) ||
5707      gl_print_string(gl, start_path, start_path[length]))
5708     return 1;
5709 /*
5710  * Move the cursor to the end of the expansion.
5711  */
5712   return gl_place_cursor(gl, (start_path - gl->line) + length);
5713 }
5714 #endif
5715 
5716 #ifndef HIDE_FILE_SYSTEM
5717 /*.......................................................................
5718  * This is the action function that lists glob expansions of the
5719  * filename that precedes the cursor position. It expands ~user/
5720  * expressions, $envvar expressions, and wildcards.
5721  */
KT_KEY_FN(gl_list_glob)5722 static KT_KEY_FN(gl_list_glob)
5723 {
5724   char *start_path;      /* The pointer to the start of the pathname in */
5725                          /*  gl->line[]. */
5726   FileExpansion *result; /* The results of the filename expansion */
5727   int pathlen;           /* The length of the pathname being expanded */
5728 /*
5729  * Locate the start of the filename that precedes the cursor position.
5730  */
5731   start_path = _pu_start_of_path(gl->line, gl->buff_curpos);
5732   if(!start_path)
5733     return 1;
5734 /*
5735  * Get the length of the string that is to be expanded.
5736  */
5737   pathlen = gl->buff_curpos - (start_path - gl->line);
5738 /*
5739  * Attempt to expand it.
5740  */
5741   result = ef_expand_file(gl->ef, start_path, pathlen);
5742 /*
5743  * If there was an error, report it.
5744  */
5745   if(!result) {
5746     return gl_print_info(gl,  ef_last_error(gl->ef), GL_END_INFO);
5747 /*
5748  * If no files matched, report this as well.
5749  */
5750   } else if(result->nfile == 0 || !result->exists) {
5751     return gl_print_info(gl, "No files match.", GL_END_INFO);
5752 /*
5753  * List the matching expansions.
5754  */
5755   } else if(gl->echo) {
5756     if(gl_start_newline(gl, 1) ||
5757        _ef_output_expansions(result, gl_write_fn, gl, gl->ncolumn))
5758       return 1;
5759     gl_queue_redisplay(gl);
5760   };
5761   return 0;
5762 }
5763 #endif
5764 
5765 /*.......................................................................
5766  * Return non-zero if a character should be considered a part of a word.
5767  *
5768  * Input:
5769  *  c       int  The character to be tested.
5770  * Output:
5771  *  return  int  True if the character should be considered part of a word.
5772  */
gl_is_word_char(int c)5773 static int gl_is_word_char(int c)
5774 {
5775   return isalnum((int)(unsigned char)c) || strchr(GL_WORD_CHARS, c) != NULL;
5776 }
5777 
5778 /*.......................................................................
5779  * Override the builtin file-completion callback that is bound to the
5780  * "complete_word" action function.
5781  *
5782  * Input:
5783  *  gl            GetLine *  The resource object of the command-line input
5784  *                           module.
5785  *  data             void *  This is passed to match_fn() whenever it is
5786  *                           called. It could, for example, point to a
5787  *                           symbol table where match_fn() could look
5788  *                           for possible completions.
5789  *  match_fn   CplMatchFn *  The function that will identify the prefix
5790  *                           to be completed from the input line, and
5791  *                           report matching symbols.
5792  * Output:
5793  *  return            int    0 - OK.
5794  *                           1 - Error.
5795  */
gl_customize_completion(GetLine * gl,void * data,CplMatchFn * match_fn)5796 int gl_customize_completion(GetLine *gl, void *data, CplMatchFn *match_fn)
5797 {
5798   sigset_t oldset; /* The signals that were blocked on entry to this function */
5799 /*
5800  * Check the arguments.
5801  */
5802   if(!gl || !match_fn) {
5803     if(gl)
5804       _err_record_msg(gl->err, "NULL argument", END_ERR_MSG);
5805     errno = EINVAL;
5806     return 1;
5807   };
5808 /*
5809  * Temporarily block all signals.
5810  */
5811   gl_mask_signals(gl, &oldset);
5812 /*
5813  * Record the new completion function and its callback data.
5814  */
5815   gl->cplfn.fn = match_fn;
5816   gl->cplfn.data = data;
5817 /*
5818  * Restore the process signal mask before returning.
5819  */
5820   gl_unmask_signals(gl, &oldset);
5821   return 0;
5822 }
5823 
5824 /*.......................................................................
5825  * Change the terminal (or stream) that getline interacts with.
5826  *
5827  * Input:
5828  *  gl            GetLine *  The resource object of the command-line input
5829  *                           module.
5830  *  input_fp         FILE *  The stdio stream to read from.
5831  *  output_fp        FILE *  The stdio stream to write to.
5832  *  term             char *  The terminal type. This can be NULL if
5833  *                           either or both of input_fp and output_fp don't
5834  *                           refer to a terminal. Otherwise it should refer
5835  *                           to an entry in the terminal information database.
5836  * Output:
5837  *  return            int    0 - OK.
5838  *                           1 - Error.
5839  */
gl_change_terminal(GetLine * gl,FILE * input_fp,FILE * output_fp,const char * term)5840 int gl_change_terminal(GetLine *gl, FILE *input_fp, FILE *output_fp,
5841 		       const char *term)
5842 {
5843   sigset_t oldset; /* The signals that were blocked on entry to this function */
5844   int status;      /* The return status of _gl_change_terminal() */
5845 /*
5846  * Check the arguments.
5847  */
5848   if(!gl) {
5849     errno = EINVAL;
5850     return 1;
5851   };
5852 /*
5853  * Block all signals.
5854  */
5855   if(gl_mask_signals(gl, &oldset))
5856     return 1;
5857 /*
5858  * Execute the private body of the function while signals are blocked.
5859  */
5860   status = _gl_change_terminal(gl, input_fp, output_fp, term);
5861 /*
5862  * Restore the process signal mask.
5863  */
5864   gl_unmask_signals(gl, &oldset);
5865   return status;
5866 }
5867 
5868 /*.......................................................................
5869  * This is the private body of the gl_change_terminal() function. It
5870  * assumes that the caller has checked its arguments and blocked the
5871  * delivery of signals.
5872  */
_gl_change_terminal(GetLine * gl,FILE * input_fp,FILE * output_fp,const char * term)5873 static int _gl_change_terminal(GetLine *gl, FILE *input_fp, FILE *output_fp,
5874 			       const char *term)
5875 {
5876   int is_term = 0;   /* True if both input_fd and output_fd are associated */
5877                      /*  with a terminal. */
5878 /*
5879  * Require that input_fp and output_fp both be valid.
5880  */
5881   if(!input_fp || !output_fp) {
5882     gl_print_info(gl, "Can't change terminal. Bad input/output stream(s).",
5883 		  GL_END_INFO);
5884     return 1;
5885   };
5886 /*
5887  * Are we displacing an existing terminal (as opposed to setting the
5888  * initial terminal)?
5889  */
5890   if(gl->input_fd >= 0) {
5891 /*
5892  * Make sure to leave the previous terminal in a usable state.
5893  */
5894     if(_gl_normal_io(gl))
5895       return 1;
5896 /*
5897  * Remove the displaced terminal from the list of fds to watch.
5898  */
5899 #ifdef HAVE_SELECT
5900     FD_CLR(gl->input_fd, &gl->rfds);
5901 #endif
5902   };
5903 /*
5904  * Record the file descriptors and streams.
5905  */
5906   gl->input_fp = input_fp;
5907   gl->input_fd = fileno(input_fp);
5908   gl->output_fp = output_fp;
5909   gl->output_fd = fileno(output_fp);
5910 /*
5911  * If needed, expand the record of the maximum file-descriptor that might
5912  * need to be monitored with select().
5913  */
5914 #ifdef HAVE_SELECT
5915   if(gl->input_fd > gl->max_fd)
5916     gl->max_fd = gl->input_fd;
5917 #endif
5918 /*
5919  * Disable terminal interaction until we have enough info to interact
5920  * with the terminal.
5921  */
5922   gl->is_term = 0;
5923 /*
5924  * For terminal editing, we need both output_fd and input_fd to refer to
5925  * a terminal. While we can't verify that they both point to the same
5926  * terminal, we can verify that they point to terminals.
5927  */
5928   is_term = isatty(gl->input_fd) && isatty(gl->output_fd);
5929 /*
5930  * If we are interacting with a terminal and no terminal type has been
5931  * specified, treat it as a generic ANSI terminal.
5932  */
5933   if(is_term && !term)
5934     term = "ansi";
5935 /*
5936  * Make a copy of the terminal type string.
5937  */
5938   if(term != gl->term) {
5939 /*
5940  * Delete any old terminal type string.
5941  */
5942     if(gl->term) {
5943       free(gl->term);
5944       gl->term = NULL;
5945     };
5946 /*
5947  * Make a copy of the new terminal-type string, if any.
5948  */
5949     if(term) {
5950       size_t termsz = strlen(term)+1;
5951 
5952       gl->term = (char *) malloc(termsz);
5953       if(gl->term)
5954 	strlcpy(gl->term, term, termsz);
5955     };
5956   };
5957 /*
5958  * Clear any terminal-specific key bindings that were taken from the
5959  * settings of the last terminal.
5960  */
5961   _kt_clear_bindings(gl->bindings, KTB_TERM);
5962 /*
5963  * If we have a terminal install new bindings for it.
5964  */
5965   if(is_term) {
5966 /*
5967  * Get the current settings of the terminal.
5968  */
5969     if(tcgetattr(gl->input_fd, &gl->oldattr)) {
5970       _err_record_msg(gl->err, "tcgetattr error", END_ERR_MSG);
5971       return 1;
5972     };
5973 /*
5974  * If we don't set this now, gl_control_strings() won't know
5975  * that it is talking to a terminal.
5976  */
5977     gl->is_term = 1;
5978 /*
5979  * Lookup the terminal control string and size information.
5980  */
5981     if(gl_control_strings(gl, term)) {
5982       gl->is_term = 0;
5983       return 1;
5984     };
5985 /*
5986  * Bind terminal-specific keys.
5987  */
5988     if(gl_bind_terminal_keys(gl))
5989       return 1;
5990   };
5991 /*
5992  * Assume that the caller has given us a terminal in a sane state.
5993  */
5994   gl->io_mode = GL_NORMAL_MODE;
5995 /*
5996  * Switch into the currently configured I/O mode.
5997  */
5998   if(_gl_io_mode(gl, gl->io_mode))
5999     return 1;
6000   return 0;
6001 }
6002 
6003 /*.......................................................................
6004  * Set up terminal-specific key bindings.
6005  *
6006  * Input:
6007  *  gl            GetLine *  The resource object of the command-line input
6008  *                           module.
6009  * Output:
6010  *  return            int    0 - OK.
6011  *                           1 - Error.
6012  */
gl_bind_terminal_keys(GetLine * gl)6013 static int gl_bind_terminal_keys(GetLine *gl)
6014 {
6015 /*
6016  * Install key-bindings for the special terminal characters.
6017  */
6018   if(gl_bind_control_char(gl, KTB_TERM, gl->oldattr.c_cc[VINTR],
6019 			  "user-interrupt") ||
6020      gl_bind_control_char(gl, KTB_TERM, gl->oldattr.c_cc[VQUIT], "abort") ||
6021      gl_bind_control_char(gl, KTB_TERM, gl->oldattr.c_cc[VSUSP], "suspend"))
6022     return 1;
6023 /*
6024  * In vi-mode, arrange for the above characters to be seen in command
6025  * mode.
6026  */
6027   if(gl->editor == GL_VI_MODE) {
6028     if(gl_bind_control_char(gl, KTB_TERM, MAKE_META(gl->oldattr.c_cc[VINTR]),
6029 			    "user-interrupt") ||
6030        gl_bind_control_char(gl, KTB_TERM, MAKE_META(gl->oldattr.c_cc[VQUIT]),
6031 			    "abort") ||
6032        gl_bind_control_char(gl, KTB_TERM, MAKE_META(gl->oldattr.c_cc[VSUSP]),
6033 			    "suspend"))
6034       return 1;
6035   };
6036 /*
6037  * Non-universal special keys.
6038  */
6039 #ifdef VLNEXT
6040   if(gl_bind_control_char(gl, KTB_TERM, gl->oldattr.c_cc[VLNEXT],
6041 			  "literal-next"))
6042     return 1;
6043 #else
6044   if(_kt_set_keybinding(gl->bindings, KTB_TERM, "^V", "literal-next")) {
6045     _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG);
6046     return 1;
6047   };
6048 #endif
6049 /*
6050  * Bind action functions to the terminal-specific arrow keys
6051  * looked up by gl_control_strings().
6052  */
6053   if(_gl_bind_arrow_keys(gl))
6054     return 1;
6055   return 0;
6056 }
6057 
6058 /*.......................................................................
6059  * This function is normally bound to control-D. When it is invoked within
6060  * a line it deletes the character which follows the cursor. When invoked
6061  * at the end of the line it lists possible file completions, and when
6062  * invoked on an empty line it causes gl_get_line() to return EOF. This
6063  * function emulates the one that is normally bound to control-D by tcsh.
6064  */
KT_KEY_FN(gl_del_char_or_list_or_eof)6065 static KT_KEY_FN(gl_del_char_or_list_or_eof)
6066 {
6067 /*
6068  * If we have an empty line arrange to return EOF.
6069  */
6070   if(gl->ntotal < 1) {
6071     gl_record_status(gl, GLR_EOF, 0);
6072     return 1;
6073 /*
6074  * If we are at the end of the line list possible completions.
6075  */
6076   } else if(gl->buff_curpos >= gl->ntotal) {
6077     return gl_list_completions(gl, 1, NULL);
6078 /*
6079  * Within the line delete the character that follows the cursor.
6080  */
6081   } else {
6082 /*
6083  * If in vi command mode, first preserve the current line for potential use
6084  * by vi-undo.
6085  */
6086     gl_save_for_undo(gl);
6087 /*
6088  * Delete 'count' characters.
6089  */
6090     return gl_forward_delete_char(gl, count, NULL);
6091   };
6092 }
6093 
6094 /*.......................................................................
6095  * This function is normally bound to control-D in vi mode. When it is
6096  * invoked within a line it lists possible file completions, and when
6097  * invoked on an empty line it causes gl_get_line() to return EOF. This
6098  * function emulates the one that is normally bound to control-D by tcsh.
6099  */
KT_KEY_FN(gl_list_or_eof)6100 static KT_KEY_FN(gl_list_or_eof)
6101 {
6102 /*
6103  * If we have an empty line arrange to return EOF.
6104  */
6105   if(gl->ntotal < 1) {
6106     gl_record_status(gl, GLR_EOF, 0);
6107     return 1;
6108 /*
6109  * Otherwise list possible completions.
6110  */
6111   } else {
6112     return gl_list_completions(gl, 1, NULL);
6113   };
6114 }
6115 
6116 /*.......................................................................
6117  * List possible completions of the word that precedes the cursor. The
6118  * callback data argument must either be NULL to select the default
6119  * file completion callback, or be a GlCplCallback object containing the
6120  * completion callback function to call.
6121  */
KT_KEY_FN(gl_list_completions)6122 static KT_KEY_FN(gl_list_completions)
6123 {
6124   int waserr = 0;   /* True after errors */
6125 /*
6126  * Get the container of the completion callback and its callback data.
6127  */
6128   GlCplCallback *cb = data ? (GlCplCallback *) data : &gl->cplfn;
6129 /*
6130  * Get the list of possible completions.
6131  */
6132   CplMatches *matches = cpl_complete_word(gl->cpl, gl->line, gl->buff_curpos,
6133 					  cb->data, cb->fn);
6134 /*
6135  * No matching completions?
6136  */
6137   if(!matches) {
6138     waserr = gl_print_info(gl, cpl_last_error(gl->cpl), GL_END_INFO);
6139 /*
6140  * List the matches.
6141  */
6142   } else if(matches->nmatch > 0 && gl->echo) {
6143     if(_gl_normal_io(gl) ||
6144        _cpl_output_completions(matches, gl_write_fn, gl, gl->ncolumn))
6145       waserr = 1;
6146   };
6147 /*
6148  * If any output had to be written to the terminal, then editing will
6149  * have been suspended, make sure that we are back in raw line editing
6150  * mode before returning.
6151  */
6152   if(_gl_raw_io(gl, 1))
6153     waserr = 1;
6154   return waserr;
6155 }
6156 
6157 /*.......................................................................
6158  * Where the user has used the symbolic arrow-key names to specify
6159  * arrow key bindings, bind the specified action functions to the default
6160  * and terminal specific arrow key sequences.
6161  *
6162  * Input:
6163  *  gl     GetLine *   The getline resource object.
6164  * Output:
6165  *  return     int     0 - OK.
6166  *                     1 - Error.
6167  */
_gl_bind_arrow_keys(GetLine * gl)6168 static int _gl_bind_arrow_keys(GetLine *gl)
6169 {
6170 /*
6171  * Process each of the arrow keys.
6172  */
6173   if(_gl_rebind_arrow_key(gl, "up", gl->u_arrow, "^[[A", "^[OA") ||
6174      _gl_rebind_arrow_key(gl, "down", gl->d_arrow, "^[[B", "^[OB") ||
6175      _gl_rebind_arrow_key(gl, "left", gl->l_arrow, "^[[D", "^[OD") ||
6176      _gl_rebind_arrow_key(gl, "right", gl->r_arrow, "^[[C", "^[OC"))
6177     return 1;
6178   return 0;
6179 }
6180 
6181 /*.......................................................................
6182  * Lookup the action function of a symbolic arrow-key binding, and bind
6183  * it to the terminal-specific and default arrow-key sequences. Note that
6184  * we don't trust the terminal-specified key sequences to be correct.
6185  * The main reason for this is that on some machines the xterm terminfo
6186  * entry is for hardware X-terminals, rather than xterm terminal emulators
6187  * and the two terminal types emit different character sequences when the
6188  * their cursor keys are pressed. As a result we also supply a couple
6189  * of default key sequences.
6190  *
6191  * Input:
6192  *  gl          GetLine *   The resource object of gl_get_line().
6193  *  name           char *   The symbolic name of the arrow key.
6194  *  term_seq       char *   The terminal-specific arrow-key sequence.
6195  *  def_seq1       char *   The first default arrow-key sequence.
6196  *  def_seq2       char *   The second arrow-key sequence.
6197  * Output:
6198  *  return          int     0 - OK.
6199  *                          1 - Error.
6200  */
_gl_rebind_arrow_key(GetLine * gl,const char * name,const char * term_seq,const char * def_seq1,const char * def_seq2)6201 static int _gl_rebind_arrow_key(GetLine *gl, const char *name,
6202 				const char *term_seq, const char *def_seq1,
6203 				const char *def_seq2)
6204 {
6205   KeySym *keysym;  /* The binding-table entry matching the arrow-key name */
6206   int nsym;        /* The number of ambiguous matches */
6207 /*
6208  * Lookup the key binding for the symbolic name of the arrow key. This
6209  * will either be the default action, or a user provided one.
6210  */
6211   if(_kt_lookup_keybinding(gl->bindings, name, strlen(name), &keysym, &nsym)
6212      == KT_EXACT_MATCH) {
6213 /*
6214  * Get the action function.
6215  */
6216     KtAction *action = keysym->actions + keysym->binder;
6217     KtKeyFn *fn = action->fn;
6218     void *data = action->data;
6219 /*
6220  * Bind this to each of the specified key sequences.
6221  */
6222     if((term_seq &&
6223 	_kt_set_keyfn(gl->bindings, KTB_TERM, term_seq, fn, data)) ||
6224        (def_seq1 &&
6225 	_kt_set_keyfn(gl->bindings, KTB_NORM, def_seq1, fn, data)) ||
6226        (def_seq2 &&
6227 	_kt_set_keyfn(gl->bindings, KTB_NORM, def_seq2, fn, data))) {
6228       _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG);
6229       return 1;
6230     };
6231   };
6232   return 0;
6233 }
6234 
6235 /*.......................................................................
6236  * Read getline configuration information from a given file.
6237  *
6238  * Input:
6239  *  gl           GetLine *  The getline resource object.
6240  *  filename  const char *  The name of the file to read configuration
6241  *                          information from. The contents of this file
6242  *                          are as described in the gl_get_line(3) man
6243  *                          page for the default ~/.teclarc configuration
6244  *                          file.
6245  *  who         KtBinder    Who bindings are to be installed for.
6246  * Output:
6247  *  return           int    0 - OK.
6248  *                          1 - Irrecoverable error.
6249  */
_gl_read_config_file(GetLine * gl,const char * filename,KtBinder who)6250 static int _gl_read_config_file(GetLine *gl, const char *filename, KtBinder who)
6251 {
6252 /*
6253  * If filesystem access is to be excluded, configuration files can't
6254  * be read.
6255  */
6256 #ifdef WITHOUT_FILE_SYSTEM
6257   _err_record_msg(gl->err,
6258 		  "Can't read configuration files without filesystem access",
6259 		  END_ERR_MSG);
6260   errno = EINVAL;
6261   return 1;
6262 #else
6263   FileExpansion *expansion; /* The expansion of the filename */
6264   FILE *fp;                 /* The opened file */
6265   int waserr = 0;           /* True if an error occurred while reading */
6266   int lineno = 1;           /* The line number being processed */
6267 /*
6268  * Check the arguments.
6269  */
6270   if(!gl || !filename) {
6271     if(gl)
6272       _err_record_msg(gl->err, "NULL argument(s)", END_ERR_MSG);
6273     errno = EINVAL;
6274     return 1;
6275   };
6276 /*
6277  * Expand the filename.
6278  */
6279   expansion = ef_expand_file(gl->ef, filename, -1);
6280   if(!expansion) {
6281     gl_print_info(gl, "Unable to expand ", filename, " (",
6282 		  ef_last_error(gl->ef), ").", GL_END_INFO);
6283     return 1;
6284   };
6285 /*
6286  * Attempt to open the file.
6287  */
6288   fp = fopen(expansion->files[0], "r");
6289 /*
6290  * It isn't an error for there to be no configuration file.
6291  */
6292   if(!fp)
6293     return 0;
6294 /*
6295  * Parse the contents of the file.
6296  */
6297   while(!waserr && !feof(fp))
6298     waserr = _gl_parse_config_line(gl, fp, glc_file_getc, filename, who,
6299 				   &lineno);
6300 /*
6301  * Bind action functions to the terminal-specific arrow keys.
6302  */
6303   if(_gl_bind_arrow_keys(gl))
6304     return 1;
6305 /*
6306  * Clean up.
6307  */
6308   (void) fclose(fp);
6309   return waserr;
6310 #endif
6311 }
6312 
6313 /*.......................................................................
6314  * Read GetLine configuration information from a string. The contents of
6315  * the string are the same as those described in the gl_get_line(3)
6316  * man page for the contents of the ~/.teclarc configuration file.
6317  */
_gl_read_config_string(GetLine * gl,const char * buffer,KtBinder who)6318 static int _gl_read_config_string(GetLine *gl, const char *buffer, KtBinder who)
6319 {
6320   const char *bptr;         /* A pointer into buffer[] */
6321   int waserr = 0;           /* True if an error occurred while reading */
6322   int lineno = 1;           /* The line number being processed */
6323 /*
6324  * Check the arguments.
6325  */
6326   if(!gl || !buffer) {
6327     if(gl)
6328       _err_record_msg(gl->err, "NULL argument(s)", END_ERR_MSG);
6329     errno = EINVAL;
6330     return 1;
6331   };
6332 /*
6333  * Get a pointer to the start of the buffer.
6334  */
6335   bptr = buffer;
6336 /*
6337  * Parse the contents of the buffer.
6338  */
6339   while(!waserr && *bptr)
6340     waserr = _gl_parse_config_line(gl, &bptr, glc_buff_getc, "", who, &lineno);
6341 /*
6342  * Bind action functions to the terminal-specific arrow keys.
6343  */
6344   if(_gl_bind_arrow_keys(gl))
6345     return 1;
6346   return waserr;
6347 }
6348 
6349 /*.......................................................................
6350  * Parse the next line of a getline configuration file.
6351  *
6352  * Input:
6353  *  gl         GetLine *  The getline resource object.
6354  *  stream        void *  The pointer representing the stream to be read
6355  *                        by getc_fn().
6356  *  getc_fn  GlcGetcFn *  A callback function which when called with
6357  *                       'stream' as its argument, returns the next
6358  *                        unread character from the stream.
6359  *  origin  const char *  The name of the entity being read (eg. a
6360  *                        file name).
6361  *  who       KtBinder    Who bindings are to be installed for.
6362  * Input/Output:
6363  *  lineno         int *  The line number being processed is to be
6364  *                        maintained in *lineno.
6365  * Output:
6366  *  return         int    0 - OK.
6367  *                        1 - Irrecoverable error.
6368  */
_gl_parse_config_line(GetLine * gl,void * stream,GlcGetcFn * getc_fn,const char * origin,KtBinder who,int * lineno)6369 static int _gl_parse_config_line(GetLine *gl, void *stream, GlcGetcFn *getc_fn,
6370 				 const char *origin, KtBinder who, int *lineno)
6371 {
6372   char buffer[GL_CONF_BUFLEN+1];  /* The input line buffer */
6373   char *argv[GL_CONF_MAXARG];     /* The argument list */
6374   int argc = 0;                   /* The number of arguments in argv[] */
6375   int c;                          /* A character from the file */
6376   int escaped = 0;                /* True if the next character is escaped */
6377   int i;
6378 /*
6379  * Skip spaces and tabs.
6380  */
6381   do c = getc_fn(stream); while(c==' ' || c=='\t');
6382 /*
6383  * Comments extend to the end of the line.
6384  */
6385   if(c=='#')
6386     do c = getc_fn(stream); while(c != '\n' && c != EOF);
6387 /*
6388  * Ignore empty lines.
6389  */
6390   if(c=='\n' || c==EOF) {
6391     (*lineno)++;
6392     return 0;
6393   };
6394 /*
6395  * Record the buffer location of the start of the first argument.
6396  */
6397   argv[argc] = buffer;
6398 /*
6399  * Read the rest of the line, stopping early if a comment is seen, or
6400  * the buffer overflows, and replacing sequences of spaces with a
6401  * '\0', and recording the thus terminated string as an argument.
6402  */
6403   i = 0;
6404   while(i<GL_CONF_BUFLEN) {
6405 /*
6406  * Did we hit the end of the latest argument?
6407  */
6408     if(c==EOF || (!escaped && (c==' ' || c=='\n' || c=='\t' || c=='#'))) {
6409 /*
6410  * Terminate the argument.
6411  */
6412       buffer[i++] = '\0';
6413       argc++;
6414 /*
6415  * Skip spaces and tabs.
6416  */
6417       while(c==' ' || c=='\t')
6418 	c = getc_fn(stream);
6419 /*
6420  * If we hit the end of the line, or the start of a comment, exit the loop.
6421  */
6422       if(c==EOF || c=='\n' || c=='#')
6423 	break;
6424 /*
6425  * Start recording the next argument.
6426  */
6427       if(argc >= GL_CONF_MAXARG) {
6428 	gl_report_config_error(gl, origin, *lineno, "Too many arguments.");
6429 	do c = getc_fn(stream); while(c!='\n' && c!=EOF);  /* Skip past eol */
6430 	return 0;
6431       };
6432       argv[argc] = buffer + i;
6433 /*
6434  * The next character was preceded by spaces, so it isn't escaped.
6435  */
6436       escaped = 0;
6437     } else {
6438 /*
6439  * If we hit an unescaped backslash, this means that we should arrange
6440  * to treat the next character like a simple alphabetical character.
6441  */
6442       if(c=='\\' && !escaped) {
6443 	escaped = 1;
6444 /*
6445  * Splice lines where the newline is escaped.
6446  */
6447       } else if(c=='\n' && escaped) {
6448 	(*lineno)++;
6449 /*
6450  * Record a normal character, preserving any preceding backslash.
6451  */
6452       } else {
6453 	if(escaped)
6454 	  buffer[i++] = '\\';
6455 	if(i>=GL_CONF_BUFLEN)
6456 	  break;
6457 	escaped = 0;
6458 	buffer[i++] = c;
6459       };
6460 /*
6461  * Get the next character.
6462  */
6463       c = getc_fn(stream);
6464     };
6465   };
6466 /*
6467  * Did the buffer overflow?
6468  */
6469   if(i>=GL_CONF_BUFLEN) {
6470     gl_report_config_error(gl, origin, *lineno, "Line too long.");
6471     return 0;
6472   };
6473 /*
6474  * The first argument should be a command name.
6475  */
6476   if(strcmp(argv[0], "bind") == 0) {
6477     const char *action = NULL; /* A NULL action removes a keybinding */
6478     const char *keyseq = NULL;
6479     switch(argc) {
6480     case 3:
6481       action = argv[2];
6482       /* FALLTHROUGH */
6483     case 2:              /* Note the intentional fallthrough */
6484       keyseq = argv[1];
6485 /*
6486  * Attempt to record the new keybinding.
6487  */
6488       if(_kt_set_keybinding(gl->bindings, who, keyseq, action)) {
6489 	gl_report_config_error(gl, origin, *lineno,
6490 			       _kt_last_error(gl->bindings));
6491       };
6492       break;
6493     default:
6494       gl_report_config_error(gl, origin, *lineno, "Wrong number of arguments.");
6495     };
6496   } else if(strcmp(argv[0], "edit-mode") == 0) {
6497     if(argc == 2 && strcmp(argv[1], "emacs") == 0) {
6498       gl_change_editor(gl, GL_EMACS_MODE);
6499     } else if(argc == 2 && strcmp(argv[1], "vi") == 0) {
6500       gl_change_editor(gl, GL_VI_MODE);
6501     } else if(argc == 2 && strcmp(argv[1], "none") == 0) {
6502       gl_change_editor(gl, GL_NO_EDITOR);
6503     } else {
6504       gl_report_config_error(gl, origin, *lineno,
6505 			     "The argument of editor should be vi or emacs.");
6506     };
6507   } else if(strcmp(argv[0], "nobeep") == 0) {
6508     gl->silence_bell = 1;
6509   } else {
6510     gl_report_config_error(gl, origin, *lineno, "Unknown command name.");
6511   };
6512 /*
6513  * Skip any trailing comment.
6514  */
6515   while(c != '\n' && c != EOF)
6516     c = getc_fn(stream);
6517   (*lineno)++;
6518   return 0;
6519 }
6520 
6521 /*.......................................................................
6522  * This is a private function of _gl_parse_config_line() which prints
6523  * out an error message about the contents of the line, prefixed by the
6524  * name of the origin of the line and its line number.
6525  *
6526  * Input:
6527  *  gl         GetLine *  The resource object of gl_get_line().
6528  *  origin  const char *  The name of the entity being read (eg. a
6529  *                        file name).
6530  *  lineno         int    The line number at which the error occurred.
6531  *  errmsg  const char *  The error message.
6532  * Output:
6533  *  return         int    0 - OK.
6534  *                        1 - Error.
6535  */
gl_report_config_error(GetLine * gl,const char * origin,int lineno,const char * errmsg)6536 static int gl_report_config_error(GetLine *gl, const char *origin, int lineno,
6537 				  const char *errmsg)
6538 {
6539   char lnum[20];   /* A buffer in which to render a single integer */
6540 /*
6541  * Convert the line number into a string.
6542  */
6543   snprintf(lnum, sizeof(lnum), "%d", lineno);
6544 /*
6545  * Have the string printed on the terminal.
6546  */
6547   return gl_print_info(gl, origin, ":", lnum, ": ", errmsg, GL_END_INFO);
6548 }
6549 
6550 /*.......................................................................
6551  * This is the _gl_parse_config_line() callback function which reads the
6552  * next character from a configuration file.
6553  */
GLC_GETC_FN(glc_file_getc)6554 static GLC_GETC_FN(glc_file_getc)
6555 {
6556   return fgetc((FILE *) stream);
6557 }
6558 
6559 /*.......................................................................
6560  * This is the _gl_parse_config_line() callback function which reads the
6561  * next character from a buffer. Its stream argument is a pointer to a
6562  * variable which is, in turn, a pointer into the buffer being read from.
6563  */
GLC_GETC_FN(glc_buff_getc)6564 static GLC_GETC_FN(glc_buff_getc)
6565 {
6566   const char **lptr = (char const **) stream;
6567   return **lptr ? *(*lptr)++ : EOF;
6568 }
6569 
6570 #ifndef HIDE_FILE_SYSTEM
6571 /*.......................................................................
6572  * When this action is triggered, it arranges to temporarily read command
6573  * lines from the regular file whos name precedes the cursor.
6574  * The current line is first discarded.
6575  */
KT_KEY_FN(gl_read_from_file)6576 static KT_KEY_FN(gl_read_from_file)
6577 {
6578   char *start_path;       /* The pointer to the start of the pathname in */
6579                           /*  gl->line[]. */
6580   FileExpansion *result;  /* The results of the filename expansion */
6581   int pathlen;            /* The length of the pathname being expanded */
6582 /*
6583  * Locate the start of the filename that precedes the cursor position.
6584  */
6585   start_path = _pu_start_of_path(gl->line, gl->buff_curpos);
6586   if(!start_path)
6587     return 1;
6588 /*
6589  * Get the length of the pathname string.
6590  */
6591   pathlen = gl->buff_curpos - (start_path - gl->line);
6592 /*
6593  * Attempt to expand the pathname.
6594  */
6595   result = ef_expand_file(gl->ef, start_path, pathlen);
6596 /*
6597  * If there was an error, report the error on a new line.
6598  */
6599   if(!result) {
6600     return gl_print_info(gl, ef_last_error(gl->ef), GL_END_INFO);
6601 /*
6602  * If no files matched, report this as well.
6603  */
6604   } else if(result->nfile == 0 || !result->exists) {
6605     return gl_print_info(gl, "No files match.", GL_END_INFO);
6606 /*
6607  * Complain if more than one file matches.
6608  */
6609   } else if(result->nfile > 1) {
6610     return gl_print_info(gl, "More than one file matches.", GL_END_INFO);
6611 /*
6612  * Disallow input from anything but normal files. In principle we could
6613  * also support input from named pipes. Terminal files would be a problem
6614  * since we wouldn't know the terminal type, and other types of files
6615  * might cause the library to lock up.
6616  */
6617   } else if(!_pu_path_is_file(result->files[0])) {
6618     return gl_print_info(gl, "Not a normal file.", GL_END_INFO);
6619   } else {
6620 /*
6621  * Attempt to open and install the specified file for reading.
6622  */
6623     gl->file_fp = fopen(result->files[0], "r");
6624     if(!gl->file_fp) {
6625       return gl_print_info(gl, "Unable to open: ", result->files[0],
6626 			   GL_END_INFO);
6627     };
6628 /*
6629  * If needed, expand the record of the maximum file-descriptor that might
6630  * need to be monitored with select().
6631  */
6632 #ifdef HAVE_SELECT
6633     if(fileno(gl->file_fp) > gl->max_fd)
6634       gl->max_fd = fileno(gl->file_fp);
6635 #endif
6636 /*
6637  * Is non-blocking I/O needed?
6638  */
6639     if(gl->raw_mode && gl->io_mode==GL_SERVER_MODE &&
6640        gl_nonblocking_io(gl, fileno(gl->file_fp))) {
6641       gl_revert_input(gl);
6642       return gl_print_info(gl, "Can't read file %s with non-blocking I/O",
6643 			   result->files[0]);
6644     };
6645 /*
6646  * Inform the user what is happening.
6647  */
6648     if(gl_print_info(gl, "<Taking input from ", result->files[0], ">",
6649 		     GL_END_INFO))
6650       return 1;
6651   };
6652   return 0;
6653 }
6654 #endif
6655 
6656 /*.......................................................................
6657  * Close any temporary file that is being used for input.
6658  *
6659  * Input:
6660  *  gl     GetLine *  The getline resource object.
6661  */
gl_revert_input(GetLine * gl)6662 static void gl_revert_input(GetLine *gl)
6663 {
6664   if(gl->file_fp)
6665     fclose(gl->file_fp);
6666   gl->file_fp = NULL;
6667   gl->endline = 1;
6668 }
6669 
6670 /*.......................................................................
6671  * This is the action function that recalls the oldest line in the
6672  * history buffer.
6673  */
KT_KEY_FN(gl_beginning_of_history)6674 static KT_KEY_FN(gl_beginning_of_history)
6675 {
6676 /*
6677  * In vi mode, switch to command mode, since the user is very
6678  * likely to want to move around newly recalled lines.
6679  */
6680   gl_vi_command_mode(gl);
6681 /*
6682  * Forget any previous recall session.
6683  */
6684   gl->preload_id = 0;
6685 /*
6686  * Record the key sequence number of this search action.
6687  */
6688   gl->last_search = gl->keyseq_count;
6689 /*
6690  * Recall the next oldest line in the history list.
6691  */
6692   if(_glh_oldest_line(gl->glh, gl->line, gl->linelen+1) == NULL)
6693     return 0;
6694 /*
6695  * Accomodate the new contents of gl->line[].
6696  */
6697   gl_update_buffer(gl);
6698 /*
6699  * Arrange to have the cursor placed at the end of the new line.
6700  */
6701   gl->buff_curpos = gl->ntotal;
6702 /*
6703  * Erase and display the new line.
6704  */
6705   gl_queue_redisplay(gl);
6706   return 0;
6707 }
6708 
6709 /*.......................................................................
6710  * If a history session is currently in progress, this action function
6711  * recalls the line that was being edited when the session started. If
6712  * no history session is in progress, it does nothing.
6713  */
KT_KEY_FN(gl_end_of_history)6714 static KT_KEY_FN(gl_end_of_history)
6715 {
6716 /*
6717  * In vi mode, switch to command mode, since the user is very
6718  * likely to want to move around newly recalled lines.
6719  */
6720   gl_vi_command_mode(gl);
6721 /*
6722  * Forget any previous recall session.
6723  */
6724   gl->preload_id = 0;
6725 /*
6726  * Record the key sequence number of this search action.
6727  */
6728   gl->last_search = gl->keyseq_count;
6729 /*
6730  * Recall the next oldest line in the history list.
6731  */
6732   if(_glh_current_line(gl->glh, gl->line, gl->linelen+1) == NULL)
6733     return 0;
6734 /*
6735  * Accomodate the new contents of gl->line[].
6736  */
6737   gl_update_buffer(gl);
6738 /*
6739  * Arrange to have the cursor placed at the end of the new line.
6740  */
6741   gl->buff_curpos = gl->ntotal;
6742 /*
6743  * Erase and display the new line.
6744  */
6745   gl_queue_redisplay(gl);
6746   return 0;
6747 }
6748 
6749 /*.......................................................................
6750  * This action function is treated specially, in that its count argument
6751  * is set to the end keystroke of the keysequence that activated it.
6752  * It accumulates a numeric argument, adding one digit on each call in
6753  * which the last keystroke was a numeric digit.
6754  */
KT_KEY_FN(gl_digit_argument)6755 static KT_KEY_FN(gl_digit_argument)
6756 {
6757 /*
6758  * Was the last keystroke a digit?
6759  */
6760   int is_digit = isdigit((int)(unsigned char) count);
6761 /*
6762  * In vi command mode, a lone '0' means goto-start-of-line.
6763  */
6764   if(gl->vi.command && gl->number < 0 && count == '0')
6765     return gl_beginning_of_line(gl, count, NULL);
6766 /*
6767  * Are we starting to accumulate a new number?
6768  */
6769   if(gl->number < 0 || !is_digit)
6770     gl->number = 0;
6771 /*
6772  * Was the last keystroke a digit?
6773  */
6774   if(is_digit) {
6775 /*
6776  * Read the numeric value of the digit, without assuming ASCII.
6777  */
6778     int n;
6779     char s[2]; s[0] = count; s[1] = '\0';
6780     n = atoi(s);
6781 /*
6782  * Append the new digit.
6783  */
6784     gl->number = gl->number * 10 + n;
6785   };
6786   return 0;
6787 }
6788 
6789 /*.......................................................................
6790  * The newline action function sets gl->endline to tell
6791  * gl_get_input_line() that the line is now complete.
6792  */
KT_KEY_FN(gl_newline)6793 static KT_KEY_FN(gl_newline)
6794 {
6795   GlhLineID id;    /* The last history line recalled while entering this line */
6796 /*
6797  * Flag the line as ended.
6798  */
6799   gl->endline = 1;
6800 /*
6801  * Record the next position in the history buffer, for potential
6802  * recall by an action function on the next call to gl_get_line().
6803  */
6804   id = _glh_line_id(gl->glh, 1);
6805   if(id)
6806     gl->preload_id = id;
6807   return 0;
6808 }
6809 
6810 /*.......................................................................
6811  * The 'repeat' action function sets gl->endline to tell
6812  * gl_get_input_line() that the line is now complete, and records the
6813  * ID of the next history line in gl->preload_id so that the next call
6814  * to gl_get_input_line() will preload the line with that history line.
6815  */
KT_KEY_FN(gl_repeat_history)6816 static KT_KEY_FN(gl_repeat_history)
6817 {
6818   gl->endline = 1;
6819   gl->preload_id = _glh_line_id(gl->glh, 1);
6820   gl->preload_history = 1;
6821   return 0;
6822 }
6823 
6824 /*.......................................................................
6825  * Flush unwritten characters to the terminal.
6826  *
6827  * Input:
6828  *  gl     GetLine *  The getline resource object.
6829  * Output:
6830  *  return     int    0 - OK.
6831  *                    1 - Either an error occured, or the output
6832  *                        blocked and non-blocking I/O is being used.
6833  *                        See gl->rtn_status for details.
6834  */
gl_flush_output(GetLine * gl)6835 static int gl_flush_output(GetLine *gl)
6836 {
6837 /*
6838  * Record the fact that we are about to write to the terminal.
6839  */
6840   gl->pending_io = GLP_WRITE;
6841 /*
6842  * Attempt to flush the output to the terminal.
6843  */
6844   errno = 0;
6845   switch(_glq_flush_queue(gl->cq, gl->flush_fn, gl)) {
6846   case GLQ_FLUSH_DONE:
6847     return gl->redisplay && !gl->postpone && gl_redisplay(gl, 1, NULL);
6848     break;
6849   case GLQ_FLUSH_AGAIN:      /* Output blocked */
6850     gl_record_status(gl, GLR_BLOCKED, BLOCKED_ERRNO);
6851     return 1;
6852     break;
6853   default:                   /* Abort the line if an error occurs */
6854     gl_record_status(gl, errno==EINTR ? GLR_SIGNAL : GLR_ERROR, errno);
6855     return 1;
6856     break;
6857   };
6858 }
6859 
6860 /*.......................................................................
6861  * This is the callback which _glq_flush_queue() uses to write buffered
6862  * characters to the terminal.
6863  */
GL_WRITE_FN(gl_flush_terminal)6864 static GL_WRITE_FN(gl_flush_terminal)
6865 {
6866   int ndone = 0;    /* The number of characters written so far */
6867 /*
6868  * Get the line-editor resource object.
6869  */
6870   GetLine *gl = (GetLine *) data;
6871 /*
6872  * Transfer the latest array of characters to stdio.
6873  */
6874   while(ndone < n) {
6875     int nnew = write(gl->output_fd, s, n-ndone);
6876 /*
6877  * If the write was successful, add to the recorded number of bytes
6878  * that have now been written.
6879  */
6880     if(nnew > 0) {
6881       ndone += nnew;
6882 /*
6883  * If a signal interrupted the call, restart the write(), since all of
6884  * the signals that gl_get_line() has been told to watch for are
6885  * currently blocked.
6886  */
6887     } else if(errno == EINTR) {
6888       continue;
6889 /*
6890  * If we managed to write something before an I/O error occurred, or
6891  * output blocked before anything was written, report the number of
6892  * bytes that were successfully written before this happened.
6893  */
6894     } else if(ndone > 0
6895 #if defined(EAGAIN)
6896 	      || errno==EAGAIN
6897 #endif
6898 #if defined(EWOULDBLOCK)
6899 	      || errno==EWOULDBLOCK
6900 #endif
6901 	      ) {
6902       return ndone;
6903 
6904 /*
6905  * To get here, an error must have occurred before anything new could
6906  * be written.
6907  */
6908     } else {
6909       return -1;
6910     };
6911   };
6912 /*
6913  * To get here, we must have successfully written the number of
6914  * bytes that was specified.
6915  */
6916   return n;
6917 }
6918 
6919 /*.......................................................................
6920  * Change the style of editing to emulate a given editor.
6921  *
6922  * Input:
6923  *  gl       GetLine *  The getline resource object.
6924  *  editor  GlEditor    The type of editor to emulate.
6925  * Output:
6926  *  return       int    0 - OK.
6927  *                      1 - Error.
6928  */
gl_change_editor(GetLine * gl,GlEditor editor)6929 static int gl_change_editor(GetLine *gl, GlEditor editor)
6930 {
6931 /*
6932  * Install the default key-bindings of the requested editor.
6933  */
6934   switch(editor) {
6935   case GL_EMACS_MODE:
6936     _kt_clear_bindings(gl->bindings, KTB_NORM);
6937     _kt_clear_bindings(gl->bindings, KTB_TERM);
6938     (void) _kt_add_bindings(gl->bindings, KTB_NORM, gl_emacs_bindings,
6939 		   sizeof(gl_emacs_bindings)/sizeof(gl_emacs_bindings[0]));
6940     break;
6941   case GL_VI_MODE:
6942     _kt_clear_bindings(gl->bindings, KTB_NORM);
6943     _kt_clear_bindings(gl->bindings, KTB_TERM);
6944     (void) _kt_add_bindings(gl->bindings, KTB_NORM, gl_vi_bindings,
6945 			    sizeof(gl_vi_bindings)/sizeof(gl_vi_bindings[0]));
6946     break;
6947   case GL_NO_EDITOR:
6948     break;
6949   default:
6950     _err_record_msg(gl->err, "Unknown editor", END_ERR_MSG);
6951     errno = EINVAL;
6952     return 1;
6953   };
6954 /*
6955  * Record the new editing mode.
6956  */
6957   gl->editor = editor;
6958   gl->vi.command = 0;     /* Start in input mode */
6959   gl->insert_curpos = 0;
6960 /*
6961  * Reinstate terminal-specific bindings.
6962  */
6963   if(gl->editor != GL_NO_EDITOR && gl->input_fp)
6964     (void) gl_bind_terminal_keys(gl);
6965   return 0;
6966 }
6967 
6968 /*.......................................................................
6969  * This is an action function that switches to editing using emacs bindings
6970  */
KT_KEY_FN(gl_emacs_editing_mode)6971 static KT_KEY_FN(gl_emacs_editing_mode)
6972 {
6973   return gl_change_editor(gl, GL_EMACS_MODE);
6974 }
6975 
6976 /*.......................................................................
6977  * This is an action function that switches to editing using vi bindings
6978  */
KT_KEY_FN(gl_vi_editing_mode)6979 static KT_KEY_FN(gl_vi_editing_mode)
6980 {
6981   return gl_change_editor(gl, GL_VI_MODE);
6982 }
6983 
6984 /*.......................................................................
6985  * This is the action function that switches to insert mode.
6986  */
KT_KEY_FN(gl_vi_insert)6987 static KT_KEY_FN(gl_vi_insert)
6988 {
6989 /*
6990  * If in vi command mode, preserve the current line for potential
6991  * use by vi-undo.
6992  */
6993   gl_save_for_undo(gl);
6994 /*
6995  * Switch to vi insert mode.
6996  */
6997   gl->insert = 1;
6998   gl->vi.command = 0;
6999   gl->insert_curpos = gl->buff_curpos;
7000   return 0;
7001 }
7002 
7003 /*.......................................................................
7004  * This is an action function that switches to overwrite mode.
7005  */
KT_KEY_FN(gl_vi_overwrite)7006 static KT_KEY_FN(gl_vi_overwrite)
7007 {
7008 /*
7009  * If in vi command mode, preserve the current line for potential
7010  * use by vi-undo.
7011  */
7012   gl_save_for_undo(gl);
7013 /*
7014  * Switch to vi overwrite mode.
7015  */
7016   gl->insert = 0;
7017   gl->vi.command = 0;
7018   gl->insert_curpos = gl->buff_curpos;
7019   return 0;
7020 }
7021 
7022 /*.......................................................................
7023  * This action function toggles the case of the character under the
7024  * cursor.
7025  */
KT_KEY_FN(gl_change_case)7026 static KT_KEY_FN(gl_change_case)
7027 {
7028   int i;
7029 /*
7030  * Keep a record of the current insert mode and the cursor position.
7031  */
7032   int insert = gl->insert;
7033 /*
7034  * If in vi command mode, preserve the current line for potential
7035  * use by vi-undo.
7036  */
7037   gl_save_for_undo(gl);
7038 /*
7039  * We want to overwrite the modified word.
7040  */
7041   gl->insert = 0;
7042 /*
7043  * Toggle the case of 'count' characters.
7044  */
7045   for(i=0; i<count && gl->buff_curpos < gl->ntotal; i++) {
7046     char *cptr = gl->line + gl->buff_curpos++;
7047 /*
7048  * Convert the character to upper case?
7049  */
7050     if(islower((int)(unsigned char) *cptr))
7051       gl_buffer_char(gl, toupper((int) *cptr), cptr - gl->line);
7052     else if(isupper((int)(unsigned char) *cptr))
7053       gl_buffer_char(gl, tolower((int) *cptr), cptr - gl->line);
7054 /*
7055  * Write the possibly modified character back. Note that for non-modified
7056  * characters we want to do this as well, so as to advance the cursor.
7057  */
7058       if(gl_print_char(gl, *cptr, cptr[1]))
7059 	return 1;
7060   };
7061 /*
7062  * Restore the insertion mode.
7063  */
7064   gl->insert = insert;
7065   return gl_place_cursor(gl, gl->buff_curpos);	/* bounds check */
7066 }
7067 
7068 /*.......................................................................
7069  * This is the action function which implements the vi-style action which
7070  * moves the cursor to the start of the line, then switches to insert mode.
7071  */
KT_KEY_FN(gl_vi_insert_at_bol)7072 static KT_KEY_FN(gl_vi_insert_at_bol)
7073 {
7074   gl_save_for_undo(gl);
7075   return gl_beginning_of_line(gl, 0, NULL) ||
7076          gl_vi_insert(gl, 0, NULL);
7077 
7078 }
7079 
7080 /*.......................................................................
7081  * This is the action function which implements the vi-style action which
7082  * moves the cursor to the end of the line, then switches to insert mode
7083  * to allow text to be appended to the line.
7084  */
KT_KEY_FN(gl_vi_append_at_eol)7085 static KT_KEY_FN(gl_vi_append_at_eol)
7086 {
7087   gl_save_for_undo(gl);
7088   gl->vi.command = 0;	/* Allow cursor at EOL */
7089   return gl_end_of_line(gl, 0, NULL) ||
7090          gl_vi_insert(gl, 0, NULL);
7091 }
7092 
7093 /*.......................................................................
7094  * This is the action function which implements the vi-style action which
7095  * moves the cursor to right one then switches to insert mode, thus
7096  * allowing text to be appended after the next character.
7097  */
KT_KEY_FN(gl_vi_append)7098 static KT_KEY_FN(gl_vi_append)
7099 {
7100   gl_save_for_undo(gl);
7101   gl->vi.command = 0;	/* Allow cursor at EOL */
7102   return gl_cursor_right(gl, 1, NULL) ||
7103          gl_vi_insert(gl, 0, NULL);
7104 }
7105 
7106 /*.......................................................................
7107  * This action function moves the cursor to the column specified by the
7108  * numeric argument. Column indexes start at 1.
7109  */
KT_KEY_FN(gl_goto_column)7110 static KT_KEY_FN(gl_goto_column)
7111 {
7112   return gl_place_cursor(gl, count - 1);
7113 }
7114 
7115 /*.......................................................................
7116  * Starting with the character under the cursor, replace 'count'
7117  * characters with the next character that the user types.
7118  */
KT_KEY_FN(gl_vi_replace_char)7119 static KT_KEY_FN(gl_vi_replace_char)
7120 {
7121   char c;  /* The replacement character */
7122   int i;
7123 /*
7124  * Keep a record of the current insert mode.
7125  */
7126   int insert = gl->insert;
7127 /*
7128  * Get the replacement character.
7129  */
7130   if(gl->vi.repeat.active) {
7131     c = gl->vi.repeat.input_char;
7132   } else {
7133     if(gl_read_terminal(gl, 1, &c))
7134       return 1;
7135     gl->vi.repeat.input_char = c;
7136   };
7137 /*
7138  * Are there 'count' characters to be replaced?
7139  */
7140   if(gl->ntotal - gl->buff_curpos >= count) {
7141 /*
7142  * If in vi command mode, preserve the current line for potential
7143  * use by vi-undo.
7144  */
7145     gl_save_for_undo(gl);
7146 /*
7147  * Temporarily switch to overwrite mode.
7148  */
7149     gl->insert = 0;
7150 /*
7151  * Overwrite the current character plus count-1 subsequent characters
7152  * with the replacement character.
7153  */
7154     for(i=0; i<count; i++)
7155       gl_add_char_to_line(gl, c);
7156 /*
7157  * Restore the original insert/overwrite mode.
7158  */
7159     gl->insert = insert;
7160   };
7161   return gl_place_cursor(gl, gl->buff_curpos);	/* bounds check */
7162 }
7163 
7164 /*.......................................................................
7165  * This is an action function which changes all characters between the
7166  * current cursor position and the end of the line.
7167  */
KT_KEY_FN(gl_vi_change_rest_of_line)7168 static KT_KEY_FN(gl_vi_change_rest_of_line)
7169 {
7170   gl_save_for_undo(gl);
7171   gl->vi.command = 0;	/* Allow cursor at EOL */
7172   return gl_kill_line(gl, count, NULL) || gl_vi_insert(gl, 0, NULL);
7173 }
7174 
7175 /*.......................................................................
7176  * This is an action function which changes all characters between the
7177  * start of the line and the current cursor position.
7178  */
KT_KEY_FN(gl_vi_change_to_bol)7179 static KT_KEY_FN(gl_vi_change_to_bol)
7180 {
7181   return gl_backward_kill_line(gl,count,NULL) || gl_vi_insert(gl,0,NULL);
7182 }
7183 
7184 /*.......................................................................
7185  * This is an action function which deletes the entire contents of the
7186  * current line and switches to insert mode.
7187  */
KT_KEY_FN(gl_vi_change_line)7188 static KT_KEY_FN(gl_vi_change_line)
7189 {
7190   return gl_delete_line(gl,count,NULL) || gl_vi_insert(gl,0,NULL);
7191 }
7192 
7193 /*.......................................................................
7194  * Starting from the cursor position and looking towards the end of the
7195  * line, copy 'count' characters to the cut buffer.
7196  */
KT_KEY_FN(gl_forward_copy_char)7197 static KT_KEY_FN(gl_forward_copy_char)
7198 {
7199 /*
7200  * Limit the count to the number of characters available.
7201  */
7202   if(gl->buff_curpos + count >= gl->ntotal)
7203     count = gl->ntotal - gl->buff_curpos;
7204   if(count < 0)
7205     count = 0;
7206 /*
7207  * Copy the characters to the cut buffer.
7208  */
7209   memcpy(gl->cutbuf, gl->line + gl->buff_curpos, count);
7210   gl->cutbuf[count] = '\0';
7211   return 0;
7212 }
7213 
7214 /*.......................................................................
7215  * Starting from the character before the cursor position and looking
7216  * backwards towards the start of the line, copy 'count' characters to
7217  * the cut buffer.
7218  */
KT_KEY_FN(gl_backward_copy_char)7219 static KT_KEY_FN(gl_backward_copy_char)
7220 {
7221 /*
7222  * Limit the count to the number of characters available.
7223  */
7224   if(count > gl->buff_curpos)
7225     count = gl->buff_curpos;
7226   if(count < 0)
7227     count = 0;
7228   gl_place_cursor(gl, gl->buff_curpos - count);
7229 /*
7230  * Copy the characters to the cut buffer.
7231  */
7232   memcpy(gl->cutbuf, gl->line + gl->buff_curpos, count);
7233   gl->cutbuf[count] = '\0';
7234   return 0;
7235 }
7236 
7237 /*.......................................................................
7238  * Starting from the cursor position copy to the specified column into the
7239  * cut buffer.
7240  */
KT_KEY_FN(gl_copy_to_column)7241 static KT_KEY_FN(gl_copy_to_column)
7242 {
7243   if (--count >= gl->buff_curpos)
7244     return gl_forward_copy_char(gl, count - gl->buff_curpos, NULL);
7245   else
7246     return gl_backward_copy_char(gl, gl->buff_curpos - count, NULL);
7247 }
7248 
7249 /*.......................................................................
7250  * Starting from the cursor position copy characters up to a matching
7251  * parenthesis into the cut buffer.
7252  */
KT_KEY_FN(gl_copy_to_parenthesis)7253 static KT_KEY_FN(gl_copy_to_parenthesis)
7254 {
7255   int curpos = gl_index_of_matching_paren(gl);
7256   if(curpos >= 0) {
7257     gl_save_for_undo(gl);
7258     if(curpos >= gl->buff_curpos)
7259       return gl_forward_copy_char(gl, curpos - gl->buff_curpos + 1, NULL);
7260     else
7261       return gl_backward_copy_char(gl, ++gl->buff_curpos - curpos + 1, NULL);
7262   };
7263   return 0;
7264 }
7265 
7266 /*.......................................................................
7267  * Starting from the cursor position copy the rest of the line into the
7268  * cut buffer.
7269  */
KT_KEY_FN(gl_copy_rest_of_line)7270 static KT_KEY_FN(gl_copy_rest_of_line)
7271 {
7272 /*
7273  * Copy the characters to the cut buffer.
7274  */
7275   memcpy(gl->cutbuf, gl->line + gl->buff_curpos, gl->ntotal - gl->buff_curpos);
7276   gl->cutbuf[gl->ntotal - gl->buff_curpos] = '\0';
7277   return 0;
7278 }
7279 
7280 /*.......................................................................
7281  * Copy from the beginning of the line to the cursor position into the
7282  * cut buffer.
7283  */
KT_KEY_FN(gl_copy_to_bol)7284 static KT_KEY_FN(gl_copy_to_bol)
7285 {
7286 /*
7287  * Copy the characters to the cut buffer.
7288  */
7289   memcpy(gl->cutbuf, gl->line, gl->buff_curpos);
7290   gl->cutbuf[gl->buff_curpos] = '\0';
7291   gl_place_cursor(gl, 0);
7292   return 0;
7293 }
7294 
7295 /*.......................................................................
7296  * Copy the entire line into the cut buffer.
7297  */
KT_KEY_FN(gl_copy_line)7298 static KT_KEY_FN(gl_copy_line)
7299 {
7300 /*
7301  * Copy the characters to the cut buffer.
7302  */
7303   memcpy(gl->cutbuf, gl->line, gl->ntotal);
7304   gl->cutbuf[gl->ntotal] = '\0';
7305   return 0;
7306 }
7307 
7308 /*.......................................................................
7309  * Search forwards for the next character that the user enters.
7310  */
KT_KEY_FN(gl_forward_find_char)7311 static KT_KEY_FN(gl_forward_find_char)
7312 {
7313   int pos = gl_find_char(gl, count, 1, 1, '\0');
7314   return pos >= 0 && gl_place_cursor(gl, pos);
7315 }
7316 
7317 /*.......................................................................
7318  * Search backwards for the next character that the user enters.
7319  */
KT_KEY_FN(gl_backward_find_char)7320 static KT_KEY_FN(gl_backward_find_char)
7321 {
7322   int pos = gl_find_char(gl, count, 0, 1, '\0');
7323   return pos >= 0 && gl_place_cursor(gl, pos);
7324 }
7325 
7326 /*.......................................................................
7327  * Search forwards for the next character that the user enters. Move up to,
7328  * but not onto, the found character.
7329  */
KT_KEY_FN(gl_forward_to_char)7330 static KT_KEY_FN(gl_forward_to_char)
7331 {
7332   int pos = gl_find_char(gl, count, 1, 0, '\0');
7333   return pos >= 0 && gl_place_cursor(gl, pos);
7334 }
7335 
7336 /*.......................................................................
7337  * Search backwards for the next character that the user enters. Move back to,
7338  * but not onto, the found character.
7339  */
KT_KEY_FN(gl_backward_to_char)7340 static KT_KEY_FN(gl_backward_to_char)
7341 {
7342   int pos = gl_find_char(gl, count, 0, 0, '\0');
7343   return pos >= 0 && gl_place_cursor(gl, pos);
7344 }
7345 
7346 /*.......................................................................
7347  * Searching in a given direction, return the index of a given (or
7348  * read) character in the input line, or the character that precedes
7349  * it in the specified search direction. Return -1 if not found.
7350  *
7351  * Input:
7352  *  gl       GetLine *  The getline resource object.
7353  *  count        int    The number of times to search.
7354  *  forward      int    True if searching forward.
7355  *  onto         int    True if the search should end on top of the
7356  *                      character, false if the search should stop
7357  *                      one character before the character in the
7358  *                      specified search direction.
7359  *  c           char    The character to be sought, or '\0' if the
7360  *                      character should be read from the user.
7361  * Output:
7362  *  return       int    The index of the character in gl->line[], or
7363  *                      -1 if not found.
7364  */
gl_find_char(GetLine * gl,int count,int forward,int onto,char c)7365 static int gl_find_char(GetLine *gl, int count, int forward, int onto, char c)
7366 {
7367   int pos;     /* The index reached in searching the input line */
7368   int i;
7369 /*
7370  * Get a character from the user?
7371  */
7372   if(!c) {
7373 /*
7374  * If we are in the process of repeating a previous change command, substitute
7375  * the last find character.
7376  */
7377     if(gl->vi.repeat.active) {
7378       c = gl->vi.find_char;
7379     } else {
7380       if(gl_read_terminal(gl, 1, &c))
7381 	return -1;
7382 /*
7383  * Record the details of the new search, for use by repeat finds.
7384  */
7385       gl->vi.find_forward = forward;
7386       gl->vi.find_onto = onto;
7387       gl->vi.find_char = c;
7388     };
7389   };
7390 /*
7391  * Which direction should we search?
7392  */
7393   if(forward) {
7394 /*
7395  * Search forwards 'count' times for the character, starting with the
7396  * character that follows the cursor.
7397  */
7398     for(i=0, pos=gl->buff_curpos; i<count && pos < gl->ntotal; i++) {
7399 /*
7400  * Advance past the last match (or past the current cursor position
7401  * on the first search).
7402  */
7403       pos++;
7404 /*
7405  * Search for the next instance of c.
7406  */
7407       for( ; pos<gl->ntotal && c!=gl->line[pos]; pos++)
7408 	;
7409     };
7410 /*
7411  * If the character was found and we have been requested to return the
7412  * position of the character that precedes the desired character, then
7413  * we have gone one character too far.
7414  */
7415     if(!onto && pos<gl->ntotal)
7416       pos--;
7417   } else {
7418 /*
7419  * Search backwards 'count' times for the character, starting with the
7420  * character that precedes the cursor.
7421  */
7422     for(i=0, pos=gl->buff_curpos; i<count && pos >= gl->insert_curpos; i++) {
7423 /*
7424  * Step back one from the last match (or from the current cursor
7425  * position on the first search).
7426  */
7427       pos--;
7428 /*
7429  * Search for the next instance of c.
7430  */
7431       for( ; pos>=gl->insert_curpos && c!=gl->line[pos]; pos--)
7432 	;
7433     };
7434 /*
7435  * If the character was found and we have been requested to return the
7436  * position of the character that precedes the desired character, then
7437  * we have gone one character too far.
7438  */
7439     if(!onto && pos>=gl->insert_curpos)
7440       pos++;
7441   };
7442 /*
7443  * If found, return the cursor position of the count'th match.
7444  * Otherwise ring the terminal bell.
7445  */
7446   if(pos >= gl->insert_curpos && pos < gl->ntotal) {
7447     return pos;
7448   } else {
7449     (void) gl_ring_bell(gl, 1, NULL);
7450     return -1;
7451   }
7452 }
7453 
7454 /*.......................................................................
7455  * Repeat the last character search in the same direction as the last
7456  * search.
7457  */
KT_KEY_FN(gl_repeat_find_char)7458 static KT_KEY_FN(gl_repeat_find_char)
7459 {
7460   int pos = gl->vi.find_char ?
7461     gl_find_char(gl, count, gl->vi.find_forward, gl->vi.find_onto,
7462 		 gl->vi.find_char) : -1;
7463   return pos >= 0 && gl_place_cursor(gl, pos);
7464 }
7465 
7466 /*.......................................................................
7467  * Repeat the last character search in the opposite direction as the last
7468  * search.
7469  */
KT_KEY_FN(gl_invert_refind_char)7470 static KT_KEY_FN(gl_invert_refind_char)
7471 {
7472   int pos = gl->vi.find_char ?
7473     gl_find_char(gl, count, !gl->vi.find_forward, gl->vi.find_onto,
7474 		 gl->vi.find_char) : -1;
7475   return pos >= 0 && gl_place_cursor(gl, pos);
7476 }
7477 
7478 /*.......................................................................
7479  * Search forward from the current position of the cursor for 'count'
7480  * word endings, returning the index of the last one found, or the end of
7481  * the line if there were less than 'count' words.
7482  *
7483  * Input:
7484  *  gl       GetLine *  The getline resource object.
7485  *  n            int    The number of word boundaries to search for.
7486  * Output:
7487  *  return       int    The buffer index of the located position.
7488  */
gl_nth_word_end_forward(GetLine * gl,int n)7489 static int gl_nth_word_end_forward(GetLine *gl, int n)
7490 {
7491   int bufpos;   /* The buffer index being checked. */
7492   int i;
7493 /*
7494  * In order to guarantee forward motion to the next word ending,
7495  * we need to start from one position to the right of the cursor
7496  * position, since this may already be at the end of a word.
7497  */
7498   bufpos = gl->buff_curpos + 1;
7499 /*
7500  * If we are at the end of the line, return the index of the last
7501  * real character on the line. Note that this will be -1 if the line
7502  * is empty.
7503  */
7504   if(bufpos >= gl->ntotal)
7505     return gl->ntotal - 1;
7506 /*
7507  * Search 'n' times, unless the end of the input line is reached first.
7508  */
7509   for(i=0; i<n && bufpos<gl->ntotal; i++) {
7510 /*
7511  * If we are not already within a word, skip to the start of the next word.
7512  */
7513     for( ; bufpos<gl->ntotal && !gl_is_word_char((int)gl->line[bufpos]);
7514 	bufpos++)
7515       ;
7516 /*
7517  * Find the end of the next word.
7518  */
7519     for( ; bufpos<gl->ntotal && gl_is_word_char((int)gl->line[bufpos]);
7520 	bufpos++)
7521       ;
7522   };
7523 /*
7524  * We will have overshot.
7525  */
7526   return bufpos > 0 ? bufpos-1 : bufpos;
7527 }
7528 
7529 /*.......................................................................
7530  * Search forward from the current position of the cursor for 'count'
7531  * word starts, returning the index of the last one found, or the end of
7532  * the line if there were less than 'count' words.
7533  *
7534  * Input:
7535  *  gl       GetLine *  The getline resource object.
7536  *  n            int    The number of word boundaries to search for.
7537  * Output:
7538  *  return       int    The buffer index of the located position.
7539  */
gl_nth_word_start_forward(GetLine * gl,int n)7540 static int gl_nth_word_start_forward(GetLine *gl, int n)
7541 {
7542   int bufpos;   /* The buffer index being checked. */
7543   int i;
7544 /*
7545  * Get the current cursor position.
7546  */
7547   bufpos = gl->buff_curpos;
7548 /*
7549  * Search 'n' times, unless the end of the input line is reached first.
7550  */
7551   for(i=0; i<n && bufpos<gl->ntotal; i++) {
7552 /*
7553  * Find the end of the current word.
7554  */
7555     for( ; bufpos<gl->ntotal && gl_is_word_char((int)gl->line[bufpos]);
7556 	bufpos++)
7557       ;
7558 /*
7559  * Skip to the start of the next word.
7560  */
7561     for( ; bufpos<gl->ntotal && !gl_is_word_char((int)gl->line[bufpos]);
7562 	bufpos++)
7563       ;
7564   };
7565   return bufpos;
7566 }
7567 
7568 /*.......................................................................
7569  * Search backward from the current position of the cursor for 'count'
7570  * word starts, returning the index of the last one found, or the start
7571  * of the line if there were less than 'count' words.
7572  *
7573  * Input:
7574  *  gl       GetLine *  The getline resource object.
7575  *  n            int    The number of word boundaries to search for.
7576  * Output:
7577  *  return       int    The buffer index of the located position.
7578  */
gl_nth_word_start_backward(GetLine * gl,int n)7579 static int gl_nth_word_start_backward(GetLine *gl, int n)
7580 {
7581   int bufpos;   /* The buffer index being checked. */
7582   int i;
7583 /*
7584  * Get the current cursor position.
7585  */
7586   bufpos = gl->buff_curpos;
7587 /*
7588  * Search 'n' times, unless the beginning of the input line (or vi insertion
7589  * point) is reached first.
7590  */
7591   for(i=0; i<n && bufpos > gl->insert_curpos; i++) {
7592 /*
7593  * Starting one character back from the last search, so as not to keep
7594  * settling on the same word-start, search backwards until finding a
7595  * word character.
7596  */
7597     while(--bufpos >= gl->insert_curpos &&
7598           !gl_is_word_char((int)gl->line[bufpos]))
7599       ;
7600 /*
7601  * Find the start of the word.
7602  */
7603     while(--bufpos >= gl->insert_curpos &&
7604           gl_is_word_char((int)gl->line[bufpos]))
7605       ;
7606 /*
7607  * We will have gone one character too far.
7608  */
7609     bufpos++;
7610   };
7611   return bufpos >= gl->insert_curpos ? bufpos : gl->insert_curpos;
7612 }
7613 
7614 /*.......................................................................
7615  * Copy one or more words into the cut buffer without moving the cursor
7616  * or deleting text.
7617  */
KT_KEY_FN(gl_forward_copy_word)7618 static KT_KEY_FN(gl_forward_copy_word)
7619 {
7620 /*
7621  * Find the location of the count'th start or end of a word
7622  * after the cursor, depending on whether in emacs or vi mode.
7623  */
7624   int next = gl->editor == GL_EMACS_MODE ?
7625     gl_nth_word_end_forward(gl, count) :
7626     gl_nth_word_start_forward(gl, count);
7627 /*
7628  * How many characters are to be copied into the cut buffer?
7629  */
7630   int n = next - gl->buff_curpos;
7631 /*
7632  * Copy the specified segment and terminate the string.
7633  */
7634   memcpy(gl->cutbuf, gl->line + gl->buff_curpos, n);
7635   gl->cutbuf[n] = '\0';
7636   return 0;
7637 }
7638 
7639 /*.......................................................................
7640  * Copy one or more words preceding the cursor into the cut buffer,
7641  * without moving the cursor or deleting text.
7642  */
KT_KEY_FN(gl_backward_copy_word)7643 static KT_KEY_FN(gl_backward_copy_word)
7644 {
7645 /*
7646  * Find the location of the count'th start of word before the cursor.
7647  */
7648   int next = gl_nth_word_start_backward(gl, count);
7649 /*
7650  * How many characters are to be copied into the cut buffer?
7651  */
7652   int n = gl->buff_curpos - next;
7653   gl_place_cursor(gl, next);
7654 /*
7655  * Copy the specified segment and terminate the string.
7656  */
7657   memcpy(gl->cutbuf, gl->line + next, n);
7658   gl->cutbuf[n] = '\0';
7659   return 0;
7660 }
7661 
7662 /*.......................................................................
7663  * Copy the characters between the cursor and the count'th instance of
7664  * a specified character in the input line, into the cut buffer.
7665  *
7666  * Input:
7667  *  gl       GetLine *  The getline resource object.
7668  *  count        int    The number of times to search.
7669  *  c           char    The character to be searched for, or '\0' if
7670  *                      the character should be read from the user.
7671  *  forward      int    True if searching forward.
7672  *  onto         int    True if the search should end on top of the
7673  *                      character, false if the search should stop
7674  *                      one character before the character in the
7675  *                      specified search direction.
7676  * Output:
7677  *  return       int    0 - OK.
7678  *                      1 - Error.
7679  *
7680  */
gl_copy_find(GetLine * gl,int count,char c,int forward,int onto)7681 static int gl_copy_find(GetLine *gl, int count, char c, int forward, int onto)
7682 {
7683   int n;  /* The number of characters in the cut buffer */
7684 /*
7685  * Search for the character, and abort the operation if not found.
7686  */
7687   int pos = gl_find_char(gl, count, forward, onto, c);
7688   if(pos < 0)
7689     return 0;
7690 /*
7691  * Copy the specified segment.
7692  */
7693   if(forward) {
7694     n = pos + 1 - gl->buff_curpos;
7695     memcpy(gl->cutbuf, gl->line + gl->buff_curpos, n);
7696   } else {
7697     n = gl->buff_curpos - pos;
7698     memcpy(gl->cutbuf, gl->line + pos, n);
7699     if(gl->editor == GL_VI_MODE)
7700       gl_place_cursor(gl, pos);
7701   }
7702 /*
7703  * Terminate the copy.
7704  */
7705   gl->cutbuf[n] = '\0';
7706   return 0;
7707 }
7708 
7709 /*.......................................................................
7710  * Copy a section up to and including a specified character into the cut
7711  * buffer without moving the cursor or deleting text.
7712  */
KT_KEY_FN(gl_forward_copy_find)7713 static KT_KEY_FN(gl_forward_copy_find)
7714 {
7715   return gl_copy_find(gl, count, '\0', 1, 1);
7716 }
7717 
7718 /*.......................................................................
7719  * Copy a section back to and including a specified character into the cut
7720  * buffer without moving the cursor or deleting text.
7721  */
KT_KEY_FN(gl_backward_copy_find)7722 static KT_KEY_FN(gl_backward_copy_find)
7723 {
7724   return gl_copy_find(gl, count, '\0', 0, 1);
7725 }
7726 
7727 /*.......................................................................
7728  * Copy a section up to and not including a specified character into the cut
7729  * buffer without moving the cursor or deleting text.
7730  */
KT_KEY_FN(gl_forward_copy_to)7731 static KT_KEY_FN(gl_forward_copy_to)
7732 {
7733   return gl_copy_find(gl, count, '\0', 1, 0);
7734 }
7735 
7736 /*.......................................................................
7737  * Copy a section back to and not including a specified character into the cut
7738  * buffer without moving the cursor or deleting text.
7739  */
KT_KEY_FN(gl_backward_copy_to)7740 static KT_KEY_FN(gl_backward_copy_to)
7741 {
7742   return gl_copy_find(gl, count, '\0', 0, 0);
7743 }
7744 
7745 /*.......................................................................
7746  * Copy to a character specified in a previous search into the cut
7747  * buffer without moving the cursor or deleting text.
7748  */
KT_KEY_FN(gl_copy_refind)7749 static KT_KEY_FN(gl_copy_refind)
7750 {
7751   return gl_copy_find(gl, count, gl->vi.find_char, gl->vi.find_forward,
7752 		      gl->vi.find_onto);
7753 }
7754 
7755 /*.......................................................................
7756  * Copy to a character specified in a previous search, but in the opposite
7757  * direction, into the cut buffer without moving the cursor or deleting text.
7758  */
KT_KEY_FN(gl_copy_invert_refind)7759 static KT_KEY_FN(gl_copy_invert_refind)
7760 {
7761   return gl_copy_find(gl, count, gl->vi.find_char, !gl->vi.find_forward,
7762 		      gl->vi.find_onto);
7763 }
7764 
7765 /*.......................................................................
7766  * Set the position of the cursor in the line input buffer and the
7767  * terminal.
7768  *
7769  * Input:
7770  *  gl       GetLine *  The getline resource object.
7771  *  buff_curpos  int    The new buffer cursor position.
7772  * Output:
7773  *  return       int    0 - OK.
7774  *                      1 - Error.
7775  */
gl_place_cursor(GetLine * gl,int buff_curpos)7776 static int gl_place_cursor(GetLine *gl, int buff_curpos)
7777 {
7778 /*
7779  * Don't allow the cursor position to go out of the bounds of the input
7780  * line.
7781  */
7782   if(buff_curpos >= gl->ntotal)
7783     buff_curpos = gl->vi.command ? gl->ntotal-1 : gl->ntotal;
7784   if(buff_curpos < 0)
7785     buff_curpos = 0;
7786 /*
7787  * Record the new buffer position.
7788  */
7789   gl->buff_curpos = buff_curpos;
7790 /*
7791  * Move the terminal cursor to the corresponding character.
7792  */
7793   return gl_set_term_curpos(gl, gl->prompt_len +
7794     gl_displayed_string_width(gl, gl->line, buff_curpos, gl->prompt_len));
7795 }
7796 
7797 /*.......................................................................
7798  * In vi command mode, this function saves the current line to the
7799  * historical buffer needed by the undo command. In emacs mode it does
7800  * nothing. In order to allow action functions to call other action
7801  * functions, gl_interpret_char() sets gl->vi.undo.saved to 0 before
7802  * invoking an action, and thereafter once any call to this function
7803  * has set it to 1, further calls are ignored.
7804  *
7805  * Input:
7806  *  gl       GetLine *  The getline resource object.
7807  */
gl_save_for_undo(GetLine * gl)7808 static void gl_save_for_undo(GetLine *gl)
7809 {
7810   if(gl->vi.command && !gl->vi.undo.saved) {
7811     strlcpy(gl->vi.undo.line, gl->line, gl->linelen);
7812     gl->vi.undo.buff_curpos = gl->buff_curpos;
7813     gl->vi.undo.ntotal = gl->ntotal;
7814     gl->vi.undo.saved = 1;
7815   };
7816   if(gl->vi.command && !gl->vi.repeat.saved &&
7817      gl->current_action.fn != gl_vi_repeat_change) {
7818     gl->vi.repeat.action = gl->current_action;
7819     gl->vi.repeat.count = gl->current_count;
7820     gl->vi.repeat.saved = 1;
7821   };
7822   return;
7823 }
7824 
7825 /*.......................................................................
7826  * In vi mode, restore the line to the way it was before the last command
7827  * mode operation, storing the current line in the buffer so that the
7828  * undo operation itself can subsequently be undone.
7829  */
KT_KEY_FN(gl_vi_undo)7830 static KT_KEY_FN(gl_vi_undo)
7831 {
7832 /*
7833  * Get pointers into the two lines.
7834  */
7835   char *undo_ptr = gl->vi.undo.line;
7836   char *line_ptr = gl->line;
7837 /*
7838  * Swap the characters of the two buffers up to the length of the shortest
7839  * line.
7840  */
7841   while(*undo_ptr && *line_ptr) {
7842     char c = *undo_ptr;
7843     *undo_ptr++ = *line_ptr;
7844     *line_ptr++ = c;
7845   };
7846 /*
7847  * Copy the rest directly.
7848  */
7849   if(gl->ntotal > gl->vi.undo.ntotal) {
7850     strlcpy(undo_ptr, line_ptr, gl->linelen);
7851     *line_ptr = '\0';
7852   } else {
7853     strlcpy(line_ptr, undo_ptr, gl->linelen);
7854     *undo_ptr = '\0';
7855   };
7856 /*
7857  * Record the length of the stored string.
7858  */
7859   gl->vi.undo.ntotal = gl->ntotal;
7860 /*
7861  * Accomodate the new contents of gl->line[].
7862  */
7863   gl_update_buffer(gl);
7864 /*
7865  * Set both cursor positions to the leftmost of the saved and current
7866  * cursor positions to emulate what vi does.
7867  */
7868   if(gl->buff_curpos < gl->vi.undo.buff_curpos)
7869     gl->vi.undo.buff_curpos = gl->buff_curpos;
7870   else
7871     gl->buff_curpos = gl->vi.undo.buff_curpos;
7872 /*
7873  * Since we have bipassed calling gl_save_for_undo(), record repeat
7874  * information inline.
7875  */
7876   gl->vi.repeat.action.fn = gl_vi_undo;
7877   gl->vi.repeat.action.data = NULL;
7878   gl->vi.repeat.count = 1;
7879 /*
7880  * Display the restored line.
7881  */
7882   gl_queue_redisplay(gl);
7883   return 0;
7884 }
7885 
7886 /*.......................................................................
7887  * Delete the following word and leave the user in vi insert mode.
7888  */
KT_KEY_FN(gl_vi_forward_change_word)7889 static KT_KEY_FN(gl_vi_forward_change_word)
7890 {
7891   gl_save_for_undo(gl);
7892   gl->vi.command = 0;	/* Allow cursor at EOL */
7893   return gl_forward_delete_word(gl, count, NULL) || gl_vi_insert(gl, 0, NULL);
7894 }
7895 
7896 /*.......................................................................
7897  * Delete the preceding word and leave the user in vi insert mode.
7898  */
KT_KEY_FN(gl_vi_backward_change_word)7899 static KT_KEY_FN(gl_vi_backward_change_word)
7900 {
7901   return gl_backward_delete_word(gl, count, NULL) || gl_vi_insert(gl, 0, NULL);
7902 }
7903 
7904 /*.......................................................................
7905  * Delete the following section and leave the user in vi insert mode.
7906  */
KT_KEY_FN(gl_vi_forward_change_find)7907 static KT_KEY_FN(gl_vi_forward_change_find)
7908 {
7909   return gl_delete_find(gl, count, '\0', 1, 1, 1);
7910 }
7911 
7912 /*.......................................................................
7913  * Delete the preceding section and leave the user in vi insert mode.
7914  */
KT_KEY_FN(gl_vi_backward_change_find)7915 static KT_KEY_FN(gl_vi_backward_change_find)
7916 {
7917   return gl_delete_find(gl, count, '\0', 0, 1, 1);
7918 }
7919 
7920 /*.......................................................................
7921  * Delete the following section and leave the user in vi insert mode.
7922  */
KT_KEY_FN(gl_vi_forward_change_to)7923 static KT_KEY_FN(gl_vi_forward_change_to)
7924 {
7925   return gl_delete_find(gl, count, '\0', 1, 0, 1);
7926 }
7927 
7928 /*.......................................................................
7929  * Delete the preceding section and leave the user in vi insert mode.
7930  */
KT_KEY_FN(gl_vi_backward_change_to)7931 static KT_KEY_FN(gl_vi_backward_change_to)
7932 {
7933   return gl_delete_find(gl, count, '\0', 0, 0, 1);
7934 }
7935 
7936 /*.......................................................................
7937  * Delete to a character specified by a previous search and leave the user
7938  * in vi insert mode.
7939  */
KT_KEY_FN(gl_vi_change_refind)7940 static KT_KEY_FN(gl_vi_change_refind)
7941 {
7942   return gl_delete_find(gl, count, gl->vi.find_char, gl->vi.find_forward,
7943 			gl->vi.find_onto, 1);
7944 }
7945 
7946 /*.......................................................................
7947  * Delete to a character specified by a previous search, but in the opposite
7948  * direction, and leave the user in vi insert mode.
7949  */
KT_KEY_FN(gl_vi_change_invert_refind)7950 static KT_KEY_FN(gl_vi_change_invert_refind)
7951 {
7952   return gl_delete_find(gl, count, gl->vi.find_char, !gl->vi.find_forward,
7953 			gl->vi.find_onto, 1);
7954 }
7955 
7956 /*.......................................................................
7957  * Delete the following character and leave the user in vi insert mode.
7958  */
KT_KEY_FN(gl_vi_forward_change_char)7959 static KT_KEY_FN(gl_vi_forward_change_char)
7960 {
7961   gl_save_for_undo(gl);
7962   gl->vi.command = 0;	/* Allow cursor at EOL */
7963   return gl_delete_chars(gl, count, 1) || gl_vi_insert(gl, 0, NULL);
7964 }
7965 
7966 /*.......................................................................
7967  * Delete the preceding character and leave the user in vi insert mode.
7968  */
KT_KEY_FN(gl_vi_backward_change_char)7969 static KT_KEY_FN(gl_vi_backward_change_char)
7970 {
7971   return gl_backward_delete_char(gl, count, NULL) || gl_vi_insert(gl, 0, NULL);
7972 }
7973 
7974 /*.......................................................................
7975  * Starting from the cursor position change characters to the specified column.
7976  */
KT_KEY_FN(gl_vi_change_to_column)7977 static KT_KEY_FN(gl_vi_change_to_column)
7978 {
7979   if (--count >= gl->buff_curpos)
7980     return gl_vi_forward_change_char(gl, count - gl->buff_curpos, NULL);
7981   else
7982     return gl_vi_backward_change_char(gl, gl->buff_curpos - count, NULL);
7983 }
7984 
7985 /*.......................................................................
7986  * Starting from the cursor position change characters to a matching
7987  * parenthesis.
7988  */
KT_KEY_FN(gl_vi_change_to_parenthesis)7989 static KT_KEY_FN(gl_vi_change_to_parenthesis)
7990 {
7991   int curpos = gl_index_of_matching_paren(gl);
7992   if(curpos >= 0) {
7993     gl_save_for_undo(gl);
7994     if(curpos >= gl->buff_curpos)
7995       return gl_vi_forward_change_char(gl, curpos - gl->buff_curpos + 1, NULL);
7996     else
7997       return gl_vi_backward_change_char(gl, ++gl->buff_curpos - curpos + 1,
7998 					NULL);
7999   };
8000   return 0;
8001 }
8002 
8003 /*.......................................................................
8004  * If in vi mode, switch to vi command mode.
8005  *
8006  * Input:
8007  *  gl       GetLine *  The getline resource object.
8008  */
gl_vi_command_mode(GetLine * gl)8009 static void gl_vi_command_mode(GetLine *gl)
8010 {
8011   if(gl->editor == GL_VI_MODE && !gl->vi.command) {
8012     gl->insert = 1;
8013     gl->vi.command = 1;
8014     gl->vi.repeat.input_curpos = gl->insert_curpos;
8015     gl->vi.repeat.command_curpos = gl->buff_curpos;
8016     gl->insert_curpos = 0;	 /* unrestrict left motion boundary */
8017     gl_cursor_left(gl, 1, NULL); /* Vi moves 1 left on entering command mode */
8018   };
8019 }
8020 
8021 /*.......................................................................
8022  * This is an action function which rings the terminal bell.
8023  */
KT_KEY_FN(gl_ring_bell)8024 static KT_KEY_FN(gl_ring_bell)
8025 {
8026   return gl->silence_bell ? 0 :
8027     gl_print_control_sequence(gl, 1, gl->sound_bell);
8028 }
8029 
8030 /*.......................................................................
8031  * This is the action function which implements the vi-repeat-change
8032  * action.
8033  */
KT_KEY_FN(gl_vi_repeat_change)8034 static KT_KEY_FN(gl_vi_repeat_change)
8035 {
8036   int status;   /* The return status of the repeated action function */
8037   int i;
8038 /*
8039  * Nothing to repeat?
8040  */
8041   if(!gl->vi.repeat.action.fn)
8042     return gl_ring_bell(gl, 1, NULL);
8043 /*
8044  * Provide a way for action functions to know whether they are being
8045  * called by us.
8046  */
8047   gl->vi.repeat.active = 1;
8048 /*
8049  * Re-run the recorded function.
8050  */
8051   status = gl->vi.repeat.action.fn(gl, gl->vi.repeat.count,
8052 				   gl->vi.repeat.action.data);
8053 /*
8054  * Mark the repeat as completed.
8055  */
8056   gl->vi.repeat.active = 0;
8057 /*
8058  * Is we are repeating a function that has just switched to input
8059  * mode to allow the user to type, re-enter the text that the user
8060  * previously entered.
8061  */
8062   if(status==0 && !gl->vi.command) {
8063 /*
8064  * Make sure that the current line has been saved.
8065  */
8066     gl_save_for_undo(gl);
8067 /*
8068  * Repeat a previous insertion or overwrite?
8069  */
8070     if(gl->vi.repeat.input_curpos >= 0 &&
8071        gl->vi.repeat.input_curpos <= gl->vi.repeat.command_curpos &&
8072        gl->vi.repeat.command_curpos <= gl->vi.undo.ntotal) {
8073 /*
8074  * Using the current line which is saved in the undo buffer, plus
8075  * the range of characters therein, as recorded by gl_vi_command_mode(),
8076  * add the characters that the user previously entered, to the input
8077  * line.
8078  */
8079       for(i=gl->vi.repeat.input_curpos; i<gl->vi.repeat.command_curpos; i++) {
8080 	if(gl_add_char_to_line(gl, gl->vi.undo.line[i]))
8081 	  return 1;
8082       };
8083     };
8084 /*
8085  * Switch back to command mode, now that the insertion has been repeated.
8086  */
8087     gl_vi_command_mode(gl);
8088   };
8089   return status;
8090 }
8091 
8092 /*.......................................................................
8093  * If the cursor is currently over a parenthesis character, return the
8094  * index of its matching parenthesis. If not currently over a parenthesis
8095  * character, return the next close parenthesis character to the right of
8096  * the cursor. If the respective parenthesis character isn't found,
8097  * ring the terminal bell and return -1.
8098  *
8099  * Input:
8100  *  gl       GetLine *  The getline resource object.
8101  * Output:
8102  *  return       int    Either the index of the matching parenthesis,
8103  *                      or -1 if not found.
8104  */
gl_index_of_matching_paren(GetLine * gl)8105 static int gl_index_of_matching_paren(GetLine *gl)
8106 {
8107   int i;
8108 /*
8109  * List the recognized parentheses, and their matches.
8110  */
8111   const char *o_paren = "([{";
8112   const char *c_paren = ")]}";
8113   const char *cptr;
8114 /*
8115  * Get the character that is currently under the cursor.
8116  */
8117   char c = gl->line[gl->buff_curpos];
8118 /*
8119  * If the character under the cursor is an open parenthesis, look forward
8120  * for the matching close parenthesis.
8121  */
8122   if((cptr=strchr(o_paren, c))) {
8123     char match = c_paren[cptr - o_paren];
8124     int matches_needed = 1;
8125     for(i=gl->buff_curpos+1; i<gl->ntotal; i++) {
8126       if(gl->line[i] == c)
8127 	matches_needed++;
8128       else if(gl->line[i] == match && --matches_needed==0)
8129 	return i;
8130     };
8131 /*
8132  * If the character under the cursor is an close parenthesis, look forward
8133  * for the matching open parenthesis.
8134  */
8135   } else if((cptr=strchr(c_paren, c))) {
8136     char match = o_paren[cptr - c_paren];
8137     int matches_needed = 1;
8138     for(i=gl->buff_curpos-1; i>=0; i--) {
8139       if(gl->line[i] == c)
8140 	matches_needed++;
8141       else if(gl->line[i] == match && --matches_needed==0)
8142 	return i;
8143     };
8144 /*
8145  * If not currently over a parenthesis character, search forwards for
8146  * the first close parenthesis (this is what the vi % binding does).
8147  */
8148   } else {
8149     for(i=gl->buff_curpos+1; i<gl->ntotal; i++)
8150       if(strchr(c_paren, gl->line[i]) != NULL)
8151 	return i;
8152   };
8153 /*
8154  * Not found.
8155  */
8156   (void) gl_ring_bell(gl, 1, NULL);
8157   return -1;
8158 }
8159 
8160 /*.......................................................................
8161  * If the cursor is currently over a parenthesis character, this action
8162  * function moves the cursor to its matching parenthesis.
8163  */
KT_KEY_FN(gl_find_parenthesis)8164 static KT_KEY_FN(gl_find_parenthesis)
8165 {
8166   int curpos = gl_index_of_matching_paren(gl);
8167   if(curpos >= 0)
8168     return gl_place_cursor(gl, curpos);
8169   return 0;
8170 }
8171 
8172 /*.......................................................................
8173  * Handle the receipt of the potential start of a new key-sequence from
8174  * the user.
8175  *
8176  * Input:
8177  *  gl      GetLine *   The resource object of this library.
8178  *  first_char char     The first character of the sequence.
8179  * Output:
8180  *  return      int     0 - OK.
8181  *                      1 - Error.
8182  */
gl_interpret_char(GetLine * gl,char first_char)8183 static int gl_interpret_char(GetLine *gl, char first_char)
8184 {
8185   char keyseq[GL_KEY_MAX+1]; /* A special key sequence being read */
8186   int nkey=0;                /* The number of characters in the key sequence */
8187   int count;                 /* The repeat count of an action function */
8188   int ret;                   /* The return value of an action function */
8189   int i;
8190 /*
8191  * Get the first character.
8192  */
8193   char c = first_char;
8194 /*
8195  * If editing is disabled, just add newly entered characters to the
8196  * input line buffer, and watch for the end of the line.
8197  */
8198   if(gl->editor == GL_NO_EDITOR) {
8199     gl_discard_chars(gl, 1);
8200     if(gl->ntotal >= gl->linelen)
8201       return 0;
8202     if(c == '\n' || c == '\r')
8203       return gl_newline(gl, 1, NULL);
8204     gl_buffer_char(gl, c, gl->ntotal);
8205     return 0;
8206   };
8207 /*
8208  * If the user is in the process of specifying a repeat count and the
8209  * new character is a digit, increment the repeat count accordingly.
8210  */
8211   if(gl->number >= 0 && isdigit((int)(unsigned char) c)) {
8212     gl_discard_chars(gl, 1);
8213     return gl_digit_argument(gl, c, NULL);
8214 /*
8215  * In vi command mode, all key-sequences entered need to be
8216  * either implicitly or explicitly prefixed with an escape character.
8217  */
8218   } else if(gl->vi.command && c != GL_ESC_CHAR) {
8219     keyseq[nkey++] = GL_ESC_CHAR;
8220 /*
8221  * If the first character of the sequence is a printable character,
8222  * then to avoid confusion with the special "up", "down", "left"
8223  * or "right" cursor key bindings, we need to prefix the
8224  * printable character with a backslash escape before looking it up.
8225  */
8226   } else if(!IS_META_CHAR(c) && !IS_CTRL_CHAR(c)) {
8227     keyseq[nkey++] = '\\';
8228   };
8229 /*
8230  * Compose a potentially multiple key-sequence in gl->keyseq.
8231  */
8232   while(nkey < GL_KEY_MAX) {
8233     KtAction *action; /* An action function */
8234     KeySym *keysym;   /* The symbol-table entry of a key-sequence */
8235     int nsym;         /* The number of ambiguously matching key-sequences */
8236 /*
8237  * If the character is an unprintable meta character, split it
8238  * into two characters, an escape character and the character
8239  * that was modified by the meta key.
8240  */
8241     if(IS_META_CHAR(c)) {
8242       keyseq[nkey++] = GL_ESC_CHAR;
8243       c = META_TO_CHAR(c);
8244       continue;
8245     };
8246 /*
8247  * Append the latest character to the key sequence.
8248  */
8249     keyseq[nkey++] = c;
8250 /*
8251  * When doing vi-style editing, an escape at the beginning of any binding
8252  * switches to command mode.
8253  */
8254     if(keyseq[0] == GL_ESC_CHAR && !gl->vi.command)
8255       gl_vi_command_mode(gl);
8256 /*
8257  * Lookup the key sequence.
8258  */
8259     switch(_kt_lookup_keybinding(gl->bindings, keyseq, nkey, &keysym, &nsym)) {
8260     case KT_EXACT_MATCH:
8261 /*
8262  * Get the matching action function.
8263  */
8264       action = keysym->actions + keysym->binder;
8265 /*
8266  * Get the repeat count, passing the last keystroke if executing the
8267  * digit-argument action.
8268  */
8269       if(action->fn == gl_digit_argument) {
8270 	count = c;
8271       } else {
8272 	count = gl->number >= 0 ? gl->number : 1;
8273       };
8274 /*
8275  * Record the function that is being invoked.
8276  */
8277       gl->current_action = *action;
8278       gl->current_count = count;
8279 /*
8280  * Mark the current line as not yet preserved for use by the vi undo command.
8281  */
8282       gl->vi.undo.saved = 0;
8283       gl->vi.repeat.saved = 0;
8284 /*
8285  * Execute the action function. Note the action function can tell
8286  * whether the provided repeat count was defaulted or specified
8287  * explicitly by looking at whether gl->number is -1 or not. If
8288  * it is negative, then no repeat count was specified by the user.
8289  */
8290       ret = action->fn(gl, count, action->data);
8291 /*
8292  * In server mode, the action will return immediately if it tries to
8293  * read input from the terminal, and no input is currently available.
8294  * If this happens, abort. Note that gl_get_input_line() will rewind
8295  * the read-ahead buffer to allow the next call to redo the function
8296  * from scratch.
8297  */
8298       if(gl->rtn_status == GLR_BLOCKED && gl->pending_io==GLP_READ)
8299 	return 1;
8300 /*
8301  * Discard the now processed characters from the key sequence buffer.
8302  */
8303       gl_discard_chars(gl, gl->nread);
8304 /*
8305  * If the latest action function wasn't a history action, cancel any
8306  * current history search.
8307  */
8308       if(gl->last_search != gl->keyseq_count)
8309 	_glh_cancel_search(gl->glh);
8310 /*
8311  * Reset the repeat count after running action functions.
8312  */
8313       if(action->fn != gl_digit_argument)
8314 	gl->number = -1;
8315       return ret ? 1 : 0;
8316       break;
8317     case KT_AMBIG_MATCH:    /* Ambiguous match - so read the next character */
8318       if(gl_read_terminal(gl, 1, &c))
8319 	return 1;
8320       break;
8321     case KT_NO_MATCH:
8322 /*
8323  * If the first character looked like it might be a prefix of a key-sequence
8324  * but it turned out not to be, ring the bell to tell the user that it
8325  * wasn't recognised.
8326  */
8327       if(keyseq[0] != '\\' && keyseq[0] != '\t') {
8328 	gl_ring_bell(gl, 1, NULL);
8329       } else {
8330 /*
8331  * The user typed a single printable character that doesn't match
8332  * the start of any keysequence, so add it to the line in accordance
8333  * with the current repeat count.
8334  */
8335 	count = gl->number >= 0 ? gl->number : 1;
8336 	for(i=0; i<count; i++)
8337 	  gl_add_char_to_line(gl, first_char);
8338 	gl->number = -1;
8339       };
8340       gl_discard_chars(gl, 1);
8341       _glh_cancel_search(gl->glh);
8342       return 0;
8343       break;
8344     case KT_BAD_MATCH:
8345       gl_ring_bell(gl, 1, NULL);
8346       gl_discard_chars(gl, gl->nread);
8347       _glh_cancel_search(gl->glh);
8348       return 1;
8349       break;
8350     };
8351   };
8352 /*
8353  * If the key sequence was too long to match, ring the bell, then
8354  * discard the first character, so that the next attempt to match a
8355  * key-sequence continues with the next key press. In practice this
8356  * shouldn't happen, since one isn't allowed to bind action functions
8357  * to keysequences that are longer than GL_KEY_MAX.
8358  */
8359   gl_ring_bell(gl, 1, NULL);
8360   gl_discard_chars(gl, 1);
8361   return 0;
8362 }
8363 
8364 /*.......................................................................
8365  * Configure the application and/or user-specific behavior of
8366  * gl_get_line().
8367  *
8368  * Note that calling this function between calling new_GetLine() and
8369  * the first call to gl_get_line(), disables the otherwise automatic
8370  * reading of ~/.teclarc on the first call to gl_get_line().
8371  *
8372  * Input:
8373  *  gl             GetLine *  The resource object of this library.
8374  *  app_string  const char *  Either NULL, or a string containing one
8375  *                            or more .teclarc command lines, separated
8376  *                            by newline characters. This can be used to
8377  *                            establish an application-specific
8378  *                            configuration, without the need for an external
8379  *                            file. This is particularly useful in embedded
8380  *                            environments where there is no filesystem.
8381  *  app_file    const char *  Either NULL, or the pathname of an
8382  *                            application-specific .teclarc file. The
8383  *                            contents of this file, if provided, are
8384  *                            read after the contents of app_string[].
8385  *  user_file   const char *  Either NULL, or the pathname of a
8386  *                            user-specific .teclarc file. Except in
8387  *                            embedded applications, this should
8388  *                            usually be "~/.teclarc".
8389  * Output:
8390  *  return             int    0 - OK.
8391  *                            1 - Bad argument(s).
8392  */
gl_configure_getline(GetLine * gl,const char * app_string,const char * app_file,const char * user_file)8393 int gl_configure_getline(GetLine *gl, const char *app_string,
8394 			 const char *app_file, const char *user_file)
8395 {
8396   sigset_t oldset; /* The signals that were blocked on entry to this function */
8397   int status;      /* The return status of _gl_configure_getline() */
8398 /*
8399  * Check the arguments.
8400  */
8401   if(!gl) {
8402     errno = EINVAL;
8403     return 1;
8404   };
8405 /*
8406  * Block all signals.
8407  */
8408   if(gl_mask_signals(gl, &oldset))
8409     return 1;
8410 /*
8411  * Execute the private body of the function while signals are blocked.
8412  */
8413   status = _gl_configure_getline(gl, app_string, app_file, user_file);
8414 /*
8415  * Restore the process signal mask.
8416  */
8417   gl_unmask_signals(gl, &oldset);
8418   return status;
8419 }
8420 
8421 /*.......................................................................
8422  * This is the private body of the gl_configure_getline() function. It
8423  * assumes that the caller has checked its arguments and blocked the
8424  * delivery of signals.
8425  */
_gl_configure_getline(GetLine * gl,const char * app_string,const char * app_file,const char * user_file)8426 static int _gl_configure_getline(GetLine *gl, const char *app_string,
8427 				 const char *app_file, const char *user_file)
8428 {
8429 /*
8430  * Mark getline as having been explicitly configured.
8431  */
8432   gl->configured = 1;
8433 /*
8434  * Start by parsing the configuration string, if provided.
8435  */
8436   if(app_string)
8437     (void) _gl_read_config_string(gl, app_string, KTB_NORM);
8438 /*
8439  * Now parse the application-specific configuration file, if provided.
8440  */
8441   if(app_file)
8442     (void) _gl_read_config_file(gl, app_file, KTB_NORM);
8443 /*
8444  * Finally, parse the user-specific configuration file, if provided.
8445  */
8446   if(user_file)
8447     (void) _gl_read_config_file(gl, user_file, KTB_USER);
8448 /*
8449  * Record the names of the configuration files to allow them to
8450  * be re-read if requested at a later time.
8451  */
8452   if(gl_record_string(&gl->app_file, app_file) ||
8453      gl_record_string(&gl->user_file, user_file)) {
8454     errno = ENOMEM;
8455     _err_record_msg(gl->err,
8456 	   "Insufficient memory to record tecla configuration file names",
8457 	   END_ERR_MSG);
8458     return 1;
8459   };
8460   return 0;
8461 }
8462 
8463 /*.......................................................................
8464  * Replace a malloc'd string (or NULL), with another malloc'd copy of
8465  * a string (or NULL).
8466  *
8467  * Input:
8468  *  sptr          char **  On input if *sptr!=NULL, *sptr will be
8469  *                         free'd and *sptr will be set to NULL. Then,
8470  *                         on output, if string!=NULL a malloc'd copy
8471  *                         of this string will be assigned to *sptr.
8472  *  string  const char *   The string to be copied, or NULL to simply
8473  *                         discard any existing string.
8474  * Output:
8475  *  return         int     0 - OK.
8476  *                         1 - Malloc failure (no error message is generated).
8477  */
gl_record_string(char ** sptr,const char * string)8478 static int gl_record_string(char **sptr, const char *string)
8479 {
8480 /*
8481  * If the original string is the same string, don't do anything.
8482  */
8483   if(*sptr == string || (*sptr && string && strcmp(*sptr, string)==0))
8484     return 0;
8485 /*
8486  * Discard any existing cached string.
8487  */
8488   if(*sptr) {
8489     free(*sptr);
8490     *sptr = NULL;
8491   };
8492 /*
8493  * Allocate memory for a copy of the specified string.
8494  */
8495   if(string) {
8496     size_t ssz = strlen(string) + 1;
8497     *sptr = (char *) malloc(ssz);
8498     if(!*sptr)
8499       return 1;
8500 /*
8501  * Copy the string.
8502  */
8503     strlcpy(*sptr, string, ssz);
8504   };
8505   return 0;
8506 }
8507 
8508 #ifndef HIDE_FILE_SYSTEM
8509 /*.......................................................................
8510  * Re-read any application-specific and user-specific files previously
8511  * specified via the gl_configure_getline() function.
8512  */
KT_KEY_FN(gl_read_init_files)8513 static KT_KEY_FN(gl_read_init_files)
8514 {
8515   return _gl_configure_getline(gl, NULL, gl->app_file, gl->user_file);
8516 }
8517 #endif
8518 
8519 /*.......................................................................
8520  * Save the contents of the history buffer to a given new file.
8521  *
8522  * Input:
8523  *  gl             GetLine *  The resource object of this library.
8524  *  filename    const char *  The name of the new file to write to.
8525  *  comment     const char *  Extra information such as timestamps will
8526  *                            be recorded on a line started with this
8527  *                            string, the idea being that the file can
8528  *                            double as a command file. Specify "" if
8529  *                            you don't care.
8530  *  max_lines          int    The maximum number of lines to save, or -1
8531  *                            to save all of the lines in the history
8532  *                            list.
8533  * Output:
8534  *  return             int     0 - OK.
8535  *                             1 - Error.
8536  */
gl_save_history(GetLine * gl,const char * filename,const char * comment,int max_lines)8537 int gl_save_history(GetLine *gl, const char *filename, const char *comment,
8538 		    int max_lines)
8539 {
8540   sigset_t oldset; /* The signals that were blocked on entry to this function */
8541   int status;      /* The return status of _gl_save_history() */
8542 /*
8543  * Check the arguments.
8544  */
8545   if(!gl || !filename || !comment) {
8546     if(gl)
8547       _err_record_msg(gl->err, "NULL argument(s)", END_ERR_MSG);
8548     errno = EINVAL;
8549     return 1;
8550   };
8551 /*
8552  * Block all signals.
8553  */
8554   if(gl_mask_signals(gl, &oldset))
8555     return 1;
8556 /*
8557  * Execute the private body of the function while signals are blocked.
8558  */
8559   status = _gl_save_history(gl, filename, comment, max_lines);
8560 /*
8561  * Restore the process signal mask.
8562  */
8563   gl_unmask_signals(gl, &oldset);
8564   return status;
8565 }
8566 
8567 /*.......................................................................
8568  * This is the private body of the gl_save_history() function. It
8569  * assumes that the caller has checked its arguments and blocked the
8570  * delivery of signals.
8571  */
_gl_save_history(GetLine * gl,const char * filename,const char * comment,int max_lines)8572 static int _gl_save_history(GetLine *gl, const char *filename,
8573 			    const char *comment, int max_lines)
8574 {
8575 /*
8576  * If filesystem access is to be excluded, then history files can't
8577  * be written.
8578  */
8579 #ifdef WITHOUT_FILE_SYSTEM
8580   _err_record_msg(gl->err, "Can't save history without filesystem access",
8581 		  END_ERR_MSG);
8582   errno = EINVAL;
8583   return 1;
8584 #else
8585   FileExpansion *expansion; /* The expansion of the filename */
8586 /*
8587  * Expand the filename.
8588  */
8589   expansion = ef_expand_file(gl->ef, filename, -1);
8590   if(!expansion) {
8591     gl_print_info(gl, "Unable to expand ", filename, " (",
8592 		  ef_last_error(gl->ef), ").", GL_END_INFO);
8593     return 1;
8594   };
8595 /*
8596  * Attempt to save to the specified file.
8597  */
8598   if(_glh_save_history(gl->glh, expansion->files[0], comment, max_lines)) {
8599     _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
8600     return 1;
8601   };
8602   return 0;
8603 #endif
8604 }
8605 
8606 /*.......................................................................
8607  * Restore the contents of the history buffer from a given new file.
8608  *
8609  * Input:
8610  *  gl             GetLine *  The resource object of this library.
8611  *  filename    const char *  The name of the new file to write to.
8612  *  comment     const char *  This must be the same string that was
8613  *                            passed to gl_save_history() when the file
8614  *                            was written.
8615  * Output:
8616  *  return             int     0 - OK.
8617  *                             1 - Error.
8618  */
gl_load_history(GetLine * gl,const char * filename,const char * comment)8619 int gl_load_history(GetLine *gl, const char *filename, const char *comment)
8620 {
8621   sigset_t oldset; /* The signals that were blocked on entry to this function */
8622   int status;      /* The return status of _gl_load_history() */
8623 /*
8624  * Check the arguments.
8625  */
8626   if(!gl || !filename || !comment) {
8627     if(gl)
8628       _err_record_msg(gl->err, "NULL argument(s)", END_ERR_MSG);
8629     errno = EINVAL;
8630     return 1;
8631   };
8632 /*
8633  * Block all signals.
8634  */
8635   if(gl_mask_signals(gl, &oldset))
8636     return 1;
8637 /*
8638  * Execute the private body of the function while signals are blocked.
8639  */
8640   status = _gl_load_history(gl, filename, comment);
8641 /*
8642  * Restore the process signal mask.
8643  */
8644   gl_unmask_signals(gl, &oldset);
8645   return status;
8646 }
8647 
8648 /*.......................................................................
8649  * This is the private body of the gl_load_history() function. It
8650  * assumes that the caller has checked its arguments and blocked the
8651  * delivery of signals.
8652  */
_gl_load_history(GetLine * gl,const char * filename,const char * comment)8653 static int _gl_load_history(GetLine *gl, const char *filename,
8654 			    const char *comment)
8655 {
8656 /*
8657  * If filesystem access is to be excluded, then history files can't
8658  * be read.
8659  */
8660 #ifdef WITHOUT_FILE_SYSTEM
8661   _err_record_msg(gl->err, "Can't load history without filesystem access",
8662 		  END_ERR_MSG);
8663   errno = EINVAL;
8664   return 1;
8665 #else
8666   FileExpansion *expansion; /* The expansion of the filename */
8667 /*
8668  * Expand the filename.
8669  */
8670   expansion = ef_expand_file(gl->ef, filename, -1);
8671   if(!expansion) {
8672     gl_print_info(gl, "Unable to expand ", filename, " (",
8673 		  ef_last_error(gl->ef), ").", GL_END_INFO);
8674     return 1;
8675   };
8676 /*
8677  * Attempt to load from the specified file.
8678  */
8679   if(_glh_load_history(gl->glh, expansion->files[0], comment,
8680 		       gl->cutbuf, gl->linelen+1)) {
8681     _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
8682     gl->cutbuf[0] = '\0';
8683     return 1;
8684   };
8685   gl->cutbuf[0] = '\0';
8686   return 0;
8687 #endif
8688 }
8689 
8690 /*.......................................................................
8691  * Where possible, register a function and associated data to be called
8692  * whenever a specified event is seen on a file descriptor.
8693  *
8694  * Input:
8695  *  gl            GetLine *  The resource object of the command-line input
8696  *                           module.
8697  *  fd                int    The file descriptor to watch.
8698  *  event       GlFdEvent    The type of activity to watch for.
8699  *  callback  GlFdEventFn *  The function to call when the specified
8700  *                           event occurs. Setting this to 0 removes
8701  *                           any existing callback.
8702  *  data             void *  A pointer to arbitrary data to pass to the
8703  *                           callback function.
8704  * Output:
8705  *  return            int    0 - OK.
8706  *                           1 - Either gl==NULL, or this facility isn't
8707  *                               available on the the host system
8708  *                               (ie. select() isn't available). No
8709  *                               error message is generated in the latter
8710  *                               case.
8711  */
gl_watch_fd(GetLine * gl,int fd,GlFdEvent event,GlFdEventFn * callback,void * data)8712 int gl_watch_fd(GetLine *gl, int fd, GlFdEvent event,
8713 		GlFdEventFn *callback, void *data)
8714 {
8715   sigset_t oldset; /* The signals that were blocked on entry to this function */
8716   int status;      /* The return status of _gl_watch_fd() */
8717 /*
8718  * Check the arguments.
8719  */
8720   if(!gl) {
8721     errno = EINVAL;
8722     return 1;
8723   };
8724   if(fd < 0) {
8725     _err_record_msg(gl->err, "Error: fd < 0", END_ERR_MSG);
8726     errno = EINVAL;
8727     return 1;
8728   };
8729 /*
8730  * Block all signals.
8731  */
8732   if(gl_mask_signals(gl, &oldset))
8733     return 1;
8734 /*
8735  * Execute the private body of the function while signals are blocked.
8736  */
8737   status = _gl_watch_fd(gl, fd, event, callback, data);
8738 /*
8739  * Restore the process signal mask.
8740  */
8741   gl_unmask_signals(gl, &oldset);
8742   return status;
8743 }
8744 
8745 /*.......................................................................
8746  * This is the private body of the gl_watch_fd() function. It
8747  * assumes that the caller has checked its arguments and blocked the
8748  * delivery of signals.
8749  */
_gl_watch_fd(GetLine * gl,int fd,GlFdEvent event,GlFdEventFn * callback,void * data)8750 static int _gl_watch_fd(GetLine *gl, int fd, GlFdEvent event,
8751 			GlFdEventFn *callback, void *data)
8752 #if !defined(HAVE_SELECT)
8753 {return 1;}               /* The facility isn't supported on this system */
8754 #else
8755 {
8756   GlFdNode *prev;  /* The node that precedes 'node' in gl->fd_nodes */
8757   GlFdNode *node;  /* The file-descriptor node being checked */
8758 /*
8759  * Search the list of already registered fd activity nodes for the specified
8760  * file descriptor.
8761  */
8762   for(prev=NULL,node=gl->fd_nodes; node && node->fd != fd;
8763       prev=node, node=node->next)
8764     ;
8765 /*
8766  * Hasn't a node been allocated for this fd yet?
8767  */
8768   if(!node) {
8769 /*
8770  * If there is no callback to record, just ignore the call.
8771  */
8772     if(!callback)
8773       return 0;
8774 /*
8775  * Allocate the new node.
8776  */
8777     node = (GlFdNode *) _new_FreeListNode(gl->fd_node_mem);
8778     if(!node) {
8779       errno = ENOMEM;
8780       _err_record_msg(gl->err, "Insufficient memory", END_ERR_MSG);
8781       return 1;
8782     };
8783 /*
8784  * Prepend the node to the list.
8785  */
8786     node->next = gl->fd_nodes;
8787     gl->fd_nodes = node;
8788 /*
8789  * Initialize the node.
8790  */
8791     node->fd = fd;
8792     node->rd.fn = 0;
8793     node->rd.data = NULL;
8794     node->ur = node->wr = node->rd;
8795   };
8796 /*
8797  * Record the new callback.
8798  */
8799   switch(event) {
8800   case GLFD_READ:
8801     node->rd.fn = callback;
8802     node->rd.data = data;
8803     if(callback)
8804       FD_SET(fd, &gl->rfds);
8805     else
8806       FD_CLR(fd, &gl->rfds);
8807     break;
8808   case GLFD_WRITE:
8809     node->wr.fn = callback;
8810     node->wr.data = data;
8811     if(callback)
8812       FD_SET(fd, &gl->wfds);
8813     else
8814       FD_CLR(fd, &gl->wfds);
8815     break;
8816   case GLFD_URGENT:
8817     node->ur.fn = callback;
8818     node->ur.data = data;
8819     if(callback)
8820       FD_SET(fd, &gl->ufds);
8821     else
8822       FD_CLR(fd, &gl->ufds);
8823     break;
8824   };
8825 /*
8826  * Keep a record of the largest file descriptor being watched.
8827  */
8828   if(fd > gl->max_fd)
8829     gl->max_fd = fd;
8830 /*
8831  * If we are deleting an existing callback, also delete the parent
8832  * activity node if no callbacks are registered to the fd anymore.
8833  */
8834   if(!callback) {
8835     if(!node->rd.fn && !node->wr.fn && !node->ur.fn) {
8836       if(prev)
8837 	prev->next = node->next;
8838       else
8839 	gl->fd_nodes = node->next;
8840       node = (GlFdNode *) _del_FreeListNode(gl->fd_node_mem, node);
8841     };
8842   };
8843   return 0;
8844 }
8845 #endif
8846 
8847 /*.......................................................................
8848  * On systems with the select() system call, the gl_inactivity_timeout()
8849  * function provides the option of setting (or cancelling) an
8850  * inactivity timeout. Inactivity, in this case, refers both to
8851  * terminal input received from the user, and to I/O on any file
8852  * descriptors registered by calls to gl_watch_fd(). If at any time,
8853  * no activity is seen for the requested time period, the specified
8854  * timeout callback function is called. On returning, this callback
8855  * returns a code which tells gl_get_line() what to do next. Note that
8856  * each call to gl_inactivity_timeout() replaces any previously installed
8857  * timeout callback, and that specifying a callback of 0, turns off
8858  * inactivity timing.
8859  *
8860  * Beware that although the timeout argument includes a nano-second
8861  * component, few computer clocks presently have resolutions finer
8862  * than a few milliseconds, so asking for less than a few milliseconds
8863  * is equivalent to zero on a lot of systems.
8864  *
8865  * Input:
8866  *  gl            GetLine *  The resource object of the command-line input
8867  *                           module.
8868  *  callback  GlTimeoutFn *  The function to call when the inactivity
8869  *                           timeout is exceeded. To turn off
8870  *                           inactivity timeouts altogether, send 0.
8871  *  data             void *  A pointer to arbitrary data to pass to the
8872  *                           callback function.
8873  *  sec     unsigned long    The number of whole seconds in the timeout.
8874  *  nsec    unsigned long    The fractional number of seconds in the
8875  *                           timeout, expressed in nano-seconds (see
8876  *                           the caveat above).
8877  * Output:
8878  *  return            int    0 - OK.
8879  *                           1 - Either gl==NULL, or this facility isn't
8880  *                               available on the the host system
8881  *                               (ie. select() isn't available). No
8882  *                               error message is generated in the latter
8883  *                               case.
8884  */
gl_inactivity_timeout(GetLine * gl,GlTimeoutFn * timeout_fn,void * data,unsigned long sec,unsigned long nsec)8885 int gl_inactivity_timeout(GetLine *gl, GlTimeoutFn *timeout_fn, void *data,
8886 		   unsigned long sec, unsigned long nsec)
8887 #if !defined(HAVE_SELECT)
8888 {return 1;}               /* The facility isn't supported on this system */
8889 #else
8890 {
8891   sigset_t oldset; /* The signals that were blocked on entry to this function */
8892 /*
8893  * Check the arguments.
8894  */
8895   if(!gl) {
8896     errno = EINVAL;
8897     return 1;
8898   };
8899 /*
8900  * Block all signals.
8901  */
8902   if(gl_mask_signals(gl, &oldset))
8903     return 1;
8904 /*
8905  * Install a new timeout?
8906  */
8907   if(timeout_fn) {
8908     gl->timer.dt.tv_sec = sec;
8909     gl->timer.dt.tv_usec = nsec / 1000;
8910     gl->timer.fn = timeout_fn;
8911     gl->timer.data = data;
8912   } else {
8913     gl->timer.fn = 0;
8914     gl->timer.data = NULL;
8915   };
8916 /*
8917  * Restore the process signal mask.
8918  */
8919   gl_unmask_signals(gl, &oldset);
8920   return 0;
8921 }
8922 #endif
8923 
8924 /*.......................................................................
8925  * When select() is available, this is a private function of
8926  * gl_read_input() which responds to file-descriptor events registered by
8927  * the caller. Note that it assumes that it is being called from within
8928  * gl_read_input()'s sigsetjump() clause.
8929  *
8930  * Input:
8931  *  gl    GetLine *  The resource object of this module.
8932  *  fd        int    The file descriptor to be watched for user input.
8933  * Output:
8934  *  return    int    0 - OK.
8935  *                   1 - An error occurred.
8936  */
gl_event_handler(GetLine * gl,int fd)8937 static int gl_event_handler(GetLine *gl, int fd)
8938 {
8939 #if !defined(HAVE_SELECT)
8940   return 0;
8941 #else
8942 /*
8943  * Set up a zero-second timeout.
8944  */
8945   struct timeval zero;
8946   zero.tv_sec = zero.tv_usec = 0;
8947 /*
8948  * If at any time no external callbacks remain, quit the loop return,
8949  * so that we can simply wait in read(). This is designed as an
8950  * optimization for when no callbacks have been registered on entry to
8951  * this function, but since callbacks can delete themselves, it can
8952  * also help later.
8953  */
8954   while(gl->fd_nodes || gl->timer.fn) {
8955     int nready;   /* The number of file descriptors that are ready for I/O */
8956 /*
8957  * Get the set of descriptors to be watched.
8958  */
8959     fd_set rfds = gl->rfds;
8960     fd_set wfds = gl->wfds;
8961     fd_set ufds = gl->ufds;
8962 /*
8963  * Get the appropriate timeout.
8964  */
8965     struct timeval dt = gl->timer.fn ? gl->timer.dt : zero;
8966 /*
8967  * Add the specified user-input file descriptor to the set that is to
8968  * be watched.
8969  */
8970     FD_SET(fd, &rfds);
8971 /*
8972  * Unblock the signals that we are watching, while select is blocked
8973  * waiting for I/O.
8974  */
8975     gl_catch_signals(gl);
8976 /*
8977  * Wait for activity on any of the file descriptors.
8978  */
8979     nready = select(gl->max_fd+1, &rfds, &wfds, &ufds,
8980 	    (gl->timer.fn || gl->io_mode==GL_SERVER_MODE) ? &dt : NULL);
8981 /*
8982  * We don't want to do a longjmp in the middle of a callback that
8983  * might be modifying global or heap data, so block all the signals
8984  * that we are trapping before executing callback functions. Note that
8985  * the caller will unblock them again when it needs to, so there is
8986  * no need to undo this before returning.
8987  */
8988     gl_mask_signals(gl, NULL);
8989 /*
8990  * If select() returns but none of the file descriptors are reported
8991  * to have activity, then select() timed out.
8992  */
8993     if(nready == 0) {
8994 /*
8995  * Note that in non-blocking server mode, the inactivity timer is used
8996  * to allow I/O to block for a specified amount of time, so in this
8997  * mode we return the postponed blocked status when an abort is
8998  * requested.
8999  */
9000       if(gl_call_timeout_handler(gl)) {
9001 	return 1;
9002       } else if(gl->io_mode == GL_SERVER_MODE) {
9003 	gl_record_status(gl, GLR_BLOCKED, BLOCKED_ERRNO);
9004 	return 1;
9005       };
9006 /*
9007  * If nready < 0, this means an error occurred.
9008  */
9009     } else if(nready < 0) {
9010       if(errno != EINTR) {
9011 	gl_record_status(gl, GLR_ERROR, errno);
9012 	return 1;
9013       };
9014 /*
9015  * If the user-input file descriptor has data available, return.
9016  */
9017     } else if(FD_ISSET(fd, &rfds)) {
9018       return 0;
9019 /*
9020  * Check for activity on any of the file descriptors registered by the
9021  * calling application, and call the associated callback functions.
9022  */
9023     } else {
9024       GlFdNode *node;   /* The fd event node being checked */
9025 /*
9026  * Search the list for the file descriptor that caused select() to return.
9027  */
9028       for(node=gl->fd_nodes; node; node=node->next) {
9029 /*
9030  * Is there urgent out of band data waiting to be read on fd?
9031  */
9032 	if(node->ur.fn && FD_ISSET(node->fd, &ufds)) {
9033 	  if(gl_call_fd_handler(gl, &node->ur, node->fd, GLFD_URGENT))
9034 	    return 1;
9035 	  break;  /* The callback may have changed the list of nodes */
9036 /*
9037  * Is the fd readable?
9038  */
9039 	} else if(node->rd.fn && FD_ISSET(node->fd, &rfds)) {
9040 	  if(gl_call_fd_handler(gl, &node->rd, node->fd, GLFD_READ))
9041 	    return 1;
9042 	  break;  /* The callback may have changed the list of nodes */
9043 /*
9044  * Is the fd writable?
9045  */
9046 	} else if(node->wr.fn && FD_ISSET(node->fd, &wfds)) {
9047 	  if(gl_call_fd_handler(gl, &node->wr, node->fd, GLFD_WRITE))
9048 	    return 1;
9049 	  break;  /* The callback may have changed the list of nodes */
9050 	};
9051       };
9052     };
9053 /*
9054  * Just in case the above event handlers asked for the input line to
9055  * be redrawn, flush any pending output.
9056  */
9057     if(gl_flush_output(gl))
9058       return 1;
9059   };
9060   return 0;
9061 }
9062 #endif
9063 
9064 #if defined(HAVE_SELECT)
9065 /*.......................................................................
9066  * This is a private function of gl_event_handler(), used to call a
9067  * file-descriptor callback.
9068  *
9069  * Input:
9070  *  gl       GetLine *  The resource object of gl_get_line().
9071  *  gfh  GlFdHandler *  The I/O handler.
9072  *  fd           int    The file-descriptor being reported.
9073  *  event  GlFdEvent    The I/O event being reported.
9074  * Output:
9075  *  return       int    0 - OK.
9076  *                      1 - Error.
9077  */
9078 static int gl_call_fd_handler(GetLine *gl, GlFdHandler *gfh, int fd,
9079 			      GlFdEvent event)
9080 {
9081   Termios attr;       /* The terminal attributes */
9082   int waserr = 0;     /* True after any error */
9083 /*
9084  * Re-enable conversion of newline characters to carriage-return/linefeed,
9085  * so that the callback can write to the terminal without having to do
9086  * anything special.
9087  */
9088   if(tcgetattr(gl->input_fd, &attr)) {
9089     _err_record_msg(gl->err, "tcgetattr error", END_ERR_MSG);
9090     return 1;
9091   };
9092   attr.c_oflag |= OPOST;
9093   while(tcsetattr(gl->input_fd, TCSADRAIN, &attr)) {
9094     if(errno != EINTR) {
9095       _err_record_msg(gl->err, "tcsetattr error", END_ERR_MSG);
9096       return 1;
9097     };
9098   };
9099 /*
9100  * Invoke the application's callback function.
9101  */
9102   switch(gfh->fn(gl, gfh->data, fd, event)) {
9103   default:
9104   case GLFD_ABORT:
9105     gl_record_status(gl, GLR_FDABORT, 0);
9106     waserr = 1;
9107     break;
9108   case GLFD_REFRESH:
9109     gl_queue_redisplay(gl);
9110     break;
9111   case GLFD_CONTINUE:
9112     break;
9113   };
9114 /*
9115  * Disable conversion of newline characters to carriage-return/linefeed.
9116  */
9117   attr.c_oflag &= ~(OPOST);
9118   while(tcsetattr(gl->input_fd, TCSADRAIN, &attr)) {
9119     if(errno != EINTR) {
9120       _err_record_msg(gl->err, "tcsetattr error", END_ERR_MSG);
9121       return 1;
9122     };
9123   };
9124   return waserr;
9125 }
9126 
9127 /*.......................................................................
9128  * This is a private function of gl_event_handler(), used to call a
9129  * inactivity timer callbacks.
9130  *
9131  * Input:
9132  *  gl       GetLine *  The resource object of gl_get_line().
9133  * Output:
9134  *  return       int    0 - OK.
9135  *                      1 - Error.
9136  */
9137 static int gl_call_timeout_handler(GetLine *gl)
9138 {
9139   Termios attr;       /* The terminal attributes */
9140   int waserr = 0;     /* True after any error */
9141 /*
9142  * Make sure that there is an inactivity timeout callback.
9143  */
9144   if(!gl->timer.fn)
9145     return 0;
9146 /*
9147  * Re-enable conversion of newline characters to carriage-return/linefeed,
9148  * so that the callback can write to the terminal without having to do
9149  * anything special.
9150  */
9151   if(tcgetattr(gl->input_fd, &attr)) {
9152     _err_record_msg(gl->err, "tcgetattr error", END_ERR_MSG);
9153     return 1;
9154   };
9155   attr.c_oflag |= OPOST;
9156   while(tcsetattr(gl->input_fd, TCSADRAIN, &attr)) {
9157     if(errno != EINTR) {
9158       _err_record_msg(gl->err, "tcsetattr error", END_ERR_MSG);
9159       return 1;
9160     };
9161   };
9162 /*
9163  * Invoke the application's callback function.
9164  */
9165   switch(gl->timer.fn(gl, gl->timer.data)) {
9166   default:
9167   case GLTO_ABORT:
9168     gl_record_status(gl, GLR_TIMEOUT, 0);
9169     waserr = 1;
9170     break;
9171   case GLTO_REFRESH:
9172     gl_queue_redisplay(gl);
9173     break;
9174   case GLTO_CONTINUE:
9175     break;
9176   };
9177 /*
9178  * Disable conversion of newline characters to carriage-return/linefeed.
9179  */
9180   attr.c_oflag &= ~(OPOST);
9181   while(tcsetattr(gl->input_fd, TCSADRAIN, &attr)) {
9182     if(errno != EINTR) {
9183       _err_record_msg(gl->err, "tcsetattr error", END_ERR_MSG);
9184       return 1;
9185     };
9186   };
9187   return waserr;
9188 }
9189 #endif  /* HAVE_SELECT */
9190 
9191 /*.......................................................................
9192  * Switch history groups. History groups represent separate history
9193  * lists recorded within a single history buffer. Different groups
9194  * are distinguished by integer identifiers chosen by the calling
9195  * appplicaton. Initially new_GetLine() sets the group identifier to
9196  * 0. Whenever a new line is appended to the history list, the current
9197  * group identifier is recorded with it, and history lookups only
9198  * consider lines marked with the current group identifier.
9199  *
9200  * Input:
9201  *  gl      GetLine *  The resource object of gl_get_line().
9202  *  id     unsigned    The new history group identifier.
9203  * Output:
9204  *  return      int    0 - OK.
9205  *                     1 - Error.
9206  */
9207 int gl_group_history(GetLine *gl, unsigned id)
9208 {
9209   sigset_t oldset; /* The signals that were blocked on entry to this function */
9210   int status;      /* The return status of this function */
9211 /*
9212  * Check the arguments.
9213  */
9214   if(!gl) {
9215     errno = EINVAL;
9216     return 1;
9217   };
9218 /*
9219  * Block all signals while we install the new configuration.
9220  */
9221   if(gl_mask_signals(gl, &oldset))
9222     return 1;
9223 /*
9224  * If the group isn't being changed, do nothing.
9225  */
9226   if(_glh_get_group(gl->glh) == id) {
9227     status = 0;
9228 /*
9229  * Establish the new group.
9230  */
9231   } else if(_glh_set_group(gl->glh, id)) {
9232     _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
9233     status = 1;
9234 /*
9235  * Prevent history information from the previous group being
9236  * inappropriately used by the next call to gl_get_line().
9237  */
9238   } else {
9239     gl->preload_history = 0;
9240     gl->last_search = -1;
9241     status = 0;
9242   };
9243 /*
9244  * Restore the process signal mask.
9245  */
9246   gl_unmask_signals(gl, &oldset);
9247   return status;
9248 }
9249 
9250 /*.......................................................................
9251  * Display the contents of the history list.
9252  *
9253  * Input:
9254  *  gl      GetLine *  The resource object of gl_get_line().
9255  *  fp         FILE *  The stdio output stream to write to.
9256  *  fmt  const char *  A format string. This containing characters to be
9257  *                     written verbatim, plus any of the following
9258  *                     format directives:
9259  *                       %D  -  The date, formatted like 2001-11-20
9260  *                       %T  -  The time of day, formatted like 23:59:59
9261  *                       %N  -  The sequential entry number of the
9262  *                              line in the history buffer.
9263  *                       %G  -  The number of the history group that
9264  *                              the line belongs to.
9265  *                       %%  -  A literal % character.
9266  *                       %H  -  The history line itself.
9267  *                     Note that a '\n' newline character is not
9268  *                     appended by default.
9269  *  all_groups  int    If true, display history lines from all
9270  *                     history groups. Otherwise only display
9271  *                     those of the current history group.
9272  *  max_lines   int    If max_lines is < 0, all available lines
9273  *                     are displayed. Otherwise only the most
9274  *                     recent max_lines lines will be displayed.
9275  * Output:
9276  *  return      int    0 - OK.
9277  *                     1 - Error.
9278  */
9279 int gl_show_history(GetLine *gl, FILE *fp, const char *fmt, int all_groups,
9280 		    int max_lines)
9281 {
9282   sigset_t oldset; /* The signals that were blocked on entry to this function */
9283   int status;      /* The return status of this function */
9284 /*
9285  * Check the arguments.
9286  */
9287   if(!gl || !fp || !fmt) {
9288     if(gl)
9289       _err_record_msg(gl->err, "NULL argument(s)", END_ERR_MSG);
9290     errno = EINVAL;
9291     return 1;
9292   };
9293 /*
9294  * Block all signals.
9295  */
9296   if(gl_mask_signals(gl, &oldset))
9297     return 1;
9298 /*
9299  * Display the specified history group(s) while signals are blocked.
9300  */
9301   status = _glh_show_history(gl->glh, _io_write_stdio, fp, fmt, all_groups,
9302 			     max_lines) || fflush(fp)==EOF;
9303   if(!status)
9304     _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
9305 /*
9306  * Restore the process signal mask.
9307  */
9308   gl_unmask_signals(gl, &oldset);
9309   return status;
9310 }
9311 
9312 /*.......................................................................
9313  * Update if necessary, and return the current size of the terminal.
9314  *
9315  * Input:
9316  *  gl            GetLine *  The resource object of gl_get_line().
9317  *  def_ncolumn       int    If the number of columns in the terminal
9318  *                           can't be determined, substitute this number.
9319  *  def_nline         int    If the number of lines in the terminal can't
9320  *                           be determined, substitute this number.
9321  * Output:
9322  *  return GlTerminalSize    The current terminal size.
9323  */
9324 GlTerminalSize gl_terminal_size(GetLine *gl, int def_ncolumn, int def_nline)
9325 {
9326   GlTerminalSize size;  /* The object to be returned */
9327   sigset_t oldset;      /* The signals that were blocked on entry */
9328                         /*  to this function */
9329 /*
9330  * Block all signals while accessing gl.
9331  */
9332   gl_mask_signals(gl, &oldset);
9333 /*
9334  * Lookup/configure the terminal size.
9335  */
9336   _gl_terminal_size(gl, def_ncolumn, def_nline, &size);
9337 /*
9338  * Restore the process signal mask before returning.
9339  */
9340   gl_unmask_signals(gl, &oldset);
9341   return size;
9342 }
9343 
9344 /*.......................................................................
9345  * This is the private body of the gl_terminal_size() function. It
9346  * assumes that the caller has checked its arguments and blocked the
9347  * delivery of signals.
9348  */
9349 static void _gl_terminal_size(GetLine *gl, int def_ncolumn, int def_nline,
9350 			      GlTerminalSize *size)
9351 {
9352   const char *env;      /* The value of an environment variable */
9353   int n;                /* A number read from env[] */
9354 /*
9355  * Set the number of lines and columns to non-sensical values so that
9356  * we know later if they have been set.
9357  */
9358   gl->nline = 0;
9359   gl->ncolumn = 0;
9360 /*
9361  * Are we reading from a terminal?
9362  */
9363   if(gl->is_term) {
9364 /*
9365  * Ask the terminal directly if possible.
9366  */
9367     (void) _gl_update_size(gl);
9368 /*
9369  * If gl_update_size() couldn't ask the terminal, it will have
9370  * left gl->nrow and gl->ncolumn unchanged. If these values haven't
9371  * been changed from their initial values of zero, we need to find
9372  * a different method to get the terminal size.
9373  *
9374  * If the number of lines isn't known yet, first see if the
9375  * LINES environment ariable exists and specifies a believable number.
9376  * If this doesn't work, look up the default size in the terminal
9377  * information database.
9378  */
9379     if(gl->nline < 1) {
9380       if((env = getenv("LINES")) && (n=atoi(env)) > 0)
9381 	gl->nline = n;
9382 #ifdef USE_TERMINFO
9383       else
9384 	gl->nline = tigetnum((char *)"lines");
9385 #elif defined(USE_TERMCAP)
9386       else
9387         gl->nline = tgetnum("li");
9388 #endif
9389     };
9390 /*
9391  * If the number of lines isn't known yet, first see if the COLUMNS
9392  * environment ariable exists and specifies a believable number.  If
9393  * this doesn't work, look up the default size in the terminal
9394  * information database.
9395  */
9396     if(gl->ncolumn < 1) {
9397       if((env = getenv("COLUMNS")) && (n=atoi(env)) > 0)
9398 	gl->ncolumn = n;
9399 #ifdef USE_TERMINFO
9400       else
9401 	gl->ncolumn = tigetnum((char *)"cols");
9402 #elif defined(USE_TERMCAP)
9403       else
9404 	gl->ncolumn = tgetnum("co");
9405 #endif
9406     };
9407   };
9408 /*
9409  * If we still haven't been able to acquire reasonable values, substitute
9410  * the default values specified by the caller.
9411  */
9412   if(gl->nline <= 0)
9413     gl->nline = def_nline;
9414   if(gl->ncolumn <= 0)
9415     gl->ncolumn = def_ncolumn;
9416 /*
9417  * Copy the new size into the return value.
9418  */
9419   if(size) {
9420     size->nline = gl->nline;
9421     size->ncolumn = gl->ncolumn;
9422   };
9423   return;
9424 }
9425 
9426 /*.......................................................................
9427  * Resize or delete the history buffer.
9428  *
9429  * Input:
9430  *  gl      GetLine *  The resource object of gl_get_line().
9431  *  bufsize  size_t    The number of bytes in the history buffer, or 0
9432  *                     to delete the buffer completely.
9433  * Output:
9434  *  return      int    0 - OK.
9435  *                     1 - Insufficient memory (the previous buffer
9436  *                         will have been retained). No error message
9437  *                         will be displayed.
9438  */
9439 int gl_resize_history(GetLine *gl, size_t bufsize)
9440 {
9441   sigset_t oldset; /* The signals that were blocked on entry to this function */
9442   int status;      /* The return status of this function */
9443 /*
9444  * Check the arguments.
9445  */
9446   if(!gl)
9447     return 1;
9448 /*
9449  * Block all signals while modifying the contents of gl.
9450  */
9451   if(gl_mask_signals(gl, &oldset))
9452     return 1;
9453 /*
9454  * Perform the resize while signals are blocked.
9455  */
9456   status = _glh_resize_history(gl->glh, bufsize);
9457   if(status)
9458     _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
9459 /*
9460  * Restore the process signal mask before returning.
9461  */
9462   gl_unmask_signals(gl, &oldset);
9463   return status;
9464 }
9465 
9466 /*.......................................................................
9467  * Set an upper limit to the number of lines that can be recorded in the
9468  * history list, or remove a previously specified limit.
9469  *
9470  * Input:
9471  *  gl      GetLine *  The resource object of gl_get_line().
9472  *  max_lines   int    The maximum number of lines to allow, or -1 to
9473  *                     cancel a previous limit and allow as many lines
9474  *                     as will fit in the current history buffer size.
9475  */
9476 void gl_limit_history(GetLine *gl, int max_lines)
9477 {
9478   if(gl) {
9479     sigset_t oldset; /* The signals that were blocked on entry to this block */
9480 /*
9481  * Temporarily block all signals.
9482  */
9483     gl_mask_signals(gl, &oldset);
9484 /*
9485  * Apply the limit while signals are blocked.
9486  */
9487     _glh_limit_history(gl->glh, max_lines);
9488 /*
9489  * Restore the process signal mask before returning.
9490  */
9491     gl_unmask_signals(gl, &oldset);
9492   };
9493 }
9494 
9495 /*.......................................................................
9496  * Discard either all historical lines, or just those associated with the
9497  * current history group.
9498  *
9499  * Input:
9500  *  gl      GetLine *  The resource object of gl_get_line().
9501  *  all_groups  int    If true, clear all of the history. If false,
9502  *                     clear only the stored lines associated with the
9503  *                     currently selected history group.
9504  */
9505 void gl_clear_history(GetLine *gl, int all_groups)
9506 {
9507   if(gl) {
9508     sigset_t oldset; /* The signals that were blocked on entry to this block */
9509 /*
9510  * Temporarily block all signals.
9511  */
9512     gl_mask_signals(gl, &oldset);
9513 /*
9514  * Clear the history buffer while signals are blocked.
9515  */
9516     _glh_clear_history(gl->glh, all_groups);
9517 /*
9518  * Restore the process signal mask before returning.
9519  */
9520     gl_unmask_signals(gl, &oldset);
9521   };
9522 }
9523 
9524 /*.......................................................................
9525  * Temporarily enable or disable the gl_get_line() history mechanism.
9526  *
9527  * Input:
9528  *  gl      GetLine *  The resource object of gl_get_line().
9529  *  enable      int    If true, turn on the history mechanism. If
9530  *                     false, disable it.
9531  */
9532 void gl_toggle_history(GetLine *gl, int enable)
9533 {
9534   if(gl) {
9535     sigset_t oldset; /* The signals that were blocked on entry to this block */
9536 /*
9537  * Temporarily block all signals.
9538  */
9539     gl_mask_signals(gl, &oldset);
9540 /*
9541  * Change the history recording mode while signals are blocked.
9542  */
9543     _glh_toggle_history(gl->glh, enable);
9544 /*
9545  * Restore the process signal mask before returning.
9546  */
9547     gl_unmask_signals(gl, &oldset);
9548   };
9549 }
9550 
9551 /*.......................................................................
9552  * Lookup a history line by its sequential number of entry in the
9553  * history buffer.
9554  *
9555  * Input:
9556  *  gl            GetLine *  The resource object of gl_get_line().
9557  *  id      unsigned long    The identification number of the line to
9558  *                           be returned, where 0 denotes the first line
9559  *                           that was entered in the history list, and
9560  *                           each subsequently added line has a number
9561  *                           one greater than the previous one. For
9562  *                           the range of lines currently in the list,
9563  *                           see the gl_range_of_history() function.
9564  * Input/Output:
9565  *  line    GlHistoryLine *  A pointer to the variable in which to
9566  *                           return the details of the line.
9567  * Output:
9568  *  return            int    0 - The line is no longer in the history
9569  *                               list, and *line has not been changed.
9570  *                           1 - The requested line can be found in
9571  *                               *line. Note that line->line is part
9572  *                               of the history buffer, so a
9573  *                               private copy should be made if you
9574  *                               wish to use it after subsequent calls
9575  *                               to any functions that take *gl as an
9576  *                               argument.
9577  */
9578 int gl_lookup_history(GetLine *gl, unsigned long id, GlHistoryLine *line)
9579 {
9580   sigset_t oldset; /* The signals that were blocked on entry to this function */
9581   int status;      /* The return status of this function */
9582 /*
9583  * Check the arguments.
9584  */
9585   if(!gl)
9586     return 0;
9587 /*
9588  * Block all signals while modifying the contents of gl.
9589  */
9590   if(gl_mask_signals(gl, &oldset))
9591     return 1;
9592 /*
9593  * Perform the lookup while signals are blocked.
9594  */
9595   status = _glh_lookup_history(gl->glh, (GlhLineID) id, &line->line,
9596 			       &line->group, &line->timestamp);
9597   if(status)
9598     _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
9599 /*
9600  * Restore the process signal mask before returning.
9601  */
9602   gl_unmask_signals(gl, &oldset);
9603   return status;
9604 }
9605 
9606 /*.......................................................................
9607  * Query the state of the history list. Note that any of the input/output
9608  * pointers can be specified as NULL.
9609  *
9610  * Input:
9611  *  gl            GetLine *  The resource object of gl_get_line().
9612  * Input/Output:
9613  *  state  GlHistoryState *  A pointer to the variable in which to record
9614  *                           the return values.
9615  */
9616 void gl_state_of_history(GetLine *gl, GlHistoryState *state)
9617 {
9618   if(gl && state) {
9619     sigset_t oldset; /* The signals that were blocked on entry to this block */
9620 /*
9621  * Temporarily block all signals.
9622  */
9623     gl_mask_signals(gl, &oldset);
9624 /*
9625  * Lookup the status while signals are blocked.
9626  */
9627     _glh_state_of_history(gl->glh, &state->enabled, &state->group,
9628 			  &state->max_lines);
9629 /*
9630  * Restore the process signal mask before returning.
9631  */
9632     gl_unmask_signals(gl, &oldset);
9633   };
9634 }
9635 
9636 /*.......................................................................
9637  * Query the number and range of lines in the history buffer.
9638  *
9639  * Input:
9640  *  gl            GetLine *  The resource object of gl_get_line().
9641  *  range  GlHistoryRange *  A pointer to the variable in which to record
9642  *                           the return values. If range->nline=0, the
9643  *                           range of lines will be given as 0-0.
9644  */
9645 void gl_range_of_history(GetLine *gl, GlHistoryRange *range)
9646 {
9647   if(gl && range) {
9648     sigset_t oldset; /* The signals that were blocked on entry to this block */
9649 /*
9650  * Temporarily block all signals.
9651  */
9652     gl_mask_signals(gl, &oldset);
9653 /*
9654  * Lookup the information while signals are blocked.
9655  */
9656     _glh_range_of_history(gl->glh, &range->oldest, &range->newest,
9657 			  &range->nlines);
9658 /*
9659  * Restore the process signal mask before returning.
9660  */
9661     gl_unmask_signals(gl, &oldset);
9662   };
9663 }
9664 
9665 /*.......................................................................
9666  * Return the size of the history buffer and the amount of the
9667  * buffer that is currently in use.
9668  *
9669  * Input:
9670  *  gl         GetLine *  The gl_get_line() resource object.
9671  * Input/Output:
9672  *  GlHistorySize size *  A pointer to the variable in which to return
9673  *                        the results.
9674  */
9675 void gl_size_of_history(GetLine *gl, GlHistorySize *size)
9676 {
9677   if(gl && size) {
9678     sigset_t oldset; /* The signals that were blocked on entry to this block */
9679 /*
9680  * Temporarily block all signals.
9681  */
9682     gl_mask_signals(gl, &oldset);
9683 /*
9684  * Lookup the information while signals are blocked.
9685  */
9686     _glh_size_of_history(gl->glh, &size->size, &size->used);
9687 /*
9688  * Restore the process signal mask before returning.
9689  */
9690     gl_unmask_signals(gl, &oldset);
9691   };
9692 }
9693 
9694 /*.......................................................................
9695  * This is the action function that lists the contents of the history
9696  * list.
9697  */
9698 static KT_KEY_FN(gl_list_history)
9699 {
9700 /*
9701  * Start a new line.
9702  */
9703   if(gl_start_newline(gl, 1))
9704     return 1;
9705 /*
9706  * List history lines that belong to the current group.
9707  */
9708   _glh_show_history(gl->glh, gl_write_fn, gl, "%N  %T   %H\r\n", 0,
9709 		    count<=1 ? -1 : count);
9710 /*
9711  * Arrange for the input line to be redisplayed.
9712  */
9713   gl_queue_redisplay(gl);
9714   return 0;
9715 }
9716 
9717 /*.......................................................................
9718  * Specify whether text that users type should be displayed or hidden.
9719  * In the latter case, only the prompt is displayed, and the final
9720  * input line is not archived in the history list.
9721  *
9722  * Input:
9723  *  gl         GetLine *  The gl_get_line() resource object.
9724  *  enable         int     0 - Disable echoing.
9725  *                         1 - Enable echoing.
9726  *                        -1 - Just query the mode without changing it.
9727  * Output:
9728  *  return         int    The echoing disposition that was in effect
9729  *                        before this function was called:
9730  *                         0 - Echoing was disabled.
9731  *                         1 - Echoing was enabled.
9732  */
9733 int gl_echo_mode(GetLine *gl, int enable)
9734 {
9735   if(gl) {
9736     sigset_t oldset; /* The signals that were blocked on entry to this block */
9737     int was_echoing; /* The echoing disposition on entry to this function */
9738 /*
9739  * Temporarily block all signals.
9740  */
9741     gl_mask_signals(gl, &oldset);
9742 /*
9743  * Install the new disposition while signals are blocked.
9744  */
9745     was_echoing = gl->echo;
9746     if(enable >= 0)
9747       gl->echo = enable;
9748 /*
9749  * Restore the process signal mask before returning.
9750  */
9751     gl_unmask_signals(gl, &oldset);
9752 /*
9753  * Return the original echoing disposition.
9754  */
9755     return was_echoing;
9756   };
9757   return 1;
9758 }
9759 
9760 /*.......................................................................
9761  * Display the prompt.
9762  *
9763  * Input:
9764  *  gl         GetLine *  The resource object of gl_get_line().
9765  * Output:
9766  *  return         int    0 - OK.
9767  *                        1 - Error.
9768  */
9769 static int gl_display_prompt(GetLine *gl)
9770 {
9771   const char *pptr;       /* A pointer into gl->prompt[] */
9772   unsigned old_attr=0;    /* The current text display attributes */
9773   unsigned new_attr=0;    /* The requested text display attributes */
9774 /*
9775  * Temporarily switch to echoing output characters.
9776  */
9777   int kept_echo = gl->echo;
9778   gl->echo = 1;
9779 /*
9780  * In case the screen got messed up, send a carriage return to
9781  * put the cursor at the beginning of the current terminal line.
9782  */
9783   if(gl_print_control_sequence(gl, 1, gl->bol))
9784     return 1;
9785 /*
9786  * Mark the line as partially displayed.
9787  */
9788   gl->displayed = 1;
9789 /*
9790  * Write the prompt, using the currently selected prompt style.
9791  */
9792   switch(gl->prompt_style) {
9793   case GL_LITERAL_PROMPT:
9794     if(gl_print_string(gl, gl->prompt, '\0'))
9795       return 1;
9796     break;
9797   case GL_FORMAT_PROMPT:
9798     for(pptr=gl->prompt; *pptr; pptr++) {
9799 /*
9800  * Does the latest character appear to be the start of a directive?
9801  */
9802       if(*pptr == '%') {
9803 /*
9804  * Check for and act on attribute changing directives.
9805  */
9806 	switch(pptr[1]) {
9807 /*
9808  * Add or remove a text attribute from the new set of attributes.
9809  */
9810 	case 'B': case 'U': case 'S': case 'P': case 'F': case 'V':
9811 	case 'b': case 'u': case 's': case 'p': case 'f': case 'v':
9812 	  switch(*++pptr) {
9813 	  case 'B':           /* Switch to a bold font */
9814 	    new_attr |= GL_TXT_BOLD;
9815 	    break;
9816 	  case 'b':           /* Switch to a non-bold font */
9817 	    new_attr &= ~GL_TXT_BOLD;
9818 	    break;
9819 	  case 'U':           /* Start underlining */
9820 	    new_attr |= GL_TXT_UNDERLINE;
9821 	    break;
9822 	  case 'u':           /* Stop underlining */
9823 	    new_attr &= ~GL_TXT_UNDERLINE;
9824 	    break;
9825 	  case 'S':           /* Start highlighting */
9826 	    new_attr |= GL_TXT_STANDOUT;
9827 	    break;
9828 	  case 's':           /* Stop highlighting */
9829 	    new_attr &= ~GL_TXT_STANDOUT;
9830 	    break;
9831 	  case 'P':           /* Switch to a pale font */
9832 	    new_attr |= GL_TXT_DIM;
9833 	    break;
9834 	  case 'p':           /* Switch to a non-pale font */
9835 	    new_attr &= ~GL_TXT_DIM;
9836 	    break;
9837 	  case 'F':           /* Switch to a flashing font */
9838 	    new_attr |= GL_TXT_BLINK;
9839 	    break;
9840 	  case 'f':           /* Switch to a steady font */
9841 	    new_attr &= ~GL_TXT_BLINK;
9842 	    break;
9843 	  case 'V':           /* Switch to reverse video */
9844 	    new_attr |= GL_TXT_REVERSE;
9845 	    break;
9846 	  case 'v':           /* Switch out of reverse video */
9847 	    new_attr &= ~GL_TXT_REVERSE;
9848 	    break;
9849 	  };
9850 	  continue;
9851 /*
9852  * A literal % is represented by %%. Skip the leading %.
9853  */
9854 	case '%':
9855 	  pptr++;
9856 	  break;
9857 	};
9858       };
9859 /*
9860  * Many terminals, when asked to turn off a single text attribute, turn
9861  * them all off, so the portable way to turn one off individually is to
9862  * explicitly turn them all off, then specify those that we want from
9863  * scratch.
9864  */
9865       if(old_attr & ~new_attr) {
9866 	if(gl_print_control_sequence(gl, 1, gl->text_attr_off))
9867 	  return 1;
9868 	old_attr = 0;
9869       };
9870 /*
9871  * Install new text attributes?
9872  */
9873       if(new_attr != old_attr) {
9874 	if(new_attr & GL_TXT_BOLD && !(old_attr & GL_TXT_BOLD) &&
9875 	   gl_print_control_sequence(gl, 1, gl->bold))
9876 	  return 1;
9877 	if(new_attr & GL_TXT_UNDERLINE && !(old_attr & GL_TXT_UNDERLINE) &&
9878 	   gl_print_control_sequence(gl, 1, gl->underline))
9879 	  return 1;
9880 	if(new_attr & GL_TXT_STANDOUT && !(old_attr & GL_TXT_STANDOUT) &&
9881 	   gl_print_control_sequence(gl, 1, gl->standout))
9882 	  return 1;
9883 	if(new_attr & GL_TXT_DIM && !(old_attr & GL_TXT_DIM) &&
9884 	   gl_print_control_sequence(gl, 1, gl->dim))
9885 	  return 1;
9886 	if(new_attr & GL_TXT_REVERSE && !(old_attr & GL_TXT_REVERSE) &&
9887 	   gl_print_control_sequence(gl, 1, gl->reverse))
9888 	  return 1;
9889 	if(new_attr & GL_TXT_BLINK && !(old_attr & GL_TXT_BLINK) &&
9890 	   gl_print_control_sequence(gl, 1, gl->blink))
9891 	  return 1;
9892 	old_attr = new_attr;
9893       };
9894 /*
9895  * Display the latest character.
9896  */
9897       if(gl_print_char(gl, *pptr, pptr[1]))
9898 	return 1;
9899     };
9900 /*
9901  * Turn off all text attributes now that we have finished drawing
9902  * the prompt.
9903  */
9904     if(gl_print_control_sequence(gl, 1, gl->text_attr_off))
9905       return 1;
9906     break;
9907   };
9908 /*
9909  * Restore the original echo mode.
9910  */
9911   gl->echo = kept_echo;
9912 /*
9913  * The prompt has now been displayed at least once.
9914  */
9915   gl->prompt_changed = 0;
9916   return 0;
9917 }
9918 
9919 /*.......................................................................
9920  * This function can be called from gl_get_line() callbacks to have
9921  * the prompt changed when they return. It has no effect if gl_get_line()
9922  * is not currently being invoked.
9923  *
9924  * Input:
9925  *  gl         GetLine *  The resource object of gl_get_line().
9926  *  prompt  const char *  The new prompt.
9927  */
9928 void gl_replace_prompt(GetLine *gl, const char *prompt)
9929 {
9930   if(gl) {
9931     sigset_t oldset; /* The signals that were blocked on entry to this block */
9932 /*
9933  * Temporarily block all signals.
9934  */
9935     gl_mask_signals(gl, &oldset);
9936 /*
9937  * Replace the prompt.
9938  */
9939     _gl_replace_prompt(gl, prompt);
9940 /*
9941  * Restore the process signal mask before returning.
9942  */
9943     gl_unmask_signals(gl, &oldset);
9944   };
9945 }
9946 
9947 /*.......................................................................
9948  * This is the private body of the gl_replace_prompt() function. It
9949  * assumes that the caller has checked its arguments and blocked the
9950  * delivery of signals.
9951  */
9952 static void _gl_replace_prompt(GetLine *gl, const char *prompt)
9953 {
9954   size_t size;
9955 
9956 /*
9957  * Substitute an empty prompt?
9958  */
9959   if(!prompt)
9960     prompt = "";
9961 /*
9962  * Gaurd against aliasing between prompt and gl->prompt.
9963  */
9964   if(gl->prompt != prompt) {
9965 /*
9966  * Get the length of the new prompt string.
9967  */
9968     size_t slen = strlen(prompt);
9969 /*
9970  * If needed, allocate a new buffer for the prompt string.
9971  */
9972     size = sizeof(char) * (slen + 1);
9973     if(!gl->prompt || slen > strlen(gl->prompt)) {
9974       char *new_prompt = gl->prompt ? realloc(gl->prompt, size) : malloc(size);
9975       if(!new_prompt)
9976 	return;
9977       gl->prompt = new_prompt;
9978     };
9979 /*
9980  * Make a copy of the new prompt.
9981  */
9982     strlcpy(gl->prompt, prompt, size);
9983   };
9984 /*
9985  * Record the statistics of the new prompt.
9986  */
9987   gl->prompt_len = gl_displayed_prompt_width(gl);
9988   gl->prompt_changed = 1;
9989   gl_queue_redisplay(gl);
9990   return;
9991 }
9992 
9993 /*.......................................................................
9994  * Work out the length of the current prompt on the terminal, according
9995  * to the current prompt formatting style.
9996  *
9997  * Input:
9998  *  gl       GetLine *  The resource object of this library.
9999  * Output:
10000  *  return       int    The number of displayed characters.
10001  */
10002 static int gl_displayed_prompt_width(GetLine *gl)
10003 {
10004   int slen=0;         /* The displayed number of characters */
10005   const char *pptr;   /* A pointer into prompt[] */
10006 /*
10007  * The length differs according to the prompt display style.
10008  */
10009   switch(gl->prompt_style) {
10010   case GL_LITERAL_PROMPT:
10011     return gl_displayed_string_width(gl, gl->prompt, -1, 0);
10012     break;
10013   case GL_FORMAT_PROMPT:
10014 /*
10015  * Add up the length of the displayed string, while filtering out
10016  * attribute directives.
10017  */
10018     for(pptr=gl->prompt; *pptr; pptr++) {
10019 /*
10020  * Does the latest character appear to be the start of a directive?
10021  */
10022       if(*pptr == '%') {
10023 /*
10024  * Check for and skip attribute changing directives.
10025  */
10026 	switch(pptr[1]) {
10027 	case 'B': case 'b': case 'U': case 'u': case 'S': case 's':
10028 	  pptr++;
10029 	  continue;
10030 /*
10031  * A literal % is represented by %%. Skip the leading %.
10032  */
10033 	case '%':
10034 	  pptr++;
10035 	  break;
10036 	};
10037       };
10038       slen += gl_displayed_char_width(gl, *pptr, slen);
10039     };
10040     break;
10041   };
10042   return slen;
10043 }
10044 
10045 /*.......................................................................
10046  * Specify whether to heed text attribute directives within prompt
10047  * strings.
10048  *
10049  * Input:
10050  *  gl           GetLine *  The resource object of gl_get_line().
10051  *  style  GlPromptStyle    The style of prompt (see the definition of
10052  *                          GlPromptStyle in libtecla.h for details).
10053  */
10054 void gl_prompt_style(GetLine *gl, GlPromptStyle style)
10055 {
10056   if(gl) {
10057     sigset_t oldset; /* The signals that were blocked on entry to this block */
10058 /*
10059  * Temporarily block all signals.
10060  */
10061     gl_mask_signals(gl, &oldset);
10062 /*
10063  * Install the new style in gl while signals are blocked.
10064  */
10065     if(style != gl->prompt_style) {
10066       gl->prompt_style = style;
10067       gl->prompt_len = gl_displayed_prompt_width(gl);
10068       gl->prompt_changed = 1;
10069       gl_queue_redisplay(gl);
10070     };
10071 /*
10072  * Restore the process signal mask before returning.
10073  */
10074     gl_unmask_signals(gl, &oldset);
10075   };
10076 }
10077 
10078 /*.......................................................................
10079  * Tell gl_get_line() how to respond to a given signal. This can be used
10080  * both to override the default responses to signals that gl_get_line()
10081  * normally catches and to add new signals to the list that are to be
10082  * caught.
10083  *
10084  * Input:
10085  *  gl           GetLine *  The resource object of gl_get_line().
10086  *  signo            int    The number of the signal to be caught.
10087  *  flags       unsigned    A bitwise union of GlSignalFlags enumerators.
10088  *  after  GlAfterSignal    What to do after the application's signal
10089  *                          handler has been called.
10090  *  errno_value      int    The value to set errno to.
10091  * Output:
10092  *  return           int    0 - OK.
10093  *                          1 - Error.
10094  */
10095 int gl_trap_signal(GetLine *gl, int signo, unsigned flags,
10096 		   GlAfterSignal after, int errno_value)
10097 {
10098   sigset_t oldset; /* The signals that were blocked on entry to this function */
10099   int status;      /* The return status of this function */
10100 /*
10101  * Check the arguments.
10102  */
10103   if(!gl) {
10104     errno = EINVAL;
10105     return 1;
10106   };
10107 /*
10108  * Block all signals while modifying the contents of gl.
10109  */
10110   if(gl_mask_signals(gl, &oldset))
10111     return 1;
10112 /*
10113  * Perform the modification while signals are blocked.
10114  */
10115   status = _gl_trap_signal(gl, signo, flags, after, errno_value);
10116 /*
10117  * Restore the process signal mask before returning.
10118  */
10119   gl_unmask_signals(gl, &oldset);
10120   return status;
10121 }
10122 
10123 /*.......................................................................
10124  * This is the private body of the gl_trap_signal() function. It
10125  * assumes that the caller has checked its arguments and blocked the
10126  * delivery of signals.
10127  */
10128 static int _gl_trap_signal(GetLine *gl, int signo, unsigned flags,
10129 			   GlAfterSignal after, int errno_value)
10130 {
10131   GlSignalNode *sig;
10132 /*
10133  * Complain if an attempt is made to trap untrappable signals.
10134  * These would otherwise cause errors later in gl_mask_signals().
10135  */
10136   if(0
10137 #ifdef SIGKILL
10138      || signo==SIGKILL
10139 #endif
10140 #ifdef SIGBLOCK
10141      || signo==SIGBLOCK
10142 #endif
10143      ) {
10144     return 1;
10145   };
10146 /*
10147  * See if the signal has already been registered.
10148  */
10149   for(sig=gl->sigs; sig && sig->signo != signo; sig = sig->next)
10150     ;
10151 /*
10152  * If the signal hasn't already been registered, allocate a node for
10153  * it.
10154  */
10155   if(!sig) {
10156     sig = (GlSignalNode *) _new_FreeListNode(gl->sig_mem);
10157     if(!sig)
10158       return 1;
10159 /*
10160  * Add the new node to the head of the list.
10161  */
10162     sig->next = gl->sigs;
10163     gl->sigs = sig;
10164 /*
10165  * Record the signal number.
10166  */
10167     sig->signo = signo;
10168 /*
10169  * Create a signal set that includes just this signal.
10170  */
10171     sigemptyset(&sig->proc_mask);
10172     if(sigaddset(&sig->proc_mask, signo) == -1) {
10173       _err_record_msg(gl->err, "sigaddset error", END_ERR_MSG);
10174       sig = (GlSignalNode *) _del_FreeListNode(gl->sig_mem, sig);
10175       return 1;
10176     };
10177 /*
10178  * Add the signal to the bit-mask of signals being trapped.
10179  */
10180     sigaddset(&gl->all_signal_set, signo);
10181   };
10182 /*
10183  * Record the new signal attributes.
10184  */
10185   sig->flags = flags;
10186   sig->after = after;
10187   sig->errno_value = errno_value;
10188   return 0;
10189 }
10190 
10191 /*.......................................................................
10192  * Remove a signal from the list of signals that gl_get_line() traps.
10193  *
10194  * Input:
10195  *  gl           GetLine *  The resource object of gl_get_line().
10196  *  signo            int    The number of the signal to be ignored.
10197  * Output:
10198  *  return           int    0 - OK.
10199  *                          1 - Error.
10200  */
10201 int gl_ignore_signal(GetLine *gl, int signo)
10202 {
10203   GlSignalNode *sig;  /* The gl->sigs list node of the specified signal */
10204   GlSignalNode *prev; /* The node that precedes sig in the list */
10205   sigset_t oldset;    /* The signals that were blocked on entry to this */
10206                       /*  function. */
10207 /*
10208  * Check the arguments.
10209  */
10210   if(!gl) {
10211     errno = EINVAL;
10212     return 1;
10213   };
10214 /*
10215  * Block all signals while modifying the contents of gl.
10216  */
10217   if(gl_mask_signals(gl, &oldset))
10218     return 1;
10219 /*
10220  * Find the node of the gl->sigs list which records the disposition
10221  * of the specified signal.
10222  */
10223   for(prev=NULL,sig=gl->sigs; sig && sig->signo != signo;
10224       prev=sig,sig=sig->next)
10225     ;
10226   if(sig) {
10227 /*
10228  * Remove the node from the list.
10229  */
10230     if(prev)
10231       prev->next = sig->next;
10232     else
10233       gl->sigs = sig->next;
10234 /*
10235  * Return the node to the freelist.
10236  */
10237     sig = (GlSignalNode *) _del_FreeListNode(gl->sig_mem, sig);
10238 /*
10239  * Remove the signal from the bit-mask union of signals being trapped.
10240  */
10241     sigdelset(&gl->all_signal_set, signo);
10242   };
10243 /*
10244  * Restore the process signal mask before returning.
10245  */
10246   gl_unmask_signals(gl, &oldset);
10247   return 0;
10248 }
10249 
10250 /*.......................................................................
10251  * This function is called when an input line has been completed. It
10252  * appends the specified newline character, terminates the line,
10253  * records the line in the history buffer if appropriate, and positions
10254  * the terminal cursor at the start of the next line.
10255  *
10256  * Input:
10257  *  gl           GetLine *  The resource object of gl_get_line().
10258  *  newline_char     int    The newline character to add to the end
10259  *                          of the line.
10260  * Output:
10261  *  return           int    0 - OK.
10262  *                          1 - Error.
10263  */
10264 static int gl_line_ended(GetLine *gl, int newline_char)
10265 {
10266 /*
10267  * If the newline character is printable, display it at the end of
10268  * the line, and add it to the input line buffer.
10269  */
10270   if(isprint((int)(unsigned char) newline_char)) {
10271     if(gl_end_of_line(gl, 1, NULL) || gl_add_char_to_line(gl, newline_char))
10272       return 1;
10273   } else {
10274 /*
10275  * Otherwise just append a newline character to the input line buffer.
10276  */
10277     newline_char = '\n';
10278     gl_buffer_char(gl, newline_char, gl->ntotal);
10279   };
10280 /*
10281  * Add the line to the history buffer if it was entered with a
10282  * newline character.
10283  */
10284   if(gl->echo && gl->automatic_history && newline_char=='\n')
10285     (void) _gl_append_history(gl, gl->line);
10286 /*
10287  * Except when depending on the system-provided line editing, start a new
10288  * line after the end of the line that has just been entered.
10289  */
10290   if(gl->editor != GL_NO_EDITOR && gl_start_newline(gl, 1))
10291     return 1;
10292 /*
10293  * Record the successful return status.
10294  */
10295   gl_record_status(gl, GLR_NEWLINE, 0);
10296 /*
10297  * Attempt to flush any pending output.
10298  */
10299   (void) gl_flush_output(gl);
10300 /*
10301  * The next call to gl_get_line() will write the prompt for a new line
10302  * (or continue the above flush if incomplete), so if we manage to
10303  * flush the terminal now, report that we are waiting to write to the
10304  * terminal.
10305  */
10306   gl->pending_io = GLP_WRITE;
10307   return 0;
10308 }
10309 
10310 /*.......................................................................
10311  * Return the last signal that was caught by the most recent call to
10312  * gl_get_line(), or -1 if no signals were caught. This is useful if
10313  * gl_get_line() returns errno=EINTR and you need to find out what signal
10314  * caused it to abort.
10315  *
10316  * Input:
10317  *  gl           GetLine *  The resource object of gl_get_line().
10318  * Output:
10319  *  return           int    The last signal caught by the most recent
10320  *                          call to gl_get_line(), or -1 if no signals
10321  *                          were caught.
10322  */
10323 int gl_last_signal(GetLine *gl)
10324 {
10325   int signo = -1;   /* The requested signal number */
10326   if(gl) {
10327     sigset_t oldset; /* The signals that were blocked on entry to this block */
10328 /*
10329  * Temporarily block all signals.
10330  */
10331     gl_mask_signals(gl, &oldset);
10332 /*
10333  * Access gl now that signals are blocked.
10334  */
10335     signo = gl->last_signal;
10336 /*
10337  * Restore the process signal mask before returning.
10338  */
10339     gl_unmask_signals(gl, &oldset);
10340   };
10341   return signo;
10342 }
10343 
10344 /*.......................................................................
10345  * Prepare to edit a new line.
10346  *
10347  * Input:
10348  *  gl         GetLine *  The resource object of this library.
10349  *  prompt        char *  The prompt to prefix the line with, or NULL to
10350  *                        use the same prompt that was used by the previous
10351  *                        line.
10352  *  start_line    char *  The initial contents of the input line, or NULL
10353  *                        if it should start out empty.
10354  *  start_pos      int    If start_line isn't NULL, this specifies the
10355  *                        index of the character over which the cursor
10356  *                        should initially be positioned within the line.
10357  *                        If you just want it to follow the last character
10358  *                        of the line, send -1.
10359  * Output:
10360  *  return    int    0 - OK.
10361  *                   1 - Error.
10362  */
10363 static int gl_present_line(GetLine *gl, const char *prompt,
10364 			   const char *start_line, int start_pos)
10365 {
10366 /*
10367  * Reset the properties of the line.
10368  */
10369   gl_reset_input_line(gl);
10370 /*
10371  * Record the new prompt and its displayed width.
10372  */
10373   if(prompt)
10374     _gl_replace_prompt(gl, prompt);
10375 /*
10376  * Reset the history search pointers.
10377  */
10378   if(_glh_cancel_search(gl->glh)) {
10379     _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
10380     return 1;
10381   };
10382 /*
10383  * If the previous line was entered via the repeat-history action,
10384  * preload the specified history line.
10385  */
10386   if(gl->preload_history) {
10387     gl->preload_history = 0;
10388     if(gl->preload_id) {
10389       if(_glh_recall_line(gl->glh, gl->preload_id, gl->line, gl->linelen+1)) {
10390 	gl_update_buffer(gl);          /* Compute gl->ntotal etc.. */
10391 	gl->buff_curpos = gl->ntotal;
10392       } else {
10393 	gl_truncate_buffer(gl, 0);
10394       };
10395       gl->preload_id = 0;
10396     };
10397 /*
10398  * Present a specified initial line?
10399  */
10400   } else if(start_line) {
10401     char *cptr;      /* A pointer into gl->line[] */
10402 /*
10403  * Measure the length of the starting line.
10404  */
10405     int start_len = strlen(start_line);
10406 /*
10407  * If the length of the line is greater than the available space,
10408  * truncate it.
10409  */
10410     if(start_len > gl->linelen)
10411       start_len = gl->linelen;
10412 /*
10413  * Load the line into the buffer.
10414  */
10415     if(start_line != gl->line)
10416       gl_buffer_string(gl, start_line, start_len, 0);
10417 /*
10418  * Strip off any trailing newline and carriage return characters.
10419  */
10420     for(cptr=gl->line + gl->ntotal - 1; cptr >= gl->line &&
10421 	(*cptr=='\n' || *cptr=='\r'); cptr--,gl->ntotal--)
10422       ;
10423     gl_truncate_buffer(gl, gl->ntotal < 0 ? 0 : gl->ntotal);
10424 /*
10425  * Where should the cursor be placed within the line?
10426  */
10427     if(start_pos < 0 || start_pos > gl->ntotal) {
10428       if(gl_place_cursor(gl, gl->ntotal))
10429 	return 1;
10430     } else {
10431       if(gl_place_cursor(gl, start_pos))
10432 	return 1;
10433     };
10434 /*
10435  * Clear the input line?
10436  */
10437   } else {
10438     gl_truncate_buffer(gl, 0);
10439   };
10440 /*
10441  * Arrange for the line to be displayed by gl_flush_output().
10442  */
10443   gl_queue_redisplay(gl);
10444 /*
10445  * Update the display.
10446  */
10447   return gl_flush_output(gl);
10448 }
10449 
10450 /*.......................................................................
10451  * Reset all line input parameters for a new input line.
10452  *
10453  * Input:
10454  *  gl      GetLine *  The line editor resource object.
10455  */
10456 static void gl_reset_input_line(GetLine *gl)
10457 {
10458   gl->ntotal = 0;
10459   gl->line[0] = '\0';
10460   gl->buff_curpos = 0;
10461   gl->term_curpos = 0;
10462   gl->term_len = 0;
10463   gl->insert_curpos = 0;
10464   gl->number = -1;
10465   gl->displayed = 0;
10466   gl->endline = 0;
10467   gl->redisplay = 0;
10468   gl->postpone = 0;
10469   gl->nbuf = 0;
10470   gl->nread = 0;
10471   gl->vi.command = 0;
10472   gl->vi.undo.line[0] = '\0';
10473   gl->vi.undo.ntotal = 0;
10474   gl->vi.undo.buff_curpos = 0;
10475   gl->vi.repeat.action.fn = 0;
10476   gl->vi.repeat.action.data = 0;
10477   gl->last_signal = -1;
10478 }
10479 
10480 /*.......................................................................
10481  * Print an informational message to the terminal, after starting a new
10482  * line.
10483  *
10484  * Input:
10485  *  gl      GetLine *  The line editor resource object.
10486  *  ...  const char *  Zero or more strings to be printed.
10487  *  ...        void *  The last argument must always be GL_END_INFO.
10488  * Output:
10489  *  return      int    0 - OK.
10490  *                     1 - Error.
10491  */
10492 static int gl_print_info(GetLine *gl, ...)
10493 {
10494   va_list ap;     /* The variable argument list */
10495   const char *s;  /* The string being printed */
10496   int waserr = 0; /* True after an error */
10497 /*
10498  * Only display output when echoing is on.
10499  */
10500   if(gl->echo) {
10501 /*
10502  * Skip to the start of the next empty line before displaying the message.
10503  */
10504     if(gl_start_newline(gl, 1))
10505       return 1;
10506 /*
10507  * Display the list of provided messages.
10508  */
10509     va_start(ap, gl);
10510     while(!waserr && (s = va_arg(ap, const char *)) != GL_END_INFO)
10511       waserr = gl_print_raw_string(gl, 1, s, -1);
10512     va_end(ap);
10513 /*
10514  * Start a newline.
10515  */
10516     waserr = waserr || gl_print_raw_string(gl, 1, "\n\r", -1);
10517 /*
10518  * Arrange for the input line to be redrawn.
10519  */
10520     gl_queue_redisplay(gl);
10521   };
10522   return waserr;
10523 }
10524 
10525 /*.......................................................................
10526  * Go to the start of the next empty line, ready to output miscellaneous
10527  * text to the screen.
10528  *
10529  * Note that when async-signal safety is required, the 'buffered'
10530  * argument must be 0.
10531  *
10532  * Input:
10533  *  gl          GetLine *  The line editor resource object.
10534  *  buffered        int    If true, used buffered I/O when writing to
10535  *                         the terminal. Otherwise use async-signal-safe
10536  *                         unbuffered I/O.
10537  * Output:
10538  *  return          int    0 - OK.
10539  *                         1 - Error.
10540  */
10541 static int gl_start_newline(GetLine *gl, int buffered)
10542 {
10543   int waserr = 0;  /* True after any I/O error */
10544 /*
10545  * Move the cursor to the start of the terminal line that follows the
10546  * last line of the partially enterred line. In order that this
10547  * function remain async-signal safe when write_fn is signal safe, we
10548  * can't call our normal output functions, since they call tputs(),
10549  * who's signal saftey isn't defined. Fortunately, we can simply use
10550  * \r and \n to move the cursor to the right place.
10551  */
10552   if(gl->displayed) {   /* Is an input line currently displayed? */
10553 /*
10554  * On which terminal lines are the cursor and the last character of the
10555  * input line?
10556  */
10557     int curs_line = gl->term_curpos / gl->ncolumn;
10558     int last_line = gl->term_len / gl->ncolumn;
10559 /*
10560  * Move the cursor to the start of the line that follows the last
10561  * terminal line that is occupied by the input line.
10562  */
10563     for( ; curs_line < last_line + 1; curs_line++)
10564       waserr = waserr || gl_print_raw_string(gl, buffered, "\n", 1);
10565     waserr = waserr || gl_print_raw_string(gl, buffered, "\r", 1);
10566 /*
10567  * Mark the line as no longer displayed.
10568  */
10569     gl_line_erased(gl);
10570   };
10571   return waserr;
10572 }
10573 
10574 /*.......................................................................
10575  * The callback through which all terminal output is routed.
10576  * This simply appends characters to a queue buffer, which is
10577  * subsequently flushed to the output channel by gl_flush_output().
10578  *
10579  * Input:
10580  *  data     void *  The pointer to a GetLine line editor resource object
10581  *                   cast to (void *).
10582  *  s  const char *  The string to be written.
10583  *  n         int    The number of characters to write from s[].
10584  * Output:
10585  *  return    int    The number of characters written. This will always
10586  *                   be equal to 'n' unless an error occurs.
10587  */
10588 static GL_WRITE_FN(gl_write_fn)
10589 {
10590   GetLine *gl = (GetLine *) data;
10591   int ndone = _glq_append_chars(gl->cq, s, n, gl->flush_fn, gl);
10592   if(ndone != n)
10593     _err_record_msg(gl->err, _glq_last_error(gl->cq), END_ERR_MSG);
10594   return ndone;
10595 }
10596 
10597 /*.......................................................................
10598  * Ask gl_get_line() what caused it to return.
10599  *
10600  * Input:
10601  *  gl             GetLine *  The line editor resource object.
10602  * Output:
10603  *  return  GlReturnStatus    The return status of the last call to
10604  *                            gl_get_line().
10605  */
10606 GlReturnStatus gl_return_status(GetLine *gl)
10607 {
10608   GlReturnStatus rtn_status = GLR_ERROR;   /* The requested status */
10609   if(gl) {
10610     sigset_t oldset; /* The signals that were blocked on entry to this block */
10611 /*
10612  * Temporarily block all signals.
10613  */
10614     gl_mask_signals(gl, &oldset);
10615 /*
10616  * Access gl while signals are blocked.
10617  */
10618     rtn_status = gl->rtn_status;
10619 /*
10620  * Restore the process signal mask before returning.
10621  */
10622     gl_unmask_signals(gl, &oldset);
10623   };
10624   return rtn_status;
10625 }
10626 
10627 /*.......................................................................
10628  * In non-blocking server-I/O mode, this function should be called
10629  * from the application's external event loop to see what type of
10630  * terminal I/O is being waited for by gl_get_line(), and thus what
10631  * direction of I/O to wait for with select() or poll().
10632  *
10633  * Input:
10634  *  gl          GetLine *  The resource object of gl_get_line().
10635  * Output:
10636  *  return  GlPendingIO    The type of pending I/O being waited for.
10637  */
10638 GlPendingIO gl_pending_io(GetLine *gl)
10639 {
10640   GlPendingIO pending_io = GLP_WRITE;   /* The requested information */
10641   if(gl) {
10642     sigset_t oldset; /* The signals that were blocked on entry to this block */
10643 /*
10644  * Temporarily block all signals.
10645  */
10646     gl_mask_signals(gl, &oldset);
10647 /*
10648  * Access gl while signals are blocked.
10649  */
10650     pending_io = gl->pending_io;
10651 /*
10652  * Restore the process signal mask before returning.
10653  */
10654     gl_unmask_signals(gl, &oldset);
10655   };
10656   return pending_io;
10657 }
10658 
10659 /*.......................................................................
10660  * In server mode, this function configures the terminal for non-blocking
10661  * raw terminal I/O. In normal I/O mode it does nothing.
10662  *
10663  * Callers of this function must be careful to trap all signals that
10664  * terminate or suspend the program, and call gl_normal_io()
10665  * from the corresponding signal handlers in order to restore the
10666  * terminal to its original settings before the program is terminated
10667  * or suspended. They should also trap the SIGCONT signal to detect
10668  * when the program resumes, and ensure that its signal handler
10669  * call gl_raw_io() to redisplay the line and resume editing.
10670  *
10671  * This function is async signal safe.
10672  *
10673  * Input:
10674  *  gl      GetLine *  The line editor resource object.
10675  * Output:
10676  *  return      int    0 - OK.
10677  *                     1 - Error.
10678  */
10679 int gl_raw_io(GetLine *gl)
10680 {
10681   sigset_t oldset; /* The signals that were blocked on entry to this function */
10682   int status;      /* The return status of _gl_raw_io() */
10683 /*
10684  * Check the arguments.
10685  */
10686   if(!gl) {
10687     errno = EINVAL;
10688     return 1;
10689   };
10690 /*
10691  * Block all signals.
10692  */
10693   if(gl_mask_signals(gl, &oldset))
10694     return 1;
10695 /*
10696  * Don't allow applications to switch into raw mode unless in server mode.
10697  */
10698   if(gl->io_mode != GL_SERVER_MODE) {
10699     _err_record_msg(gl->err, "Can't switch to raw I/O unless in server mode",
10700 		    END_ERR_MSG);
10701     errno = EPERM;
10702     status = 1;
10703   } else {
10704 /*
10705  * Execute the private body of the function while signals are blocked.
10706  */
10707     status = _gl_raw_io(gl, 1);
10708   };
10709 /*
10710  * Restore the process signal mask.
10711  */
10712   gl_unmask_signals(gl, &oldset);
10713   return status;
10714 }
10715 
10716 /*.......................................................................
10717  * This is the private body of the public function, gl_raw_io().
10718  * It assumes that the caller has checked its arguments and blocked the
10719  * delivery of signals.
10720  *
10721  * This function is async signal safe.
10722  */
10723 static int _gl_raw_io(GetLine *gl, int redisplay)
10724 {
10725 /*
10726  * If we are already in the correct mode, do nothing.
10727  */
10728   if(gl->raw_mode)
10729     return 0;
10730 /*
10731  * Switch the terminal to raw mode.
10732  */
10733   if(gl->is_term && gl_raw_terminal_mode(gl))
10734     return 1;
10735 /*
10736  * Switch to non-blocking I/O mode?
10737  */
10738   if(gl->io_mode==GL_SERVER_MODE &&
10739      (gl_nonblocking_io(gl, gl->input_fd) ||
10740       gl_nonblocking_io(gl, gl->output_fd) ||
10741       (gl->file_fp && gl_nonblocking_io(gl, fileno(gl->file_fp))))) {
10742     if(gl->is_term)
10743       gl_restore_terminal_attributes(gl);
10744     return 1;
10745   };
10746 /*
10747  * If an input line is being entered, arrange for it to be
10748  * displayed.
10749  */
10750   if(redisplay) {
10751     gl->postpone = 0;
10752     gl_queue_redisplay(gl);
10753   };
10754   return 0;
10755 }
10756 
10757 /*.......................................................................
10758  * Restore the terminal to the state that it had when
10759  * gl_raw_io() was last called. After calling
10760  * gl_raw_io(), this function must be called before
10761  * terminating or suspending the program, and before attempting other
10762  * uses of the terminal from within the program. See gl_raw_io()
10763  * for more details.
10764  *
10765  * Input:
10766  *  gl      GetLine *  The line editor resource object.
10767  * Output:
10768  *  return      int    0 - OK.
10769  *                     1 - Error.
10770  */
10771 int gl_normal_io(GetLine *gl)
10772 {
10773   sigset_t oldset; /* The signals that were blocked on entry to this function */
10774   int status;      /* The return status of _gl_normal_io() */
10775 /*
10776  * Check the arguments.
10777  */
10778   if(!gl) {
10779     errno = EINVAL;
10780     return 1;
10781   };
10782 /*
10783  * Block all signals.
10784  */
10785   if(gl_mask_signals(gl, &oldset))
10786     return 1;
10787 /*
10788  * Execute the private body of the function while signals are blocked.
10789  */
10790   status = _gl_normal_io(gl);
10791 /*
10792  * Restore the process signal mask.
10793  */
10794   gl_unmask_signals(gl, &oldset);
10795   return status;
10796 }
10797 
10798 /*.......................................................................
10799  * This is the private body of the public function, gl_normal_io().
10800  * It assumes that the caller has checked its arguments and blocked the
10801  * delivery of signals.
10802  */
10803 static int _gl_normal_io(GetLine *gl)
10804 {
10805 /*
10806  * If we are already in normal mode, do nothing.
10807  */
10808   if(!gl->raw_mode)
10809     return 0;
10810 /*
10811  * Postpone subsequent redisplays until after _gl_raw_io(gl, 1)
10812  * is next called.
10813  */
10814   gl->postpone = 1;
10815 /*
10816  * Switch back to blocking I/O. Note that this is essential to do
10817  * here, because when using non-blocking I/O, the terminal output
10818  * buffering code can't always make room for new output without calling
10819  * malloc(), and a call to malloc() would mean that this function
10820  * couldn't safely be called from signal handlers.
10821  */
10822   if(gl->io_mode==GL_SERVER_MODE &&
10823      (gl_blocking_io(gl, gl->input_fd) ||
10824       gl_blocking_io(gl, gl->output_fd) ||
10825       (gl->file_fp && gl_blocking_io(gl, fileno(gl->file_fp)))))
10826     return 1;
10827 /*
10828  * Move the cursor to the next empty terminal line. Note that
10829  * unbuffered I/O is requested, to ensure that gl_start_newline() be
10830  * async-signal-safe.
10831  */
10832   if(gl->is_term && gl_start_newline(gl, 0))
10833     return 1;
10834 /*
10835  * Switch the terminal to normal mode.
10836  */
10837   if(gl->is_term && gl_restore_terminal_attributes(gl)) {
10838 /*
10839  * On error, revert to non-blocking I/O if needed, so that on failure
10840  * we remain in raw mode.
10841  */
10842     if(gl->io_mode==GL_SERVER_MODE) {
10843       gl_nonblocking_io(gl, gl->input_fd);
10844       gl_nonblocking_io(gl, gl->output_fd);
10845       if(gl->file_fp)
10846 	gl_nonblocking_io(gl, fileno(gl->file_fp));
10847     };
10848     return 1;
10849   };
10850   return 0;
10851 }
10852 
10853 /*.......................................................................
10854  * This function allows you to install an additional completion
10855  * action, or to change the completion function of an existing
10856  * one. This should be called before the first call to gl_get_line()
10857  * so that the name of the action be defined before the user's
10858  * configuration file is read.
10859  *
10860  * Input:
10861  *  gl            GetLine *  The resource object of the command-line input
10862  *                           module.
10863  *  data             void *  This is passed to match_fn() whenever it is
10864  *                           called. It could, for example, point to a
10865  *                           symbol table that match_fn() would look up
10866  *                           matches in.
10867  *  match_fn   CplMatchFn *  The function that will identify the prefix
10868  *                           to be completed from the input line, and
10869  *                           report matching symbols.
10870  *  list_only         int    If non-zero, install an action that only lists
10871  *                           possible completions, rather than attempting
10872  *                           to perform the completion.
10873  *  name       const char *  The name with which users can refer to the
10874  *                           binding in tecla configuration files.
10875  *  keyseq     const char *  Either NULL, or a key sequence with which
10876  *                           to invoke the binding. This should be
10877  *                           specified in the same manner as key-sequences
10878  *                           in tecla configuration files (eg. "M-^I").
10879  * Output:
10880  *  return            int    0 - OK.
10881  *                           1 - Error.
10882  */
10883 int gl_completion_action(GetLine *gl, void *data, CplMatchFn *match_fn,
10884 			 int list_only, const char *name, const char *keyseq)
10885 {
10886   sigset_t oldset; /* The signals that were blocked on entry to this function */
10887   int status;      /* The return status of _gl_completion_action() */
10888 /*
10889  * Check the arguments.
10890  */
10891   if(!gl || !name || !match_fn) {
10892     errno = EINVAL;
10893     return 1;
10894   };
10895 /*
10896  * Block all signals.
10897  */
10898   if(gl_mask_signals(gl, &oldset))
10899     return 1;
10900 /*
10901  * Install the new action while signals are blocked.
10902  */
10903   status = _gl_completion_action(gl, data, match_fn, list_only, name, keyseq);
10904 /*
10905  * Restore the process signal mask.
10906  */
10907   gl_unmask_signals(gl, &oldset);
10908   return status;
10909 }
10910 
10911 /*.......................................................................
10912  * This is the private body of the public function, gl_completion_action().
10913  * It assumes that the caller has checked its arguments and blocked the
10914  * delivery of signals.
10915  */
10916 static int _gl_completion_action(GetLine *gl, void *data, CplMatchFn *match_fn,
10917 				 int list_only, const char *name,
10918 				 const char *keyseq)
10919 {
10920   KtKeyFn *current_fn;      /* An existing action function */
10921   void *current_data;       /* The action-function callback data */
10922 /*
10923  * Which action function is desired?
10924  */
10925   KtKeyFn *action_fn = list_only ? gl_list_completions : gl_complete_word;
10926 /*
10927  * Is there already an action of the specified name?
10928  */
10929   if(_kt_lookup_action(gl->bindings, name, &current_fn, &current_data) == 0) {
10930 /*
10931  * If the action has the same type as the one being requested,
10932  * simply change the contents of its GlCplCallback callback data.
10933  */
10934     if(current_fn == action_fn) {
10935       GlCplCallback *cb = (GlCplCallback *) current_data;
10936       cb->fn = match_fn;
10937       cb->data = data;
10938     } else {
10939       errno = EINVAL;
10940       _err_record_msg(gl->err,
10941         "Illegal attempt to change the type of an existing completion action",
10942         END_ERR_MSG);
10943       return 1;
10944     };
10945 /*
10946  * No existing action has the specified name.
10947  */
10948   } else {
10949 /*
10950  * Allocate a new GlCplCallback callback object.
10951  */
10952     GlCplCallback *cb = (GlCplCallback *) _new_FreeListNode(gl->cpl_mem);
10953     if(!cb) {
10954       errno = ENOMEM;
10955       _err_record_msg(gl->err, "Insufficient memory to add completion action",
10956 		      END_ERR_MSG);
10957       return 1;
10958     };
10959 /*
10960  * Record the completion callback data.
10961  */
10962     cb->fn = match_fn;
10963     cb->data = data;
10964 /*
10965  * Attempt to register the new action.
10966  */
10967     if(_kt_set_action(gl->bindings, name, action_fn, cb)) {
10968       _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG);
10969       _del_FreeListNode(gl->cpl_mem, (void *) cb);
10970       return 1;
10971     };
10972   };
10973 /*
10974  * Bind the action to a given key-sequence?
10975  */
10976   if(keyseq && _kt_set_keybinding(gl->bindings, KTB_NORM, keyseq, name)) {
10977     _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG);
10978     return 1;
10979   };
10980   return 0;
10981 }
10982 
10983 /*.......................................................................
10984  * Register an application-provided function as an action function.
10985  * This should preferably be called before the first call to gl_get_line()
10986  * so that the name of the action becomes defined before the user's
10987  * configuration file is read.
10988  *
10989  * Input:
10990  *  gl            GetLine *  The resource object of the command-line input
10991  *                           module.
10992  *  data             void *  Arbitrary application-specific callback
10993  *                           data to be passed to the callback
10994  *                           function, fn().
10995  *  fn         GlActionFn *  The application-specific function that
10996  *                           implements the action. This will be invoked
10997  *                           whenever the user presses any
10998  *                           key-sequence which is bound to this action.
10999  *  name       const char *  The name with which users can refer to the
11000  *                           binding in tecla configuration files.
11001  *  keyseq     const char *  The key sequence with which to invoke
11002  *                           the binding. This should be specified in the
11003  *                           same manner as key-sequences in tecla
11004  *                           configuration files (eg. "M-^I").
11005  * Output:
11006  *  return            int    0 - OK.
11007  *                           1 - Error.
11008  */
11009 int gl_register_action(GetLine *gl, void *data, GlActionFn *fn,
11010                        const char *name, const char *keyseq)
11011 {
11012   sigset_t oldset; /* The signals that were blocked on entry to this function */
11013   int status;      /* The return status of _gl_register_action() */
11014 /*
11015  * Check the arguments.
11016  */
11017   if(!gl || !name || !fn) {
11018     errno = EINVAL;
11019     return 1;
11020   };
11021 /*
11022  * Block all signals.
11023  */
11024   if(gl_mask_signals(gl, &oldset))
11025     return 1;
11026 /*
11027  * Install the new action while signals are blocked.
11028  */
11029   status = _gl_register_action(gl, data, fn, name, keyseq);
11030 /*
11031  * Restore the process signal mask.
11032  */
11033   gl_unmask_signals(gl, &oldset);
11034   return status;
11035 }
11036 
11037 /*.......................................................................
11038  * This is the private body of the public function, gl_register_action().
11039  * It assumes that the caller has checked its arguments and blocked the
11040  * delivery of signals.
11041  */
11042 static int _gl_register_action(GetLine *gl, void *data, GlActionFn *fn,
11043 			       const char *name, const char *keyseq)
11044 {
11045   KtKeyFn *current_fn;      /* An existing action function */
11046   void *current_data;       /* The action-function callback data */
11047 /*
11048  * Get the action function which actually runs the application-provided
11049  * function.
11050  */
11051   KtKeyFn *action_fn = gl_run_external_action;
11052 /*
11053  * Is there already an action of the specified name?
11054  */
11055   if(_kt_lookup_action(gl->bindings, name, &current_fn, &current_data) == 0) {
11056 /*
11057  * If the action has the same type as the one being requested,
11058  * simply change the contents of its GlCplCallback callback data.
11059  */
11060     if(current_fn == action_fn) {
11061       GlExternalAction *a = (GlExternalAction *) current_data;
11062       a->fn = fn;
11063       a->data = data;
11064     } else {
11065       errno = EINVAL;
11066       _err_record_msg(gl->err,
11067         "Illegal attempt to change the type of an existing action",
11068 		      END_ERR_MSG);
11069       return 1;
11070     };
11071 /*
11072  * No existing action has the specified name.
11073  */
11074   } else {
11075 /*
11076  * Allocate a new GlCplCallback callback object.
11077  */
11078     GlExternalAction *a =
11079       (GlExternalAction *) _new_FreeListNode(gl->ext_act_mem);
11080     if(!a) {
11081       errno = ENOMEM;
11082       _err_record_msg(gl->err, "Insufficient memory to add completion action",
11083 		      END_ERR_MSG);
11084       return 1;
11085     };
11086 /*
11087  * Record the completion callback data.
11088  */
11089     a->fn = fn;
11090     a->data = data;
11091 /*
11092  * Attempt to register the new action.
11093  */
11094     if(_kt_set_action(gl->bindings, name, action_fn, a)) {
11095       _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG);
11096       _del_FreeListNode(gl->cpl_mem, (void *) a);
11097       return 1;
11098     };
11099   };
11100 /*
11101  * Bind the action to a given key-sequence?
11102  */
11103   if(keyseq && _kt_set_keybinding(gl->bindings, KTB_NORM, keyseq, name)) {
11104     _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG);
11105     return 1;
11106   };
11107   return 0;
11108 }
11109 
11110 /*.......................................................................
11111  * Invoke an action function previously registered by a call to
11112  * gl_register_action().
11113  */
11114 static KT_KEY_FN(gl_run_external_action)
11115 {
11116   GlAfterAction status;  /* The return value of the action function */
11117 /*
11118  * Get the container of the action function and associated callback data.
11119  */
11120   GlExternalAction *a = (GlExternalAction *) data;
11121 /*
11122  * Invoke the action function.
11123  */
11124   status = a->fn(gl, a->data, count, gl->buff_curpos, gl->line);
11125 /*
11126  * If the callback took us out of raw (possibly non-blocking) input
11127  * mode, restore this mode, and queue a redisplay of the input line.
11128  */
11129   if(_gl_raw_io(gl, 1))
11130     return 1;
11131 /*
11132  * Finally, check to see what the action function wants us to do next.
11133  */
11134   switch(status) {
11135   default:
11136   case GLA_ABORT:
11137     gl_record_status(gl, GLR_ERROR, errno);
11138     return 1;
11139     break;
11140   case GLA_RETURN:
11141     return gl_newline(gl, 1, NULL);
11142     break;
11143   case GLA_CONTINUE:
11144     break;
11145   };
11146   return 0;
11147 }
11148 
11149 /*.......................................................................
11150  * In server-I/O mode the terminal is left in raw mode between calls
11151  * to gl_get_line(), so it is necessary for the application to install
11152  * terminal restoring signal handlers for signals that could terminate
11153  * or suspend the process, plus a terminal reconfiguration handler to
11154  * be called when a process resumption signal is received, and finally
11155  * a handler to be called when a terminal-resize signal is received.
11156  *
11157  * Since there are many signals that by default terminate or suspend
11158  * processes, and different systems support different sub-sets of
11159  * these signals, this function provides a convenient wrapper around
11160  * sigaction() for assigning the specified handlers to all appropriate
11161  * signals. It also arranges that when any one of these signals is
11162  * being handled, all other catchable signals are blocked. This is
11163  * necessary so that the specified signal handlers can safely call
11164  * gl_raw_io(), gl_normal_io() and gl_update_size() without
11165  * reentrancy issues.
11166  *
11167  * Input:
11168  *  term_handler  void (*)(int)  The signal handler to invoke when
11169  *                               a process terminating signal is
11170  *                               received.
11171  *  susp_handler  void (*)(int)  The signal handler to invoke when
11172  *                               a process suspending signal is
11173  *                               received.
11174  *  cont_handler  void (*)(int)  The signal handler to invoke when
11175  *                               a process resumption signal is
11176  *                               received (ie. SIGCONT).
11177  *  size_handler  void (*)(int)  The signal handler to invoke when
11178  *                               a terminal-resize signal (ie. SIGWINCH)
11179  *                               is received.
11180  * Output:
11181  *  return                  int  0 - OK.
11182  *                               1 - Error.
11183  */
11184 int gl_tty_signals(void (*term_handler)(int), void (*susp_handler)(int),
11185 		   void (*cont_handler)(int), void (*size_handler)(int))
11186 {
11187   int i;
11188 /*
11189  * Search for signals of the specified classes, and assign the
11190  * associated signal handler to them.
11191  */
11192   for(i=0; i<sizeof(gl_signal_list)/sizeof(gl_signal_list[0]); i++) {
11193     const struct GlDefSignal *sig = gl_signal_list + i;
11194     if(sig->attr & GLSA_SUSP) {
11195       if(gl_set_tty_signal(sig->signo, term_handler))
11196 	return 1;
11197     } else if(sig->attr & GLSA_TERM) {
11198       if(gl_set_tty_signal(sig->signo, susp_handler))
11199 	return 1;
11200     } else if(sig->attr & GLSA_CONT) {
11201       if(gl_set_tty_signal(sig->signo, cont_handler))
11202 	return 1;
11203     } else if(sig->attr & GLSA_SIZE) {
11204       if(gl_set_tty_signal(sig->signo, size_handler))
11205 	return 1;
11206     };
11207   };
11208   return 0;
11209 }
11210 
11211 /*.......................................................................
11212  * This is a private function of gl_tty_signals(). It installs a given
11213  * signal handler, and arranges that when that signal handler is being
11214  * invoked other signals are blocked. The latter is important to allow
11215  * functions like gl_normal_io(), gl_raw_io() and gl_update_size()
11216  * to be called from signal handlers.
11217  *
11218  * Input:
11219  *  signo     int           The signal to be trapped.
11220  *  handler  void (*)(int)  The signal handler to assign to the signal.
11221  */
11222 static int gl_set_tty_signal(int signo, void (*handler)(int))
11223 {
11224   SigAction act;   /* The signal handler configuation */
11225 /*
11226  * Arrange to block all trappable signals except the one that is being
11227  * assigned (the trapped signal will be blocked automatically by the
11228  * system).
11229  */
11230   gl_list_trappable_signals(&act.sa_mask);
11231   sigdelset(&act.sa_mask, signo);
11232 /*
11233  * Assign the signal handler.
11234  */
11235   act.sa_handler = handler;
11236 /*
11237  * There is only one portable signal handling flag, and it isn't
11238  * relevant to us, so don't specify any flags.
11239  */
11240   act.sa_flags = 0;
11241 /*
11242  * Register the signal handler.
11243  */
11244   if(sigaction(signo, &act, NULL))
11245     return 1;
11246   return 0;
11247 }
11248 
11249 /*.......................................................................
11250  * Display a left-justified string over multiple terminal lines,
11251  * taking account of the current width of the terminal. Optional
11252  * indentation and an optional prefix string can be specified to be
11253  * displayed at the start of each new terminal line used. Similarly,
11254  * an optional suffix can be specified to be displayed at the end of
11255  * each terminal line.  If needed, a single paragraph can be broken
11256  * across multiple calls.  Note that literal newlines in the input
11257  * string can be used to force a newline at any point and that you
11258  * should use this feature to explicitly end all paragraphs, including
11259  * at the end of the last string that you write. Note that when a new
11260  * line is started between two words that are separated by spaces,
11261  * those spaces are not output, whereas when a new line is started
11262  * because a newline character was found in the string, only the
11263  * spaces before the newline character are discarded.
11264  *
11265  * Input:
11266  *  gl         GetLine *  The resource object of gl_get_line().
11267  *  indentation    int    The number of spaces of indentation to write
11268  *                        at the beginning of each new terminal line.
11269  *  prefix  const char *  An optional prefix string to write after the
11270  *                        indentation margin at the start of each new
11271  *                        terminal line. You can specify NULL if no
11272  *                        prefix is required.
11273  *  suffix  const char *  An optional suffix string to draw at the end
11274  *                        of the terminal line. Spaces will be added
11275  *                        where necessary to ensure that the suffix ends
11276  *                        in the last column of the terminal line. If
11277  *                        no suffix is desired, specify NULL.
11278  *  fill_char      int    The padding character to use when indenting
11279  *                        the line or padding up to the suffix.
11280  *  def_width      int    If the terminal width isn't known, such as when
11281  *                        writing to a pipe or redirecting to a file,
11282  *                        this number specifies what width to assume.
11283  *  start          int    The number of characters already written to
11284  *                        the start of the current terminal line. This
11285  *                        is primarily used to allow individual
11286  *                        paragraphs to be written over multiple calls
11287  *                        to this function, but can also be used to
11288  *                        allow you to start the first line of a
11289  *                        paragraph with a different prefix or
11290  *                        indentation than those specified above.
11291  *  string  const char *  The string to be written.
11292  * Output:
11293  *  return         int    On error -1 is returned. Otherwise the
11294  *                        return value is the terminal column index at
11295  *                        which the cursor was left after writing the
11296  *                        final word in the string. Successful return
11297  *                        values can thus be passed verbatim to the
11298  *                        'start' arguments of subsequent calls to
11299  *                        gl_display_text() to allow the printing of a
11300  *                        paragraph to be broken across multiple calls
11301  *                        to gl_display_text().
11302  */
11303 int gl_display_text(GetLine *gl, int indentation, const char *prefix,
11304 		    const char *suffix, int fill_char,
11305 		    int def_width, int start, const char *string)
11306 {
11307   sigset_t oldset; /* The signals that were blocked on entry to this function */
11308   int status;      /* The return status of _gl_completion_action() */
11309 /*
11310  * Check the arguments?
11311  */
11312   if(!gl || !string) {
11313     errno = EINVAL;
11314     return -1;
11315   };
11316 /*
11317  * Block all signals.
11318  */
11319   if(gl_mask_signals(gl, &oldset))
11320     return -1;
11321 /*
11322  * Display the text while signals are blocked.
11323  */
11324   status = _io_display_text(_io_write_stdio, gl->output_fp, indentation,
11325 			    prefix, suffix, fill_char,
11326 			    gl->ncolumn > 0 ? gl->ncolumn : def_width,
11327 			    start, string);
11328 /*
11329  * Restore the process signal mask.
11330  */
11331   gl_unmask_signals(gl, &oldset);
11332   return status;
11333 }
11334 
11335 /*.......................................................................
11336  * Block all of the signals that we are currently trapping.
11337  *
11338  * Input:
11339  *  gl       GetLine *   The resource object of gl_get_line().
11340  * Input/Output:
11341  *  oldset   sigset_t *   The superseded process signal mask
11342  *                        will be return in *oldset unless oldset is
11343  *                        NULL.
11344  * Output:
11345  *  return        int     0 - OK.
11346  *                        1 - Error.
11347  */
11348 static int gl_mask_signals(GetLine *gl, sigset_t *oldset)
11349 {
11350 /*
11351  * Block all signals in all_signal_set, along with any others that are
11352  * already blocked by the application.
11353  */
11354   if(sigprocmask(SIG_BLOCK, &gl->all_signal_set, oldset) >= 0) {
11355     gl->signals_masked = 1;
11356     return 0;
11357   };
11358 /*
11359  * On error attempt to query the current process signal mask, so
11360  * that oldset be the correct process signal mask to restore later
11361  * if the caller of this function ignores the error return value.
11362  */
11363   if(oldset)
11364     (void) sigprocmask(SIG_SETMASK, NULL, oldset);
11365   gl->signals_masked = 0;
11366   return 1;
11367 }
11368 
11369 /*.......................................................................
11370  * Restore a process signal mask that was previously returned via the
11371  * oldset argument of gl_mask_signals().
11372  *
11373  * Input:
11374  *  gl        GetLine *   The resource object of gl_get_line().
11375  * Input/Output:
11376  *  oldset   sigset_t *   The process signal mask to be restored.
11377  * Output:
11378  *  return        int     0 - OK.
11379  *                        1 - Error.
11380  */
11381 static int gl_unmask_signals(GetLine *gl, sigset_t *oldset)
11382 {
11383   gl->signals_masked = 0;
11384   return sigprocmask(SIG_SETMASK, oldset, NULL) < 0;
11385 }
11386 
11387 /*.......................................................................
11388  * Arrange to temporarily catch the signals marked in gl->use_signal_set.
11389  *
11390  * Input:
11391  *  gl        GetLine *   The resource object of gl_get_line().
11392  * Output:
11393  *  return        int     0 - OK.
11394  *                        1 - Error.
11395  */
11396 static int gl_catch_signals(GetLine *gl)
11397 {
11398   return sigprocmask(SIG_UNBLOCK, &gl->use_signal_set, NULL) < 0;
11399 }
11400 
11401 /*.......................................................................
11402  * Select the I/O mode to be used by gl_get_line().
11403  *
11404  * Input:
11405  *  gl         GetLine *  The resource object of gl_get_line().
11406  *  mode      GlIOMode    The I/O mode to establish.
11407  * Output:
11408  *  return         int    0 - OK.
11409  *                        1 - Error.
11410  */
11411 int gl_io_mode(GetLine *gl, GlIOMode mode)
11412 {
11413   sigset_t oldset; /* The signals that were blocked on entry to this function */
11414   int status;      /* The return status of _gl_io_mode() */
11415 /*
11416  * Check the arguments.
11417  */
11418   if(!gl) {
11419     errno = EINVAL;
11420     return 1;
11421   };
11422 /*
11423  * Check that the requested mode is known.
11424  */
11425   switch(mode) {
11426   case GL_NORMAL_MODE:
11427   case GL_SERVER_MODE:
11428     break;
11429   default:
11430     errno = EINVAL;
11431     _err_record_msg(gl->err, "Unknown gl_get_line() I/O mode requested.",
11432 		    END_ERR_MSG);
11433     return 1;
11434   };
11435 /*
11436  * Block all signals.
11437  */
11438   if(gl_mask_signals(gl, &oldset))
11439     return 1;
11440 /*
11441  * Invoke the private body of this function.
11442  */
11443   status = _gl_io_mode(gl, mode);
11444 /*
11445  * Restore the process signal mask.
11446  */
11447   gl_unmask_signals(gl, &oldset);
11448   return status;
11449 }
11450 
11451 /*.......................................................................
11452  * This is the private body of the public function, gl_io_mode().
11453  * It assumes that the caller has checked its arguments and blocked the
11454  * delivery of signals.
11455  */
11456 static int _gl_io_mode(GetLine *gl, GlIOMode mode)
11457 {
11458 /*
11459  * Are we already in the specified mode?
11460  */
11461   if(mode == gl->io_mode)
11462     return 0;
11463 /*
11464  * First revert to normal I/O in the current I/O mode.
11465  */
11466   _gl_normal_io(gl);
11467 /*
11468  * Record the new mode.
11469  */
11470   gl->io_mode = mode;
11471 /*
11472  * Perform any actions needed by the new mode.
11473  */
11474   if(mode==GL_SERVER_MODE) {
11475     if(_gl_raw_io(gl, 1))
11476       return 1;
11477   };
11478   return 0;
11479 }
11480 
11481 /*.......................................................................
11482  * Return extra information (ie. in addition to that provided by errno)
11483  * about the last error to occur in either gl_get_line() or its
11484  * associated public functions.
11485  *
11486  * Input:
11487  *  gl         GetLine *  The resource object of gl_get_line().
11488  * Input/Output:
11489  *  buff          char *  An optional output buffer. Note that if the
11490  *                        calling application calls any gl_*()
11491  *                        functions from signal handlers, it should
11492  *                        provide a buffer here, so that a copy of
11493  *                        the latest error message can safely be made
11494  *                        while signals are blocked.
11495  *  n           size_t    The allocated size of buff[].
11496  * Output:
11497  *  return  const char *  A pointer to the error message. This will
11498  *                        be the buff argument, unless buff==NULL, in
11499  *                        which case it will be a pointer to an
11500  *                        internal error buffer. In the latter case,
11501  *                        note that the contents of the returned buffer
11502  *                        will change on subsequent calls to any gl_*()
11503  *                        functions.
11504  */
11505 const char *gl_error_message(GetLine *gl, char *buff, size_t n)
11506 {
11507   if(!gl) {
11508     static const char *msg = "NULL GetLine argument";
11509     if(buff) {
11510       strncpy(buff, msg, n);
11511       buff[n-1] = '\0';
11512     } else {
11513       return msg;
11514     };
11515   } else if(buff) {
11516     sigset_t oldset; /* The signals that were blocked on entry to this block */
11517 /*
11518  * Temporarily block all signals.
11519  */
11520     gl_mask_signals(gl, &oldset);
11521 /*
11522  * Copy the error message into the specified buffer.
11523  */
11524     if(buff && n > 0) {
11525       strncpy(buff, _err_get_msg(gl->err), n);
11526       buff[n-1] = '\0';
11527     };
11528 /*
11529  * Restore the process signal mask before returning.
11530  */
11531     gl_unmask_signals(gl, &oldset);
11532   } else {
11533     return _err_get_msg(gl->err);
11534   };
11535   return buff;
11536 }
11537 
11538 /*.......................................................................
11539  * Return the signal mask used by gl_get_line(). This is the set of
11540  * signals that gl_get_line() is currently configured to trap.
11541  *
11542  * Input:
11543  *  gl         GetLine *  The resource object of gl_get_line().
11544  * Input/Output:
11545  *  set       sigset_t *  The set of signals will be returned in *set,
11546  *                        in the form of a signal process mask, as
11547  *                        used by sigaction(), sigprocmask(),
11548  *                        sigpending(), sigsuspend(), sigsetjmp() and
11549  *                        other standard POSIX signal-aware
11550  *                        functions.
11551  * Output:
11552  *  return         int    0 - OK.
11553  *                        1 - Error (examine errno for reason).
11554  */
11555 int gl_list_signals(GetLine *gl, sigset_t *set)
11556 {
11557 /*
11558  * Check the arguments.
11559  */
11560   if(!gl || !set) {
11561     if(gl)
11562       _err_record_msg(gl->err, "NULL argument(s)", END_ERR_MSG);
11563     errno = EINVAL;
11564     return 1;
11565   };
11566 /*
11567  * Copy the signal mask into *set.
11568  */
11569   memcpy(set, &gl->all_signal_set, sizeof(*set));
11570   return 0;
11571 }
11572 
11573 /*.......................................................................
11574  * By default, gl_get_line() doesn't trap signals that are blocked
11575  * when it is called. This default can be changed either on a
11576  * per-signal basis by calling gl_trap_signal(), or on a global basis
11577  * by calling this function. What this function does is add the
11578  * GLS_UNBLOCK_SIG flag to all signals that are currently configured
11579  * to be trapped by gl_get_line(), such that when subsequent calls to
11580  * gl_get_line() wait for I/O, these signals are temporarily
11581  * unblocked. This behavior is useful in non-blocking server-I/O mode,
11582  * where it is used to avoid race conditions related to handling these
11583  * signals externally to gl_get_line(). See the demonstration code in
11584  * demo3.c, or the gl_handle_signal() man page for further
11585  * information.
11586  *
11587  * Input:
11588  *  gl         GetLine *   The resource object of gl_get_line().
11589  */
11590 void gl_catch_blocked(GetLine *gl)
11591 {
11592   sigset_t oldset;    /* The process signal mask to restore */
11593   GlSignalNode *sig;  /* A signal node in gl->sigs */
11594 /*
11595  * Check the arguments.
11596  */
11597   if(!gl) {
11598     errno = EINVAL;
11599     return;
11600   };
11601 /*
11602  * Temporarily block all signals while we modify the contents of gl.
11603  */
11604   gl_mask_signals(gl, &oldset);
11605 /*
11606  * Add the GLS_UNBLOCK_SIG flag to all configured signals.
11607  */
11608   for(sig=gl->sigs; sig; sig=sig->next)
11609     sig->flags |= GLS_UNBLOCK_SIG;
11610 /*
11611  * Restore the process signal mask that was superseded by the call
11612  * to gl_mask_signals().
11613  */
11614   gl_unmask_signals(gl, &oldset);
11615   return;
11616 }
11617 
11618 /*.......................................................................
11619  * Respond to signals who's default effects have important
11620  * consequences to gl_get_line(). This is intended for use in
11621  * non-blocking server mode, where the external event loop is
11622  * responsible for catching signals. Signals that are handled include
11623  * those that by default terminate or suspend the process, and the
11624  * signal that indicates that the terminal size has changed. Note that
11625  * this function is not signal safe and should thus not be called from
11626  * a signal handler itself. See the gl_io_mode() man page for how it
11627  * should be used.
11628  *
11629  * In the case of signals that by default terminate or suspend
11630  * processes, command-line editing will be suspended, the terminal
11631  * returned to a usable state, then the default disposition of the
11632  * signal restored and the signal resent, in order to suspend or
11633  * terminate the process.  If the process subsequently resumes,
11634  * command-line editing is resumed.
11635  *
11636  * In the case of signals that indicate that the terminal has been
11637  * resized, the new size will be queried, and any input line that is
11638  * being edited will be redrawn to fit the new dimensions of the
11639  * terminal.
11640  *
11641  * Input:
11642  *  signo    int    The number of the signal to respond to.
11643  *  gl   GetLine *  The first element of an array of 'ngl' GetLine
11644  *                  objects.
11645  *  ngl      int    The number of elements in the gl[] array. Normally
11646  *                  this will be one.
11647  */
11648 void gl_handle_signal(int signo, GetLine *gl, int ngl)
11649 {
11650   int attr;             /* The attributes of the specified signal */
11651   sigset_t all_signals; /* The set of trappable signals */
11652   sigset_t oldset;      /* The process signal mask to restore */
11653   int i;
11654 /*
11655  * NULL operation?
11656  */
11657   if(ngl < 1 || !gl)
11658     return;
11659 /*
11660  * Look up the default attributes of the specified signal.
11661  */
11662   attr = gl_classify_signal(signo);
11663 /*
11664  * If the signal isn't known, we are done.
11665  */
11666   if(!attr)
11667     return;
11668 /*
11669  * Temporarily block all signals while we modify the gl objects.
11670  */
11671   gl_list_trappable_signals(&all_signals);
11672   sigprocmask(SIG_BLOCK, &all_signals, &oldset);
11673 /*
11674  * Suspend or terminate the process?
11675  */
11676   if(attr & (GLSA_SUSP | GLSA_TERM)) {
11677     gl_suspend_process(signo, gl, ngl);
11678 /*
11679  * Resize the terminal? Note that ioctl() isn't defined as being
11680  * signal safe, so we can't call gl_update_size() here. However,
11681  * gl_get_line() checks for resizes on each call, so simply arrange
11682  * for the application's event loop to call gl_get_line() as soon as
11683  * it becomes possible to write to the terminal. Note that if the
11684  * caller is calling select() or poll when this happens, these functions
11685  * get interrupted, since a signal has been caught.
11686  */
11687   } else if(attr & GLSA_SIZE) {
11688     for(i=0; i<ngl; i++)
11689       gl[i].pending_io = GLP_WRITE;
11690   };
11691 /*
11692  * Restore the process signal mask that was superseded by the call
11693  * to gl_mask_signals().
11694  */
11695   sigprocmask(SIG_SETMASK, &oldset, NULL);
11696   return;
11697 }
11698 
11699 /*.......................................................................
11700  * Respond to an externally caught process suspension or
11701  * termination signal.
11702  *
11703  * After restoring the terminal to a usable state, suspend or
11704  * terminate the calling process, using the original signal with its
11705  * default disposition restored to do so. If the process subsequently
11706  * resumes, resume editing any input lines that were being entered.
11707  *
11708  * Input:
11709  *  signo    int    The signal number to suspend the process with. Note
11710  *                  that the default disposition of this signal will be
11711  *                  restored before the signal is sent, so provided
11712  *                  that the default disposition of this signal is to
11713  *                  either suspend or terminate the application,
11714  *                  that is what wil happen, regardless of what signal
11715  *                  handler is currently assigned to this signal.
11716  *  gl   GetLine *  The first element of an array of 'ngl' GetLine objects
11717  *                  whose terminals should be restored to a sane state
11718  *                  while the application is suspended.
11719  *  ngl      int    The number of elements in the gl[] array.
11720  */
11721 static void gl_suspend_process(int signo, GetLine *gl, int ngl)
11722 {
11723   sigset_t only_signo;          /* A signal set containing just signo */
11724   sigset_t oldset;              /* The signal mask on entry to this function */
11725   sigset_t all_signals;         /* A signal set containing all signals */
11726   struct sigaction old_action;  /* The current signal handler */
11727   struct sigaction def_action;  /* The default signal handler */
11728   int i;
11729 /*
11730  * Create a signal mask containing the signal that was trapped.
11731  */
11732   sigemptyset(&only_signo);
11733   sigaddset(&only_signo, signo);
11734 /*
11735  * Temporarily block all signals.
11736  */
11737   gl_list_trappable_signals(&all_signals);
11738   sigprocmask(SIG_BLOCK, &all_signals, &oldset);
11739 /*
11740  * Restore the terminal to a usable state.
11741  */
11742   for(i=0; i<ngl; i++) {
11743     GetLine *obj = gl + i;
11744     if(obj->raw_mode) {
11745       _gl_normal_io(obj);
11746       if(!obj->raw_mode)        /* Check that gl_normal_io() succeded */
11747 	obj->raw_mode = -1;     /* Flag raw mode as needing to be restored */
11748     };
11749   };
11750 /*
11751  * Restore the system default disposition of the signal that we
11752  * caught.  Note that this signal is currently blocked. Note that we
11753  * don't use memcpy() to copy signal sets here, because the signal safety
11754  * of memcpy() is undefined.
11755  */
11756   def_action.sa_handler = SIG_DFL;
11757   {
11758     char *orig = (char *) &all_signals;
11759     char *dest = (char *) &def_action.sa_mask;
11760     for(i=0; i<sizeof(sigset_t); i++)
11761       *dest++ = *orig++;
11762   };
11763   sigaction(signo, &def_action, &old_action);
11764 /*
11765  * Resend the signal, and unblock it so that it gets delivered to
11766  * the application. This will invoke the default action of this signal.
11767  */
11768   raise(signo);
11769   sigprocmask(SIG_UNBLOCK, &only_signo, NULL);
11770 /*
11771  * If the process resumes again, it will resume here.
11772  * Block the signal again, then restore our signal handler.
11773  */
11774   sigprocmask(SIG_BLOCK, &only_signo, NULL);
11775   sigaction(signo, &old_action, NULL);
11776 /*
11777  * Resume command-line editing.
11778  */
11779   for(i=0; i<ngl; i++) {
11780     GetLine *obj = gl + i;
11781     if(obj->raw_mode == -1) { /* Did we flag the need to restore raw mode? */
11782       obj->raw_mode = 0;      /* gl_raw_io() does nothing unless raw_mode==0 */
11783       _gl_raw_io(obj, 1);
11784     };
11785   };
11786 /*
11787  * Restore the process signal mask to the way it was when this function
11788  * was called.
11789  */
11790   sigprocmask(SIG_SETMASK, &oldset, NULL);
11791   return;
11792 }
11793 
11794 /*.......................................................................
11795  * Return the information about the default attributes of a given signal.
11796  * The attributes that are returned are as defined by the standards that
11797  * created them, including POSIX, SVR4 and 4.3+BSD, and are taken from a
11798  * table in Richard Steven's book, "Advanced programming in the UNIX
11799  * environment".
11800  *
11801  * Input:
11802  *  signo        int   The signal to be characterized.
11803  * Output:
11804  *  return       int   A bitwise union of GlSigAttr enumerators, or 0
11805  *                     if the signal isn't known.
11806  */
11807 static int gl_classify_signal(int signo)
11808 {
11809   int i;
11810 /*
11811  * Search for the specified signal in the gl_signal_list[] table.
11812  */
11813   for(i=0; i<sizeof(gl_signal_list)/sizeof(gl_signal_list[0]); i++) {
11814     const struct GlDefSignal *sig = gl_signal_list + i;
11815     if(sig->signo == signo)
11816       return sig->attr;
11817   };
11818 /*
11819  * Signal not known.
11820  */
11821   return 0;
11822 }
11823 
11824 /*.......................................................................
11825  * When in non-blocking server mode, this function can be used to abandon
11826  * the current incompletely entered input line, and prepare to start
11827  * editing a new line on the next call to gl_get_line().
11828  *
11829  * Input:
11830  *  gl      GetLine *  The line editor resource object.
11831  */
11832 void gl_abandon_line(GetLine *gl)
11833 {
11834   sigset_t oldset;    /* The process signal mask to restore */
11835 /*
11836  * Check the arguments.
11837  */
11838   if(!gl) {
11839     errno = EINVAL;
11840     return;
11841   };
11842 /*
11843  * Temporarily block all signals while we modify the contents of gl.
11844  */
11845   gl_mask_signals(gl, &oldset);
11846 /*
11847  * Mark the input line as discarded.
11848  */
11849   _gl_abandon_line(gl);
11850 /*
11851  * Restore the process signal mask that was superseded by the call
11852  * to gl_mask_signals().
11853  */
11854   gl_unmask_signals(gl, &oldset);
11855   return;
11856 }
11857 
11858 /*.......................................................................
11859  * This is the private body of the gl_abandon_line() function. It
11860  * assumes that the caller has checked its arguments and blocked the
11861  * delivery of signals.
11862  */
11863 void _gl_abandon_line(GetLine *gl)
11864 {
11865   gl->endline = 1;
11866   gl->pending_io = GLP_WRITE;
11867 }
11868 
11869 /*.......................................................................
11870  * How many characters are needed to write a number as an octal string?
11871  *
11872  * Input:
11873  *  num   unsigned   The to be measured.
11874  * Output:
11875  *  return     int   The number of characters needed.
11876  */
11877 static int gl_octal_width(unsigned num)
11878 {
11879   int n;    /* The number of characters needed to render the number */
11880   for(n=1; num /= 8; n++)
11881     ;
11882   return n;
11883 }
11884 
11885 /*.......................................................................
11886  * Tell gl_get_line() the current terminal size. Note that this is only
11887  * necessary on systems where changes in terminal size aren't reported
11888  * via SIGWINCH.
11889  *
11890  * Input:
11891  *  gl            GetLine *  The resource object of gl_get_line().
11892  *  ncolumn           int    The number of columns in the terminal.
11893  *  nline             int    The number of lines in the terminal.
11894  * Output:
11895  *  return            int    0 - OK.
11896  *                           1 - Error.
11897  */
11898 int gl_set_term_size(GetLine *gl, int ncolumn, int nline)
11899 {
11900   sigset_t oldset;      /* The signals that were blocked on entry */
11901                         /*  to this function */
11902   int status;           /* The return status */
11903 /*
11904  * Block all signals while accessing gl.
11905  */
11906   gl_mask_signals(gl, &oldset);
11907 /*
11908  * Install the new terminal size.
11909  */
11910   status = _gl_set_term_size(gl, ncolumn, nline);
11911 /*
11912  * Restore the process signal mask before returning.
11913  */
11914   gl_unmask_signals(gl, &oldset);
11915   return status;
11916 }
11917 
11918 /*.......................................................................
11919  * This is the private body of the gl_set_term_size() function. It
11920  * assumes that the caller has checked its arguments and blocked the
11921  * delivery of signals.
11922  */
11923 static int _gl_set_term_size(GetLine *gl, int ncolumn, int nline)
11924 {
11925 /*
11926  * Check the arguments.
11927  */
11928   if(!gl) {
11929     errno = EINVAL;
11930     return 1;
11931   };
11932 /*
11933  * Reject non-sensical dimensions.
11934  */
11935   if(ncolumn <= 0 || nline <= 0) {
11936     _err_record_msg(gl->err, "Invalid terminal size", END_ERR_MSG);
11937     errno = EINVAL;
11938     return 1;
11939   };
11940 /*
11941  * Install the new dimensions in the terminal driver if possible, so
11942  * that future calls to gl_query_size() get the new value.
11943  */
11944 #ifdef TIOCSWINSZ
11945   if(gl->is_term) {
11946     struct winsize size;
11947     size.ws_row = nline;
11948     size.ws_col = ncolumn;
11949     size.ws_xpixel = 0;
11950     size.ws_ypixel = 0;
11951     if(ioctl(gl->output_fd, TIOCSWINSZ, &size) == -1) {
11952       _err_record_msg(gl->err, "Can't change terminal size", END_ERR_MSG);
11953       return 1;
11954     };
11955   };
11956 #endif
11957 /*
11958  * If an input line is in the process of being edited, redisplay it to
11959  * accomodate the new dimensions, and record the new dimensions in
11960  * gl->nline and gl->ncolumn.
11961  */
11962   return gl_handle_tty_resize(gl, ncolumn, nline);
11963 }
11964 
11965 /*.......................................................................
11966  * Record a character in the input line buffer at a given position.
11967  *
11968  * Input:
11969  *  gl    GetLine *   The resource object of gl_get_line().
11970  *  c        char     The character to be recorded.
11971  *  bufpos    int     The index in the buffer at which to record the
11972  *                    character.
11973  * Output:
11974  *  return    int     0 - OK.
11975  *                    1 - Insufficient room.
11976  */
11977 static int gl_buffer_char(GetLine *gl, char c, int bufpos)
11978 {
11979 /*
11980  * Guard against buffer overruns.
11981  */
11982   if(bufpos >= gl->linelen)
11983     return 1;
11984 /*
11985  * Record the new character.
11986  */
11987   gl->line[bufpos] = c;
11988 /*
11989  * If the new character was placed beyond the end of the current input
11990  * line, update gl->ntotal to reflect the increased number of characters
11991  * that are in gl->line, and terminate the string.
11992  */
11993   if(bufpos >= gl->ntotal) {
11994     gl->ntotal = bufpos+1;
11995     gl->line[gl->ntotal] = '\0';
11996   };
11997   return 0;
11998 }
11999 
12000 /*.......................................................................
12001  * Copy a given string into the input buffer, overwriting the current
12002  * contents.
12003  *
12004  * Input:
12005  *  gl    GetLine *   The resource object of gl_get_line().
12006  *  s  const char *   The string to be recorded.
12007  *  n         int     The number of characters to be copied from the
12008  *                    string.
12009  *  bufpos    int     The index in the buffer at which to place the
12010  *                    the first character of the string.
12011  * Output:
12012  *  return    int     0 - OK.
12013  *                    1 - String truncated to fit.
12014  */
12015 static int gl_buffer_string(GetLine *gl, const char *s, int n, int bufpos)
12016 {
12017   int nnew;  /* The number of characters actually recorded */
12018   int i;
12019 /*
12020  * How many of the characters will fit within the buffer?
12021  */
12022   nnew = bufpos + n <= gl->linelen ? n : (gl->linelen - bufpos);
12023 /*
12024  * Record the first nnew characters of s[] in the buffer.
12025  */
12026   for(i=0; i<nnew; i++)
12027     gl_buffer_char(gl, s[i], bufpos + i);
12028 /*
12029  * Was the string truncated?
12030  */
12031   return nnew < n;
12032 }
12033 
12034 /*.......................................................................
12035  * Make room in the input buffer for a string to be inserted. This
12036  * involves moving the characters that follow a specified point, towards
12037  * the end of the buffer.
12038  *
12039  * Input:
12040  *  gl    GetLine *   The resource object of gl_get_line().
12041  *  start     int     The index of the first character to be moved.
12042  *  n         int     The width of the gap.
12043  * Output:
12044  *  return    int     0 - OK.
12045  *                    1 - Insufficient room.
12046  */
12047 static int gl_make_gap_in_buffer(GetLine *gl, int start, int n)
12048 {
12049 /*
12050  * Ensure that the buffer has sufficient space.
12051  */
12052   if(gl->ntotal + n > gl->linelen)
12053     return 1;
12054 /*
12055  * Move everything including and beyond the character at 'start'
12056  * towards the end of the string.
12057  */
12058   memmove(gl->line + start + n, gl->line + start, gl->ntotal - start + 1);
12059 /*
12060  * Update the recorded size of the line.
12061  */
12062   gl->ntotal += n;
12063   return 1;
12064 }
12065 
12066 /*.......................................................................
12067  * Remove a given number of characters from the input buffer. This
12068  * involves moving the characters that follow the removed characters to
12069  * where the removed sub-string started in the input buffer.
12070  *
12071  * Input:
12072  *  gl    GetLine *   The resource object of gl_get_line().
12073  *  start     int     The first character to be removed.
12074  *  n         int     The number of characters to remove.
12075  */
12076 static void gl_remove_from_buffer(GetLine *gl, int start, int n)
12077 {
12078   memmove(gl->line + start, gl->line + start + n, gl->ntotal - start - n + 1);
12079 /*
12080  * Update the recorded size of the line.
12081  */
12082   gl->ntotal -= n;
12083 }
12084 
12085 /*.......................................................................
12086  * Truncate the string in the input line buffer after a given number of
12087  * characters.
12088  *
12089  * Input:
12090  *  gl       GetLine *   The resource object of gl_get_line().
12091  *  n            int     The new length of the line.
12092  * Output:
12093  *  return       int     0 - OK.
12094  *                       1 - n > gl->linelen.
12095  */
12096 static int gl_truncate_buffer(GetLine *gl, int n)
12097 {
12098   if(n > gl->linelen)
12099     return 1;
12100   gl->line[n] = '\0';
12101   gl->ntotal = n;
12102   return 0;
12103 }
12104 
12105 /*.......................................................................
12106  * When the contents of gl->line[] are changed without calling any of the
12107  * gl_ buffer manipulation functions, this function must be called to
12108  * compute the length of this string, and ancillary information.
12109  *
12110  * Input:
12111  *  gl      GetLine *   The resource object of gl_get_line().
12112  */
12113 static void gl_update_buffer(GetLine *gl)
12114 {
12115   int len;  /* The length of the line */
12116 /*
12117  * Measure the length of the input line.
12118  */
12119   for(len=0; len <= gl->linelen && gl->line[len]; len++)
12120     ;
12121 /*
12122  * Just in case the string wasn't correctly terminated, do so here.
12123  */
12124   gl->line[len] = '\0';
12125 /*
12126  * Record the number of characters that are now in gl->line[].
12127  */
12128   gl->ntotal = len;
12129 /*
12130  * Ensure that the cursor stays within the bounds of the modified
12131  * input line.
12132  */
12133   if(gl->buff_curpos > gl->ntotal)
12134     gl->buff_curpos = gl->ntotal;
12135 /*
12136  * Arrange for the input line to be redrawn.
12137  */
12138   gl_queue_redisplay(gl);
12139   return;
12140 }
12141 
12142 /*.......................................................................
12143  * Erase the displayed input line, including its prompt, and leave the
12144  * cursor where the erased line started. Note that to allow this
12145  * function to be used when responding to a terminal resize, this
12146  * function is designed to work even if the horizontal cursor position
12147  * doesn't match the internally recorded position.
12148  *
12149  * Input:
12150  *  gl      GetLine *   The resource object of gl_get_line().
12151  * Output:
12152  *  return      int     0 - OK.
12153  *                      1 - Error.
12154  */
12155 static int gl_erase_line(GetLine *gl)
12156 {
12157 /*
12158  * Is a line currently displayed?
12159  */
12160   if(gl->displayed) {
12161 /*
12162  * Relative the the start of the input line, which terminal line of
12163  * the current input line is the cursor currently on?
12164  */
12165     int cursor_line = gl->term_curpos / gl->ncolumn;
12166 /*
12167  * Move the cursor to the start of the line.
12168  */
12169     for( ; cursor_line > 0; cursor_line--) {
12170       if(gl_print_control_sequence(gl, 1, gl->up))
12171 	return 1;
12172     };
12173     if(gl_print_control_sequence(gl, 1, gl->bol))
12174       return 1;
12175 /*
12176  * Clear from the start of the line to the end of the terminal.
12177  */
12178     if(gl_print_control_sequence(gl, gl->nline, gl->clear_eod))
12179       return 1;
12180 /*
12181  * Mark the line as no longer displayed.
12182  */
12183     gl_line_erased(gl);
12184   };
12185   return 0;
12186 }
12187 
12188 /*.......................................................................
12189  * Arrange for the input line to be redisplayed by gl_flush_output(),
12190  * as soon as the output queue becomes empty.
12191  *
12192  * Input:
12193  *  gl          GetLine *   The resource object of gl_get_line().
12194  */
12195 static void gl_queue_redisplay(GetLine *gl)
12196 {
12197   gl->redisplay = 1;
12198   gl->pending_io = GLP_WRITE;
12199 }
12200 
12201 /*.......................................................................
12202  * Truncate the displayed input line starting from the current
12203  * terminal cursor position, and leave the cursor at the end of the
12204  * truncated line. The input-line buffer is not affected.
12205  *
12206  * Input:
12207  *  gl     GetLine *   The resource object of gl_get_line().
12208  * Output:
12209  *  return     int     0 - OK.
12210  *                     1 - Error.
12211  */
12212 static int gl_truncate_display(GetLine *gl)
12213 {
12214 /*
12215  * Keep a record of the current terminal cursor position.
12216  */
12217   int term_curpos = gl->term_curpos;
12218 /*
12219  * First clear from the cursor to the end of the current input line.
12220  */
12221   if(gl_print_control_sequence(gl, 1, gl->clear_eol))
12222     return 1;
12223 /*
12224  * If there is more than one line displayed, go to the start of the
12225  * next line and clear from there to the end of the display. Note that
12226  * we can't use clear_eod to do the whole job of clearing from the
12227  * current cursor position to the end of the terminal because
12228  * clear_eod is only defined when used at the start of a terminal line
12229  * (eg. with gnome terminals, clear_eod clears from the start of the
12230  * current terminal line, rather than from the current cursor
12231  * position).
12232  */
12233   if(gl->term_len / gl->ncolumn > gl->term_curpos / gl->ncolumn) {
12234     if(gl_print_control_sequence(gl, 1, gl->down) ||
12235        gl_print_control_sequence(gl, 1, gl->bol) ||
12236        gl_print_control_sequence(gl, gl->nline, gl->clear_eod))
12237       return 1;
12238 /*
12239  * Where is the cursor now?
12240  */
12241     gl->term_curpos = gl->ncolumn * (term_curpos / gl->ncolumn + 1);
12242 /*
12243  * Restore the cursor position.
12244  */
12245     gl_set_term_curpos(gl, term_curpos);
12246   };
12247 /*
12248  * Update the recorded position of the final character.
12249  */
12250   gl->term_len = gl->term_curpos;
12251   return 0;
12252 }
12253 
12254 /*.......................................................................
12255  * Return the set of all trappable signals.
12256  *
12257  * Input:
12258  *  signals   sigset_t *  The set of signals will be recorded in
12259  *                        *signals.
12260  */
12261 static void gl_list_trappable_signals(sigset_t *signals)
12262 {
12263 /*
12264  * Start with the set of all signals.
12265  */
12266   sigfillset(signals);
12267 /*
12268  * Remove un-trappable signals from this set.
12269  */
12270 #ifdef SIGKILL
12271   sigdelset(signals, SIGKILL);
12272 #endif
12273 #ifdef SIGSTOP
12274   sigdelset(signals, SIGSTOP);
12275 #endif
12276 }
12277 
12278 /*.......................................................................
12279  * Read an input line from a non-interactive input stream.
12280  *
12281  * Input:
12282  *  gl     GetLine *   The resource object of gl_get_line().
12283  * Output:
12284  *  return     int     0 - OK
12285  *                     1 - Error.
12286  */
12287 static int gl_read_stream_line(GetLine *gl)
12288 {
12289   char c = '\0'; /* The latest character read from fp */
12290 /*
12291  * Record the fact that we are about to read input.
12292  */
12293   gl->pending_io = GLP_READ;
12294 /*
12295  * If we are starting a new line, reset the line-input parameters.
12296  */
12297   if(gl->endline)
12298     gl_reset_input_line(gl);
12299 /*
12300  * Read one character at a time.
12301  */
12302   while(gl->ntotal < gl->linelen && c != '\n') {
12303 /*
12304  * Attempt to read one more character.
12305  */
12306     switch(gl_read_input(gl, &c)) {
12307     case GL_READ_OK:
12308       break;
12309     case GL_READ_EOF:        /* Reached end-of-file? */
12310 /*
12311  * If any characters were read before the end-of-file condition,
12312  * interpolate a newline character, so that the caller sees a
12313  * properly terminated line. Otherwise return an end-of-file
12314  * condition.
12315  */
12316       if(gl->ntotal > 0) {
12317 	c = '\n';
12318       } else {
12319 	gl_record_status(gl, GLR_EOF, 0);
12320 	return 1;
12321       };
12322       break;
12323     case GL_READ_BLOCKED:    /* Input blocked? */
12324       gl_record_status(gl, GLR_BLOCKED, BLOCKED_ERRNO);
12325       return 1;
12326       break;
12327     case GL_READ_ERROR:     /* I/O error? */
12328       return 1;
12329       break;
12330     };
12331 /*
12332  * Append the character to the line buffer.
12333  */
12334     if(gl_buffer_char(gl, c, gl->ntotal))
12335       return 1;
12336   };
12337 /*
12338  * Was the end of the input line reached before running out of buffer space?
12339  */
12340   gl->endline = (c == '\n');
12341   return 0;
12342 }
12343 
12344 /*.......................................................................
12345  * Read a single character from a non-interactive input stream.
12346  *
12347  * Input:
12348  *  gl     GetLine *   The resource object of gl_get_line().
12349  * Output:
12350  *  return     int     The character, or EOF on error.
12351  */
12352 static int gl_read_stream_char(GetLine *gl)
12353 {
12354   char c = '\0';    /* The latest character read from fp */
12355   int retval = EOF; /* The return value of this function */
12356 /*
12357  * Arrange to discard any incomplete input line.
12358  */
12359   _gl_abandon_line(gl);
12360 /*
12361  * Record the fact that we are about to read input.
12362  */
12363   gl->pending_io = GLP_READ;
12364 /*
12365  * Attempt to read one more character.
12366  */
12367   switch(gl_read_input(gl, &c)) {
12368   case GL_READ_OK:      /* Success */
12369     retval = c;
12370     break;
12371   case GL_READ_BLOCKED: /* The read blocked */
12372     gl_record_status(gl, GLR_BLOCKED, BLOCKED_ERRNO);
12373     retval = EOF;  /* Failure */
12374     break;
12375   case GL_READ_EOF:     /* End of file reached */
12376     gl_record_status(gl, GLR_EOF, 0);
12377     retval = EOF;  /* Failure */
12378     break;
12379   case GL_READ_ERROR:
12380     retval = EOF;  /* Failure */
12381     break;
12382   };
12383   return retval;
12384 }
12385 
12386 /*.......................................................................
12387  * Bind a key sequence to a given action.
12388  *
12389  * Input:
12390  *  gl          GetLine *   The resource object of gl_get_line().
12391  *  origin  GlKeyOrigin     The originator of the key binding.
12392  *  key      const char *   The key-sequence to be bound (or unbound).
12393  *  action   const char *   The name of the action to bind the key to,
12394  *                          or either NULL or "" to unbind the
12395  *                          key-sequence.
12396  * Output:
12397  *  return          int     0 - OK
12398  *                          1 - Error.
12399  */
12400 int gl_bind_keyseq(GetLine *gl, GlKeyOrigin origin, const char *keyseq,
12401 		   const char *action)
12402 {
12403   KtBinder binder;  /* The private internal equivalent of 'origin' */
12404 /*
12405  * Check the arguments.
12406  */
12407   if(!gl || !keyseq) {
12408     errno = EINVAL;
12409     if(gl)
12410       _err_record_msg(gl->err, "NULL argument(s)", END_ERR_MSG);
12411     return 1;
12412   };
12413 /*
12414  * An empty action string requests that the key-sequence be unbound.
12415  * This is indicated to _kt_set_keybinding() by passing a NULL action
12416  * string, so convert an empty string to a NULL action pointer.
12417  */
12418   if(action && *action=='\0')
12419     action = NULL;
12420 /*
12421  * Translate the public originator enumeration to the private equivalent.
12422  */
12423   binder = origin==GL_USER_KEY ? KTB_USER : KTB_NORM;
12424 /*
12425  * Bind the action to a given key-sequence?
12426  */
12427   if(keyseq && _kt_set_keybinding(gl->bindings, binder, keyseq, action)) {
12428     _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG);
12429     return 1;
12430   };
12431   return 0;
12432 }
12433 
12434 /*.......................................................................
12435  * This is the public wrapper around the gl_clear_termina() function.
12436  * It clears the terminal and leaves the cursor at the home position.
12437  * In server I/O mode, the next call to gl_get_line() will also
12438  * redisplay the current input line.
12439  *
12440  * Input:
12441  *  gl          GetLine *   The resource object of gl_get_line().
12442  * Output:
12443  *  return          int     0 - OK.
12444  *                          1 - Error.
12445  */
12446 int gl_erase_terminal(GetLine *gl)
12447 {
12448   sigset_t oldset;      /* The signals that were blocked on entry */
12449                         /*  to this function */
12450   int status;           /* The return status */
12451 /*
12452  * Block all signals while accessing gl.
12453  */
12454   gl_mask_signals(gl, &oldset);
12455 /*
12456  * Clear the terminal.
12457  */
12458   status = gl_clear_screen(gl, 1, NULL);
12459 /*
12460  * Attempt to flush the clear-screen control codes to the terminal.
12461  * If this doesn't complete the job, the next call to gl_get_line()
12462  * will.
12463  */
12464   (void) gl_flush_output(gl);
12465 /*
12466  * Restore the process signal mask before returning.
12467  */
12468   gl_unmask_signals(gl, &oldset);
12469   return status;
12470 }
12471 
12472 /*.......................................................................
12473  * This function must be called by any function that erases the input
12474  * line.
12475  *
12476  * Input:
12477  *  gl          GetLine *   The resource object of gl_get_line().
12478  */
12479 static void gl_line_erased(GetLine *gl)
12480 {
12481   gl->displayed = 0;
12482   gl->term_curpos = 0;
12483   gl->term_len = 0;
12484 }
12485 
12486 /*.......................................................................
12487  * Append a specified line to the history list.
12488  *
12489  * Input:
12490  *  gl          GetLine *   The resource object of gl_get_line().
12491  *  line     const char *   The line to be added.
12492  * Output:
12493  *  return          int     0 - OK.
12494  *                          1 - Error.
12495  */
12496 int gl_append_history(GetLine *gl, const char *line)
12497 {
12498   sigset_t oldset;      /* The signals that were blocked on entry */
12499                         /*  to this function */
12500   int status;           /* The return status */
12501 /*
12502  * Check the arguments.
12503  */
12504   if(!gl || !line) {
12505     errno = EINVAL;
12506     return 1;
12507   };
12508 /*
12509  * Block all signals.
12510  */
12511   if(gl_mask_signals(gl, &oldset))
12512     return 1;
12513 /*
12514  * Execute the private body of the function while signals are blocked.
12515  */
12516   status = _gl_append_history(gl, line);
12517 /*
12518  * Restore the process signal mask.
12519  */
12520   gl_unmask_signals(gl, &oldset);
12521   return status;
12522 }
12523 
12524 /*.......................................................................
12525  * This is the private body of the public function, gl_append_history().
12526  * It assumes that the caller has checked its arguments and blocked the
12527  * delivery of signals.
12528  */
12529 static int _gl_append_history(GetLine *gl, const char *line)
12530 {
12531   int status =_glh_add_history(gl->glh, line, 0);
12532   if(status)
12533     _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
12534   return status;
12535 }
12536 
12537 /*.......................................................................
12538  * Enable or disable the automatic addition of newly entered lines to the
12539  * history list.
12540  *
12541  * Input:
12542  *  gl          GetLine *   The resource object of gl_get_line().
12543  *  enable          int     If true, subsequently entered lines will
12544  *                          automatically be added to the history list
12545  *                          before they are returned to the caller of
12546  *                          gl_get_line(). If 0, the choice of how and
12547  *                          when to archive lines in the history list,
12548  *                          is left up to the calling application, which
12549  *                          can do so via calls to gl_append_history().
12550  * Output:
12551  *  return          int     0 - OK.
12552  *                          1 - Error.
12553  */
12554 int gl_automatic_history(GetLine *gl, int enable)
12555 {
12556   sigset_t oldset;      /* The signals that were blocked on entry */
12557                         /*  to this function */
12558 /*
12559  * Check the arguments.
12560  */
12561   if(!gl) {
12562     errno = EINVAL;
12563     return 1;
12564   };
12565 /*
12566  * Block all signals.
12567  */
12568   if(gl_mask_signals(gl, &oldset))
12569     return 1;
12570 /*
12571  * Execute the private body of the function while signals are blocked.
12572  */
12573   gl->automatic_history = enable;
12574 /*
12575  * Restore the process signal mask.
12576  */
12577   gl_unmask_signals(gl, &oldset);
12578   return 0;
12579 }
12580 
12581 /*.......................................................................
12582  * This is a public function that reads a single uninterpretted
12583  * character from the user, without displaying anything.
12584  *
12585  * Input:
12586  *  gl     GetLine *  A resource object previously returned by
12587  *                    new_GetLine().
12588  * Output:
12589  *  return     int    The character that was read, or EOF if the read
12590  *                    had to be aborted (in which case you can call
12591  *                    gl_return_status() to find out why).
12592  */
12593 int gl_read_char(GetLine *gl)
12594 {
12595   int retval;   /* The return value of _gl_read_char() */
12596 /*
12597  * This function can be called from application callback functions,
12598  * so check whether signals have already been masked, so that we don't
12599  * do it again, and overwrite gl->old_signal_set.
12600  */
12601   int was_masked = gl->signals_masked;
12602 /*
12603  * Check the arguments.
12604  */
12605   if(!gl) {
12606     errno = EINVAL;
12607     return EOF;
12608   };
12609 /*
12610  * Temporarily block all of the signals that we have been asked to trap.
12611  */
12612   if(!was_masked && gl_mask_signals(gl, &gl->old_signal_set))
12613     return EOF;
12614 /*
12615  * Perform the character reading task.
12616  */
12617   retval = _gl_read_char(gl);
12618 /*
12619  * Restore the process signal mask to how it was when this function was
12620  * first called.
12621  */
12622   if(!was_masked)
12623     gl_unmask_signals(gl, &gl->old_signal_set);
12624   return retval;
12625 }
12626 
12627 /*.......................................................................
12628  * This is the main body of the public function gl_read_char().
12629  */
12630 static int _gl_read_char(GetLine *gl)
12631 {
12632   int retval = EOF;  /* The return value */
12633   int waserr = 0;    /* True if an error occurs */
12634   char c;            /* The character read */
12635 /*
12636  * This function can be called from application callback functions,
12637  * so check whether signals have already been overriden, so that we don't
12638  * overwrite the preserved signal handlers with gl_get_line()s. Also
12639  * record whether we are currently in raw I/O mode or not, so that this
12640  * can be left in the same state on leaving this function.
12641  */
12642   int was_overriden = gl->signals_overriden;
12643   int was_raw = gl->raw_mode;
12644 /*
12645  * Also keep a record of the direction of any I/O that gl_get_line()
12646  * is awaiting, so that we can restore this status on return.
12647  */
12648   GlPendingIO old_pending_io = gl->pending_io;
12649 /*
12650  * Assume that this call will successfully complete the input operation
12651  * until proven otherwise.
12652  */
12653   gl_clear_status(gl);
12654 /*
12655  * If this is the first call to this function or gl_get_line(),
12656  * since new_GetLine(), complete any postponed configuration.
12657  */
12658   if(!gl->configured) {
12659     (void) _gl_configure_getline(gl, NULL, NULL, TECLA_CONFIG_FILE);
12660     gl->configured = 1;
12661   };
12662 /*
12663  * Before installing our signal handler functions, record the fact
12664  * that there are no pending signals.
12665  */
12666   gl_pending_signal = -1;
12667 /*
12668  * Temporarily override the signal handlers of the calling program,
12669  * so that we can intercept signals that would leave the terminal
12670  * in a bad state.
12671  */
12672   if(!was_overriden)
12673     waserr = gl_override_signal_handlers(gl);
12674 /*
12675  * After recording the current terminal settings, switch the terminal
12676  * into raw input mode, without redisplaying any partially entered input
12677  * line.
12678  */
12679   if(!was_raw)
12680     waserr = waserr || _gl_raw_io(gl, 0);
12681 /*
12682  * Attempt to read the line. This will require more than one attempt if
12683  * either a current temporary input file is opened by gl_get_input_line()
12684  * or the end of a temporary input file is reached by gl_read_stream_line().
12685  */
12686   while(!waserr) {
12687 /*
12688  * Read a line from a non-interactive stream?
12689  */
12690     if(gl->file_fp || !gl->is_term) {
12691       retval = gl_read_stream_char(gl);
12692       if(retval != EOF) {            /* Success? */
12693 	break;
12694       } else if(gl->file_fp) {  /* End of temporary input file? */
12695 	gl_revert_input(gl);
12696 	gl_record_status(gl, GLR_NEWLINE, 0);
12697       } else {                  /* An error? */
12698 	waserr = 1;
12699 	break;
12700       };
12701     };
12702 /*
12703  * Read from the terminal? Note that the above if() block may have
12704  * changed gl->file_fp, so it is necessary to retest it here, rather
12705  * than using an else statement.
12706  */
12707     if(!gl->file_fp && gl->is_term) {
12708 /*
12709  * Flush any pending output to the terminal before waiting
12710  * for the user to type a character.
12711  */
12712       if(_glq_char_count(gl->cq) > 0 && gl_flush_output(gl)) {
12713 	retval = EOF;
12714 /*
12715  * Read one character. Don't append it to the key buffer, since
12716  * this would subseuqnely appear as bogus input to the line editor.
12717  */
12718       } else if(gl_read_terminal(gl, 0, &c) == 0) {
12719 /*
12720  * Record the character for return.
12721  */
12722 	retval = c;
12723 /*
12724  * In this mode, count each character as being a new key-sequence.
12725  */
12726 	gl->keyseq_count++;
12727 /*
12728  * Delete the character that was read, from the key-press buffer.
12729  */
12730 	gl_discard_chars(gl, 1);
12731       };
12732       if(retval==EOF)
12733 	waserr = 1;
12734       else
12735 	break;
12736     };
12737   };
12738 /*
12739  * If an error occurred, but gl->rtn_status is still set to
12740  * GLR_NEWLINE, change the status to GLR_ERROR. Otherwise
12741  * leave it at whatever specific value was assigned by the function
12742  * that aborted input. This means that only functions that trap
12743  * non-generic errors have to remember to update gl->rtn_status
12744  * themselves.
12745  */
12746   if(waserr && gl->rtn_status == GLR_NEWLINE)
12747     gl_record_status(gl, GLR_ERROR, errno);
12748 /*
12749  * Restore terminal settings, if they were changed by this function.
12750  */
12751   if(!was_raw && gl->io_mode != GL_SERVER_MODE)
12752     _gl_normal_io(gl);
12753 /*
12754  * Restore the signal handlers, if they were overriden by this function.
12755  */
12756   if(!was_overriden)
12757     gl_restore_signal_handlers(gl);
12758 /*
12759  * If this function gets aborted early, the errno value associated
12760  * with the event that caused this to happen is recorded in
12761  * gl->rtn_errno. Since errno may have been overwritten by cleanup
12762  * functions after this, restore its value to the value that it had
12763  * when the error condition occured, so that the caller can examine it
12764  * to find out what happened.
12765  */
12766   errno = gl->rtn_errno;
12767 /*
12768  * Error conditions are signalled to the caller, by setting the returned
12769  * character to EOF.
12770  */
12771   if(gl->rtn_status != GLR_NEWLINE)
12772     retval = EOF;
12773 /*
12774  * Restore the indication of what direction of I/O gl_get_line()
12775  * was awaiting before this call.
12776  */
12777   gl->pending_io = old_pending_io;
12778 /*
12779  * Return the acquired character.
12780  */
12781   return retval;
12782 }
12783 
12784 /*.......................................................................
12785  * Reset the GetLine completion status. This function should be called
12786  * at the start of gl_get_line(), gl_read_char() and gl_query_char()
12787  * to discard the completion status and non-zero errno value of any
12788  * preceding calls to these functions.
12789  *
12790  * Input:
12791  *  gl       GetLine *  The resource object of this module.
12792  */
12793 static void gl_clear_status(GetLine *gl)
12794 {
12795   gl_record_status(gl, GLR_NEWLINE, 0);
12796 }
12797 
12798 /*.......................................................................
12799  * When an error or other event causes gl_get_line() to return, this
12800  * function should be called to record information about what
12801  * happened, including the value of errno and the value that
12802  * gl_return_status() should return.
12803  *
12804  * Input:
12805  *  gl                GetLine *  The resource object of this module.
12806  *  rtn_status GlReturnStatus    The completion status. To clear a
12807  *                               previous abnormal completion status,
12808  *                               specify GLR_NEWLINE (this is what
12809  *                               gl_clear_status() does).
12810  *  rtn_errno             int    The associated value of errno.
12811  */
12812 static void gl_record_status(GetLine *gl, GlReturnStatus rtn_status,
12813 			     int rtn_errno)
12814 {
12815 /*
12816  * If rtn_status==GLR_NEWLINE, then this resets the completion status, so we
12817  * should always heed this. Otherwise, only record the first abnormal
12818  * condition that occurs after such a reset.
12819  */
12820   if(rtn_status == GLR_NEWLINE || gl->rtn_status == GLR_NEWLINE) {
12821     gl->rtn_status = rtn_status;
12822     gl->rtn_errno = rtn_errno;
12823   };
12824 }
12825 
12826