1 /* 2 * Copyright (c) 2000, 2001, 2002, 2003, 2004 by Martin C. Shepherd. 3 * 4 * All rights reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, and/or sell copies of the Software, and to permit persons 11 * to whom the Software is furnished to do so, provided that the above 12 * copyright notice(s) and this permission notice appear in all copies of 13 * the Software and that both the above copyright notice(s) and this 14 * permission notice appear in supporting documentation. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 19 * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 20 * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL 21 * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING 22 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 23 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 24 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 25 * 26 * Except as contained in this notice, the name of a copyright holder 27 * shall not be used in advertising or otherwise to promote the sale, use 28 * or other dealings in this Software without prior written authorization 29 * of the copyright holder. 30 */ 31 32 /* 33 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 34 * Use is subject to license terms. 35 */ 36 37 #pragma ident "%Z%%M% %I% %E% SMI" 38 39 /* 40 * Standard headers. 41 */ 42 #include <stdio.h> 43 #include <stdlib.h> 44 #include <signal.h> 45 #include <string.h> 46 #include <errno.h> 47 #include <ctype.h> 48 #include <setjmp.h> 49 #include <stdarg.h> 50 51 /* 52 * UNIX headers. 53 */ 54 #include <sys/ioctl.h> 55 #ifdef HAVE_SELECT 56 #ifdef HAVE_SYS_SELECT_H 57 #include <sys/select.h> 58 #endif 59 #include <sys/time.h> 60 #include <sys/types.h> 61 #endif 62 63 /* 64 * Handle the different sources of terminal control string and size 65 * information. Note that if no terminal information database is available, 66 * ANSI VT100 control sequences are used. 67 */ 68 #if defined(USE_TERMINFO) || defined(USE_TERMCAP) 69 /* 70 * Include curses.h or ncurses/curses.h depending on which is available. 71 */ 72 #ifdef HAVE_CURSES_H 73 #include <curses.h> 74 #elif defined(HAVE_NCURSES_CURSES_H) 75 #include <ncurses/curses.h> 76 #endif 77 /* 78 * Include term.h where available. 79 */ 80 #if defined(HAVE_TERM_H) 81 #include <term.h> 82 #elif defined(HAVE_NCURSES_TERM_H) 83 #include <ncurses/term.h> 84 #endif 85 /* 86 * When using termcap, include termcap.h on systems that have it. 87 * Otherwise assume that all prototypes are provided by curses.h. 88 */ 89 #if defined(USE_TERMCAP) && defined(HAVE_TERMCAP_H) 90 #include <termcap.h> 91 #endif 92 93 /* 94 * Under Solaris default Curses the output function that tputs takes is 95 * declared to have a char argument. On all other systems and on Solaris 96 * X/Open Curses (Issue 4, Version 2) it expects an int argument (using 97 * c89 or options -I /usr/xpg4/include -L /usr/xpg4/lib -R /usr/xpg4/lib 98 * selects XPG4v2 Curses on Solaris 2.6 and later). 99 * 100 * Similarly, under Mac OS X, the return value of the tputs output 101 * function is declared as void, whereas it is declared as int on 102 * other systems. 103 */ 104 #if defined __sun && defined __SVR4 && !defined _XOPEN_CURSES 105 typedef int TputsRetType; 106 typedef char TputsArgType; /* int tputs(char c, FILE *fp) */ 107 #define TPUTS_RETURNS_VALUE 1 108 #elif defined(__APPLE__) && defined(__MACH__) 109 typedef void TputsRetType; 110 typedef int TputsArgType; /* void tputs(int c, FILE *fp) */ 111 #define TPUTS_RETURNS_VALUE 0 112 #else 113 typedef int TputsRetType; 114 typedef int TputsArgType; /* int tputs(int c, FILE *fp) */ 115 #define TPUTS_RETURNS_VALUE 1 116 #endif 117 118 /* 119 * Use the above specifications to prototype our tputs callback function. 120 */ 121 static TputsRetType gl_tputs_putchar(TputsArgType c); 122 123 #endif /* defined(USE_TERMINFO) || defined(USE_TERMCAP) */ 124 125 /* 126 * If the library is being compiled without filesystem access facilities, 127 * ensure that none of the action functions that normally do access the 128 * filesystem are bound by default, and that it they do get bound, that 129 * they don't do anything. 130 */ 131 #if WITHOUT_FILE_SYSTEM 132 #define HIDE_FILE_SYSTEM 133 #endif 134 135 /* 136 * POSIX headers. 137 */ 138 #include <unistd.h> 139 #include <fcntl.h> 140 #include <termios.h> 141 142 /* 143 * Provide typedefs for standard POSIX structures. 144 */ 145 typedef struct sigaction SigAction; 146 typedef struct termios Termios; 147 148 /* 149 * Which flag is used to select non-blocking I/O with fcntl()? 150 */ 151 #undef NON_BLOCKING_FLAG 152 #if defined(O_NONBLOCK) 153 #define NON_BLOCKING_FLAG (O_NONBLOCK) 154 #elif defined(O_NDELAY) 155 #define NON_BLOCKING_FLAG (O_NDELAY) 156 #endif 157 158 /* 159 * What value should we give errno if I/O blocks when it shouldn't. 160 */ 161 #undef BLOCKED_ERRNO 162 #if defined(EAGAIN) 163 #define BLOCKED_ERRNO (EAGAIN) 164 #elif defined(EWOULDBLOCK) 165 #define BLOCKED_ERRNO (EWOULDBLOCK) 166 #elif defined(EIO) 167 #define BLOCKED_ERRNO (EIO) 168 #else 169 #define BLOCKED_ERRNO 0 170 #endif 171 172 /* 173 * Local headers. 174 */ 175 #ifndef WITHOUT_FILE_SYSTEM 176 #include "pathutil.h" 177 #endif 178 #include "libtecla.h" 179 #include "keytab.h" 180 #include "getline.h" 181 #include "ioutil.h" 182 #include "history.h" 183 #include "freelist.h" 184 #include "stringrp.h" 185 #include "chrqueue.h" 186 #include "cplmatch.h" 187 #ifndef WITHOUT_FILE_SYSTEM 188 #include "expand.h" 189 #endif 190 #include "errmsg.h" 191 192 /* 193 * Enumerate the available editing styles. 194 */ 195 typedef enum { 196 GL_EMACS_MODE, /* Emacs style editing */ 197 GL_VI_MODE, /* Vi style editing */ 198 GL_NO_EDITOR /* Fall back to the basic OS-provided editing */ 199 } GlEditor; 200 201 /* 202 * Set the largest key-sequence that can be handled. 203 */ 204 #define GL_KEY_MAX 64 205 206 /* 207 * In vi mode, the following datatype is used to implement the 208 * undo command. It records a copy of the input line from before 209 * the command-mode action which edited the input line. 210 */ 211 typedef struct { 212 char *line; /* A historical copy of the input line */ 213 int buff_curpos; /* The historical location of the cursor in */ 214 /* line[] when the line was modified. */ 215 int ntotal; /* The number of characters in line[] */ 216 int saved; /* True once a line has been saved after the */ 217 /* last call to gl_interpret_char(). */ 218 } ViUndo; 219 220 /* 221 * In vi mode, the following datatype is used to record information 222 * needed by the vi-repeat-change command. 223 */ 224 typedef struct { 225 KtAction action; /* The last action function that made a */ 226 /* change to the line. */ 227 int count; /* The repeat count that was passed to the */ 228 /* above command. */ 229 int input_curpos; /* Whenever vi command mode is entered, the */ 230 /* the position at which it was first left */ 231 /* is recorded here. */ 232 int command_curpos; /* Whenever vi command mode is entered, the */ 233 /* the location of the cursor is recorded */ 234 /* here. */ 235 char input_char; /* Commands that call gl_read_terminal() */ 236 /* record the character here, so that it can */ 237 /* used on repeating the function. */ 238 int saved; /* True if a function has been saved since the */ 239 /* last call to gl_interpret_char(). */ 240 int active; /* True while a function is being repeated. */ 241 } ViRepeat; 242 243 /* 244 * The following datatype is used to encapsulate information specific 245 * to vi mode. 246 */ 247 typedef struct { 248 ViUndo undo; /* Information needed to implement the vi */ 249 /* undo command. */ 250 ViRepeat repeat; /* Information needed to implement the vi */ 251 /* repeat command. */ 252 int command; /* True in vi command-mode */ 253 int find_forward; /* True if the last character search was in the */ 254 /* forward direction. */ 255 int find_onto; /* True if the last character search left the */ 256 /* on top of the located character, as opposed */ 257 /* to just before or after it. */ 258 char find_char; /* The last character sought, or '\0' if no */ 259 /* searches have been performed yet. */ 260 } ViMode; 261 262 #ifdef HAVE_SELECT 263 /* 264 * Define a type for recording a file-descriptor callback and its associated 265 * data. 266 */ 267 typedef struct { 268 GlFdEventFn *fn; /* The callback function */ 269 void *data; /* Anonymous data to pass to the callback function */ 270 } GlFdHandler; 271 272 /* 273 * A list of nodes of the following type is used to record file-activity 274 * event handlers, but only on systems that have the select() system call. 275 */ 276 typedef struct GlFdNode GlFdNode; 277 struct GlFdNode { 278 GlFdNode *next; /* The next in the list of nodes */ 279 int fd; /* The file descriptor being watched */ 280 GlFdHandler rd; /* The callback to call when fd is readable */ 281 GlFdHandler wr; /* The callback to call when fd is writable */ 282 GlFdHandler ur; /* The callback to call when fd has urgent data */ 283 }; 284 285 /* 286 * Set the number of the above structures to allocate every time that 287 * the freelist of GlFdNode's becomes exhausted. 288 */ 289 #define GLFD_FREELIST_BLOCKING 10 290 291 292 static int gl_call_fd_handler(GetLine *gl, GlFdHandler *gfh, int fd, 293 GlFdEvent event); 294 295 static int gl_call_timeout_handler(GetLine *gl); 296 297 #endif 298 299 /* 300 * Each signal that gl_get_line() traps is described by a list node 301 * of the following type. 302 */ 303 typedef struct GlSignalNode GlSignalNode; 304 struct GlSignalNode { 305 GlSignalNode *next; /* The next signal in the list */ 306 int signo; /* The number of the signal */ 307 sigset_t proc_mask; /* A process mask which only includes signo */ 308 SigAction original; /* The signal disposition of the calling program */ 309 /* for this signal. */ 310 unsigned flags; /* A bitwise union of GlSignalFlags enumerators */ 311 GlAfterSignal after; /* What to do after the signal has been handled */ 312 int errno_value; /* What to set errno to */ 313 }; 314 315 /* 316 * Set the number of the above structures to allocate every time that 317 * the freelist of GlSignalNode's becomes exhausted. 318 */ 319 #define GLS_FREELIST_BLOCKING 30 320 321 /* 322 * Completion handlers and their callback data are recorded in 323 * nodes of the following type. 324 */ 325 typedef struct GlCplCallback GlCplCallback; 326 struct GlCplCallback { 327 CplMatchFn *fn; /* The completion callback function */ 328 void *data; /* Arbitrary callback data */ 329 }; 330 331 /* 332 * The following function is used as the default completion handler when 333 * the filesystem is to be hidden. It simply reports no completions. 334 */ 335 #ifdef HIDE_FILE_SYSTEM 336 static CPL_MATCH_FN(gl_no_completions); 337 #endif 338 339 /* 340 * Specify how many GlCplCallback nodes are added to the GlCplCallback freelist 341 * whenever it becomes exhausted. 342 */ 343 #define GL_CPL_FREELIST_BLOCKING 10 344 345 /* 346 * External action functions and their callback data are recorded in 347 * nodes of the following type. 348 */ 349 typedef struct GlExternalAction GlExternalAction; 350 struct GlExternalAction { 351 GlActionFn *fn; /* The function which implements the action */ 352 void *data; /* Arbitrary callback data */ 353 }; 354 355 /* 356 * Specify how many GlExternalAction nodes are added to the 357 * GlExternalAction freelist whenever it becomes exhausted. 358 */ 359 #define GL_EXT_ACT_FREELIST_BLOCKING 10 360 361 /* 362 * Define the contents of the GetLine object. 363 * Note that the typedef for this object can be found in libtecla.h. 364 */ 365 struct GetLine { 366 ErrMsg *err; /* The error-reporting buffer */ 367 GlHistory *glh; /* The line-history buffer */ 368 WordCompletion *cpl; /* String completion resource object */ 369 GlCplCallback cplfn; /* The completion callback */ 370 #ifndef WITHOUT_FILE_SYSTEM 371 ExpandFile *ef; /* ~user/, $envvar and wildcard expansion */ 372 /* resource object. */ 373 #endif 374 StringGroup *capmem; /* Memory for recording terminal capability */ 375 /* strings. */ 376 GlCharQueue *cq; /* The terminal output character queue */ 377 int input_fd; /* The file descriptor to read on */ 378 int output_fd; /* The file descriptor to write to */ 379 FILE *input_fp; /* A stream wrapper around input_fd */ 380 FILE *output_fp; /* A stream wrapper around output_fd */ 381 FILE *file_fp; /* When input is being temporarily taken from */ 382 /* a file, this is its file-pointer. Otherwise */ 383 /* it is NULL. */ 384 char *term; /* The terminal type specified on the last call */ 385 /* to gl_change_terminal(). */ 386 int is_term; /* True if stdin is a terminal */ 387 GlWriteFn *flush_fn; /* The function to call to write to the terminal */ 388 GlIOMode io_mode; /* The I/O mode established by gl_io_mode() */ 389 int raw_mode; /* True while the terminal is in raw mode */ 390 GlPendingIO pending_io; /* The type of I/O that is currently pending */ 391 GlReturnStatus rtn_status; /* The reason why gl_get_line() returned */ 392 int rtn_errno; /* THe value of errno associated with rtn_status */ 393 size_t linelen; /* The max number of characters per line */ 394 char *line; /* A line-input buffer of allocated size */ 395 /* linelen+2. The extra 2 characters are */ 396 /* reserved for "\n\0". */ 397 char *cutbuf; /* A cut-buffer of the same size as line[] */ 398 char *prompt; /* The current prompt string */ 399 int prompt_len; /* The length of the prompt string */ 400 int prompt_changed; /* True after a callback changes the prompt */ 401 int prompt_style; /* How the prompt string is displayed */ 402 FreeList *cpl_mem; /* Memory for GlCplCallback objects */ 403 FreeList *ext_act_mem; /* Memory for GlExternalAction objects */ 404 FreeList *sig_mem; /* Memory for nodes of the signal list */ 405 GlSignalNode *sigs; /* The head of the list of signals */ 406 int signals_masked; /* True between calls to gl_mask_signals() and */ 407 /* gl_unmask_signals() */ 408 int signals_overriden; /* True between calls to gl_override_signals() */ 409 /* and gl_restore_signals() */ 410 sigset_t all_signal_set; /* The set of all signals that we are trapping */ 411 sigset_t old_signal_set; /* The set of blocked signals on entry to */ 412 /* gl_get_line(). */ 413 sigset_t use_signal_set; /* The subset of all_signal_set to unblock */ 414 /* while waiting for key-strokes */ 415 Termios oldattr; /* Saved terminal attributes. */ 416 KeyTab *bindings; /* A table of key-bindings */ 417 int ntotal; /* The number of characters in gl->line[] */ 418 int buff_curpos; /* The cursor position within gl->line[] */ 419 int term_curpos; /* The cursor position on the terminal */ 420 int term_len; /* The number of terminal characters used to */ 421 /* display the current input line. */ 422 int buff_mark; /* A marker location in the buffer */ 423 int insert_curpos; /* The cursor position at start of insert */ 424 int insert; /* True in insert mode */ 425 int number; /* If >= 0, a numeric argument is being read */ 426 int endline; /* True to tell gl_get_input_line() to return */ 427 /* the current contents of gl->line[] */ 428 int displayed; /* True if an input line is currently displayed */ 429 int redisplay; /* If true, the input line will be redrawn */ 430 /* either after the current action function */ 431 /* returns, or when gl_get_input_line() */ 432 /* is next called. */ 433 int postpone; /* _gl_normal_io() sets this flag, to */ 434 /* postpone any redisplays until */ 435 /* is next called, to resume line editing. */ 436 char keybuf[GL_KEY_MAX+1]; /* A buffer of currently unprocessed key presses */ 437 int nbuf; /* The number of characters in keybuf[] */ 438 int nread; /* The number of characters read from keybuf[] */ 439 KtAction current_action; /* The action function that is being invoked */ 440 int current_count; /* The repeat count passed to */ 441 /* current_acction.fn() */ 442 GlhLineID preload_id; /* When not zero, this should be the ID of a */ 443 /* line in the history buffer for potential */ 444 /* recall. */ 445 int preload_history; /* If true, preload the above history line when */ 446 /* gl_get_input_line() is next called. */ 447 long keyseq_count; /* The number of key sequences entered by the */ 448 /* the user since new_GetLine() was called. */ 449 long last_search; /* The value of keyseq_count during the last */ 450 /* history search operation. */ 451 GlEditor editor; /* The style of editing, (eg. vi or emacs) */ 452 int silence_bell; /* True if gl_ring_bell() should do nothing. */ 453 int automatic_history; /* True to automatically archive entered lines */ 454 /* in the history list. */ 455 ViMode vi; /* Parameters used when editing in vi mode */ 456 const char *left; /* The string that moves the cursor 1 character */ 457 /* left. */ 458 const char *right; /* The string that moves the cursor 1 character */ 459 /* right. */ 460 const char *up; /* The string that moves the cursor 1 character */ 461 /* up. */ 462 const char *down; /* The string that moves the cursor 1 character */ 463 /* down. */ 464 const char *home; /* The string that moves the cursor home */ 465 const char *bol; /* Move cursor to beginning of line */ 466 const char *clear_eol; /* The string that clears from the cursor to */ 467 /* the end of the line. */ 468 const char *clear_eod; /* The string that clears from the cursor to */ 469 /* the end of the display. */ 470 const char *u_arrow; /* The string returned by the up-arrow key */ 471 const char *d_arrow; /* The string returned by the down-arrow key */ 472 const char *l_arrow; /* The string returned by the left-arrow key */ 473 const char *r_arrow; /* The string returned by the right-arrow key */ 474 const char *sound_bell; /* The string needed to ring the terminal bell */ 475 const char *bold; /* Switch to the bold font */ 476 const char *underline; /* Underline subsequent characters */ 477 const char *standout; /* Turn on standout mode */ 478 const char *dim; /* Switch to a dim font */ 479 const char *reverse; /* Turn on reverse video */ 480 const char *blink; /* Switch to a blinking font */ 481 const char *text_attr_off; /* Turn off all text attributes */ 482 int nline; /* The height of the terminal in lines */ 483 int ncolumn; /* The width of the terminal in columns */ 484 #ifdef USE_TERMCAP 485 char *tgetent_buf; /* The buffer that is used by tgetent() to */ 486 /* store a terminal description. */ 487 char *tgetstr_buf; /* The buffer that is used by tgetstr() to */ 488 /* store terminal capabilities. */ 489 #endif 490 #ifdef USE_TERMINFO 491 const char *left_n; /* The parameter string that moves the cursor */ 492 /* n characters left. */ 493 const char *right_n; /* The parameter string that moves the cursor */ 494 /* n characters right. */ 495 #endif 496 char *app_file; /* The pathname of the application-specific */ 497 /* .teclarc configuration file, or NULL. */ 498 char *user_file; /* The pathname of the user-specific */ 499 /* .teclarc configuration file, or NULL. */ 500 int configured; /* True as soon as any teclarc configuration */ 501 /* file has been read. */ 502 int echo; /* True to display the line as it is being */ 503 /* entered. If 0, only the prompt will be */ 504 /* displayed, and the line will not be */ 505 /* archived in the history list. */ 506 int last_signal; /* The last signal that was caught by */ 507 /* the last call to gl_get_line(), or -1 */ 508 /* if no signal has been caught yet. */ 509 #ifdef HAVE_SELECT 510 FreeList *fd_node_mem; /* A freelist of GlFdNode structures */ 511 GlFdNode *fd_nodes; /* The list of fd event descriptions */ 512 fd_set rfds; /* The set of fds to watch for readability */ 513 fd_set wfds; /* The set of fds to watch for writability */ 514 fd_set ufds; /* The set of fds to watch for urgent data */ 515 int max_fd; /* The maximum file-descriptor being watched */ 516 struct { /* Inactivity timeout related data */ 517 struct timeval dt; /* The inactivity timeout when timer.fn() */ 518 /* isn't 0 */ 519 GlTimeoutFn *fn; /* The application callback to call when */ 520 /* the inactivity timer expires, or 0 if */ 521 /* timeouts are not required. */ 522 void *data; /* Application provided data to be passed to */ 523 /* timer.fn(). */ 524 } timer; 525 #endif 526 }; 527 528 /* 529 * Define the max amount of space needed to store a termcap terminal 530 * description. Unfortunately this has to be done by guesswork, so 531 * there is the potential for buffer overflows if we guess too small. 532 * Fortunately termcap has been replaced by terminfo on most 533 * platforms, and with terminfo this isn't an issue. The value that I 534 * am using here is the conventional value, as recommended by certain 535 * web references. 536 */ 537 #ifdef USE_TERMCAP 538 #define TERMCAP_BUF_SIZE 2048 539 #endif 540 541 /* 542 * Set the size of the string segments used to store terminal capability 543 * strings. 544 */ 545 #define CAPMEM_SEGMENT_SIZE 512 546 547 /* 548 * If no terminal size information is available, substitute the 549 * following vt100 default sizes. 550 */ 551 #define GL_DEF_NLINE 24 552 #define GL_DEF_NCOLUMN 80 553 554 /* 555 * Enumerate the attributes needed to classify different types of 556 * signals. These attributes reflect the standard default 557 * characteristics of these signals (according to Richard Steven's 558 * Advanced Programming in the UNIX Environment). Note that these values 559 * are all powers of 2, so that they can be combined in a bitwise union. 560 */ 561 typedef enum { 562 GLSA_TERM=1, /* A signal that terminates processes */ 563 GLSA_SUSP=2, /* A signal that suspends processes */ 564 GLSA_CONT=4, /* A signal that is sent when suspended processes resume */ 565 GLSA_IGN=8, /* A signal that is ignored */ 566 GLSA_CORE=16, /* A signal that generates a core dump */ 567 GLSA_HARD=32, /* A signal generated by a hardware exception */ 568 GLSA_SIZE=64 /* A signal indicating terminal size changes */ 569 } GlSigAttr; 570 571 /* 572 * List the signals that we need to catch. In general these are 573 * those that by default terminate or suspend the process, since 574 * in such cases we need to restore terminal settings. 575 */ 576 static const struct GlDefSignal { 577 int signo; /* The number of the signal */ 578 unsigned flags; /* A bitwise union of GlSignalFlags enumerators */ 579 GlAfterSignal after; /* What to do after the signal has been delivered */ 580 int attr; /* The default attributes of this signal, expressed */ 581 /* as a bitwise union of GlSigAttr enumerators */ 582 int errno_value; /* What to set errno to */ 583 } gl_signal_list[] = { 584 {SIGABRT, GLS_SUSPEND_INPUT, GLS_ABORT, GLSA_TERM|GLSA_CORE, EINTR}, 585 {SIGALRM, GLS_RESTORE_ENV, GLS_CONTINUE, GLSA_TERM, 0}, 586 {SIGCONT, GLS_RESTORE_ENV, GLS_CONTINUE, GLSA_CONT|GLSA_IGN, 0}, 587 #if defined(SIGHUP) 588 #ifdef ENOTTY 589 {SIGHUP, GLS_SUSPEND_INPUT, GLS_ABORT, GLSA_TERM, ENOTTY}, 590 #else 591 {SIGHUP, GLS_SUSPEND_INPUT, GLS_ABORT, GLSA_TERM, EINTR}, 592 #endif 593 #endif 594 {SIGINT, GLS_SUSPEND_INPUT, GLS_ABORT, GLSA_TERM, EINTR}, 595 #if defined(SIGPIPE) 596 #ifdef EPIPE 597 {SIGPIPE, GLS_SUSPEND_INPUT, GLS_ABORT, GLSA_TERM, EPIPE}, 598 #else 599 {SIGPIPE, GLS_SUSPEND_INPUT, GLS_ABORT, GLSA_TERM, EINTR}, 600 #endif 601 #endif 602 #ifdef SIGPOLL 603 {SIGPOLL, GLS_SUSPEND_INPUT, GLS_ABORT, GLSA_TERM, EINTR}, 604 #endif 605 #ifdef SIGPWR 606 {SIGPWR, GLS_RESTORE_ENV, GLS_CONTINUE, GLSA_IGN, 0}, 607 #endif 608 #ifdef SIGQUIT 609 {SIGQUIT, GLS_SUSPEND_INPUT, GLS_ABORT, GLSA_TERM|GLSA_CORE, EINTR}, 610 #endif 611 {SIGTERM, GLS_SUSPEND_INPUT, GLS_ABORT, GLSA_TERM, EINTR}, 612 #ifdef SIGTSTP 613 {SIGTSTP, GLS_SUSPEND_INPUT, GLS_CONTINUE, GLSA_SUSP, 0}, 614 #endif 615 #ifdef SIGTTIN 616 {SIGTTIN, GLS_SUSPEND_INPUT, GLS_CONTINUE, GLSA_SUSP, 0}, 617 #endif 618 #ifdef SIGTTOU 619 {SIGTTOU, GLS_SUSPEND_INPUT, GLS_CONTINUE, GLSA_SUSP, 0}, 620 #endif 621 #ifdef SIGUSR1 622 {SIGUSR1, GLS_RESTORE_ENV, GLS_CONTINUE, GLSA_TERM, 0}, 623 #endif 624 #ifdef SIGUSR2 625 {SIGUSR2, GLS_RESTORE_ENV, GLS_CONTINUE, GLSA_TERM, 0}, 626 #endif 627 #ifdef SIGVTALRM 628 {SIGVTALRM, GLS_RESTORE_ENV, GLS_CONTINUE, GLSA_TERM, 0}, 629 #endif 630 #ifdef SIGWINCH 631 {SIGWINCH, GLS_RESTORE_ENV, GLS_CONTINUE, GLSA_SIZE|GLSA_IGN, 0}, 632 #endif 633 #ifdef SIGXCPU 634 {SIGXCPU, GLS_RESTORE_ENV, GLS_CONTINUE, GLSA_TERM|GLSA_CORE, 0}, 635 #endif 636 #ifdef SIGXFSZ 637 {SIGXFSZ, GLS_RESTORE_ENV, GLS_CONTINUE, GLSA_TERM|GLSA_CORE, 0}, 638 #endif 639 }; 640 641 /* 642 * Define file-scope variables for use in signal handlers. 643 */ 644 static volatile sig_atomic_t gl_pending_signal = -1; 645 static sigjmp_buf gl_setjmp_buffer; 646 647 static void gl_signal_handler(int signo); 648 649 static int gl_check_caught_signal(GetLine *gl); 650 651 /* 652 * Respond to an externally caught process suspension or 653 * termination signal. 654 */ 655 static void gl_suspend_process(int signo, GetLine *gl, int ngl); 656 657 /* Return the default attributes of a given signal */ 658 659 static int gl_classify_signal(int signo); 660 661 /* 662 * Unfortunately both terminfo and termcap require one to use the tputs() 663 * function to output terminal control characters, and this function 664 * doesn't allow one to specify a file stream. As a result, the following 665 * file-scope variable is used to pass the current output file stream. 666 * This is bad, but there doesn't seem to be any alternative. 667 */ 668 static GetLine *tputs_gl = NULL; 669 670 /* 671 * Define a tab to be a string of 8 spaces. 672 */ 673 #define TAB_WIDTH 8 674 675 /* 676 * Lookup the current size of the terminal. 677 */ 678 static void gl_query_size(GetLine *gl, int *ncolumn, int *nline); 679 680 /* 681 * Getline calls this to temporarily override certain signal handlers 682 * of the calling program. 683 */ 684 static int gl_override_signal_handlers(GetLine *gl); 685 686 /* 687 * Getline calls this to restore the signal handlers of the calling 688 * program. 689 */ 690 static int gl_restore_signal_handlers(GetLine *gl); 691 692 /* 693 * Temporarily block the delivery of all signals that gl_get_line() 694 * is currently configured to trap. 695 */ 696 static int gl_mask_signals(GetLine *gl, sigset_t *oldset); 697 698 /* 699 * Restore the process signal mask that was overriden by a previous 700 * call to gl_mask_signals(). 701 */ 702 static int gl_unmask_signals(GetLine *gl, sigset_t *oldset); 703 704 /* 705 * Unblock the signals that gl_get_line() has been configured to catch. 706 */ 707 static int gl_catch_signals(GetLine *gl); 708 709 /* 710 * Return the set of all trappable signals. 711 */ 712 static void gl_list_trappable_signals(sigset_t *signals); 713 714 /* 715 * Put the terminal into raw input mode, after saving the original 716 * terminal attributes in gl->oldattr. 717 */ 718 static int gl_raw_terminal_mode(GetLine *gl); 719 720 /* 721 * Restore the terminal attributes from gl->oldattr. 722 */ 723 static int gl_restore_terminal_attributes(GetLine *gl); 724 725 /* 726 * Switch to non-blocking I/O if possible. 727 */ 728 static int gl_nonblocking_io(GetLine *gl, int fd); 729 730 /* 731 * Switch to blocking I/O if possible. 732 */ 733 static int gl_blocking_io(GetLine *gl, int fd); 734 735 /* 736 * Read a line from the user in raw mode. 737 */ 738 static int gl_get_input_line(GetLine *gl, const char *prompt, 739 const char *start_line, int start_pos); 740 741 /* 742 * Query the user for a single character. 743 */ 744 static int gl_get_query_char(GetLine *gl, const char *prompt, int defchar); 745 746 /* 747 * Read input from a non-interactive input stream. 748 */ 749 static int gl_read_stream_line(GetLine *gl); 750 751 /* 752 * Read a single character from a non-interactive input stream. 753 */ 754 static int gl_read_stream_char(GetLine *gl); 755 756 /* 757 * Prepare to edit a new line. 758 */ 759 static int gl_present_line(GetLine *gl, const char *prompt, 760 const char *start_line, int start_pos); 761 762 /* 763 * Reset all line input parameters for a new input line. 764 */ 765 static void gl_reset_input_line(GetLine *gl); 766 767 /* 768 * Handle the receipt of the potential start of a new key-sequence from 769 * the user. 770 */ 771 static int gl_interpret_char(GetLine *gl, char c); 772 773 /* 774 * Bind a single control or meta character to an action. 775 */ 776 static int gl_bind_control_char(GetLine *gl, KtBinder binder, 777 char c, const char *action); 778 779 /* 780 * Set up terminal-specific key bindings. 781 */ 782 static int gl_bind_terminal_keys(GetLine *gl); 783 784 /* 785 * Lookup terminal control string and size information. 786 */ 787 static int gl_control_strings(GetLine *gl, const char *term); 788 789 /* 790 * Wrappers around the terminfo and termcap functions that lookup 791 * strings in the terminal information databases. 792 */ 793 #ifdef USE_TERMINFO 794 static const char *gl_tigetstr(GetLine *gl, const char *name); 795 #elif defined(USE_TERMCAP) 796 static const char *gl_tgetstr(GetLine *gl, const char *name, char **bufptr); 797 #endif 798 799 /* 800 * Output a binary string directly to the terminal. 801 */ 802 static int gl_print_raw_string(GetLine *gl, int buffered, 803 const char *string, int n); 804 805 /* 806 * Print an informational message, starting and finishing on new lines. 807 * After the list of strings to be printed, the last argument MUST be 808 * GL_END_INFO. 809 */ 810 static int gl_print_info(GetLine *gl, ...); 811 #define GL_END_INFO ((const char *)0) 812 813 /* 814 * Start a newline and place the cursor at its start. 815 */ 816 static int gl_start_newline(GetLine *gl, int buffered); 817 818 /* 819 * Output a terminal control sequence. 820 */ 821 static int gl_print_control_sequence(GetLine *gl, int nline, 822 const char *string); 823 824 /* 825 * Output a character or string to the terminal after converting tabs 826 * to spaces and control characters to a caret followed by the modified 827 * character. 828 */ 829 static int gl_print_char(GetLine *gl, char c, char pad); 830 static int gl_print_string(GetLine *gl, const char *string, char pad); 831 832 /* 833 * Delete nc characters starting from the one under the cursor. 834 * Optionally copy the deleted characters to the cut buffer. 835 */ 836 static int gl_delete_chars(GetLine *gl, int nc, int cut); 837 838 /* 839 * Add a character to the line buffer at the current cursor position, 840 * inserting or overwriting according the current mode. 841 */ 842 static int gl_add_char_to_line(GetLine *gl, char c); 843 844 /* 845 * Insert/append a string to the line buffer and terminal at the current 846 * cursor position. 847 */ 848 static int gl_add_string_to_line(GetLine *gl, const char *s); 849 850 /* 851 * Record a new character in the input-line buffer. 852 */ 853 static int gl_buffer_char(GetLine *gl, char c, int bufpos); 854 855 /* 856 * Record a string in the input-line buffer. 857 */ 858 static int gl_buffer_string(GetLine *gl, const char *s, int n, int bufpos); 859 860 /* 861 * Make way to insert a string in the input-line buffer. 862 */ 863 static int gl_make_gap_in_buffer(GetLine *gl, int start, int n); 864 865 /* 866 * Remove characters from the input-line buffer, and move any characters 867 * that followed them to the start of the vacated space. 868 */ 869 static void gl_remove_from_buffer(GetLine *gl, int start, int n); 870 871 /* 872 * Terminate the input-line buffer after a specified number of characters. 873 */ 874 static int gl_truncate_buffer(GetLine *gl, int n); 875 876 /* 877 * Delete the displayed part of the input line that follows the current 878 * terminal cursor position. 879 */ 880 static int gl_truncate_display(GetLine *gl); 881 882 /* 883 * Accomodate changes to the contents of the input line buffer 884 * that weren't made by the above gl_*buffer functions. 885 */ 886 static void gl_update_buffer(GetLine *gl); 887 888 /* 889 * Read a single character from the terminal. 890 */ 891 static int gl_read_terminal(GetLine *gl, int keep, char *c); 892 893 /* 894 * Discard processed characters from the key-press lookahead buffer. 895 */ 896 static void gl_discard_chars(GetLine *gl, int nused); 897 898 /* 899 * Move the terminal cursor n positions to the left or right. 900 */ 901 static int gl_terminal_move_cursor(GetLine *gl, int n); 902 903 /* 904 * Move the terminal cursor to a given position. 905 */ 906 static int gl_set_term_curpos(GetLine *gl, int term_curpos); 907 908 /* 909 * Set the position of the cursor both in the line input buffer and on the 910 * terminal. 911 */ 912 static int gl_place_cursor(GetLine *gl, int buff_curpos); 913 914 /* 915 * How many characters are needed to write a number as an octal string? 916 */ 917 static int gl_octal_width(unsigned num); 918 919 /* 920 * Return the number of spaces needed to display a tab character at 921 * a given location of the terminal. 922 */ 923 static int gl_displayed_tab_width(GetLine *gl, int term_curpos); 924 925 /* 926 * Return the number of terminal characters needed to display a 927 * given raw character. 928 */ 929 static int gl_displayed_char_width(GetLine *gl, char c, int term_curpos); 930 931 /* 932 * Return the number of terminal characters needed to display a 933 * given substring. 934 */ 935 static int gl_displayed_string_width(GetLine *gl, const char *string, int nc, 936 int term_curpos); 937 938 /* 939 * Return non-zero if 'c' is to be considered part of a word. 940 */ 941 static int gl_is_word_char(int c); 942 943 /* 944 * Read a tecla configuration file. 945 */ 946 static int _gl_read_config_file(GetLine *gl, const char *filename, KtBinder who); 947 948 /* 949 * Read a tecla configuration string. 950 */ 951 static int _gl_read_config_string(GetLine *gl, const char *buffer, KtBinder who); 952 953 /* 954 * Define the callback function used by _gl_parse_config_line() to 955 * read the next character of a configuration stream. 956 */ 957 #define GLC_GETC_FN(fn) int (fn)(void *stream) 958 typedef GLC_GETC_FN(GlcGetcFn); 959 960 static GLC_GETC_FN(glc_file_getc); /* Read from a file */ 961 static GLC_GETC_FN(glc_buff_getc); /* Read from a string */ 962 963 /* 964 * Parse a single configuration command line. 965 */ 966 static int _gl_parse_config_line(GetLine *gl, void *stream, GlcGetcFn *getc_fn, 967 const char *origin, KtBinder who, int *lineno); 968 static int gl_report_config_error(GetLine *gl, const char *origin, int lineno, 969 const char *errmsg); 970 971 /* 972 * Bind the actual arrow key bindings to match those of the symbolic 973 * arrow-key bindings. 974 */ 975 static int _gl_bind_arrow_keys(GetLine *gl); 976 977 /* 978 * Copy the binding of the specified symbolic arrow-key binding to 979 * the terminal specific, and default arrow-key key-sequences. 980 */ 981 static int _gl_rebind_arrow_key(GetLine *gl, const char *name, 982 const char *term_seq, 983 const char *def_seq1, 984 const char *def_seq2); 985 986 /* 987 * After the gl_read_from_file() action has been used to tell gl_get_line() 988 * to temporarily read input from a file, gl_revert_input() arranges 989 * for input to be reverted to the input stream last registered with 990 * gl_change_terminal(). 991 */ 992 static void gl_revert_input(GetLine *gl); 993 994 /* 995 * Flush unwritten characters to the terminal. 996 */ 997 static int gl_flush_output(GetLine *gl); 998 999 /* 1000 * The callback through which all terminal output is routed. 1001 * This simply appends characters to a queue buffer, which is 1002 * subsequently flushed to the output channel by gl_flush_output(). 1003 */ 1004 static GL_WRITE_FN(gl_write_fn); 1005 1006 /* 1007 * The callback function which the output character queue object 1008 * calls to transfer characters to the output channel. 1009 */ 1010 static GL_WRITE_FN(gl_flush_terminal); 1011 1012 /* 1013 * Enumerate the possible return statuses of gl_read_input(). 1014 */ 1015 typedef enum { 1016 GL_READ_OK, /* A character was read successfully */ 1017 GL_READ_ERROR, /* A read-error occurred */ 1018 GL_READ_BLOCKED, /* The read would have blocked the caller */ 1019 GL_READ_EOF /* The end of the current input file was reached */ 1020 } GlReadStatus; 1021 1022 static GlReadStatus gl_read_input(GetLine *gl, char *c); 1023 /* 1024 * Private functions of gl_read_input(). 1025 */ 1026 static int gl_event_handler(GetLine *gl, int fd); 1027 static int gl_read_unmasked(GetLine *gl, int fd, char *c); 1028 1029 1030 /* 1031 * A private function of gl_tty_signals(). 1032 */ 1033 static int gl_set_tty_signal(int signo, void (*handler)(int)); 1034 1035 /* 1036 * Change the editor style being emulated. 1037 */ 1038 static int gl_change_editor(GetLine *gl, GlEditor editor); 1039 1040 /* 1041 * Searching in a given direction, return the index of a given (or 1042 * read) character in the input line, or the character that precedes 1043 * it in the specified search direction. Return -1 if not found. 1044 */ 1045 static int gl_find_char(GetLine *gl, int count, int forward, int onto, char c); 1046 1047 /* 1048 * Return the buffer index of the nth word ending after the cursor. 1049 */ 1050 static int gl_nth_word_end_forward(GetLine *gl, int n); 1051 1052 /* 1053 * Return the buffer index of the nth word start after the cursor. 1054 */ 1055 static int gl_nth_word_start_forward(GetLine *gl, int n); 1056 1057 /* 1058 * Return the buffer index of the nth word start before the cursor. 1059 */ 1060 static int gl_nth_word_start_backward(GetLine *gl, int n); 1061 1062 /* 1063 * When called when vi command mode is enabled, this function saves the 1064 * current line and cursor position for potential restoration later 1065 * by the vi undo command. 1066 */ 1067 static void gl_save_for_undo(GetLine *gl); 1068 1069 /* 1070 * If in vi mode, switch to vi command mode. 1071 */ 1072 static void gl_vi_command_mode(GetLine *gl); 1073 1074 /* 1075 * In vi mode this is used to delete up to or onto a given or read 1076 * character in the input line. Also switch to insert mode if requested 1077 * after the deletion. 1078 */ 1079 static int gl_delete_find(GetLine *gl, int count, char c, int forward, 1080 int onto, int change); 1081 1082 /* 1083 * Copy the characters between the cursor and the count'th instance of 1084 * a specified (or read) character in the input line, into the cut buffer. 1085 */ 1086 static int gl_copy_find(GetLine *gl, int count, char c, int forward, int onto); 1087 1088 /* 1089 * Return the line index of the parenthesis that either matches the one under 1090 * the cursor, or not over a parenthesis character, the index of the next 1091 * close parenthesis. Return -1 if not found. 1092 */ 1093 static int gl_index_of_matching_paren(GetLine *gl); 1094 1095 /* 1096 * Replace a malloc'd string (or NULL), with another malloc'd copy of 1097 * a string (or NULL). 1098 */ 1099 static int gl_record_string(char **sptr, const char *string); 1100 1101 /* 1102 * Enumerate text display attributes as powers of two, suitable for 1103 * use in a bit-mask. 1104 */ 1105 typedef enum { 1106 GL_TXT_STANDOUT=1, /* Display text highlighted */ 1107 GL_TXT_UNDERLINE=2, /* Display text underlined */ 1108 GL_TXT_REVERSE=4, /* Display text with reverse video */ 1109 GL_TXT_BLINK=8, /* Display blinking text */ 1110 GL_TXT_DIM=16, /* Display text in a dim font */ 1111 GL_TXT_BOLD=32 /* Display text using a bold font */ 1112 } GlTextAttr; 1113 1114 /* 1115 * Display the prompt regardless of the current visibility mode. 1116 */ 1117 static int gl_display_prompt(GetLine *gl); 1118 1119 /* 1120 * Return the number of characters used by the prompt on the terminal. 1121 */ 1122 static int gl_displayed_prompt_width(GetLine *gl); 1123 1124 /* 1125 * Prepare to return the current input line to the caller of gl_get_line(). 1126 */ 1127 static int gl_line_ended(GetLine *gl, int newline_char); 1128 1129 /* 1130 * Arrange for the input line to be redisplayed when the current contents 1131 * of the output queue have been flushed. 1132 */ 1133 static void gl_queue_redisplay(GetLine *gl); 1134 1135 /* 1136 * Erase the displayed representation of the input line, without 1137 * touching the buffered copy. 1138 */ 1139 static int gl_erase_line(GetLine *gl); 1140 1141 /* 1142 * This function is called whenever the input line has been erased. 1143 */ 1144 static void gl_line_erased(GetLine *gl); 1145 1146 /* 1147 * Arrange for the current input line to be discarded. 1148 */ 1149 void _gl_abandon_line(GetLine *gl); 1150 1151 /* 1152 * The following are private internally callable versions of pertinent 1153 * public functions. Unlike their public wrapper functions, they don't 1154 * block signals while running, and assume that their arguments are valid. 1155 * They are designed to be called from places where signals are already 1156 * blocked, and where simple sanity checks have already been applied to 1157 * their arguments. 1158 */ 1159 static char *_gl_get_line(GetLine *gl, const char *prompt, 1160 const char *start_line, int start_pos); 1161 static int _gl_query_char(GetLine *gl, const char *prompt, char defchar); 1162 static int _gl_read_char(GetLine *gl); 1163 static int _gl_update_size(GetLine *gl); 1164 /* 1165 * Redraw the current input line to account for a change in the terminal 1166 * size. Also install the new size in gl. 1167 */ 1168 static int gl_handle_tty_resize(GetLine *gl, int ncolumn, int nline); 1169 1170 static int _gl_change_terminal(GetLine *gl, FILE *input_fp, FILE *output_fp, 1171 const char *term); 1172 static int _gl_configure_getline(GetLine *gl, const char *app_string, 1173 const char *app_file, const char *user_file); 1174 static int _gl_save_history(GetLine *gl, const char *filename, 1175 const char *comment, int max_lines); 1176 static int _gl_load_history(GetLine *gl, const char *filename, 1177 const char *comment); 1178 static int _gl_watch_fd(GetLine *gl, int fd, GlFdEvent event, 1179 GlFdEventFn *callback, void *data); 1180 static void _gl_terminal_size(GetLine *gl, int def_ncolumn, int def_nline, 1181 GlTerminalSize *size); 1182 static void _gl_replace_prompt(GetLine *gl, const char *prompt); 1183 static int _gl_trap_signal(GetLine *gl, int signo, unsigned flags, 1184 GlAfterSignal after, int errno_value); 1185 static int _gl_raw_io(GetLine *gl, int redisplay); 1186 static int _gl_normal_io(GetLine *gl); 1187 static int _gl_completion_action(GetLine *gl, void *data, CplMatchFn *match_fn, 1188 int list_only, const char *name, 1189 const char *keyseq); 1190 static int _gl_register_action(GetLine *gl, void *data, GlActionFn *fn, 1191 const char *name, const char *keyseq); 1192 static int _gl_io_mode(GetLine *gl, GlIOMode mode); 1193 static int _gl_set_term_size(GetLine *gl, int ncolumn, int nline); 1194 static int _gl_append_history(GetLine *gl, const char *line); 1195 1196 /* 1197 * Reset the completion status and associated errno value in 1198 * gl->rtn_status and gl->rtn_errno. 1199 */ 1200 static void gl_clear_status(GetLine *gl); 1201 1202 /* 1203 * Record a completion status, unless a previous abnormal completion 1204 * status has already been recorded for the current call. 1205 */ 1206 static void gl_record_status(GetLine *gl, GlReturnStatus rtn_status, 1207 int rtn_errno); 1208 1209 /* 1210 * Set the maximum length of a line in a user's tecla configuration 1211 * file (not counting comments). 1212 */ 1213 #define GL_CONF_BUFLEN 100 1214 1215 /* 1216 * Set the maximum number of arguments supported by individual commands 1217 * in tecla configuration files. 1218 */ 1219 #define GL_CONF_MAXARG 10 1220 1221 /* 1222 * Prototype the available action functions. 1223 */ 1224 static KT_KEY_FN(gl_user_interrupt); 1225 static KT_KEY_FN(gl_abort); 1226 static KT_KEY_FN(gl_suspend); 1227 static KT_KEY_FN(gl_stop_output); 1228 static KT_KEY_FN(gl_start_output); 1229 static KT_KEY_FN(gl_literal_next); 1230 static KT_KEY_FN(gl_cursor_left); 1231 static KT_KEY_FN(gl_cursor_right); 1232 static KT_KEY_FN(gl_insert_mode); 1233 static KT_KEY_FN(gl_beginning_of_line); 1234 static KT_KEY_FN(gl_end_of_line); 1235 static KT_KEY_FN(gl_delete_line); 1236 static KT_KEY_FN(gl_kill_line); 1237 static KT_KEY_FN(gl_forward_word); 1238 static KT_KEY_FN(gl_backward_word); 1239 static KT_KEY_FN(gl_forward_delete_char); 1240 static KT_KEY_FN(gl_backward_delete_char); 1241 static KT_KEY_FN(gl_forward_delete_word); 1242 static KT_KEY_FN(gl_backward_delete_word); 1243 static KT_KEY_FN(gl_delete_refind); 1244 static KT_KEY_FN(gl_delete_invert_refind); 1245 static KT_KEY_FN(gl_delete_to_column); 1246 static KT_KEY_FN(gl_delete_to_parenthesis); 1247 static KT_KEY_FN(gl_forward_delete_find); 1248 static KT_KEY_FN(gl_backward_delete_find); 1249 static KT_KEY_FN(gl_forward_delete_to); 1250 static KT_KEY_FN(gl_backward_delete_to); 1251 static KT_KEY_FN(gl_upcase_word); 1252 static KT_KEY_FN(gl_downcase_word); 1253 static KT_KEY_FN(gl_capitalize_word); 1254 static KT_KEY_FN(gl_redisplay); 1255 static KT_KEY_FN(gl_clear_screen); 1256 static KT_KEY_FN(gl_transpose_chars); 1257 static KT_KEY_FN(gl_set_mark); 1258 static KT_KEY_FN(gl_exchange_point_and_mark); 1259 static KT_KEY_FN(gl_kill_region); 1260 static KT_KEY_FN(gl_copy_region_as_kill); 1261 static KT_KEY_FN(gl_yank); 1262 static KT_KEY_FN(gl_up_history); 1263 static KT_KEY_FN(gl_down_history); 1264 static KT_KEY_FN(gl_history_search_backward); 1265 static KT_KEY_FN(gl_history_re_search_backward); 1266 static KT_KEY_FN(gl_history_search_forward); 1267 static KT_KEY_FN(gl_history_re_search_forward); 1268 static KT_KEY_FN(gl_complete_word); 1269 #ifndef HIDE_FILE_SYSTEM 1270 static KT_KEY_FN(gl_expand_filename); 1271 static KT_KEY_FN(gl_read_from_file); 1272 static KT_KEY_FN(gl_read_init_files); 1273 static KT_KEY_FN(gl_list_glob); 1274 #endif 1275 static KT_KEY_FN(gl_del_char_or_list_or_eof); 1276 static KT_KEY_FN(gl_list_or_eof); 1277 static KT_KEY_FN(gl_beginning_of_history); 1278 static KT_KEY_FN(gl_end_of_history); 1279 static KT_KEY_FN(gl_digit_argument); 1280 static KT_KEY_FN(gl_newline); 1281 static KT_KEY_FN(gl_repeat_history); 1282 static KT_KEY_FN(gl_vi_insert); 1283 static KT_KEY_FN(gl_vi_overwrite); 1284 static KT_KEY_FN(gl_change_case); 1285 static KT_KEY_FN(gl_vi_insert_at_bol); 1286 static KT_KEY_FN(gl_vi_append_at_eol); 1287 static KT_KEY_FN(gl_vi_append); 1288 static KT_KEY_FN(gl_backward_kill_line); 1289 static KT_KEY_FN(gl_goto_column); 1290 static KT_KEY_FN(gl_forward_to_word); 1291 static KT_KEY_FN(gl_vi_replace_char); 1292 static KT_KEY_FN(gl_vi_change_rest_of_line); 1293 static KT_KEY_FN(gl_vi_change_line); 1294 static KT_KEY_FN(gl_vi_change_to_bol); 1295 static KT_KEY_FN(gl_vi_change_refind); 1296 static KT_KEY_FN(gl_vi_change_invert_refind); 1297 static KT_KEY_FN(gl_vi_change_to_column); 1298 static KT_KEY_FN(gl_vi_change_to_parenthesis); 1299 static KT_KEY_FN(gl_vi_forward_change_word); 1300 static KT_KEY_FN(gl_vi_backward_change_word); 1301 static KT_KEY_FN(gl_vi_forward_change_find); 1302 static KT_KEY_FN(gl_vi_backward_change_find); 1303 static KT_KEY_FN(gl_vi_forward_change_to); 1304 static KT_KEY_FN(gl_vi_backward_change_to); 1305 static KT_KEY_FN(gl_vi_forward_change_char); 1306 static KT_KEY_FN(gl_vi_backward_change_char); 1307 static KT_KEY_FN(gl_forward_copy_char); 1308 static KT_KEY_FN(gl_backward_copy_char); 1309 static KT_KEY_FN(gl_forward_find_char); 1310 static KT_KEY_FN(gl_backward_find_char); 1311 static KT_KEY_FN(gl_forward_to_char); 1312 static KT_KEY_FN(gl_backward_to_char); 1313 static KT_KEY_FN(gl_repeat_find_char); 1314 static KT_KEY_FN(gl_invert_refind_char); 1315 static KT_KEY_FN(gl_append_yank); 1316 static KT_KEY_FN(gl_backward_copy_word); 1317 static KT_KEY_FN(gl_forward_copy_word); 1318 static KT_KEY_FN(gl_copy_to_bol); 1319 static KT_KEY_FN(gl_copy_refind); 1320 static KT_KEY_FN(gl_copy_invert_refind); 1321 static KT_KEY_FN(gl_copy_to_column); 1322 static KT_KEY_FN(gl_copy_to_parenthesis); 1323 static KT_KEY_FN(gl_copy_rest_of_line); 1324 static KT_KEY_FN(gl_copy_line); 1325 static KT_KEY_FN(gl_backward_copy_find); 1326 static KT_KEY_FN(gl_forward_copy_find); 1327 static KT_KEY_FN(gl_backward_copy_to); 1328 static KT_KEY_FN(gl_forward_copy_to); 1329 static KT_KEY_FN(gl_vi_undo); 1330 static KT_KEY_FN(gl_emacs_editing_mode); 1331 static KT_KEY_FN(gl_vi_editing_mode); 1332 static KT_KEY_FN(gl_ring_bell); 1333 static KT_KEY_FN(gl_vi_repeat_change); 1334 static KT_KEY_FN(gl_find_parenthesis); 1335 static KT_KEY_FN(gl_list_history); 1336 static KT_KEY_FN(gl_list_completions); 1337 static KT_KEY_FN(gl_run_external_action); 1338 1339 /* 1340 * Name the available action functions. 1341 */ 1342 static const struct {const char *name; KT_KEY_FN(*fn);} gl_actions[] = { 1343 {"user-interrupt", gl_user_interrupt}, 1344 {"abort", gl_abort}, 1345 {"suspend", gl_suspend}, 1346 {"stop-output", gl_stop_output}, 1347 {"start-output", gl_start_output}, 1348 {"literal-next", gl_literal_next}, 1349 {"cursor-right", gl_cursor_right}, 1350 {"cursor-left", gl_cursor_left}, 1351 {"insert-mode", gl_insert_mode}, 1352 {"beginning-of-line", gl_beginning_of_line}, 1353 {"end-of-line", gl_end_of_line}, 1354 {"delete-line", gl_delete_line}, 1355 {"kill-line", gl_kill_line}, 1356 {"forward-word", gl_forward_word}, 1357 {"backward-word", gl_backward_word}, 1358 {"forward-delete-char", gl_forward_delete_char}, 1359 {"backward-delete-char", gl_backward_delete_char}, 1360 {"forward-delete-word", gl_forward_delete_word}, 1361 {"backward-delete-word", gl_backward_delete_word}, 1362 {"delete-refind", gl_delete_refind}, 1363 {"delete-invert-refind", gl_delete_invert_refind}, 1364 {"delete-to-column", gl_delete_to_column}, 1365 {"delete-to-parenthesis", gl_delete_to_parenthesis}, 1366 {"forward-delete-find", gl_forward_delete_find}, 1367 {"backward-delete-find", gl_backward_delete_find}, 1368 {"forward-delete-to", gl_forward_delete_to}, 1369 {"backward-delete-to", gl_backward_delete_to}, 1370 {"upcase-word", gl_upcase_word}, 1371 {"downcase-word", gl_downcase_word}, 1372 {"capitalize-word", gl_capitalize_word}, 1373 {"redisplay", gl_redisplay}, 1374 {"clear-screen", gl_clear_screen}, 1375 {"transpose-chars", gl_transpose_chars}, 1376 {"set-mark", gl_set_mark}, 1377 {"exchange-point-and-mark", gl_exchange_point_and_mark}, 1378 {"kill-region", gl_kill_region}, 1379 {"copy-region-as-kill", gl_copy_region_as_kill}, 1380 {"yank", gl_yank}, 1381 {"up-history", gl_up_history}, 1382 {"down-history", gl_down_history}, 1383 {"history-search-backward", gl_history_search_backward}, 1384 {"history-re-search-backward", gl_history_re_search_backward}, 1385 {"history-search-forward", gl_history_search_forward}, 1386 {"history-re-search-forward", gl_history_re_search_forward}, 1387 {"complete-word", gl_complete_word}, 1388 #ifndef HIDE_FILE_SYSTEM 1389 {"expand-filename", gl_expand_filename}, 1390 {"read-from-file", gl_read_from_file}, 1391 {"read-init-files", gl_read_init_files}, 1392 {"list-glob", gl_list_glob}, 1393 #endif 1394 {"del-char-or-list-or-eof", gl_del_char_or_list_or_eof}, 1395 {"beginning-of-history", gl_beginning_of_history}, 1396 {"end-of-history", gl_end_of_history}, 1397 {"digit-argument", gl_digit_argument}, 1398 {"newline", gl_newline}, 1399 {"repeat-history", gl_repeat_history}, 1400 {"vi-insert", gl_vi_insert}, 1401 {"vi-overwrite", gl_vi_overwrite}, 1402 {"vi-insert-at-bol", gl_vi_insert_at_bol}, 1403 {"vi-append-at-eol", gl_vi_append_at_eol}, 1404 {"vi-append", gl_vi_append}, 1405 {"change-case", gl_change_case}, 1406 {"backward-kill-line", gl_backward_kill_line}, 1407 {"goto-column", gl_goto_column}, 1408 {"forward-to-word", gl_forward_to_word}, 1409 {"vi-replace-char", gl_vi_replace_char}, 1410 {"vi-change-rest-of-line", gl_vi_change_rest_of_line}, 1411 {"vi-change-line", gl_vi_change_line}, 1412 {"vi-change-to-bol", gl_vi_change_to_bol}, 1413 {"vi-change-refind", gl_vi_change_refind}, 1414 {"vi-change-invert-refind", gl_vi_change_invert_refind}, 1415 {"vi-change-to-column", gl_vi_change_to_column}, 1416 {"vi-change-to-parenthesis", gl_vi_change_to_parenthesis}, 1417 {"forward-copy-char", gl_forward_copy_char}, 1418 {"backward-copy-char", gl_backward_copy_char}, 1419 {"forward-find-char", gl_forward_find_char}, 1420 {"backward-find-char", gl_backward_find_char}, 1421 {"forward-to-char", gl_forward_to_char}, 1422 {"backward-to-char", gl_backward_to_char}, 1423 {"repeat-find-char", gl_repeat_find_char}, 1424 {"invert-refind-char", gl_invert_refind_char}, 1425 {"append-yank", gl_append_yank}, 1426 {"backward-copy-word", gl_backward_copy_word}, 1427 {"forward-copy-word", gl_forward_copy_word}, 1428 {"copy-to-bol", gl_copy_to_bol}, 1429 {"copy-refind", gl_copy_refind}, 1430 {"copy-invert-refind", gl_copy_invert_refind}, 1431 {"copy-to-column", gl_copy_to_column}, 1432 {"copy-to-parenthesis", gl_copy_to_parenthesis}, 1433 {"copy-rest-of-line", gl_copy_rest_of_line}, 1434 {"copy-line", gl_copy_line}, 1435 {"backward-copy-find", gl_backward_copy_find}, 1436 {"forward-copy-find", gl_forward_copy_find}, 1437 {"backward-copy-to", gl_backward_copy_to}, 1438 {"forward-copy-to", gl_forward_copy_to}, 1439 {"list-or-eof", gl_list_or_eof}, 1440 {"vi-undo", gl_vi_undo}, 1441 {"vi-backward-change-word", gl_vi_backward_change_word}, 1442 {"vi-forward-change-word", gl_vi_forward_change_word}, 1443 {"vi-backward-change-find", gl_vi_backward_change_find}, 1444 {"vi-forward-change-find", gl_vi_forward_change_find}, 1445 {"vi-backward-change-to", gl_vi_backward_change_to}, 1446 {"vi-forward-change-to", gl_vi_forward_change_to}, 1447 {"vi-backward-change-char", gl_vi_backward_change_char}, 1448 {"vi-forward-change-char", gl_vi_forward_change_char}, 1449 {"emacs-mode", gl_emacs_editing_mode}, 1450 {"vi-mode", gl_vi_editing_mode}, 1451 {"ring-bell", gl_ring_bell}, 1452 {"vi-repeat-change", gl_vi_repeat_change}, 1453 {"find-parenthesis", gl_find_parenthesis}, 1454 {"list-history", gl_list_history}, 1455 }; 1456 1457 /* 1458 * Define the default key-bindings in emacs mode. 1459 */ 1460 static const KtKeyBinding gl_emacs_bindings[] = { 1461 {"right", "cursor-right"}, 1462 {"^F", "cursor-right"}, 1463 {"left", "cursor-left"}, 1464 {"^B", "cursor-left"}, 1465 {"M-i", "insert-mode"}, 1466 {"M-I", "insert-mode"}, 1467 {"^A", "beginning-of-line"}, 1468 {"^E", "end-of-line"}, 1469 {"^U", "delete-line"}, 1470 {"^K", "kill-line"}, 1471 {"M-f", "forward-word"}, 1472 {"M-F", "forward-word"}, 1473 {"M-b", "backward-word"}, 1474 {"M-B", "backward-word"}, 1475 {"^D", "del-char-or-list-or-eof"}, 1476 {"^H", "backward-delete-char"}, 1477 {"^?", "backward-delete-char"}, 1478 {"M-d", "forward-delete-word"}, 1479 {"M-D", "forward-delete-word"}, 1480 {"M-^H", "backward-delete-word"}, 1481 {"M-^?", "backward-delete-word"}, 1482 {"M-u", "upcase-word"}, 1483 {"M-U", "upcase-word"}, 1484 {"M-l", "downcase-word"}, 1485 {"M-L", "downcase-word"}, 1486 {"M-c", "capitalize-word"}, 1487 {"M-C", "capitalize-word"}, 1488 {"^R", "redisplay"}, 1489 {"^L", "clear-screen"}, 1490 {"^T", "transpose-chars"}, 1491 {"^@", "set-mark"}, 1492 {"^X^X", "exchange-point-and-mark"}, 1493 {"^W", "kill-region"}, 1494 {"M-w", "copy-region-as-kill"}, 1495 {"M-W", "copy-region-as-kill"}, 1496 {"^Y", "yank"}, 1497 {"^P", "up-history"}, 1498 {"up", "up-history"}, 1499 {"^N", "down-history"}, 1500 {"down", "down-history"}, 1501 {"M-p", "history-search-backward"}, 1502 {"M-P", "history-search-backward"}, 1503 {"M-n", "history-search-forward"}, 1504 {"M-N", "history-search-forward"}, 1505 {"\t", "complete-word"}, 1506 #ifndef HIDE_FILE_SYSTEM 1507 {"^X*", "expand-filename"}, 1508 {"^X^F", "read-from-file"}, 1509 {"^X^R", "read-init-files"}, 1510 {"^Xg", "list-glob"}, 1511 {"^XG", "list-glob"}, 1512 #endif 1513 {"^Xh", "list-history"}, 1514 {"^XH", "list-history"}, 1515 {"M-<", "beginning-of-history"}, 1516 {"M->", "end-of-history"}, 1517 {"M-0", "digit-argument"}, 1518 {"M-1", "digit-argument"}, 1519 {"M-2", "digit-argument"}, 1520 {"M-3", "digit-argument"}, 1521 {"M-4", "digit-argument"}, 1522 {"M-5", "digit-argument"}, 1523 {"M-6", "digit-argument"}, 1524 {"M-7", "digit-argument"}, 1525 {"M-8", "digit-argument"}, 1526 {"M-9", "digit-argument"}, 1527 {"\r", "newline"}, 1528 {"\n", "newline"}, 1529 {"M-o", "repeat-history"}, 1530 {"M-C-v", "vi-mode"}, 1531 }; 1532 1533 /* 1534 * Define the default key-bindings in vi mode. Note that in vi-mode 1535 * meta-key bindings are command-mode bindings. For example M-i first 1536 * switches to command mode if not already in that mode, then moves 1537 * the cursor one position right, as in vi. 1538 */ 1539 static const KtKeyBinding gl_vi_bindings[] = { 1540 {"^D", "list-or-eof"}, 1541 #ifndef HIDE_FILE_SYSTEM 1542 {"^G", "list-glob"}, 1543 #endif 1544 {"^H", "backward-delete-char"}, 1545 {"\t", "complete-word"}, 1546 {"\r", "newline"}, 1547 {"\n", "newline"}, 1548 {"^L", "clear-screen"}, 1549 {"^N", "down-history"}, 1550 {"^P", "up-history"}, 1551 {"^R", "redisplay"}, 1552 {"^U", "backward-kill-line"}, 1553 {"^W", "backward-delete-word"}, 1554 #ifndef HIDE_FILE_SYSTEM 1555 {"^X^F", "read-from-file"}, 1556 {"^X^R", "read-init-files"}, 1557 {"^X*", "expand-filename"}, 1558 #endif 1559 {"^?", "backward-delete-char"}, 1560 {"M- ", "cursor-right"}, 1561 {"M-$", "end-of-line"}, 1562 #ifndef HIDE_FILE_SYSTEM 1563 {"M-*", "expand-filename"}, 1564 #endif 1565 {"M-+", "down-history"}, 1566 {"M--", "up-history"}, 1567 {"M-<", "beginning-of-history"}, 1568 {"M->", "end-of-history"}, 1569 {"M-^", "beginning-of-line"}, 1570 {"M-;", "repeat-find-char"}, 1571 {"M-,", "invert-refind-char"}, 1572 {"M-|", "goto-column"}, 1573 {"M-~", "change-case"}, 1574 {"M-.", "vi-repeat-change"}, 1575 {"M-%", "find-parenthesis"}, 1576 {"M-0", "digit-argument"}, 1577 {"M-1", "digit-argument"}, 1578 {"M-2", "digit-argument"}, 1579 {"M-3", "digit-argument"}, 1580 {"M-4", "digit-argument"}, 1581 {"M-5", "digit-argument"}, 1582 {"M-6", "digit-argument"}, 1583 {"M-7", "digit-argument"}, 1584 {"M-8", "digit-argument"}, 1585 {"M-9", "digit-argument"}, 1586 {"M-a", "vi-append"}, 1587 {"M-A", "vi-append-at-eol"}, 1588 {"M-b", "backward-word"}, 1589 {"M-B", "backward-word"}, 1590 {"M-C", "vi-change-rest-of-line"}, 1591 {"M-cb", "vi-backward-change-word"}, 1592 {"M-cB", "vi-backward-change-word"}, 1593 {"M-cc", "vi-change-line"}, 1594 {"M-ce", "vi-forward-change-word"}, 1595 {"M-cE", "vi-forward-change-word"}, 1596 {"M-cw", "vi-forward-change-word"}, 1597 {"M-cW", "vi-forward-change-word"}, 1598 {"M-cF", "vi-backward-change-find"}, 1599 {"M-cf", "vi-forward-change-find"}, 1600 {"M-cT", "vi-backward-change-to"}, 1601 {"M-ct", "vi-forward-change-to"}, 1602 {"M-c;", "vi-change-refind"}, 1603 {"M-c,", "vi-change-invert-refind"}, 1604 {"M-ch", "vi-backward-change-char"}, 1605 {"M-c^H", "vi-backward-change-char"}, 1606 {"M-c^?", "vi-backward-change-char"}, 1607 {"M-cl", "vi-forward-change-char"}, 1608 {"M-c ", "vi-forward-change-char"}, 1609 {"M-c^", "vi-change-to-bol"}, 1610 {"M-c0", "vi-change-to-bol"}, 1611 {"M-c$", "vi-change-rest-of-line"}, 1612 {"M-c|", "vi-change-to-column"}, 1613 {"M-c%", "vi-change-to-parenthesis"}, 1614 {"M-dh", "backward-delete-char"}, 1615 {"M-d^H", "backward-delete-char"}, 1616 {"M-d^?", "backward-delete-char"}, 1617 {"M-dl", "forward-delete-char"}, 1618 {"M-d ", "forward-delete-char"}, 1619 {"M-dd", "delete-line"}, 1620 {"M-db", "backward-delete-word"}, 1621 {"M-dB", "backward-delete-word"}, 1622 {"M-de", "forward-delete-word"}, 1623 {"M-dE", "forward-delete-word"}, 1624 {"M-dw", "forward-delete-word"}, 1625 {"M-dW", "forward-delete-word"}, 1626 {"M-dF", "backward-delete-find"}, 1627 {"M-df", "forward-delete-find"}, 1628 {"M-dT", "backward-delete-to"}, 1629 {"M-dt", "forward-delete-to"}, 1630 {"M-d;", "delete-refind"}, 1631 {"M-d,", "delete-invert-refind"}, 1632 {"M-d^", "backward-kill-line"}, 1633 {"M-d0", "backward-kill-line"}, 1634 {"M-d$", "kill-line"}, 1635 {"M-D", "kill-line"}, 1636 {"M-d|", "delete-to-column"}, 1637 {"M-d%", "delete-to-parenthesis"}, 1638 {"M-e", "forward-word"}, 1639 {"M-E", "forward-word"}, 1640 {"M-f", "forward-find-char"}, 1641 {"M-F", "backward-find-char"}, 1642 {"M--", "up-history"}, 1643 {"M-h", "cursor-left"}, 1644 {"M-H", "beginning-of-history"}, 1645 {"M-i", "vi-insert"}, 1646 {"M-I", "vi-insert-at-bol"}, 1647 {"M-j", "down-history"}, 1648 {"M-J", "history-search-forward"}, 1649 {"M-k", "up-history"}, 1650 {"M-K", "history-search-backward"}, 1651 {"M-l", "cursor-right"}, 1652 {"M-L", "end-of-history"}, 1653 {"M-n", "history-re-search-forward"}, 1654 {"M-N", "history-re-search-backward"}, 1655 {"M-p", "append-yank"}, 1656 {"M-P", "yank"}, 1657 {"M-r", "vi-replace-char"}, 1658 {"M-R", "vi-overwrite"}, 1659 {"M-s", "vi-forward-change-char"}, 1660 {"M-S", "vi-change-line"}, 1661 {"M-t", "forward-to-char"}, 1662 {"M-T", "backward-to-char"}, 1663 {"M-u", "vi-undo"}, 1664 {"M-w", "forward-to-word"}, 1665 {"M-W", "forward-to-word"}, 1666 {"M-x", "forward-delete-char"}, 1667 {"M-X", "backward-delete-char"}, 1668 {"M-yh", "backward-copy-char"}, 1669 {"M-y^H", "backward-copy-char"}, 1670 {"M-y^?", "backward-copy-char"}, 1671 {"M-yl", "forward-copy-char"}, 1672 {"M-y ", "forward-copy-char"}, 1673 {"M-ye", "forward-copy-word"}, 1674 {"M-yE", "forward-copy-word"}, 1675 {"M-yw", "forward-copy-word"}, 1676 {"M-yW", "forward-copy-word"}, 1677 {"M-yb", "backward-copy-word"}, 1678 {"M-yB", "backward-copy-word"}, 1679 {"M-yf", "forward-copy-find"}, 1680 {"M-yF", "backward-copy-find"}, 1681 {"M-yt", "forward-copy-to"}, 1682 {"M-yT", "backward-copy-to"}, 1683 {"M-y;", "copy-refind"}, 1684 {"M-y,", "copy-invert-refind"}, 1685 {"M-y^", "copy-to-bol"}, 1686 {"M-y0", "copy-to-bol"}, 1687 {"M-y$", "copy-rest-of-line"}, 1688 {"M-yy", "copy-line"}, 1689 {"M-Y", "copy-line"}, 1690 {"M-y|", "copy-to-column"}, 1691 {"M-y%", "copy-to-parenthesis"}, 1692 {"M-^E", "emacs-mode"}, 1693 {"M-^H", "cursor-left"}, 1694 {"M-^?", "cursor-left"}, 1695 {"M-^L", "clear-screen"}, 1696 {"M-^N", "down-history"}, 1697 {"M-^P", "up-history"}, 1698 {"M-^R", "redisplay"}, 1699 {"M-^D", "list-or-eof"}, 1700 {"M-\r", "newline"}, 1701 {"M-\t", "complete-word"}, 1702 {"M-\n", "newline"}, 1703 #ifndef HIDE_FILE_SYSTEM 1704 {"M-^X^R", "read-init-files"}, 1705 #endif 1706 {"M-^Xh", "list-history"}, 1707 {"M-^XH", "list-history"}, 1708 {"down", "down-history"}, 1709 {"up", "up-history"}, 1710 {"left", "cursor-left"}, 1711 {"right", "cursor-right"}, 1712 }; 1713 1714 /*....................................................................... 1715 * Create a new GetLine object. 1716 * 1717 * Input: 1718 * linelen size_t The maximum line length to allow for. 1719 * histlen size_t The number of bytes to allocate for recording 1720 * a circular buffer of history lines. 1721 * Output: 1722 * return GetLine * The new object, or NULL on error. 1723 */ 1724 GetLine *new_GetLine(size_t linelen, size_t histlen) 1725 { 1726 GetLine *gl; /* The object to be returned */ 1727 int i; 1728 /* 1729 * Check the arguments. 1730 */ 1731 if(linelen < 10) { 1732 errno = ENOMEM; 1733 return NULL; 1734 }; 1735 /* 1736 * Allocate the container. 1737 */ 1738 gl = (GetLine *) malloc(sizeof(GetLine)); 1739 if(!gl) { 1740 errno = ENOMEM; 1741 return NULL; 1742 }; 1743 /* 1744 * Before attempting any operation that might fail, initialize the 1745 * container at least up to the point at which it can safely be passed 1746 * to del_GetLine(). 1747 */ 1748 gl->err = NULL; 1749 gl->glh = NULL; 1750 gl->cpl = NULL; 1751 #ifndef HIDE_FILE_SYSTEM 1752 gl->cplfn.fn = cpl_file_completions; 1753 #else 1754 gl->cplfn.fn = gl_no_completions; 1755 #endif 1756 gl->cplfn.data = NULL; 1757 #ifndef WITHOUT_FILE_SYSTEM 1758 gl->ef = NULL; 1759 #endif 1760 gl->capmem = NULL; 1761 gl->cq = NULL; 1762 gl->input_fd = -1; 1763 gl->output_fd = -1; 1764 gl->input_fp = NULL; 1765 gl->output_fp = NULL; 1766 gl->file_fp = NULL; 1767 gl->term = NULL; 1768 gl->is_term = 0; 1769 gl->flush_fn = gl_flush_terminal; 1770 gl->io_mode = GL_NORMAL_MODE; 1771 gl->raw_mode = 0; 1772 gl->pending_io = GLP_WRITE; /* We will start by writing the prompt */ 1773 gl_clear_status(gl); 1774 gl->linelen = linelen; 1775 gl->line = NULL; 1776 gl->cutbuf = NULL; 1777 gl->prompt = NULL; 1778 gl->prompt_len = 0; 1779 gl->prompt_changed = 0; 1780 gl->prompt_style = GL_LITERAL_PROMPT; 1781 gl->cpl_mem = NULL; 1782 gl->ext_act_mem = NULL; 1783 gl->sig_mem = NULL; 1784 gl->sigs = NULL; 1785 gl->signals_masked = 0; 1786 gl->signals_overriden = 0; 1787 sigemptyset(&gl->all_signal_set); 1788 sigemptyset(&gl->old_signal_set); 1789 sigemptyset(&gl->use_signal_set); 1790 gl->bindings = NULL; 1791 gl->ntotal = 0; 1792 gl->buff_curpos = 0; 1793 gl->term_curpos = 0; 1794 gl->term_len = 0; 1795 gl->buff_mark = 0; 1796 gl->insert_curpos = 0; 1797 gl->insert = 1; 1798 gl->number = -1; 1799 gl->endline = 1; 1800 gl->displayed = 0; 1801 gl->redisplay = 0; 1802 gl->postpone = 0; 1803 gl->keybuf[0]='\0'; 1804 gl->nbuf = 0; 1805 gl->nread = 0; 1806 gl->current_action.fn = 0; 1807 gl->current_action.data = NULL; 1808 gl->current_count = 0; 1809 gl->preload_id = 0; 1810 gl->preload_history = 0; 1811 gl->keyseq_count = 0; 1812 gl->last_search = -1; 1813 gl->editor = GL_EMACS_MODE; 1814 gl->silence_bell = 0; 1815 gl->automatic_history = 1; 1816 gl->vi.undo.line = NULL; 1817 gl->vi.undo.buff_curpos = 0; 1818 gl->vi.undo.ntotal = 0; 1819 gl->vi.undo.saved = 0; 1820 gl->vi.repeat.action.fn = 0; 1821 gl->vi.repeat.action.data = 0; 1822 gl->vi.repeat.count = 0; 1823 gl->vi.repeat.input_curpos = 0; 1824 gl->vi.repeat.command_curpos = 0; 1825 gl->vi.repeat.input_char = '\0'; 1826 gl->vi.repeat.saved = 0; 1827 gl->vi.repeat.active = 0; 1828 gl->vi.command = 0; 1829 gl->vi.find_forward = 0; 1830 gl->vi.find_onto = 0; 1831 gl->vi.find_char = '\0'; 1832 gl->left = NULL; 1833 gl->right = NULL; 1834 gl->up = NULL; 1835 gl->down = NULL; 1836 gl->home = NULL; 1837 gl->bol = 0; 1838 gl->clear_eol = NULL; 1839 gl->clear_eod = NULL; 1840 gl->u_arrow = NULL; 1841 gl->d_arrow = NULL; 1842 gl->l_arrow = NULL; 1843 gl->r_arrow = NULL; 1844 gl->sound_bell = NULL; 1845 gl->bold = NULL; 1846 gl->underline = NULL; 1847 gl->standout = NULL; 1848 gl->dim = NULL; 1849 gl->reverse = NULL; 1850 gl->blink = NULL; 1851 gl->text_attr_off = NULL; 1852 gl->nline = 0; 1853 gl->ncolumn = 0; 1854 #ifdef USE_TERMINFO 1855 gl->left_n = NULL; 1856 gl->right_n = NULL; 1857 #elif defined(USE_TERMCAP) 1858 gl->tgetent_buf = NULL; 1859 gl->tgetstr_buf = NULL; 1860 #endif 1861 gl->app_file = NULL; 1862 gl->user_file = NULL; 1863 gl->configured = 0; 1864 gl->echo = 1; 1865 gl->last_signal = -1; 1866 #ifdef HAVE_SELECT 1867 gl->fd_node_mem = NULL; 1868 gl->fd_nodes = NULL; 1869 FD_ZERO(&gl->rfds); 1870 FD_ZERO(&gl->wfds); 1871 FD_ZERO(&gl->ufds); 1872 gl->max_fd = 0; 1873 gl->timer.dt.tv_sec = 0; 1874 gl->timer.dt.tv_usec = 0; 1875 gl->timer.fn = 0; 1876 gl->timer.data = NULL; 1877 #endif 1878 /* 1879 * Allocate an error reporting buffer. 1880 */ 1881 gl->err = _new_ErrMsg(); 1882 if(!gl->err) 1883 return del_GetLine(gl); 1884 /* 1885 * Allocate the history buffer. 1886 */ 1887 gl->glh = _new_GlHistory(histlen); 1888 if(!gl->glh) 1889 return del_GetLine(gl); 1890 /* 1891 * Allocate the resource object for file-completion. 1892 */ 1893 gl->cpl = new_WordCompletion(); 1894 if(!gl->cpl) 1895 return del_GetLine(gl); 1896 /* 1897 * Allocate the resource object for file-completion. 1898 */ 1899 #ifndef WITHOUT_FILE_SYSTEM 1900 gl->ef = new_ExpandFile(); 1901 if(!gl->ef) 1902 return del_GetLine(gl); 1903 #endif 1904 /* 1905 * Allocate a string-segment memory allocator for use in storing terminal 1906 * capablity strings. 1907 */ 1908 gl->capmem = _new_StringGroup(CAPMEM_SEGMENT_SIZE); 1909 if(!gl->capmem) 1910 return del_GetLine(gl); 1911 /* 1912 * Allocate the character queue that is used to buffer terminal output. 1913 */ 1914 gl->cq = _new_GlCharQueue(); 1915 if(!gl->cq) 1916 return del_GetLine(gl); 1917 /* 1918 * Allocate a line buffer, leaving 2 extra characters for the terminating 1919 * '\n' and '\0' characters 1920 */ 1921 gl->line = (char *) malloc(linelen + 2); 1922 if(!gl->line) { 1923 errno = ENOMEM; 1924 return del_GetLine(gl); 1925 }; 1926 /* 1927 * Start with an empty input line. 1928 */ 1929 gl_truncate_buffer(gl, 0); 1930 /* 1931 * Allocate a cut buffer. 1932 */ 1933 gl->cutbuf = (char *) malloc(linelen + 2); 1934 if(!gl->cutbuf) { 1935 errno = ENOMEM; 1936 return del_GetLine(gl); 1937 }; 1938 gl->cutbuf[0] = '\0'; 1939 /* 1940 * Allocate an initial empty prompt. 1941 */ 1942 _gl_replace_prompt(gl, NULL); 1943 if(!gl->prompt) { 1944 errno = ENOMEM; 1945 return del_GetLine(gl); 1946 }; 1947 /* 1948 * Allocate a vi undo buffer. 1949 */ 1950 gl->vi.undo.line = (char *) malloc(linelen + 2); 1951 if(!gl->vi.undo.line) { 1952 errno = ENOMEM; 1953 return del_GetLine(gl); 1954 }; 1955 gl->vi.undo.line[0] = '\0'; 1956 /* 1957 * Allocate a freelist from which to allocate nodes for the list 1958 * of completion functions. 1959 */ 1960 gl->cpl_mem = _new_FreeList(sizeof(GlCplCallback), GL_CPL_FREELIST_BLOCKING); 1961 if(!gl->cpl_mem) 1962 return del_GetLine(gl); 1963 /* 1964 * Allocate a freelist from which to allocate nodes for the list 1965 * of external action functions. 1966 */ 1967 gl->ext_act_mem = _new_FreeList(sizeof(GlExternalAction), 1968 GL_EXT_ACT_FREELIST_BLOCKING); 1969 if(!gl->ext_act_mem) 1970 return del_GetLine(gl); 1971 /* 1972 * Allocate a freelist from which to allocate nodes for the list 1973 * of signals. 1974 */ 1975 gl->sig_mem = _new_FreeList(sizeof(GlSignalNode), GLS_FREELIST_BLOCKING); 1976 if(!gl->sig_mem) 1977 return del_GetLine(gl); 1978 /* 1979 * Install initial dispositions for the default list of signals that 1980 * gl_get_line() traps. 1981 */ 1982 for(i=0; i<sizeof(gl_signal_list)/sizeof(gl_signal_list[0]); i++) { 1983 const struct GlDefSignal *sig = gl_signal_list + i; 1984 if(_gl_trap_signal(gl, sig->signo, sig->flags, sig->after, 1985 sig->errno_value)) 1986 return del_GetLine(gl); 1987 }; 1988 /* 1989 * Allocate an empty table of key bindings. 1990 */ 1991 gl->bindings = _new_KeyTab(); 1992 if(!gl->bindings) 1993 return del_GetLine(gl); 1994 /* 1995 * Define the available actions that can be bound to key sequences. 1996 */ 1997 for(i=0; i<sizeof(gl_actions)/sizeof(gl_actions[0]); i++) { 1998 if(_kt_set_action(gl->bindings, gl_actions[i].name, gl_actions[i].fn, NULL)) 1999 return del_GetLine(gl); 2000 }; 2001 /* 2002 * Set up the default bindings. 2003 */ 2004 if(gl_change_editor(gl, gl->editor)) 2005 return del_GetLine(gl); 2006 /* 2007 * Allocate termcap buffers. 2008 */ 2009 #ifdef USE_TERMCAP 2010 gl->tgetent_buf = (char *) malloc(TERMCAP_BUF_SIZE); 2011 gl->tgetstr_buf = (char *) malloc(TERMCAP_BUF_SIZE); 2012 if(!gl->tgetent_buf || !gl->tgetstr_buf) { 2013 errno = ENOMEM; 2014 return del_GetLine(gl); 2015 }; 2016 #endif 2017 /* 2018 * Set up for I/O assuming stdin and stdout. 2019 */ 2020 if(_gl_change_terminal(gl, stdin, stdout, getenv("TERM"))) 2021 return del_GetLine(gl); 2022 /* 2023 * Create a freelist for use in allocating GlFdNode list nodes. 2024 */ 2025 #ifdef HAVE_SELECT 2026 gl->fd_node_mem = _new_FreeList(sizeof(GlFdNode), GLFD_FREELIST_BLOCKING); 2027 if(!gl->fd_node_mem) 2028 return del_GetLine(gl); 2029 #endif 2030 /* 2031 * We are done for now. 2032 */ 2033 return gl; 2034 } 2035 2036 /*....................................................................... 2037 * Delete a GetLine object. 2038 * 2039 * Input: 2040 * gl GetLine * The object to be deleted. 2041 * Output: 2042 * return GetLine * The deleted object (always NULL). 2043 */ 2044 GetLine *del_GetLine(GetLine *gl) 2045 { 2046 if(gl) { 2047 /* 2048 * If the terminal is in raw server mode, reset it. 2049 */ 2050 _gl_normal_io(gl); 2051 /* 2052 * Deallocate all objects contained by gl. 2053 */ 2054 gl->err = _del_ErrMsg(gl->err); 2055 gl->glh = _del_GlHistory(gl->glh); 2056 gl->cpl = del_WordCompletion(gl->cpl); 2057 #ifndef WITHOUT_FILE_SYSTEM 2058 gl->ef = del_ExpandFile(gl->ef); 2059 #endif 2060 gl->capmem = _del_StringGroup(gl->capmem); 2061 gl->cq = _del_GlCharQueue(gl->cq); 2062 if(gl->file_fp) 2063 fclose(gl->file_fp); 2064 if(gl->term) 2065 free(gl->term); 2066 if(gl->line) 2067 free(gl->line); 2068 if(gl->cutbuf) 2069 free(gl->cutbuf); 2070 if(gl->prompt) 2071 free(gl->prompt); 2072 gl->cpl_mem = _del_FreeList(gl->cpl_mem, 1); 2073 gl->ext_act_mem = _del_FreeList(gl->ext_act_mem, 1); 2074 gl->sig_mem = _del_FreeList(gl->sig_mem, 1); 2075 gl->sigs = NULL; /* Already freed by freeing sig_mem */ 2076 gl->bindings = _del_KeyTab(gl->bindings); 2077 if(gl->vi.undo.line) 2078 free(gl->vi.undo.line); 2079 #ifdef USE_TERMCAP 2080 if(gl->tgetent_buf) 2081 free(gl->tgetent_buf); 2082 if(gl->tgetstr_buf) 2083 free(gl->tgetstr_buf); 2084 #endif 2085 if(gl->app_file) 2086 free(gl->app_file); 2087 if(gl->user_file) 2088 free(gl->user_file); 2089 #ifdef HAVE_SELECT 2090 gl->fd_node_mem = _del_FreeList(gl->fd_node_mem, 1); 2091 gl->fd_nodes = NULL; /* Already freed by freeing gl->fd_node_mem */ 2092 #endif 2093 /* 2094 * Delete the now empty container. 2095 */ 2096 free(gl); 2097 }; 2098 return NULL; 2099 } 2100 2101 /*....................................................................... 2102 * Bind a control or meta character to an action. 2103 * 2104 * Input: 2105 * gl GetLine * The resource object of this program. 2106 * binder KtBinder The source of the binding. 2107 * c char The control or meta character. 2108 * If this is '\0', the call is ignored. 2109 * action const char * The action name to bind the key to. 2110 * Output: 2111 * return int 0 - OK. 2112 * 1 - Error. 2113 */ 2114 static int gl_bind_control_char(GetLine *gl, KtBinder binder, char c, 2115 const char *action) 2116 { 2117 char keyseq[2]; 2118 /* 2119 * Quietly reject binding to the NUL control character, since this 2120 * is an ambiguous prefix of all bindings. 2121 */ 2122 if(c == '\0') 2123 return 0; 2124 /* 2125 * Making sure not to bind characters which aren't either control or 2126 * meta characters. 2127 */ 2128 if(IS_CTRL_CHAR(c) || IS_META_CHAR(c)) { 2129 keyseq[0] = c; 2130 keyseq[1] = '\0'; 2131 } else { 2132 return 0; 2133 }; 2134 /* 2135 * Install the binding. 2136 */ 2137 if(_kt_set_keybinding(gl->bindings, binder, keyseq, action)) { 2138 _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG); 2139 return 1; 2140 }; 2141 return 0; 2142 } 2143 2144 /*....................................................................... 2145 * Read a line from the user. 2146 * 2147 * Input: 2148 * gl GetLine * A resource object returned by new_GetLine(). 2149 * prompt char * The prompt to prefix the line with. 2150 * start_line char * The initial contents of the input line, or NULL 2151 * if it should start out empty. 2152 * start_pos int If start_line isn't NULL, this specifies the 2153 * index of the character over which the cursor 2154 * should initially be positioned within the line. 2155 * If you just want it to follow the last character 2156 * of the line, send -1. 2157 * Output: 2158 * return char * An internal buffer containing the input line, or 2159 * NULL at the end of input. If the line fitted in 2160 * the buffer there will be a '\n' newline character 2161 * before the terminating '\0'. If it was truncated 2162 * there will be no newline character, and the remains 2163 * of the line should be retrieved via further calls 2164 * to this function. 2165 */ 2166 char *gl_get_line(GetLine *gl, const char *prompt, 2167 const char *start_line, int start_pos) 2168 { 2169 char *retval; /* The return value of _gl_get_line() */ 2170 /* 2171 * Check the arguments. 2172 */ 2173 if(!gl) { 2174 errno = EINVAL; 2175 return NULL; 2176 }; 2177 /* 2178 * Temporarily block all of the signals that we have been asked to trap. 2179 */ 2180 if(gl_mask_signals(gl, &gl->old_signal_set)) 2181 return NULL; 2182 /* 2183 * Perform the command-line editing task. 2184 */ 2185 retval = _gl_get_line(gl, prompt, start_line, start_pos); 2186 /* 2187 * Restore the process signal mask to how it was when this function was 2188 * first called. 2189 */ 2190 gl_unmask_signals(gl, &gl->old_signal_set); 2191 return retval; 2192 } 2193 2194 2195 /*....................................................................... 2196 * This is the main body of the public function gl_get_line(). 2197 */ 2198 static char *_gl_get_line(GetLine *gl, const char *prompt, 2199 const char *start_line, int start_pos) 2200 { 2201 int waserr = 0; /* True if an error occurs */ 2202 /* 2203 * Assume that this call will successfully complete the input 2204 * line until proven otherwise. 2205 */ 2206 gl_clear_status(gl); 2207 /* 2208 * If this is the first call to this function since new_GetLine(), 2209 * complete any postponed configuration. 2210 */ 2211 if(!gl->configured) { 2212 (void) _gl_configure_getline(gl, NULL, NULL, TECLA_CONFIG_FILE); 2213 gl->configured = 1; 2214 }; 2215 /* 2216 * Before installing our signal handler functions, record the fact 2217 * that there are no pending signals. 2218 */ 2219 gl_pending_signal = -1; 2220 /* 2221 * Temporarily override the signal handlers of the calling program, 2222 * so that we can intercept signals that would leave the terminal 2223 * in a bad state. 2224 */ 2225 waserr = gl_override_signal_handlers(gl); 2226 /* 2227 * After recording the current terminal settings, switch the terminal 2228 * into raw input mode. 2229 */ 2230 waserr = waserr || _gl_raw_io(gl, 1); 2231 /* 2232 * Attempt to read the line. This will require more than one attempt if 2233 * either a current temporary input file is opened by gl_get_input_line() 2234 * or the end of a temporary input file is reached by gl_read_stream_line(). 2235 */ 2236 while(!waserr) { 2237 /* 2238 * Read a line from a non-interactive stream? 2239 */ 2240 if(gl->file_fp || !gl->is_term) { 2241 if(gl_read_stream_line(gl)==0) { 2242 break; 2243 } else if(gl->file_fp) { 2244 gl_revert_input(gl); 2245 gl_record_status(gl, GLR_NEWLINE, 0); 2246 } else { 2247 waserr = 1; 2248 break; 2249 }; 2250 }; 2251 /* 2252 * Read from the terminal? Note that the above if() block may have 2253 * changed gl->file_fp, so it is necessary to retest it here, rather 2254 * than using an else statement. 2255 */ 2256 if(!gl->file_fp && gl->is_term) { 2257 if(gl_get_input_line(gl, prompt, start_line, start_pos)) 2258 waserr = 1; 2259 else 2260 break; 2261 }; 2262 }; 2263 /* 2264 * If an error occurred, but gl->rtn_status is still set to 2265 * GLR_NEWLINE, change the status to GLR_ERROR. Otherwise 2266 * leave it at whatever specific value was assigned by the function 2267 * that aborted input. This means that only functions that trap 2268 * non-generic errors have to remember to update gl->rtn_status 2269 * themselves. 2270 */ 2271 if(waserr && gl->rtn_status == GLR_NEWLINE) 2272 gl_record_status(gl, GLR_ERROR, errno); 2273 /* 2274 * Restore terminal settings. 2275 */ 2276 if(gl->io_mode != GL_SERVER_MODE) 2277 _gl_normal_io(gl); 2278 /* 2279 * Restore the signal handlers. 2280 */ 2281 gl_restore_signal_handlers(gl); 2282 /* 2283 * If gl_get_line() gets aborted early, the errno value associated 2284 * with the event that caused this to happen is recorded in 2285 * gl->rtn_errno. Since errno may have been overwritten by cleanup 2286 * functions after this, restore its value to the value that it had 2287 * when the error condition occured, so that the caller can examine it 2288 * to find out what happened. 2289 */ 2290 errno = gl->rtn_errno; 2291 /* 2292 * Check the completion status to see how to return. 2293 */ 2294 switch(gl->rtn_status) { 2295 case GLR_NEWLINE: /* Success */ 2296 return gl->line; 2297 case GLR_BLOCKED: /* These events abort the current input line, */ 2298 case GLR_SIGNAL: /* when in normal blocking I/O mode, but only */ 2299 case GLR_TIMEOUT: /* temporarily pause line editing when in */ 2300 case GLR_FDABORT: /* non-blocking server I/O mode. */ 2301 if(gl->io_mode != GL_SERVER_MODE) 2302 _gl_abandon_line(gl); 2303 return NULL; 2304 case GLR_ERROR: /* Unrecoverable errors abort the input line, */ 2305 case GLR_EOF: /* regardless of the I/O mode. */ 2306 default: 2307 _gl_abandon_line(gl); 2308 return NULL; 2309 }; 2310 } 2311 2312 /*....................................................................... 2313 * Read a single character from the user. 2314 * 2315 * Input: 2316 * gl GetLine * A resource object returned by new_GetLine(). 2317 * prompt char * The prompt to prefix the line with, or NULL if 2318 * no prompt is required. 2319 * defchar char The character to substitute if the 2320 * user simply hits return, or '\n' if you don't 2321 * need to substitute anything. 2322 * Output: 2323 * return int The character that was read, or EOF if the read 2324 * had to be aborted (in which case you can call 2325 * gl_return_status() to find out why). 2326 */ 2327 int gl_query_char(GetLine *gl, const char *prompt, char defchar) 2328 { 2329 int retval; /* The return value of _gl_query_char() */ 2330 /* 2331 * Check the arguments. 2332 */ 2333 if(!gl) { 2334 errno = EINVAL; 2335 return EOF; 2336 }; 2337 /* 2338 * Temporarily block all of the signals that we have been asked to trap. 2339 */ 2340 if(gl_mask_signals(gl, &gl->old_signal_set)) 2341 return EOF; 2342 /* 2343 * Perform the character reading task. 2344 */ 2345 retval = _gl_query_char(gl, prompt, defchar); 2346 /* 2347 * Restore the process signal mask to how it was when this function was 2348 * first called. 2349 */ 2350 gl_unmask_signals(gl, &gl->old_signal_set); 2351 return retval; 2352 } 2353 2354 /*....................................................................... 2355 * This is the main body of the public function gl_query_char(). 2356 */ 2357 static int _gl_query_char(GetLine *gl, const char *prompt, char defchar) 2358 { 2359 int c = EOF; /* The character to be returned */ 2360 int waserr = 0; /* True if an error occurs */ 2361 /* 2362 * Assume that this call will successfully complete the input operation 2363 * until proven otherwise. 2364 */ 2365 gl_clear_status(gl); 2366 /* 2367 * If this is the first call to this function or gl_get_line(), 2368 * since new_GetLine(), complete any postponed configuration. 2369 */ 2370 if(!gl->configured) { 2371 (void) _gl_configure_getline(gl, NULL, NULL, TECLA_CONFIG_FILE); 2372 gl->configured = 1; 2373 }; 2374 /* 2375 * Before installing our signal handler functions, record the fact 2376 * that there are no pending signals. 2377 */ 2378 gl_pending_signal = -1; 2379 /* 2380 * Temporarily override the signal handlers of the calling program, 2381 * so that we can intercept signals that would leave the terminal 2382 * in a bad state. 2383 */ 2384 waserr = gl_override_signal_handlers(gl); 2385 /* 2386 * After recording the current terminal settings, switch the terminal 2387 * into raw input mode without redisplaying any partially entered 2388 * input line. 2389 */ 2390 waserr = waserr || _gl_raw_io(gl, 0); 2391 /* 2392 * Attempt to read the line. This will require more than one attempt if 2393 * either a current temporary input file is opened by gl_get_input_line() 2394 * or the end of a temporary input file is reached by gl_read_stream_line(). 2395 */ 2396 while(!waserr) { 2397 /* 2398 * Read a line from a non-interactive stream? 2399 */ 2400 if(gl->file_fp || !gl->is_term) { 2401 c = gl_read_stream_char(gl); 2402 if(c != EOF) { /* Success? */ 2403 if(c=='\n') c = defchar; 2404 break; 2405 } else if(gl->file_fp) { /* End of temporary input file? */ 2406 gl_revert_input(gl); 2407 gl_record_status(gl, GLR_NEWLINE, 0); 2408 } else { /* An error? */ 2409 waserr = 1; 2410 break; 2411 }; 2412 }; 2413 /* 2414 * Read from the terminal? Note that the above if() block may have 2415 * changed gl->file_fp, so it is necessary to retest it here, rather 2416 * than using an else statement. 2417 */ 2418 if(!gl->file_fp && gl->is_term) { 2419 c = gl_get_query_char(gl, prompt, defchar); 2420 if(c==EOF) 2421 waserr = 1; 2422 else 2423 break; 2424 }; 2425 }; 2426 /* 2427 * If an error occurred, but gl->rtn_status is still set to 2428 * GLR_NEWLINE, change the status to GLR_ERROR. Otherwise 2429 * leave it at whatever specific value was assigned by the function 2430 * that aborted input. This means that only functions that trap 2431 * non-generic errors have to remember to update gl->rtn_status 2432 * themselves. 2433 */ 2434 if(waserr && gl->rtn_status == GLR_NEWLINE) 2435 gl_record_status(gl, GLR_ERROR, errno); 2436 /* 2437 * Restore terminal settings. 2438 */ 2439 if(gl->io_mode != GL_SERVER_MODE) 2440 _gl_normal_io(gl); 2441 /* 2442 * Restore the signal handlers. 2443 */ 2444 gl_restore_signal_handlers(gl); 2445 /* 2446 * If this function gets aborted early, the errno value associated 2447 * with the event that caused this to happen is recorded in 2448 * gl->rtn_errno. Since errno may have been overwritten by cleanup 2449 * functions after this, restore its value to the value that it had 2450 * when the error condition occured, so that the caller can examine it 2451 * to find out what happened. 2452 */ 2453 errno = gl->rtn_errno; 2454 /* 2455 * Error conditions are signalled to the caller, by setting the returned 2456 * character to EOF. 2457 */ 2458 if(gl->rtn_status != GLR_NEWLINE) 2459 c = EOF; 2460 /* 2461 * In this mode, every character that is read is a completed 2462 * transaction, just like reading a completed input line, so prepare 2463 * for the next input line or character. 2464 */ 2465 _gl_abandon_line(gl); 2466 /* 2467 * Return the acquired character. 2468 */ 2469 return c; 2470 } 2471 2472 /*....................................................................... 2473 * Record of the signal handlers of the calling program, so that they 2474 * can be restored later. 2475 * 2476 * Input: 2477 * gl GetLine * The resource object of this library. 2478 * Output: 2479 * return int 0 - OK. 2480 * 1 - Error. 2481 */ 2482 static int gl_override_signal_handlers(GetLine *gl) 2483 { 2484 GlSignalNode *sig; /* A node in the list of signals to be caught */ 2485 /* 2486 * Set up our signal handler. 2487 */ 2488 SigAction act; 2489 act.sa_handler = gl_signal_handler; 2490 memcpy(&act.sa_mask, &gl->all_signal_set, sizeof(sigset_t)); 2491 act.sa_flags = 0; 2492 /* 2493 * Get the subset of the signals that we are supposed to trap that 2494 * should actually be trapped. 2495 */ 2496 sigemptyset(&gl->use_signal_set); 2497 for(sig=gl->sigs; sig; sig=sig->next) { 2498 /* 2499 * Trap this signal? If it is blocked by the calling program and we 2500 * haven't been told to unblock it, don't arrange to trap this signal. 2501 */ 2502 if(sig->flags & GLS_UNBLOCK_SIG || 2503 !sigismember(&gl->old_signal_set, sig->signo)) { 2504 if(sigaddset(&gl->use_signal_set, sig->signo) == -1) { 2505 _err_record_msg(gl->err, "sigaddset error", END_ERR_MSG); 2506 return 1; 2507 }; 2508 }; 2509 }; 2510 /* 2511 * Override the actions of the signals that we are trapping. 2512 */ 2513 for(sig=gl->sigs; sig; sig=sig->next) { 2514 if(sigismember(&gl->use_signal_set, sig->signo)) { 2515 sigdelset(&act.sa_mask, sig->signo); 2516 if(sigaction(sig->signo, &act, &sig->original)) { 2517 _err_record_msg(gl->err, "sigaction error", END_ERR_MSG); 2518 return 1; 2519 }; 2520 sigaddset(&act.sa_mask, sig->signo); 2521 }; 2522 }; 2523 /* 2524 * Record the fact that the application's signal handlers have now 2525 * been overriden. 2526 */ 2527 gl->signals_overriden = 1; 2528 /* 2529 * Just in case a SIGWINCH signal was sent to the process while our 2530 * SIGWINCH signal handler wasn't in place, check to see if the terminal 2531 * size needs updating. 2532 */ 2533 if(_gl_update_size(gl)) 2534 return 1; 2535 return 0; 2536 } 2537 2538 /*....................................................................... 2539 * Restore the signal handlers of the calling program. 2540 * 2541 * Input: 2542 * gl GetLine * The resource object of this library. 2543 * Output: 2544 * return int 0 - OK. 2545 * 1 - Error. 2546 */ 2547 static int gl_restore_signal_handlers(GetLine *gl) 2548 { 2549 GlSignalNode *sig; /* A node in the list of signals to be caught */ 2550 /* 2551 * Restore application signal handlers that were overriden 2552 * by gl_override_signal_handlers(). 2553 */ 2554 for(sig=gl->sigs; sig; sig=sig->next) { 2555 if(sigismember(&gl->use_signal_set, sig->signo) && 2556 sigaction(sig->signo, &sig->original, NULL)) { 2557 _err_record_msg(gl->err, "sigaction error", END_ERR_MSG); 2558 return 1; 2559 }; 2560 }; 2561 /* 2562 * Record the fact that the application's signal handlers have now 2563 * been restored. 2564 */ 2565 gl->signals_overriden = 0; 2566 return 0; 2567 } 2568 2569 /*....................................................................... 2570 * This signal handler simply records the fact that a given signal was 2571 * caught in the file-scope gl_pending_signal variable. 2572 */ 2573 static void gl_signal_handler(int signo) 2574 { 2575 gl_pending_signal = signo; 2576 siglongjmp(gl_setjmp_buffer, 1); 2577 } 2578 2579 /*....................................................................... 2580 * Switch the terminal into raw mode after storing the previous terminal 2581 * settings in gl->attributes. 2582 * 2583 * Input: 2584 * gl GetLine * The resource object of this program. 2585 * Output: 2586 * return int 0 - OK. 2587 * 1 - Error. 2588 */ 2589 static int gl_raw_terminal_mode(GetLine *gl) 2590 { 2591 Termios newattr; /* The new terminal attributes */ 2592 /* 2593 * If the terminal is already in raw mode, do nothing. 2594 */ 2595 if(gl->raw_mode) 2596 return 0; 2597 /* 2598 * Record the current terminal attributes. 2599 */ 2600 if(tcgetattr(gl->input_fd, &gl->oldattr)) { 2601 _err_record_msg(gl->err, "tcgetattr error", END_ERR_MSG); 2602 return 1; 2603 }; 2604 /* 2605 * This function shouldn't do anything but record the current terminal 2606 * attritubes if editing has been disabled. 2607 */ 2608 if(gl->editor == GL_NO_EDITOR) 2609 return 0; 2610 /* 2611 * Modify the existing attributes. 2612 */ 2613 newattr = gl->oldattr; 2614 /* 2615 * Turn off local echo, canonical input mode and extended input processing. 2616 */ 2617 newattr.c_lflag &= ~(ECHO | ICANON | IEXTEN); 2618 /* 2619 * Don't translate carriage return to newline, turn off input parity 2620 * checking, don't strip off 8th bit, turn off output flow control. 2621 */ 2622 newattr.c_iflag &= ~(ICRNL | INPCK | ISTRIP); 2623 /* 2624 * Clear size bits, turn off parity checking, and allow 8-bit characters. 2625 */ 2626 newattr.c_cflag &= ~(CSIZE | PARENB); 2627 newattr.c_cflag |= CS8; 2628 /* 2629 * Turn off output processing. 2630 */ 2631 newattr.c_oflag &= ~(OPOST); 2632 /* 2633 * Request one byte at a time, without waiting. 2634 */ 2635 newattr.c_cc[VMIN] = gl->io_mode==GL_SERVER_MODE ? 0:1; 2636 newattr.c_cc[VTIME] = 0; 2637 /* 2638 * Install the new terminal modes. 2639 */ 2640 while(tcsetattr(gl->input_fd, TCSADRAIN, &newattr)) { 2641 if(errno != EINTR) { 2642 _err_record_msg(gl->err, "tcsetattr error", END_ERR_MSG); 2643 return 1; 2644 }; 2645 }; 2646 /* 2647 * Record the new terminal mode. 2648 */ 2649 gl->raw_mode = 1; 2650 return 0; 2651 } 2652 2653 /*....................................................................... 2654 * Restore the terminal attributes recorded in gl->oldattr. 2655 * 2656 * Input: 2657 * gl GetLine * The resource object of this library. 2658 * Output: 2659 * return int 0 - OK. 2660 * 1 - Error. 2661 */ 2662 static int gl_restore_terminal_attributes(GetLine *gl) 2663 { 2664 int waserr = 0; 2665 /* 2666 * If not in raw mode, do nothing. 2667 */ 2668 if(!gl->raw_mode) 2669 return 0; 2670 /* 2671 * Before changing the terminal attributes, make sure that all output 2672 * has been passed to the terminal. 2673 */ 2674 if(gl_flush_output(gl)) 2675 waserr = 1; 2676 /* 2677 * Reset the terminal attributes to the values that they had on 2678 * entry to gl_get_line(). 2679 */ 2680 while(tcsetattr(gl->input_fd, TCSADRAIN, &gl->oldattr)) { 2681 if(errno != EINTR) { 2682 _err_record_msg(gl->err, "tcsetattr error", END_ERR_MSG); 2683 waserr = 1; 2684 break; 2685 }; 2686 }; 2687 /* 2688 * Record the new terminal mode. 2689 */ 2690 gl->raw_mode = 0; 2691 return waserr; 2692 } 2693 2694 /*....................................................................... 2695 * Switch the terminal file descriptor to use non-blocking I/O. 2696 * 2697 * Input: 2698 * gl GetLine * The resource object of gl_get_line(). 2699 * fd int The file descriptor to make non-blocking. 2700 */ 2701 static int gl_nonblocking_io(GetLine *gl, int fd) 2702 { 2703 int fcntl_flags; /* The new file-descriptor control flags */ 2704 /* 2705 * Is non-blocking I/O supported on this system? Note that even 2706 * without non-blocking I/O, the terminal will probably still act as 2707 * though it was non-blocking, because we also set the terminal 2708 * attributes to return immediately if no input is available and we 2709 * use select() to wait to be able to write. If select() also isn't 2710 * available, then input will probably remain fine, but output could 2711 * block, depending on the behaviour of the terminal driver. 2712 */ 2713 #if defined(NON_BLOCKING_FLAG) 2714 /* 2715 * Query the current file-control flags, and add the 2716 * non-blocking I/O flag. 2717 */ 2718 fcntl_flags = fcntl(fd, F_GETFL) | NON_BLOCKING_FLAG; 2719 /* 2720 * Install the new control flags. 2721 */ 2722 if(fcntl(fd, F_SETFL, fcntl_flags) == -1) { 2723 _err_record_msg(gl->err, "fcntl error", END_ERR_MSG); 2724 return 1; 2725 }; 2726 #endif 2727 return 0; 2728 } 2729 2730 /*....................................................................... 2731 * Switch to blocking terminal I/O. 2732 * 2733 * Input: 2734 * gl GetLine * The resource object of gl_get_line(). 2735 * fd int The file descriptor to make blocking. 2736 */ 2737 static int gl_blocking_io(GetLine *gl, int fd) 2738 { 2739 int fcntl_flags; /* The new file-descriptor control flags */ 2740 /* 2741 * Is non-blocking I/O implemented on this system? 2742 */ 2743 #if defined(NON_BLOCKING_FLAG) 2744 /* 2745 * Query the current file control flags and remove the non-blocking 2746 * I/O flag. 2747 */ 2748 fcntl_flags = fcntl(fd, F_GETFL) & ~NON_BLOCKING_FLAG; 2749 /* 2750 * Install the modified control flags. 2751 */ 2752 if(fcntl(fd, F_SETFL, fcntl_flags) == -1) { 2753 _err_record_msg(gl->err, "fcntl error", END_ERR_MSG); 2754 return 1; 2755 }; 2756 #endif 2757 return 0; 2758 } 2759 2760 /*....................................................................... 2761 * Read a new input line from the user. 2762 * 2763 * Input: 2764 * gl GetLine * The resource object of this library. 2765 * prompt char * The prompt to prefix the line with, or NULL to 2766 * use the same prompt that was used by the previous 2767 * line. 2768 * start_line char * The initial contents of the input line, or NULL 2769 * if it should start out empty. 2770 * start_pos int If start_line isn't NULL, this specifies the 2771 * index of the character over which the cursor 2772 * should initially be positioned within the line. 2773 * If you just want it to follow the last character 2774 * of the line, send -1. 2775 * Output: 2776 * return int 0 - OK. 2777 * 1 - Error. 2778 */ 2779 static int gl_get_input_line(GetLine *gl, const char *prompt, 2780 const char *start_line, int start_pos) 2781 { 2782 char c; /* The character being read */ 2783 /* 2784 * Flush any pending output to the terminal. 2785 */ 2786 if(_glq_char_count(gl->cq) > 0 && gl_flush_output(gl)) 2787 return 1; 2788 /* 2789 * Are we starting a new line? 2790 */ 2791 if(gl->endline) { 2792 /* 2793 * Delete any incompletely enterred line. 2794 */ 2795 if(gl_erase_line(gl)) 2796 return 1; 2797 /* 2798 * Display the new line to be edited. 2799 */ 2800 if(gl_present_line(gl, prompt, start_line, start_pos)) 2801 return 1; 2802 }; 2803 /* 2804 * Read one character at a time. 2805 */ 2806 while(gl_read_terminal(gl, 1, &c) == 0) { 2807 /* 2808 * Increment the count of the number of key sequences entered. 2809 */ 2810 gl->keyseq_count++; 2811 /* 2812 * Interpret the character either as the start of a new key-sequence, 2813 * as a continuation of a repeat count, or as a printable character 2814 * to be added to the line. 2815 */ 2816 if(gl_interpret_char(gl, c)) 2817 break; 2818 /* 2819 * If we just ran an action function which temporarily asked for 2820 * input to be taken from a file, abort this call. 2821 */ 2822 if(gl->file_fp) 2823 return 0; 2824 /* 2825 * Has the line been completed? 2826 */ 2827 if(gl->endline) 2828 return gl_line_ended(gl, c); 2829 }; 2830 /* 2831 * To get here, gl_read_terminal() must have returned non-zero. See 2832 * whether a signal was caught that requested that the current line 2833 * be returned. 2834 */ 2835 if(gl->endline) 2836 return gl_line_ended(gl, '\n'); 2837 /* 2838 * If I/O blocked while attempting to get the latest character 2839 * of the key sequence, rewind the key buffer to allow interpretation of 2840 * the current key sequence to be restarted on the next call to this 2841 * function. 2842 */ 2843 if(gl->rtn_status == GLR_BLOCKED && gl->pending_io == GLP_READ) 2844 gl->nread = 0; 2845 return 1; 2846 } 2847 2848 /*....................................................................... 2849 * This is the private function of gl_query_char() that handles 2850 * prompting the user, reading a character from the terminal, and 2851 * displaying what the user entered. 2852 * 2853 * Input: 2854 * gl GetLine * The resource object of this library. 2855 * prompt char * The prompt to prefix the line with. 2856 * defchar char The character to substitute if the 2857 * user simply hits return, or '\n' if you don't 2858 * need to substitute anything. 2859 * Output: 2860 * return int The character that was read, or EOF if something 2861 * prevented a character from being read. 2862 */ 2863 static int gl_get_query_char(GetLine *gl, const char *prompt, int defchar) 2864 { 2865 char c; /* The character being read */ 2866 int retval; /* The return value of this function */ 2867 /* 2868 * Flush any pending output to the terminal. 2869 */ 2870 if(_glq_char_count(gl->cq) > 0 && gl_flush_output(gl)) 2871 return EOF; 2872 /* 2873 * Delete any incompletely entered line. 2874 */ 2875 if(gl_erase_line(gl)) 2876 return EOF; 2877 /* 2878 * Reset the line input parameters and display the prompt, if any. 2879 */ 2880 if(gl_present_line(gl, prompt, NULL, 0)) 2881 return EOF; 2882 /* 2883 * Read one character. 2884 */ 2885 if(gl_read_terminal(gl, 1, &c) == 0) { 2886 /* 2887 * In this mode, count each character as being a new key-sequence. 2888 */ 2889 gl->keyseq_count++; 2890 /* 2891 * Delete the character that was read, from the key-press buffer. 2892 */ 2893 gl_discard_chars(gl, gl->nread); 2894 /* 2895 * Convert carriage returns to newlines. 2896 */ 2897 if(c == '\r') 2898 c = '\n'; 2899 /* 2900 * If the user just hit return, subsitute the default character. 2901 */ 2902 if(c == '\n') 2903 c = defchar; 2904 /* 2905 * Display the entered character to the right of the prompt. 2906 */ 2907 if(c!='\n') { 2908 if(gl_end_of_line(gl, 1, NULL)==0) 2909 gl_print_char(gl, c, ' '); 2910 }; 2911 /* 2912 * Record the return character, and mark the call as successful. 2913 */ 2914 retval = c; 2915 gl_record_status(gl, GLR_NEWLINE, 0); 2916 /* 2917 * Was a signal caught whose disposition is to cause the current input 2918 * line to be returned? If so return a newline character. 2919 */ 2920 } else if(gl->endline) { 2921 retval = '\n'; 2922 gl_record_status(gl, GLR_NEWLINE, 0); 2923 } else { 2924 retval = EOF; 2925 }; 2926 /* 2927 * Start a new line. 2928 */ 2929 if(gl_start_newline(gl, 1)) 2930 return EOF; 2931 /* 2932 * Attempt to flush any pending output. 2933 */ 2934 (void) gl_flush_output(gl); 2935 /* 2936 * Return either the character that was read, or EOF if an error occurred. 2937 */ 2938 return retval; 2939 } 2940 2941 /*....................................................................... 2942 * Add a character to the line buffer at the current cursor position, 2943 * inserting or overwriting according the current mode. 2944 * 2945 * Input: 2946 * gl GetLine * The resource object of this library. 2947 * c char The character to be added. 2948 * Output: 2949 * return int 0 - OK. 2950 * 1 - Insufficient room. 2951 */ 2952 static int gl_add_char_to_line(GetLine *gl, char c) 2953 { 2954 /* 2955 * Keep a record of the current cursor position. 2956 */ 2957 int buff_curpos = gl->buff_curpos; 2958 int term_curpos = gl->term_curpos; 2959 /* 2960 * Work out the displayed width of the new character. 2961 */ 2962 int width = gl_displayed_char_width(gl, c, term_curpos); 2963 /* 2964 * If we are in insert mode, or at the end of the line, 2965 * check that we can accomodate a new character in the buffer. 2966 * If not, simply return, leaving it up to the calling program 2967 * to check for the absence of a newline character. 2968 */ 2969 if((gl->insert || buff_curpos >= gl->ntotal) && gl->ntotal >= gl->linelen) 2970 return 0; 2971 /* 2972 * Are we adding characters to the line (ie. inserting or appending)? 2973 */ 2974 if(gl->insert || buff_curpos >= gl->ntotal) { 2975 /* 2976 * If inserting, make room for the new character. 2977 */ 2978 if(buff_curpos < gl->ntotal) 2979 gl_make_gap_in_buffer(gl, buff_curpos, 1); 2980 /* 2981 * Copy the character into the buffer. 2982 */ 2983 gl_buffer_char(gl, c, buff_curpos); 2984 gl->buff_curpos++; 2985 /* 2986 * Redraw the line from the cursor position to the end of the line, 2987 * and move the cursor to just after the added character. 2988 */ 2989 if(gl_print_string(gl, gl->line + buff_curpos, '\0') || 2990 gl_set_term_curpos(gl, term_curpos + width)) 2991 return 1; 2992 /* 2993 * Are we overwriting an existing character? 2994 */ 2995 } else { 2996 /* 2997 * Get the width of the character being overwritten. 2998 */ 2999 int old_width = gl_displayed_char_width(gl, gl->line[buff_curpos], 3000 term_curpos); 3001 /* 3002 * Overwrite the character in the buffer. 3003 */ 3004 gl_buffer_char(gl, c, buff_curpos); 3005 /* 3006 * If we are replacing with a narrower character, we need to 3007 * redraw the terminal string to the end of the line, then 3008 * overwrite the trailing old_width - width characters 3009 * with spaces. 3010 */ 3011 if(old_width > width) { 3012 if(gl_print_string(gl, gl->line + buff_curpos, '\0')) 3013 return 1; 3014 /* 3015 * Clear to the end of the terminal. 3016 */ 3017 if(gl_truncate_display(gl)) 3018 return 1; 3019 /* 3020 * Move the cursor to the end of the new character. 3021 */ 3022 if(gl_set_term_curpos(gl, term_curpos + width)) 3023 return 1; 3024 gl->buff_curpos++; 3025 /* 3026 * If we are replacing with a wider character, then we will be 3027 * inserting new characters, and thus extending the line. 3028 */ 3029 } else if(width > old_width) { 3030 /* 3031 * Redraw the line from the cursor position to the end of the line, 3032 * and move the cursor to just after the added character. 3033 */ 3034 if(gl_print_string(gl, gl->line + buff_curpos, '\0') || 3035 gl_set_term_curpos(gl, term_curpos + width)) 3036 return 1; 3037 gl->buff_curpos++; 3038 /* 3039 * The original and replacement characters have the same width, 3040 * so simply overwrite. 3041 */ 3042 } else { 3043 /* 3044 * Copy the character into the buffer. 3045 */ 3046 gl_buffer_char(gl, c, buff_curpos); 3047 gl->buff_curpos++; 3048 /* 3049 * Overwrite the original character. 3050 */ 3051 if(gl_print_char(gl, c, gl->line[gl->buff_curpos])) 3052 return 1; 3053 }; 3054 }; 3055 return 0; 3056 } 3057 3058 /*....................................................................... 3059 * Insert/append a string to the line buffer and terminal at the current 3060 * cursor position. 3061 * 3062 * Input: 3063 * gl GetLine * The resource object of this library. 3064 * s char * The string to be added. 3065 * Output: 3066 * return int 0 - OK. 3067 * 1 - Insufficient room. 3068 */ 3069 static int gl_add_string_to_line(GetLine *gl, const char *s) 3070 { 3071 int buff_slen; /* The length of the string being added to line[] */ 3072 int term_slen; /* The length of the string being written to the terminal */ 3073 int buff_curpos; /* The original value of gl->buff_curpos */ 3074 int term_curpos; /* The original value of gl->term_curpos */ 3075 /* 3076 * Keep a record of the current cursor position. 3077 */ 3078 buff_curpos = gl->buff_curpos; 3079 term_curpos = gl->term_curpos; 3080 /* 3081 * How long is the string to be added? 3082 */ 3083 buff_slen = strlen(s); 3084 term_slen = gl_displayed_string_width(gl, s, buff_slen, term_curpos); 3085 /* 3086 * Check that we can accomodate the string in the buffer. 3087 * If not, simply return, leaving it up to the calling program 3088 * to check for the absence of a newline character. 3089 */ 3090 if(gl->ntotal + buff_slen > gl->linelen) 3091 return 0; 3092 /* 3093 * Move the characters that follow the cursor in the buffer by 3094 * buff_slen characters to the right. 3095 */ 3096 if(gl->ntotal > gl->buff_curpos) 3097 gl_make_gap_in_buffer(gl, gl->buff_curpos, buff_slen); 3098 /* 3099 * Copy the string into the buffer. 3100 */ 3101 gl_buffer_string(gl, s, buff_slen, gl->buff_curpos); 3102 gl->buff_curpos += buff_slen; 3103 /* 3104 * Write the modified part of the line to the terminal, then move 3105 * the terminal cursor to the end of the displayed input string. 3106 */ 3107 if(gl_print_string(gl, gl->line + buff_curpos, '\0') || 3108 gl_set_term_curpos(gl, term_curpos + term_slen)) 3109 return 1; 3110 return 0; 3111 } 3112 3113 /*....................................................................... 3114 * Read a single character from the terminal. 3115 * 3116 * Input: 3117 * gl GetLine * The resource object of this library. 3118 * keep int If true, the returned character will be kept in 3119 * the input buffer, for potential replays. It should 3120 * subsequently be removed from the buffer when the 3121 * key sequence that it belongs to has been fully 3122 * processed, by calling gl_discard_chars(). 3123 * Input/Output: 3124 * c char * The character that is read, is assigned to *c. 3125 * Output: 3126 * return int 0 - OK. 3127 * 1 - Either an I/O error occurred, or a signal was 3128 * caught who's disposition is to abort gl_get_line() 3129 * or to have gl_get_line() return the current line 3130 * as though the user had pressed return. In the 3131 * latter case gl->endline will be non-zero. 3132 */ 3133 static int gl_read_terminal(GetLine *gl, int keep, char *c) 3134 { 3135 /* 3136 * Before waiting for a new character to be input, flush unwritten 3137 * characters to the terminal. 3138 */ 3139 if(gl_flush_output(gl)) 3140 return 1; 3141 /* 3142 * Record the fact that we are about to read from the terminal. 3143 */ 3144 gl->pending_io = GLP_READ; 3145 /* 3146 * If there is already an unread character in the buffer, 3147 * return it. 3148 */ 3149 if(gl->nread < gl->nbuf) { 3150 *c = gl->keybuf[gl->nread]; 3151 /* 3152 * Retain the character in the key buffer, but mark it as having been read? 3153 */ 3154 if(keep) { 3155 gl->nread++; 3156 /* 3157 * Completely remove the character from the key buffer? 3158 */ 3159 } else { 3160 memmove(gl->keybuf + gl->nread, gl->keybuf + gl->nread + 1, 3161 gl->nbuf - gl->nread - 1); 3162 }; 3163 return 0; 3164 }; 3165 /* 3166 * Make sure that there is space in the key buffer for one more character. 3167 * This should always be true if gl_interpret_char() is called for each 3168 * new character added, since it will clear the buffer once it has recognized 3169 * or rejected a key sequence. 3170 */ 3171 if(gl->nbuf + 1 > GL_KEY_MAX) { 3172 gl_print_info(gl, "gl_read_terminal: Buffer overflow avoided.", 3173 GL_END_INFO); 3174 errno = EIO; 3175 return 1; 3176 }; 3177 /* 3178 * Read one character from the terminal. 3179 */ 3180 switch(gl_read_input(gl, c)) { 3181 case GL_READ_OK: 3182 break; 3183 case GL_READ_BLOCKED: 3184 gl_record_status(gl, GLR_BLOCKED, BLOCKED_ERRNO); 3185 return 1; 3186 break; 3187 default: 3188 return 1; 3189 break; 3190 }; 3191 /* 3192 * Append the character to the key buffer? 3193 */ 3194 if(keep) { 3195 gl->keybuf[gl->nbuf] = *c; 3196 gl->nread = ++gl->nbuf; 3197 }; 3198 return 0; 3199 } 3200 3201 /*....................................................................... 3202 * Read one or more keypresses from the terminal of an input stream. 3203 * 3204 * Input: 3205 * gl GetLine * The resource object of this module. 3206 * c char * The character that was read is assigned to *c. 3207 * Output: 3208 * return GlReadStatus The completion status of the read operation. 3209 */ 3210 static GlReadStatus gl_read_input(GetLine *gl, char *c) 3211 { 3212 /* 3213 * We may have to repeat the read if window change signals are received. 3214 */ 3215 for(;;) { 3216 /* 3217 * Which file descriptor should we read from? Mark this volatile, so 3218 * that siglongjmp() can't clobber it. 3219 */ 3220 volatile int fd = gl->file_fp ? fileno(gl->file_fp) : gl->input_fd; 3221 /* 3222 * If the endline flag becomes set, don't wait for another character. 3223 */ 3224 if(gl->endline) 3225 return GL_READ_ERROR; 3226 /* 3227 * Since the code in this function can block, trap signals. 3228 */ 3229 if(sigsetjmp(gl_setjmp_buffer, 1)==0) { 3230 /* 3231 * Handle the different I/O modes. 3232 */ 3233 switch(gl->io_mode) { 3234 /* 3235 * In normal I/O mode, we call the event handler before attempting 3236 * to read, since read() blocks. 3237 */ 3238 case GL_NORMAL_MODE: 3239 if(gl_event_handler(gl, fd)) 3240 return GL_READ_ERROR; 3241 return gl_read_unmasked(gl, fd, c); /* Read one character */ 3242 break; 3243 /* 3244 * In non-blocking server I/O mode, we attempt to read a character, 3245 * and only if this fails, call the event handler to wait for a any 3246 * user-configured timeout and any other user-configured events. In 3247 * addition, we turn off the fcntl() non-blocking flag when reading 3248 * from the terminal, to work around a bug in Solaris. We can do this 3249 * without causing the read() to block, because when in non-blocking 3250 * server-I/O mode, gl_raw_io() sets the VMIN terminal attribute to 0, 3251 * which tells the terminal driver to return immediately if no 3252 * characters are available to be read. 3253 */ 3254 case GL_SERVER_MODE: 3255 { 3256 GlReadStatus status; /* The return status */ 3257 if(isatty(fd)) /* If we reading from a terminal, */ 3258 gl_blocking_io(gl, fd); /* switch to blocking I/O */ 3259 status = gl_read_unmasked(gl, fd, c); /* Try reading */ 3260 if(status == GL_READ_BLOCKED) { /* Nothing readable yet */ 3261 if(gl_event_handler(gl, fd)) /* Wait for input */ 3262 status = GL_READ_ERROR; 3263 else 3264 status = gl_read_unmasked(gl, fd, c); /* Try reading again */ 3265 }; 3266 gl_nonblocking_io(gl, fd); /* Restore non-blocking I/O */ 3267 return status; 3268 }; 3269 break; 3270 }; 3271 }; 3272 /* 3273 * To get here, one of the signals that we are trapping must have 3274 * been received. Note that by using sigsetjmp() instead of setjmp() 3275 * the signal mask that was blocking these signals will have been 3276 * reinstated, so we can be sure that no more of these signals will 3277 * be received until we explicitly unblock them again. 3278 * 3279 * First, if non-blocking I/O was temporarily disabled, reinstate it. 3280 */ 3281 if(gl->io_mode == GL_SERVER_MODE) 3282 gl_nonblocking_io(gl, fd); 3283 /* 3284 * Now respond to the signal that was caught. 3285 */ 3286 if(gl_check_caught_signal(gl)) 3287 return GL_READ_ERROR; 3288 }; 3289 } 3290 3291 /*....................................................................... 3292 * This is a private function of gl_read_input(), which unblocks signals 3293 * temporarily while it reads a single character from the specified file 3294 * descriptor. 3295 * 3296 * Input: 3297 * gl GetLine * The resource object of this module. 3298 * fd int The file descriptor to read from. 3299 * c char * The character that was read is assigned to *c. 3300 * Output: 3301 * return GlReadStatus The completion status of the read. 3302 */ 3303 static int gl_read_unmasked(GetLine *gl, int fd, char *c) 3304 { 3305 int nread; /* The return value of read() */ 3306 /* 3307 * Unblock the signals that we are trapping, while waiting for I/O. 3308 */ 3309 gl_catch_signals(gl); 3310 /* 3311 * Attempt to read one character from the terminal, restarting the read 3312 * if any signals that we aren't trapping, are received. 3313 */ 3314 do { 3315 errno = 0; 3316 nread = read(fd, c, 1); 3317 } while(nread < 0 && errno==EINTR); 3318 /* 3319 * Block all of the signals that we are trapping. 3320 */ 3321 gl_mask_signals(gl, NULL); 3322 /* 3323 * Check the completion status of the read. 3324 */ 3325 switch(nread) { 3326 case 1: 3327 return GL_READ_OK; 3328 case 0: 3329 return (isatty(fd) || errno != 0) ? GL_READ_BLOCKED : GL_READ_EOF; 3330 default: 3331 return GL_READ_ERROR; 3332 }; 3333 } 3334 3335 /*....................................................................... 3336 * Remove a specified number of characters from the start of the 3337 * key-press lookahead buffer, gl->keybuf[], and arrange for the next 3338 * read to start from the character at the start of the shifted buffer. 3339 * 3340 * Input: 3341 * gl GetLine * The resource object of this module. 3342 * nused int The number of characters to discard from the start 3343 * of the buffer. 3344 */ 3345 static void gl_discard_chars(GetLine *gl, int nused) 3346 { 3347 int nkeep = gl->nbuf - nused; 3348 if(nkeep > 0) { 3349 memmove(gl->keybuf, gl->keybuf + nused, nkeep); 3350 gl->nbuf = nkeep; 3351 gl->nread = 0; 3352 } else { 3353 gl->nbuf = gl->nread = 0; 3354 }; 3355 } 3356 3357 /*....................................................................... 3358 * This function is called to handle signals caught between calls to 3359 * sigsetjmp() and siglongjmp(). 3360 * 3361 * Input: 3362 * gl GetLine * The resource object of this library. 3363 * Output: 3364 * return int 0 - Signal handled internally. 3365 * 1 - Signal requires gl_get_line() to abort. 3366 */ 3367 static int gl_check_caught_signal(GetLine *gl) 3368 { 3369 GlSignalNode *sig; /* The signal disposition */ 3370 SigAction keep_action; /* The signal disposition of tecla signal handlers */ 3371 unsigned flags; /* The signal processing flags to use */ 3372 int signo; /* The signal to be handled */ 3373 /* 3374 * Was no signal caught? 3375 */ 3376 if(gl_pending_signal == -1) 3377 return 0; 3378 /* 3379 * Get the signal to be handled. 3380 */ 3381 signo = gl_pending_signal; 3382 /* 3383 * Mark the signal as handled. Note that at this point, all of 3384 * the signals that we are trapping are blocked from delivery. 3385 */ 3386 gl_pending_signal = -1; 3387 /* 3388 * Record the signal that was caught, so that the user can query it later. 3389 */ 3390 gl->last_signal = signo; 3391 /* 3392 * In non-blocking server mode, the application is responsible for 3393 * responding to terminal signals, and we don't want gl_get_line()s 3394 * normal signal handling to clash with this, so whenever a signal 3395 * is caught, we arrange for gl_get_line() to abort and requeue the 3396 * signal while signals are still blocked. If the application 3397 * had the signal unblocked when gl_get_line() was called, the signal 3398 * will be delivered again as soon as gl_get_line() restores the 3399 * process signal mask, just before returning to the application. 3400 * Note that the caller of this function should set gl->pending_io 3401 * to the appropriate choice of GLP_READ and GLP_WRITE, before returning. 3402 */ 3403 if(gl->io_mode==GL_SERVER_MODE) { 3404 gl_record_status(gl, GLR_SIGNAL, EINTR); 3405 raise(signo); 3406 return 1; 3407 }; 3408 /* 3409 * Lookup the requested disposition of this signal. 3410 */ 3411 for(sig=gl->sigs; sig && sig->signo != signo; sig=sig->next) 3412 ; 3413 if(!sig) 3414 return 0; 3415 /* 3416 * Get the signal response flags for this signal. 3417 */ 3418 flags = sig->flags; 3419 /* 3420 * Did we receive a terminal size signal? 3421 */ 3422 #ifdef SIGWINCH 3423 if(signo == SIGWINCH && _gl_update_size(gl)) 3424 return 1; 3425 #endif 3426 /* 3427 * Start a fresh line? 3428 */ 3429 if(flags & GLS_RESTORE_LINE) { 3430 if(gl_start_newline(gl, 0)) 3431 return 1; 3432 }; 3433 /* 3434 * Restore terminal settings to how they were before gl_get_line() was 3435 * called? 3436 */ 3437 if(flags & GLS_RESTORE_TTY) 3438 gl_restore_terminal_attributes(gl); 3439 /* 3440 * Restore signal handlers to how they were before gl_get_line() was 3441 * called? If this hasn't been requested, only reinstate the signal 3442 * handler of the signal that we are handling. 3443 */ 3444 if(flags & GLS_RESTORE_SIG) { 3445 gl_restore_signal_handlers(gl); 3446 gl_unmask_signals(gl, &gl->old_signal_set); 3447 } else { 3448 (void) sigaction(sig->signo, &sig->original, &keep_action); 3449 (void) sigprocmask(SIG_UNBLOCK, &sig->proc_mask, NULL); 3450 }; 3451 /* 3452 * Forward the signal to the application's signal handler. 3453 */ 3454 if(!(flags & GLS_DONT_FORWARD)) 3455 raise(signo); 3456 /* 3457 * Reinstate our signal handlers. 3458 */ 3459 if(flags & GLS_RESTORE_SIG) { 3460 gl_mask_signals(gl, NULL); 3461 gl_override_signal_handlers(gl); 3462 } else { 3463 (void) sigaction(sig->signo, &keep_action, NULL); 3464 (void) sigprocmask(SIG_BLOCK, &sig->proc_mask, NULL); 3465 }; 3466 /* 3467 * Do we need to reinstate our terminal settings? 3468 */ 3469 if(flags & GLS_RESTORE_TTY) 3470 gl_raw_terminal_mode(gl); 3471 /* 3472 * Redraw the line? 3473 */ 3474 if(flags & GLS_REDRAW_LINE) 3475 gl_queue_redisplay(gl); 3476 /* 3477 * What next? 3478 */ 3479 switch(sig->after) { 3480 case GLS_RETURN: 3481 gl_newline(gl, 1, NULL); 3482 return gl_flush_output(gl); 3483 break; 3484 case GLS_ABORT: 3485 gl_record_status(gl, GLR_SIGNAL, sig->errno_value); 3486 return 1; 3487 break; 3488 case GLS_CONTINUE: 3489 return gl_flush_output(gl); 3490 break; 3491 }; 3492 return 0; 3493 } 3494 3495 /*....................................................................... 3496 * Get pertinent terminal control strings and the initial terminal size. 3497 * 3498 * Input: 3499 * gl GetLine * The resource object of this library. 3500 * term char * The type of the terminal. 3501 * Output: 3502 * return int 0 - OK. 3503 * 1 - Error. 3504 */ 3505 static int gl_control_strings(GetLine *gl, const char *term) 3506 { 3507 int bad_term = 0; /* True if term is unusable */ 3508 /* 3509 * Discard any existing control strings from a previous terminal. 3510 */ 3511 gl->left = NULL; 3512 gl->right = NULL; 3513 gl->up = NULL; 3514 gl->down = NULL; 3515 gl->home = NULL; 3516 gl->bol = 0; 3517 gl->clear_eol = NULL; 3518 gl->clear_eod = NULL; 3519 gl->u_arrow = NULL; 3520 gl->d_arrow = NULL; 3521 gl->l_arrow = NULL; 3522 gl->r_arrow = NULL; 3523 gl->sound_bell = NULL; 3524 gl->bold = NULL; 3525 gl->underline = NULL; 3526 gl->standout = NULL; 3527 gl->dim = NULL; 3528 gl->reverse = NULL; 3529 gl->blink = NULL; 3530 gl->text_attr_off = NULL; 3531 gl->nline = 0; 3532 gl->ncolumn = 0; 3533 #ifdef USE_TERMINFO 3534 gl->left_n = NULL; 3535 gl->right_n = NULL; 3536 #endif 3537 /* 3538 * If possible lookup the information in a terminal information 3539 * database. 3540 */ 3541 #ifdef USE_TERMINFO 3542 { 3543 int errret; 3544 if(!term || setupterm((char *)term, gl->input_fd, &errret) == ERR) { 3545 bad_term = 1; 3546 } else { 3547 _clr_StringGroup(gl->capmem); 3548 gl->left = gl_tigetstr(gl, "cub1"); 3549 gl->right = gl_tigetstr(gl, "cuf1"); 3550 gl->up = gl_tigetstr(gl, "cuu1"); 3551 gl->down = gl_tigetstr(gl, "cud1"); 3552 gl->home = gl_tigetstr(gl, "home"); 3553 gl->clear_eol = gl_tigetstr(gl, "el"); 3554 gl->clear_eod = gl_tigetstr(gl, "ed"); 3555 gl->u_arrow = gl_tigetstr(gl, "kcuu1"); 3556 gl->d_arrow = gl_tigetstr(gl, "kcud1"); 3557 gl->l_arrow = gl_tigetstr(gl, "kcub1"); 3558 gl->r_arrow = gl_tigetstr(gl, "kcuf1"); 3559 gl->left_n = gl_tigetstr(gl, "cub"); 3560 gl->right_n = gl_tigetstr(gl, "cuf"); 3561 gl->sound_bell = gl_tigetstr(gl, "bel"); 3562 gl->bold = gl_tigetstr(gl, "bold"); 3563 gl->underline = gl_tigetstr(gl, "smul"); 3564 gl->standout = gl_tigetstr(gl, "smso"); 3565 gl->dim = gl_tigetstr(gl, "dim"); 3566 gl->reverse = gl_tigetstr(gl, "rev"); 3567 gl->blink = gl_tigetstr(gl, "blink"); 3568 gl->text_attr_off = gl_tigetstr(gl, "sgr0"); 3569 }; 3570 }; 3571 #elif defined(USE_TERMCAP) 3572 if(!term || tgetent(gl->tgetent_buf, (char *)term) < 0) { 3573 bad_term = 1; 3574 } else { 3575 char *tgetstr_buf_ptr = gl->tgetstr_buf; 3576 _clr_StringGroup(gl->capmem); 3577 gl->left = gl_tgetstr(gl, "le", &tgetstr_buf_ptr); 3578 gl->right = gl_tgetstr(gl, "nd", &tgetstr_buf_ptr); 3579 gl->up = gl_tgetstr(gl, "up", &tgetstr_buf_ptr); 3580 gl->down = gl_tgetstr(gl, "do", &tgetstr_buf_ptr); 3581 gl->home = gl_tgetstr(gl, "ho", &tgetstr_buf_ptr); 3582 gl->clear_eol = gl_tgetstr(gl, "ce", &tgetstr_buf_ptr); 3583 gl->clear_eod = gl_tgetstr(gl, "cd", &tgetstr_buf_ptr); 3584 gl->u_arrow = gl_tgetstr(gl, "ku", &tgetstr_buf_ptr); 3585 gl->d_arrow = gl_tgetstr(gl, "kd", &tgetstr_buf_ptr); 3586 gl->l_arrow = gl_tgetstr(gl, "kl", &tgetstr_buf_ptr); 3587 gl->r_arrow = gl_tgetstr(gl, "kr", &tgetstr_buf_ptr); 3588 gl->sound_bell = gl_tgetstr(gl, "bl", &tgetstr_buf_ptr); 3589 gl->bold = gl_tgetstr(gl, "md", &tgetstr_buf_ptr); 3590 gl->underline = gl_tgetstr(gl, "us", &tgetstr_buf_ptr); 3591 gl->standout = gl_tgetstr(gl, "so", &tgetstr_buf_ptr); 3592 gl->dim = gl_tgetstr(gl, "mh", &tgetstr_buf_ptr); 3593 gl->reverse = gl_tgetstr(gl, "mr", &tgetstr_buf_ptr); 3594 gl->blink = gl_tgetstr(gl, "mb", &tgetstr_buf_ptr); 3595 gl->text_attr_off = gl_tgetstr(gl, "me", &tgetstr_buf_ptr); 3596 }; 3597 #endif 3598 /* 3599 * Report term being unusable. 3600 */ 3601 if(bad_term) { 3602 gl_print_info(gl, "Bad terminal type: \"", term ? term : "(null)", 3603 "\". Will assume vt100.", GL_END_INFO); 3604 }; 3605 /* 3606 * Fill in missing information with ANSI VT100 strings. 3607 */ 3608 if(!gl->left) 3609 gl->left = "\b"; /* ^H */ 3610 if(!gl->right) 3611 gl->right = GL_ESC_STR "[C"; 3612 if(!gl->up) 3613 gl->up = GL_ESC_STR "[A"; 3614 if(!gl->down) 3615 gl->down = "\n"; 3616 if(!gl->home) 3617 gl->home = GL_ESC_STR "[H"; 3618 if(!gl->bol) 3619 gl->bol = "\r"; 3620 if(!gl->clear_eol) 3621 gl->clear_eol = GL_ESC_STR "[K"; 3622 if(!gl->clear_eod) 3623 gl->clear_eod = GL_ESC_STR "[J"; 3624 if(!gl->u_arrow) 3625 gl->u_arrow = GL_ESC_STR "[A"; 3626 if(!gl->d_arrow) 3627 gl->d_arrow = GL_ESC_STR "[B"; 3628 if(!gl->l_arrow) 3629 gl->l_arrow = GL_ESC_STR "[D"; 3630 if(!gl->r_arrow) 3631 gl->r_arrow = GL_ESC_STR "[C"; 3632 if(!gl->sound_bell) 3633 gl->sound_bell = "\a"; 3634 if(!gl->bold) 3635 gl->bold = GL_ESC_STR "[1m"; 3636 if(!gl->underline) 3637 gl->underline = GL_ESC_STR "[4m"; 3638 if(!gl->standout) 3639 gl->standout = GL_ESC_STR "[1;7m"; 3640 if(!gl->dim) 3641 gl->dim = ""; /* Not available */ 3642 if(!gl->reverse) 3643 gl->reverse = GL_ESC_STR "[7m"; 3644 if(!gl->blink) 3645 gl->blink = GL_ESC_STR "[5m"; 3646 if(!gl->text_attr_off) 3647 gl->text_attr_off = GL_ESC_STR "[m"; 3648 /* 3649 * Find out the current terminal size. 3650 */ 3651 (void) _gl_terminal_size(gl, GL_DEF_NCOLUMN, GL_DEF_NLINE, NULL); 3652 return 0; 3653 } 3654 3655 #ifdef USE_TERMINFO 3656 /*....................................................................... 3657 * This is a private function of gl_control_strings() used to look up 3658 * a termninal capability string from the terminfo database and make 3659 * a private copy of it. 3660 * 3661 * Input: 3662 * gl GetLine * The resource object of gl_get_line(). 3663 * name const char * The name of the terminfo string to look up. 3664 * Output: 3665 * return const char * The local copy of the capability, or NULL 3666 * if not available. 3667 */ 3668 static const char *gl_tigetstr(GetLine *gl, const char *name) 3669 { 3670 const char *value = tigetstr((char *)name); 3671 if(!value || value == (char *) -1) 3672 return NULL; 3673 return _sg_store_string(gl->capmem, value, 0); 3674 } 3675 #elif defined(USE_TERMCAP) 3676 /*....................................................................... 3677 * This is a private function of gl_control_strings() used to look up 3678 * a termninal capability string from the termcap database and make 3679 * a private copy of it. Note that some emulations of tgetstr(), such 3680 * as that used by Solaris, ignores the buffer pointer that is past to 3681 * it, so we can't assume that a private copy has been made that won't 3682 * be trashed by another call to gl_control_strings() by another 3683 * GetLine object. So we make what may be a redundant private copy 3684 * of the string in gl->capmem. 3685 * 3686 * Input: 3687 * gl GetLine * The resource object of gl_get_line(). 3688 * name const char * The name of the terminfo string to look up. 3689 * Input/Output: 3690 * bufptr char ** On input *bufptr points to the location in 3691 * gl->tgetstr_buf at which to record the 3692 * capability string. On output *bufptr is 3693 * incremented over the stored string. 3694 * Output: 3695 * return const char * The local copy of the capability, or NULL 3696 * on error. 3697 */ 3698 static const char *gl_tgetstr(GetLine *gl, const char *name, char **bufptr) 3699 { 3700 const char *value = tgetstr((char *)name, bufptr); 3701 if(!value || value == (char *) -1) 3702 return NULL; 3703 return _sg_store_string(gl->capmem, value, 0); 3704 } 3705 #endif 3706 3707 /*....................................................................... 3708 * This is an action function that implements a user interrupt (eg. ^C). 3709 */ 3710 static KT_KEY_FN(gl_user_interrupt) 3711 { 3712 raise(SIGINT); 3713 return 1; 3714 } 3715 3716 /*....................................................................... 3717 * This is an action function that implements the abort signal. 3718 */ 3719 static KT_KEY_FN(gl_abort) 3720 { 3721 raise(SIGABRT); 3722 return 1; 3723 } 3724 3725 /*....................................................................... 3726 * This is an action function that sends a suspend signal (eg. ^Z) to the 3727 * the parent process. 3728 */ 3729 static KT_KEY_FN(gl_suspend) 3730 { 3731 raise(SIGTSTP); 3732 return 0; 3733 } 3734 3735 /*....................................................................... 3736 * This is an action function that halts output to the terminal. 3737 */ 3738 static KT_KEY_FN(gl_stop_output) 3739 { 3740 tcflow(gl->output_fd, TCOOFF); 3741 return 0; 3742 } 3743 3744 /*....................................................................... 3745 * This is an action function that resumes halted terminal output. 3746 */ 3747 static KT_KEY_FN(gl_start_output) 3748 { 3749 tcflow(gl->output_fd, TCOON); 3750 return 0; 3751 } 3752 3753 /*....................................................................... 3754 * This is an action function that allows the next character to be accepted 3755 * without any interpretation as a special character. 3756 */ 3757 static KT_KEY_FN(gl_literal_next) 3758 { 3759 char c; /* The character to be added to the line */ 3760 int i; 3761 /* 3762 * Get the character to be inserted literally. 3763 */ 3764 if(gl_read_terminal(gl, 1, &c)) 3765 return 1; 3766 /* 3767 * Add the character to the line 'count' times. 3768 */ 3769 for(i=0; i<count; i++) 3770 gl_add_char_to_line(gl, c); 3771 return 0; 3772 } 3773 3774 /*....................................................................... 3775 * Return the width of a tab character at a given position when 3776 * displayed at a given position on the terminal. This is needed 3777 * because the width of tab characters depends on where they are, 3778 * relative to the preceding tab stops. 3779 * 3780 * Input: 3781 * gl GetLine * The resource object of this library. 3782 * term_curpos int The destination terminal location of the character. 3783 * Output: 3784 * return int The number of terminal charaters needed. 3785 */ 3786 static int gl_displayed_tab_width(GetLine *gl, int term_curpos) 3787 { 3788 return TAB_WIDTH - ((term_curpos % gl->ncolumn) % TAB_WIDTH); 3789 } 3790 3791 /*....................................................................... 3792 * Return the number of characters needed to display a given character 3793 * on the screen. Tab characters require eight spaces, and control 3794 * characters are represented by a caret followed by the modified 3795 * character. 3796 * 3797 * Input: 3798 * gl GetLine * The resource object of this library. 3799 * c char The character to be displayed. 3800 * term_curpos int The destination terminal location of the character. 3801 * This is needed because the width of tab characters 3802 * depends on where they are, relative to the 3803 * preceding tab stops. 3804 * Output: 3805 * return int The number of terminal charaters needed. 3806 */ 3807 static int gl_displayed_char_width(GetLine *gl, char c, int term_curpos) 3808 { 3809 if(c=='\t') 3810 return gl_displayed_tab_width(gl, term_curpos); 3811 if(IS_CTRL_CHAR(c)) 3812 return 2; 3813 if(!isprint((int)(unsigned char) c)) 3814 return gl_octal_width((int)(unsigned char)c) + 1; 3815 return 1; 3816 } 3817 3818 3819 /*....................................................................... 3820 * Work out the length of given string of characters on the terminal. 3821 * 3822 * Input: 3823 * gl GetLine * The resource object of this library. 3824 * string char * The string to be measured. 3825 * nc int The number of characters to be measured, or -1 3826 * to measure the whole string. 3827 * term_curpos int The destination terminal location of the character. 3828 * This is needed because the width of tab characters 3829 * depends on where they are, relative to the 3830 * preceding tab stops. 3831 * Output: 3832 * return int The number of displayed characters. 3833 */ 3834 static int gl_displayed_string_width(GetLine *gl, const char *string, int nc, 3835 int term_curpos) 3836 { 3837 int slen = 0; /* The displayed number of characters */ 3838 int i; 3839 /* 3840 * How many characters are to be measured? 3841 */ 3842 if(nc < 0) 3843 nc = strlen(string); 3844 /* 3845 * Add up the length of the displayed string. 3846 */ 3847 for(i=0; i<nc; i++) 3848 slen += gl_displayed_char_width(gl, string[i], term_curpos + slen); 3849 return slen; 3850 } 3851 3852 /*....................................................................... 3853 * Write a string verbatim to the current terminal or output stream. 3854 * 3855 * Note that when async-signal safety is required, the 'buffered' 3856 * argument must be 0, and n must not be -1. 3857 * 3858 * Input: 3859 * gl GetLine * The resource object of the gl_get_line(). 3860 * buffered int If true, used buffered I/O when writing to 3861 * the terminal. Otherwise use async-signal-safe 3862 * unbuffered I/O. 3863 * string const char * The string to be written (this need not be 3864 * '\0' terminated unless n<0). 3865 * n int The number of characters to write from the 3866 * prefix of string[], or -1 to request that 3867 * gl_print_raw_string() use strlen() to figure 3868 * out the length. 3869 * Output: 3870 * return int 0 - OK. 3871 * 1 - Error. 3872 */ 3873 static int gl_print_raw_string(GetLine *gl, int buffered, 3874 const char *string, int n) 3875 { 3876 GlWriteFn *write_fn = buffered ? gl_write_fn : gl->flush_fn; 3877 /* 3878 * Only display output when echoing is turned on. 3879 */ 3880 if(gl->echo) { 3881 int ndone = 0; /* The number of characters written so far */ 3882 /* 3883 * When using un-buffered I/O, flush pending output first. 3884 */ 3885 if(!buffered) { 3886 if(gl_flush_output(gl)) 3887 return 1; 3888 }; 3889 /* 3890 * If no length has been provided, measure the length of the string. 3891 */ 3892 if(n < 0) 3893 n = strlen(string); 3894 /* 3895 * Write the string. 3896 */ 3897 if(write_fn(gl, string + ndone, n-ndone) != n) 3898 return 1; 3899 }; 3900 return 0; 3901 } 3902 3903 /*....................................................................... 3904 * Output a terminal control sequence. When using terminfo, 3905 * this must be a sequence returned by tgetstr() or tigetstr() 3906 * respectively. 3907 * 3908 * Input: 3909 * gl GetLine * The resource object of this library. 3910 * nline int The number of lines affected by the operation, 3911 * or 1 if not relevant. 3912 * string char * The control sequence to be sent. 3913 * Output: 3914 * return int 0 - OK. 3915 * 1 - Error. 3916 */ 3917 static int gl_print_control_sequence(GetLine *gl, int nline, const char *string) 3918 { 3919 int waserr = 0; /* True if an error occurs */ 3920 /* 3921 * Only write characters to the terminal when echoing is enabled. 3922 */ 3923 if(gl->echo) { 3924 #if defined(USE_TERMINFO) || defined(USE_TERMCAP) 3925 tputs_gl = gl; 3926 errno = 0; 3927 tputs((char *)string, nline, gl_tputs_putchar); 3928 waserr = errno != 0; 3929 #else 3930 waserr = gl_print_raw_string(gl, 1, string, -1); 3931 #endif 3932 }; 3933 return waserr; 3934 } 3935 3936 #if defined(USE_TERMINFO) || defined(USE_TERMCAP) 3937 /*....................................................................... 3938 * The following callback function is called by tputs() to output a raw 3939 * control character to the terminal. 3940 */ 3941 static TputsRetType gl_tputs_putchar(TputsArgType c) 3942 { 3943 char ch = c; 3944 #if TPUTS_RETURNS_VALUE 3945 return gl_print_raw_string(tputs_gl, 1, &ch, 1); 3946 #else 3947 (void) gl_print_raw_string(tputs_gl, 1, &ch, 1); 3948 #endif 3949 } 3950 #endif 3951 3952 /*....................................................................... 3953 * Move the terminal cursor n characters to the left or right. 3954 * 3955 * Input: 3956 * gl GetLine * The resource object of this program. 3957 * n int number of positions to the right (> 0) or left (< 0). 3958 * Output: 3959 * return int 0 - OK. 3960 * 1 - Error. 3961 */ 3962 static int gl_terminal_move_cursor(GetLine *gl, int n) 3963 { 3964 int cur_row, cur_col; /* The current terminal row and column index of */ 3965 /* the cursor wrt the start of the input line. */ 3966 int new_row, new_col; /* The target terminal row and column index of */ 3967 /* the cursor wrt the start of the input line. */ 3968 /* 3969 * Do nothing if the input line isn't currently displayed. In this 3970 * case, the cursor will be moved to the right place when the line 3971 * is next redisplayed. 3972 */ 3973 if(!gl->displayed) 3974 return 0; 3975 /* 3976 * How far can we move left? 3977 */ 3978 if(gl->term_curpos + n < 0) 3979 n = gl->term_curpos; 3980 /* 3981 * Break down the current and target cursor locations into rows and columns. 3982 */ 3983 cur_row = gl->term_curpos / gl->ncolumn; 3984 cur_col = gl->term_curpos % gl->ncolumn; 3985 new_row = (gl->term_curpos + n) / gl->ncolumn; 3986 new_col = (gl->term_curpos + n) % gl->ncolumn; 3987 /* 3988 * Move down to the next line. 3989 */ 3990 for(; cur_row < new_row; cur_row++) { 3991 if(gl_print_control_sequence(gl, 1, gl->down)) 3992 return 1; 3993 }; 3994 /* 3995 * Move up to the previous line. 3996 */ 3997 for(; cur_row > new_row; cur_row--) { 3998 if(gl_print_control_sequence(gl, 1, gl->up)) 3999 return 1; 4000 }; 4001 /* 4002 * Move to the right within the target line? 4003 */ 4004 if(cur_col < new_col) { 4005 #ifdef USE_TERMINFO 4006 /* 4007 * Use a parameterized control sequence if it generates less control 4008 * characters (guess based on ANSI terminal termcap entry). 4009 */ 4010 if(gl->right_n != NULL && new_col - cur_col > 1) { 4011 if(gl_print_control_sequence(gl, 1, tparm((char *)gl->right_n, 4012 (long)(new_col - cur_col), 0l, 0l, 0l, 0l, 0l, 0l, 0l, 0l))) 4013 return 1; 4014 } else 4015 #endif 4016 { 4017 for(; cur_col < new_col; cur_col++) { 4018 if(gl_print_control_sequence(gl, 1, gl->right)) 4019 return 1; 4020 }; 4021 }; 4022 /* 4023 * Move to the left within the target line? 4024 */ 4025 } else if(cur_col > new_col) { 4026 #ifdef USE_TERMINFO 4027 /* 4028 * Use a parameterized control sequence if it generates less control 4029 * characters (guess based on ANSI terminal termcap entry). 4030 */ 4031 if(gl->left_n != NULL && cur_col - new_col > 3) { 4032 if(gl_print_control_sequence(gl, 1, tparm((char *)gl->left_n, 4033 (long)(cur_col - new_col), 0l, 0l, 0l, 0l, 0l, 0l, 0l, 0l))) 4034 return 1; 4035 } else 4036 #endif 4037 { 4038 for(; cur_col > new_col; cur_col--) { 4039 if(gl_print_control_sequence(gl, 1, gl->left)) 4040 return 1; 4041 }; 4042 }; 4043 } 4044 /* 4045 * Update the recorded position of the terminal cursor. 4046 */ 4047 gl->term_curpos += n; 4048 return 0; 4049 } 4050 4051 /*....................................................................... 4052 * Write a character to the terminal after expanding tabs and control 4053 * characters to their multi-character representations. 4054 * 4055 * Input: 4056 * gl GetLine * The resource object of this program. 4057 * c char The character to be output. 4058 * pad char Many terminals have the irritating feature that 4059 * when one writes a character in the last column of 4060 * of the terminal, the cursor isn't wrapped to the 4061 * start of the next line until one more character 4062 * is written. Some terminals don't do this, so 4063 * after such a write, we don't know where the 4064 * terminal is unless we output an extra character. 4065 * This argument specifies the character to write. 4066 * If at the end of the input line send '\0' or a 4067 * space, and a space will be written. Otherwise, 4068 * pass the next character in the input line 4069 * following the one being written. 4070 * Output: 4071 * return int 0 - OK. 4072 */ 4073 static int gl_print_char(GetLine *gl, char c, char pad) 4074 { 4075 char string[TAB_WIDTH + 4]; /* A work area for composing compound strings */ 4076 int nchar; /* The number of terminal characters */ 4077 int i; 4078 /* 4079 * Check for special characters. 4080 */ 4081 if(c == '\t') { 4082 /* 4083 * How many spaces do we need to represent a tab at the current terminal 4084 * column? 4085 */ 4086 nchar = gl_displayed_tab_width(gl, gl->term_curpos); 4087 /* 4088 * Compose the tab string. 4089 */ 4090 for(i=0; i<nchar; i++) 4091 string[i] = ' '; 4092 } else if(IS_CTRL_CHAR(c)) { 4093 string[0] = '^'; 4094 string[1] = CTRL_TO_CHAR(c); 4095 nchar = 2; 4096 } else if(!isprint((int)(unsigned char) c)) { 4097 snprintf(string, sizeof(string), "\\%o", (int)(unsigned char)c); 4098 nchar = strlen(string); 4099 } else { 4100 string[0] = c; 4101 nchar = 1; 4102 }; 4103 /* 4104 * Terminate the string. 4105 */ 4106 string[nchar] = '\0'; 4107 /* 4108 * Write the string to the terminal. 4109 */ 4110 if(gl_print_raw_string(gl, 1, string, -1)) 4111 return 1; 4112 /* 4113 * Except for one exception to be described in a moment, the cursor should 4114 * now have been positioned after the character that was just output. 4115 */ 4116 gl->term_curpos += nchar; 4117 /* 4118 * Keep a record of the number of characters in the terminal version 4119 * of the input line. 4120 */ 4121 if(gl->term_curpos > gl->term_len) 4122 gl->term_len = gl->term_curpos; 4123 /* 4124 * If the new character ended exactly at the end of a line, 4125 * most terminals won't move the cursor onto the next line until we 4126 * have written a character on the next line, so append an extra 4127 * space then move the cursor back. 4128 */ 4129 if(gl->term_curpos % gl->ncolumn == 0) { 4130 int term_curpos = gl->term_curpos; 4131 if(gl_print_char(gl, pad ? pad : ' ', ' ') || 4132 gl_set_term_curpos(gl, term_curpos)) 4133 return 1; 4134 }; 4135 return 0; 4136 } 4137 4138 /*....................................................................... 4139 * Write a string to the terminal after expanding tabs and control 4140 * characters to their multi-character representations. 4141 * 4142 * Input: 4143 * gl GetLine * The resource object of this program. 4144 * string char * The string to be output. 4145 * pad char Many terminals have the irritating feature that 4146 * when one writes a character in the last column of 4147 * of the terminal, the cursor isn't wrapped to the 4148 * start of the next line until one more character 4149 * is written. Some terminals don't do this, so 4150 * after such a write, we don't know where the 4151 * terminal is unless we output an extra character. 4152 * This argument specifies the character to write. 4153 * If at the end of the input line send '\0' or a 4154 * space, and a space will be written. Otherwise, 4155 * pass the next character in the input line 4156 * following the one being written. 4157 * Output: 4158 * return int 0 - OK. 4159 */ 4160 static int gl_print_string(GetLine *gl, const char *string, char pad) 4161 { 4162 const char *cptr; /* A pointer into string[] */ 4163 for(cptr=string; *cptr; cptr++) { 4164 char nextc = cptr[1]; 4165 if(gl_print_char(gl, *cptr, nextc ? nextc : pad)) 4166 return 1; 4167 }; 4168 return 0; 4169 } 4170 4171 /*....................................................................... 4172 * Move the terminal cursor position. 4173 * 4174 * Input: 4175 * gl GetLine * The resource object of this library. 4176 * term_curpos int The destination terminal cursor position. 4177 * Output: 4178 * return int 0 - OK. 4179 * 1 - Error. 4180 */ 4181 static int gl_set_term_curpos(GetLine *gl, int term_curpos) 4182 { 4183 return gl_terminal_move_cursor(gl, term_curpos - gl->term_curpos); 4184 } 4185 4186 /*....................................................................... 4187 * This is an action function that moves the buffer cursor one character 4188 * left, and updates the terminal cursor to match. 4189 */ 4190 static KT_KEY_FN(gl_cursor_left) 4191 { 4192 return gl_place_cursor(gl, gl->buff_curpos - count); 4193 } 4194 4195 /*....................................................................... 4196 * This is an action function that moves the buffer cursor one character 4197 * right, and updates the terminal cursor to match. 4198 */ 4199 static KT_KEY_FN(gl_cursor_right) 4200 { 4201 return gl_place_cursor(gl, gl->buff_curpos + count); 4202 } 4203 4204 /*....................................................................... 4205 * This is an action function that toggles between overwrite and insert 4206 * mode. 4207 */ 4208 static KT_KEY_FN(gl_insert_mode) 4209 { 4210 gl->insert = !gl->insert; 4211 return 0; 4212 } 4213 4214 /*....................................................................... 4215 * This is an action function which moves the cursor to the beginning of 4216 * the line. 4217 */ 4218 static KT_KEY_FN(gl_beginning_of_line) 4219 { 4220 return gl_place_cursor(gl, 0); 4221 } 4222 4223 /*....................................................................... 4224 * This is an action function which moves the cursor to the end of 4225 * the line. 4226 */ 4227 static KT_KEY_FN(gl_end_of_line) 4228 { 4229 return gl_place_cursor(gl, gl->ntotal); 4230 } 4231 4232 /*....................................................................... 4233 * This is an action function which deletes the entire contents of the 4234 * current line. 4235 */ 4236 static KT_KEY_FN(gl_delete_line) 4237 { 4238 /* 4239 * If in vi command mode, preserve the current line for potential 4240 * use by vi-undo. 4241 */ 4242 gl_save_for_undo(gl); 4243 /* 4244 * Copy the contents of the line to the cut buffer. 4245 */ 4246 strlcpy(gl->cutbuf, gl->line, gl->linelen); 4247 /* 4248 * Clear the buffer. 4249 */ 4250 gl_truncate_buffer(gl, 0); 4251 /* 4252 * Move the terminal cursor to just after the prompt. 4253 */ 4254 if(gl_place_cursor(gl, 0)) 4255 return 1; 4256 /* 4257 * Clear from the end of the prompt to the end of the terminal. 4258 */ 4259 if(gl_truncate_display(gl)) 4260 return 1; 4261 return 0; 4262 } 4263 4264 /*....................................................................... 4265 * This is an action function which deletes all characters between the 4266 * current cursor position and the end of the line. 4267 */ 4268 static KT_KEY_FN(gl_kill_line) 4269 { 4270 /* 4271 * If in vi command mode, preserve the current line for potential 4272 * use by vi-undo. 4273 */ 4274 gl_save_for_undo(gl); 4275 /* 4276 * Copy the part of the line that is about to be deleted to the cut buffer. 4277 */ 4278 strlcpy(gl->cutbuf, gl->line + gl->buff_curpos, gl->linelen); 4279 /* 4280 * Terminate the buffered line at the current cursor position. 4281 */ 4282 gl_truncate_buffer(gl, gl->buff_curpos); 4283 /* 4284 * Clear the part of the line that follows the cursor. 4285 */ 4286 if(gl_truncate_display(gl)) 4287 return 1; 4288 /* 4289 * Explicitly reset the cursor position to allow vi command mode 4290 * constraints on its position to be set. 4291 */ 4292 return gl_place_cursor(gl, gl->buff_curpos); 4293 } 4294 4295 /*....................................................................... 4296 * This is an action function which deletes all characters between the 4297 * start of the line and the current cursor position. 4298 */ 4299 static KT_KEY_FN(gl_backward_kill_line) 4300 { 4301 /* 4302 * How many characters are to be deleted from before the cursor? 4303 */ 4304 int nc = gl->buff_curpos - gl->insert_curpos; 4305 if (!nc) 4306 return 0; 4307 /* 4308 * Move the cursor to the start of the line, or in vi input mode, 4309 * the start of the sub-line at which insertion started, and delete 4310 * up to the old cursor position. 4311 */ 4312 return gl_place_cursor(gl, gl->insert_curpos) || 4313 gl_delete_chars(gl, nc, gl->editor == GL_EMACS_MODE || gl->vi.command); 4314 } 4315 4316 /*....................................................................... 4317 * This is an action function which moves the cursor forward by a word. 4318 */ 4319 static KT_KEY_FN(gl_forward_word) 4320 { 4321 return gl_place_cursor(gl, gl_nth_word_end_forward(gl, count) + 4322 (gl->editor==GL_EMACS_MODE)); 4323 } 4324 4325 /*....................................................................... 4326 * This is an action function which moves the cursor forward to the start 4327 * of the next word. 4328 */ 4329 static KT_KEY_FN(gl_forward_to_word) 4330 { 4331 return gl_place_cursor(gl, gl_nth_word_start_forward(gl, count)); 4332 } 4333 4334 /*....................................................................... 4335 * This is an action function which moves the cursor backward by a word. 4336 */ 4337 static KT_KEY_FN(gl_backward_word) 4338 { 4339 return gl_place_cursor(gl, gl_nth_word_start_backward(gl, count)); 4340 } 4341 4342 /*....................................................................... 4343 * Delete one or more characters, starting with the one under the cursor. 4344 * 4345 * Input: 4346 * gl GetLine * The resource object of this library. 4347 * nc int The number of characters to delete. 4348 * cut int If true, copy the characters to the cut buffer. 4349 * Output: 4350 * return int 0 - OK. 4351 * 1 - Error. 4352 */ 4353 static int gl_delete_chars(GetLine *gl, int nc, int cut) 4354 { 4355 /* 4356 * If in vi command mode, preserve the current line for potential 4357 * use by vi-undo. 4358 */ 4359 gl_save_for_undo(gl); 4360 /* 4361 * If there are fewer than nc characters following the cursor, limit 4362 * nc to the number available. 4363 */ 4364 if(gl->buff_curpos + nc > gl->ntotal) 4365 nc = gl->ntotal - gl->buff_curpos; 4366 /* 4367 * Copy the about to be deleted region to the cut buffer. 4368 */ 4369 if(cut) { 4370 memcpy(gl->cutbuf, gl->line + gl->buff_curpos, nc); 4371 gl->cutbuf[nc] = '\0'; 4372 } 4373 /* 4374 * Nothing to delete? 4375 */ 4376 if(nc <= 0) 4377 return 0; 4378 /* 4379 * In vi overwrite mode, restore any previously overwritten characters 4380 * from the undo buffer. 4381 */ 4382 if(gl->editor == GL_VI_MODE && !gl->vi.command && !gl->insert) { 4383 /* 4384 * How many of the characters being deleted can be restored from the 4385 * undo buffer? 4386 */ 4387 int nrestore = gl->buff_curpos + nc <= gl->vi.undo.ntotal ? 4388 nc : gl->vi.undo.ntotal - gl->buff_curpos; 4389 /* 4390 * Restore any available characters. 4391 */ 4392 if(nrestore > 0) { 4393 gl_buffer_string(gl, gl->vi.undo.line + gl->buff_curpos, nrestore, 4394 gl->buff_curpos); 4395 }; 4396 /* 4397 * If their were insufficient characters in the undo buffer, then this 4398 * implies that we are deleting from the end of the line, so we need 4399 * to terminate the line either where the undo buffer ran out, or if 4400 * we are deleting from beyond the end of the undo buffer, at the current 4401 * cursor position. 4402 */ 4403 if(nc != nrestore) { 4404 gl_truncate_buffer(gl, (gl->vi.undo.ntotal > gl->buff_curpos) ? 4405 gl->vi.undo.ntotal : gl->buff_curpos); 4406 }; 4407 } else { 4408 /* 4409 * Copy the remaining part of the line back over the deleted characters. 4410 */ 4411 gl_remove_from_buffer(gl, gl->buff_curpos, nc); 4412 }; 4413 /* 4414 * Redraw the remaining characters following the cursor. 4415 */ 4416 if(gl_print_string(gl, gl->line + gl->buff_curpos, '\0')) 4417 return 1; 4418 /* 4419 * Clear to the end of the terminal. 4420 */ 4421 if(gl_truncate_display(gl)) 4422 return 1; 4423 /* 4424 * Place the cursor at the start of where the deletion was performed. 4425 */ 4426 return gl_place_cursor(gl, gl->buff_curpos); 4427 } 4428 4429 /*....................................................................... 4430 * This is an action function which deletes character(s) under the 4431 * cursor without moving the cursor. 4432 */ 4433 static KT_KEY_FN(gl_forward_delete_char) 4434 { 4435 /* 4436 * Delete 'count' characters. 4437 */ 4438 return gl_delete_chars(gl, count, gl->vi.command); 4439 } 4440 4441 /*....................................................................... 4442 * This is an action function which deletes character(s) under the 4443 * cursor and moves the cursor back one character. 4444 */ 4445 static KT_KEY_FN(gl_backward_delete_char) 4446 { 4447 /* 4448 * Restrict the deletion count to the number of characters that 4449 * precede the insertion point. 4450 */ 4451 if(count > gl->buff_curpos - gl->insert_curpos) 4452 count = gl->buff_curpos - gl->insert_curpos; 4453 /* 4454 * If in vi command mode, preserve the current line for potential 4455 * use by vi-undo. 4456 */ 4457 gl_save_for_undo(gl); 4458 return gl_cursor_left(gl, count, NULL) || 4459 gl_delete_chars(gl, count, gl->vi.command); 4460 } 4461 4462 /*....................................................................... 4463 * Starting from the cursor position delete to the specified column. 4464 */ 4465 static KT_KEY_FN(gl_delete_to_column) 4466 { 4467 if (--count >= gl->buff_curpos) 4468 return gl_forward_delete_char(gl, count - gl->buff_curpos, NULL); 4469 else 4470 return gl_backward_delete_char(gl, gl->buff_curpos - count, NULL); 4471 } 4472 4473 /*....................................................................... 4474 * Starting from the cursor position delete characters to a matching 4475 * parenthesis. 4476 */ 4477 static KT_KEY_FN(gl_delete_to_parenthesis) 4478 { 4479 int curpos = gl_index_of_matching_paren(gl); 4480 if(curpos >= 0) { 4481 gl_save_for_undo(gl); 4482 if(curpos >= gl->buff_curpos) 4483 return gl_forward_delete_char(gl, curpos - gl->buff_curpos + 1, NULL); 4484 else 4485 return gl_backward_delete_char(gl, ++gl->buff_curpos - curpos + 1, NULL); 4486 }; 4487 return 0; 4488 } 4489 4490 /*....................................................................... 4491 * This is an action function which deletes from the cursor to the end 4492 * of the word that the cursor is either in or precedes. 4493 */ 4494 static KT_KEY_FN(gl_forward_delete_word) 4495 { 4496 /* 4497 * If in vi command mode, preserve the current line for potential 4498 * use by vi-undo. 4499 */ 4500 gl_save_for_undo(gl); 4501 /* 4502 * In emacs mode delete to the end of the word. In vi mode delete to the 4503 * start of the net word. 4504 */ 4505 if(gl->editor == GL_EMACS_MODE) { 4506 return gl_delete_chars(gl, 4507 gl_nth_word_end_forward(gl,count) - gl->buff_curpos + 1, 1); 4508 } else { 4509 return gl_delete_chars(gl, 4510 gl_nth_word_start_forward(gl,count) - gl->buff_curpos, 4511 gl->vi.command); 4512 }; 4513 } 4514 4515 /*....................................................................... 4516 * This is an action function which deletes the word that precedes the 4517 * cursor. 4518 */ 4519 static KT_KEY_FN(gl_backward_delete_word) 4520 { 4521 /* 4522 * Keep a record of the current cursor position. 4523 */ 4524 int buff_curpos = gl->buff_curpos; 4525 /* 4526 * If in vi command mode, preserve the current line for potential 4527 * use by vi-undo. 4528 */ 4529 gl_save_for_undo(gl); 4530 /* 4531 * Move back 'count' words. 4532 */ 4533 if(gl_backward_word(gl, count, NULL)) 4534 return 1; 4535 /* 4536 * Delete from the new cursor position to the original one. 4537 */ 4538 return gl_delete_chars(gl, buff_curpos - gl->buff_curpos, 4539 gl->editor == GL_EMACS_MODE || gl->vi.command); 4540 } 4541 4542 /*....................................................................... 4543 * Searching in a given direction, delete to the count'th 4544 * instance of a specified or queried character, in the input line. 4545 * 4546 * Input: 4547 * gl GetLine * The getline resource object. 4548 * count int The number of times to search. 4549 * c char The character to be searched for, or '\0' if 4550 * the character should be read from the user. 4551 * forward int True if searching forward. 4552 * onto int True if the search should end on top of the 4553 * character, false if the search should stop 4554 * one character before the character in the 4555 * specified search direction. 4556 * change int If true, this function is being called upon 4557 * to do a vi change command, in which case the 4558 * user will be left in insert mode after the 4559 * deletion. 4560 * Output: 4561 * return int 0 - OK. 4562 * 1 - Error. 4563 */ 4564 static int gl_delete_find(GetLine *gl, int count, char c, int forward, 4565 int onto, int change) 4566 { 4567 /* 4568 * Search for the character, and abort the deletion if not found. 4569 */ 4570 int pos = gl_find_char(gl, count, forward, onto, c); 4571 if(pos < 0) 4572 return 0; 4573 /* 4574 * If in vi command mode, preserve the current line for potential 4575 * use by vi-undo. 4576 */ 4577 gl_save_for_undo(gl); 4578 /* 4579 * Allow the cursor to be at the end of the line if this is a change 4580 * command. 4581 */ 4582 if(change) 4583 gl->vi.command = 0; 4584 /* 4585 * Delete the appropriate span of characters. 4586 */ 4587 if(forward) { 4588 if(gl_delete_chars(gl, pos - gl->buff_curpos + 1, 1)) 4589 return 1; 4590 } else { 4591 int buff_curpos = gl->buff_curpos; 4592 if(gl_place_cursor(gl, pos) || 4593 gl_delete_chars(gl, buff_curpos - gl->buff_curpos, 1)) 4594 return 1; 4595 }; 4596 /* 4597 * If this is a change operation, switch the insert mode. 4598 */ 4599 if(change && gl_vi_insert(gl, 0, NULL)) 4600 return 1; 4601 return 0; 4602 } 4603 4604 /*....................................................................... 4605 * This is an action function which deletes forward from the cursor up to and 4606 * including a specified character. 4607 */ 4608 static KT_KEY_FN(gl_forward_delete_find) 4609 { 4610 return gl_delete_find(gl, count, '\0', 1, 1, 0); 4611 } 4612 4613 /*....................................................................... 4614 * This is an action function which deletes backward from the cursor back to 4615 * and including a specified character. 4616 */ 4617 static KT_KEY_FN(gl_backward_delete_find) 4618 { 4619 return gl_delete_find(gl, count, '\0', 0, 1, 0); 4620 } 4621 4622 /*....................................................................... 4623 * This is an action function which deletes forward from the cursor up to but 4624 * not including a specified character. 4625 */ 4626 static KT_KEY_FN(gl_forward_delete_to) 4627 { 4628 return gl_delete_find(gl, count, '\0', 1, 0, 0); 4629 } 4630 4631 /*....................................................................... 4632 * This is an action function which deletes backward from the cursor back to 4633 * but not including a specified character. 4634 */ 4635 static KT_KEY_FN(gl_backward_delete_to) 4636 { 4637 return gl_delete_find(gl, count, '\0', 0, 0, 0); 4638 } 4639 4640 /*....................................................................... 4641 * This is an action function which deletes to a character specified by a 4642 * previous search. 4643 */ 4644 static KT_KEY_FN(gl_delete_refind) 4645 { 4646 return gl_delete_find(gl, count, gl->vi.find_char, gl->vi.find_forward, 4647 gl->vi.find_onto, 0); 4648 } 4649 4650 /*....................................................................... 4651 * This is an action function which deletes to a character specified by a 4652 * previous search, but in the opposite direction. 4653 */ 4654 static KT_KEY_FN(gl_delete_invert_refind) 4655 { 4656 return gl_delete_find(gl, count, gl->vi.find_char, 4657 !gl->vi.find_forward, gl->vi.find_onto, 0); 4658 } 4659 4660 /*....................................................................... 4661 * This is an action function which converts the characters in the word 4662 * following the cursor to upper case. 4663 */ 4664 static KT_KEY_FN(gl_upcase_word) 4665 { 4666 /* 4667 * Locate the count'th word ending after the cursor. 4668 */ 4669 int last = gl_nth_word_end_forward(gl, count); 4670 /* 4671 * If in vi command mode, preserve the current line for potential 4672 * use by vi-undo. 4673 */ 4674 gl_save_for_undo(gl); 4675 /* 4676 * Upcase characters from the current cursor position to 'last'. 4677 */ 4678 while(gl->buff_curpos <= last) { 4679 char *cptr = gl->line + gl->buff_curpos; 4680 /* 4681 * Convert the character to upper case? 4682 */ 4683 if(islower((int)(unsigned char) *cptr)) 4684 gl_buffer_char(gl, toupper((int) *cptr), gl->buff_curpos); 4685 gl->buff_curpos++; 4686 /* 4687 * Write the possibly modified character back. Note that for non-modified 4688 * characters we want to do this as well, so as to advance the cursor. 4689 */ 4690 if(gl_print_char(gl, *cptr, cptr[1])) 4691 return 1; 4692 }; 4693 return gl_place_cursor(gl, gl->buff_curpos); /* bounds check */ 4694 } 4695 4696 /*....................................................................... 4697 * This is an action function which converts the characters in the word 4698 * following the cursor to lower case. 4699 */ 4700 static KT_KEY_FN(gl_downcase_word) 4701 { 4702 /* 4703 * Locate the count'th word ending after the cursor. 4704 */ 4705 int last = gl_nth_word_end_forward(gl, count); 4706 /* 4707 * If in vi command mode, preserve the current line for potential 4708 * use by vi-undo. 4709 */ 4710 gl_save_for_undo(gl); 4711 /* 4712 * Upcase characters from the current cursor position to 'last'. 4713 */ 4714 while(gl->buff_curpos <= last) { 4715 char *cptr = gl->line + gl->buff_curpos; 4716 /* 4717 * Convert the character to upper case? 4718 */ 4719 if(isupper((int)(unsigned char) *cptr)) 4720 gl_buffer_char(gl, tolower((int) *cptr), gl->buff_curpos); 4721 gl->buff_curpos++; 4722 /* 4723 * Write the possibly modified character back. Note that for non-modified 4724 * characters we want to do this as well, so as to advance the cursor. 4725 */ 4726 if(gl_print_char(gl, *cptr, cptr[1])) 4727 return 1; 4728 }; 4729 return gl_place_cursor(gl, gl->buff_curpos); /* bounds check */ 4730 } 4731 4732 /*....................................................................... 4733 * This is an action function which converts the first character of the 4734 * following word to upper case, in order to capitalize the word, and 4735 * leaves the cursor at the end of the word. 4736 */ 4737 static KT_KEY_FN(gl_capitalize_word) 4738 { 4739 char *cptr; /* &gl->line[gl->buff_curpos] */ 4740 int first; /* True for the first letter of the word */ 4741 int i; 4742 /* 4743 * Keep a record of the current insert mode and the cursor position. 4744 */ 4745 int insert = gl->insert; 4746 /* 4747 * If in vi command mode, preserve the current line for potential 4748 * use by vi-undo. 4749 */ 4750 gl_save_for_undo(gl); 4751 /* 4752 * We want to overwrite the modified word. 4753 */ 4754 gl->insert = 0; 4755 /* 4756 * Capitalize 'count' words. 4757 */ 4758 for(i=0; i<count && gl->buff_curpos < gl->ntotal; i++) { 4759 int pos = gl->buff_curpos; 4760 /* 4761 * If we are not already within a word, skip to the start of the word. 4762 */ 4763 for(cptr = gl->line + pos ; pos<gl->ntotal && !gl_is_word_char((int) *cptr); 4764 pos++, cptr++) 4765 ; 4766 /* 4767 * Move the cursor to the new position. 4768 */ 4769 if(gl_place_cursor(gl, pos)) 4770 return 1; 4771 /* 4772 * While searching for the end of the word, change lower case letters 4773 * to upper case. 4774 */ 4775 for(first=1; gl->buff_curpos<gl->ntotal && gl_is_word_char((int) *cptr); 4776 gl->buff_curpos++, cptr++) { 4777 /* 4778 * Convert the character to upper case? 4779 */ 4780 if(first) { 4781 if(islower((int)(unsigned char) *cptr)) 4782 gl_buffer_char(gl, toupper((int) *cptr), cptr - gl->line); 4783 } else { 4784 if(isupper((int)(unsigned char) *cptr)) 4785 gl_buffer_char(gl, tolower((int) *cptr), cptr - gl->line); 4786 }; 4787 first = 0; 4788 /* 4789 * Write the possibly modified character back. Note that for non-modified 4790 * characters we want to do this as well, so as to advance the cursor. 4791 */ 4792 if(gl_print_char(gl, *cptr, cptr[1])) 4793 return 1; 4794 }; 4795 }; 4796 /* 4797 * Restore the insertion mode. 4798 */ 4799 gl->insert = insert; 4800 return gl_place_cursor(gl, gl->buff_curpos); /* bounds check */ 4801 } 4802 4803 /*....................................................................... 4804 * This is an action function which redraws the current line. 4805 */ 4806 static KT_KEY_FN(gl_redisplay) 4807 { 4808 /* 4809 * Keep a record of the current cursor position. 4810 */ 4811 int buff_curpos = gl->buff_curpos; 4812 /* 4813 * Do nothing if there is no line to be redisplayed. 4814 */ 4815 if(gl->endline) 4816 return 0; 4817 /* 4818 * Erase the current input line. 4819 */ 4820 if(gl_erase_line(gl)) 4821 return 1; 4822 /* 4823 * Display the current prompt. 4824 */ 4825 if(gl_display_prompt(gl)) 4826 return 1; 4827 /* 4828 * Render the part of the line that the user has typed in so far. 4829 */ 4830 if(gl_print_string(gl, gl->line, '\0')) 4831 return 1; 4832 /* 4833 * Restore the cursor position. 4834 */ 4835 if(gl_place_cursor(gl, buff_curpos)) 4836 return 1; 4837 /* 4838 * Mark the redisplay operation as having been completed. 4839 */ 4840 gl->redisplay = 0; 4841 /* 4842 * Flush the redisplayed line to the terminal. 4843 */ 4844 return gl_flush_output(gl); 4845 } 4846 4847 /*....................................................................... 4848 * This is an action function which clears the display and redraws the 4849 * input line from the home position. 4850 */ 4851 static KT_KEY_FN(gl_clear_screen) 4852 { 4853 /* 4854 * Home the cursor and clear from there to the end of the display. 4855 */ 4856 if(gl_print_control_sequence(gl, gl->nline, gl->home) || 4857 gl_print_control_sequence(gl, gl->nline, gl->clear_eod)) 4858 return 1; 4859 /* 4860 * The input line is no longer displayed. 4861 */ 4862 gl_line_erased(gl); 4863 /* 4864 * Arrange for the input line to be redisplayed. 4865 */ 4866 gl_queue_redisplay(gl); 4867 return 0; 4868 } 4869 4870 /*....................................................................... 4871 * This is an action function which swaps the character under the cursor 4872 * with the character to the left of the cursor. 4873 */ 4874 static KT_KEY_FN(gl_transpose_chars) 4875 { 4876 char from[3]; /* The original string of 2 characters */ 4877 char swap[3]; /* The swapped string of two characters */ 4878 /* 4879 * If we are at the beginning or end of the line, there aren't two 4880 * characters to swap. 4881 */ 4882 if(gl->buff_curpos < 1 || gl->buff_curpos >= gl->ntotal) 4883 return 0; 4884 /* 4885 * If in vi command mode, preserve the current line for potential 4886 * use by vi-undo. 4887 */ 4888 gl_save_for_undo(gl); 4889 /* 4890 * Get the original and swapped strings of the two characters. 4891 */ 4892 from[0] = gl->line[gl->buff_curpos - 1]; 4893 from[1] = gl->line[gl->buff_curpos]; 4894 from[2] = '\0'; 4895 swap[0] = gl->line[gl->buff_curpos]; 4896 swap[1] = gl->line[gl->buff_curpos - 1]; 4897 swap[2] = '\0'; 4898 /* 4899 * Move the cursor to the start of the two characters. 4900 */ 4901 if(gl_place_cursor(gl, gl->buff_curpos-1)) 4902 return 1; 4903 /* 4904 * Swap the two characters in the buffer. 4905 */ 4906 gl_buffer_char(gl, swap[0], gl->buff_curpos); 4907 gl_buffer_char(gl, swap[1], gl->buff_curpos+1); 4908 /* 4909 * If the sum of the displayed width of the two characters 4910 * in their current and final positions is the same, swapping can 4911 * be done by just overwriting with the two swapped characters. 4912 */ 4913 if(gl_displayed_string_width(gl, from, -1, gl->term_curpos) == 4914 gl_displayed_string_width(gl, swap, -1, gl->term_curpos)) { 4915 int insert = gl->insert; 4916 gl->insert = 0; 4917 if(gl_print_char(gl, swap[0], swap[1]) || 4918 gl_print_char(gl, swap[1], gl->line[gl->buff_curpos+2])) 4919 return 1; 4920 gl->insert = insert; 4921 /* 4922 * If the swapped substring has a different displayed size, we need to 4923 * redraw everything after the first of the characters. 4924 */ 4925 } else { 4926 if(gl_print_string(gl, gl->line + gl->buff_curpos, '\0') || 4927 gl_truncate_display(gl)) 4928 return 1; 4929 }; 4930 /* 4931 * Advance the cursor to the character after the swapped pair. 4932 */ 4933 return gl_place_cursor(gl, gl->buff_curpos + 2); 4934 } 4935 4936 /*....................................................................... 4937 * This is an action function which sets a mark at the current cursor 4938 * location. 4939 */ 4940 static KT_KEY_FN(gl_set_mark) 4941 { 4942 gl->buff_mark = gl->buff_curpos; 4943 return 0; 4944 } 4945 4946 /*....................................................................... 4947 * This is an action function which swaps the mark location for the 4948 * cursor location. 4949 */ 4950 static KT_KEY_FN(gl_exchange_point_and_mark) 4951 { 4952 /* 4953 * Get the old mark position, and limit to the extent of the input 4954 * line. 4955 */ 4956 int old_mark = gl->buff_mark <= gl->ntotal ? gl->buff_mark : gl->ntotal; 4957 /* 4958 * Make the current cursor position the new mark. 4959 */ 4960 gl->buff_mark = gl->buff_curpos; 4961 /* 4962 * Move the cursor to the old mark position. 4963 */ 4964 return gl_place_cursor(gl, old_mark); 4965 } 4966 4967 /*....................................................................... 4968 * This is an action function which deletes the characters between the 4969 * mark and the cursor, recording them in gl->cutbuf for later pasting. 4970 */ 4971 static KT_KEY_FN(gl_kill_region) 4972 { 4973 /* 4974 * If in vi command mode, preserve the current line for potential 4975 * use by vi-undo. 4976 */ 4977 gl_save_for_undo(gl); 4978 /* 4979 * Limit the mark to be within the line. 4980 */ 4981 if(gl->buff_mark > gl->ntotal) 4982 gl->buff_mark = gl->ntotal; 4983 /* 4984 * If there are no characters between the cursor and the mark, simply clear 4985 * the cut buffer. 4986 */ 4987 if(gl->buff_mark == gl->buff_curpos) { 4988 gl->cutbuf[0] = '\0'; 4989 return 0; 4990 }; 4991 /* 4992 * If the mark is before the cursor, swap the cursor and the mark. 4993 */ 4994 if(gl->buff_mark < gl->buff_curpos && gl_exchange_point_and_mark(gl,1,NULL)) 4995 return 1; 4996 /* 4997 * Delete the characters. 4998 */ 4999 if(gl_delete_chars(gl, gl->buff_mark - gl->buff_curpos, 1)) 5000 return 1; 5001 /* 5002 * Make the mark the same as the cursor position. 5003 */ 5004 gl->buff_mark = gl->buff_curpos; 5005 return 0; 5006 } 5007 5008 /*....................................................................... 5009 * This is an action function which records the characters between the 5010 * mark and the cursor, in gl->cutbuf for later pasting. 5011 */ 5012 static KT_KEY_FN(gl_copy_region_as_kill) 5013 { 5014 int ca, cb; /* The indexes of the first and last characters in the region */ 5015 int mark; /* The position of the mark */ 5016 /* 5017 * Get the position of the mark, limiting it to lie within the line. 5018 */ 5019 mark = gl->buff_mark > gl->ntotal ? gl->ntotal : gl->buff_mark; 5020 /* 5021 * If there are no characters between the cursor and the mark, clear 5022 * the cut buffer. 5023 */ 5024 if(mark == gl->buff_curpos) { 5025 gl->cutbuf[0] = '\0'; 5026 return 0; 5027 }; 5028 /* 5029 * Get the line indexes of the first and last characters in the region. 5030 */ 5031 if(mark < gl->buff_curpos) { 5032 ca = mark; 5033 cb = gl->buff_curpos - 1; 5034 } else { 5035 ca = gl->buff_curpos; 5036 cb = mark - 1; 5037 }; 5038 /* 5039 * Copy the region to the cut buffer. 5040 */ 5041 memcpy(gl->cutbuf, gl->line + ca, cb + 1 - ca); 5042 gl->cutbuf[cb + 1 - ca] = '\0'; 5043 return 0; 5044 } 5045 5046 /*....................................................................... 5047 * This is an action function which inserts the contents of the cut 5048 * buffer at the current cursor location. 5049 */ 5050 static KT_KEY_FN(gl_yank) 5051 { 5052 int i; 5053 /* 5054 * Set the mark at the current location. 5055 */ 5056 gl->buff_mark = gl->buff_curpos; 5057 /* 5058 * Do nothing else if the cut buffer is empty. 5059 */ 5060 if(gl->cutbuf[0] == '\0') 5061 return gl_ring_bell(gl, 1, NULL); 5062 /* 5063 * If in vi command mode, preserve the current line for potential 5064 * use by vi-undo. 5065 */ 5066 gl_save_for_undo(gl); 5067 /* 5068 * Insert the string count times. 5069 */ 5070 for(i=0; i<count; i++) { 5071 if(gl_add_string_to_line(gl, gl->cutbuf)) 5072 return 1; 5073 }; 5074 /* 5075 * gl_add_string_to_line() leaves the cursor after the last character that 5076 * was pasted, whereas vi leaves the cursor over the last character pasted. 5077 */ 5078 if(gl->editor == GL_VI_MODE && gl_cursor_left(gl, 1, NULL)) 5079 return 1; 5080 return 0; 5081 } 5082 5083 /*....................................................................... 5084 * This is an action function which inserts the contents of the cut 5085 * buffer one character beyond the current cursor location. 5086 */ 5087 static KT_KEY_FN(gl_append_yank) 5088 { 5089 int was_command = gl->vi.command; 5090 int i; 5091 /* 5092 * If the cut buffer is empty, ring the terminal bell. 5093 */ 5094 if(gl->cutbuf[0] == '\0') 5095 return gl_ring_bell(gl, 1, NULL); 5096 /* 5097 * Set the mark at the current location + 1. 5098 */ 5099 gl->buff_mark = gl->buff_curpos + 1; 5100 /* 5101 * If in vi command mode, preserve the current line for potential 5102 * use by vi-undo. 5103 */ 5104 gl_save_for_undo(gl); 5105 /* 5106 * Arrange to paste the text in insert mode after the current character. 5107 */ 5108 if(gl_vi_append(gl, 0, NULL)) 5109 return 1; 5110 /* 5111 * Insert the string count times. 5112 */ 5113 for(i=0; i<count; i++) { 5114 if(gl_add_string_to_line(gl, gl->cutbuf)) 5115 return 1; 5116 }; 5117 /* 5118 * Switch back to command mode if necessary. 5119 */ 5120 if(was_command) 5121 gl_vi_command_mode(gl); 5122 return 0; 5123 } 5124 5125 /*....................................................................... 5126 * Attempt to ask the terminal for its current size. On systems that 5127 * don't support the TIOCWINSZ ioctl() for querying the terminal size, 5128 * the current values of gl->ncolumn and gl->nrow are returned. 5129 * 5130 * Input: 5131 * gl GetLine * The resource object of gl_get_line(). 5132 * Input/Output: 5133 * ncolumn int * The number of columns will be assigned to *ncolumn. 5134 * nline int * The number of lines will be assigned to *nline. 5135 */ 5136 static void gl_query_size(GetLine *gl, int *ncolumn, int *nline) 5137 { 5138 #ifdef TIOCGWINSZ 5139 /* 5140 * Query the new terminal window size. Ignore invalid responses. 5141 */ 5142 struct winsize size; 5143 if(ioctl(gl->output_fd, TIOCGWINSZ, &size) == 0 && 5144 size.ws_row > 0 && size.ws_col > 0) { 5145 *ncolumn = size.ws_col; 5146 *nline = size.ws_row; 5147 return; 5148 }; 5149 #endif 5150 /* 5151 * Return the existing values. 5152 */ 5153 *ncolumn = gl->ncolumn; 5154 *nline = gl->nline; 5155 return; 5156 } 5157 5158 /*....................................................................... 5159 * Query the size of the terminal, and if it has changed, redraw the 5160 * current input line accordingly. 5161 * 5162 * Input: 5163 * gl GetLine * The resource object of gl_get_line(). 5164 * Output: 5165 * return int 0 - OK. 5166 * 1 - Error. 5167 */ 5168 static int _gl_update_size(GetLine *gl) 5169 { 5170 int ncolumn, nline; /* The new size of the terminal */ 5171 /* 5172 * Query the new terminal window size. 5173 */ 5174 gl_query_size(gl, &ncolumn, &nline); 5175 /* 5176 * Update gl and the displayed line to fit the new dimensions. 5177 */ 5178 return gl_handle_tty_resize(gl, ncolumn, nline); 5179 } 5180 5181 /*....................................................................... 5182 * Redraw the current input line to account for a change in the terminal 5183 * size. Also install the new size in gl. 5184 * 5185 * Input: 5186 * gl GetLine * The resource object of gl_get_line(). 5187 * ncolumn int The new number of columns. 5188 * nline int The new number of lines. 5189 * Output: 5190 * return int 0 - OK. 5191 * 1 - Error. 5192 */ 5193 static int gl_handle_tty_resize(GetLine *gl, int ncolumn, int nline) 5194 { 5195 /* 5196 * If the input device isn't a terminal, just record the new size. 5197 */ 5198 if(!gl->is_term) { 5199 gl->nline = nline; 5200 gl->ncolumn = ncolumn; 5201 /* 5202 * Has the size actually changed? 5203 */ 5204 } else if(ncolumn != gl->ncolumn || nline != gl->nline) { 5205 /* 5206 * If we are currently editing a line, erase it. 5207 */ 5208 if(gl_erase_line(gl)) 5209 return 1; 5210 /* 5211 * Update the recorded window size. 5212 */ 5213 gl->nline = nline; 5214 gl->ncolumn = ncolumn; 5215 /* 5216 * Arrange for the input line to be redrawn before the next character 5217 * is read from the terminal. 5218 */ 5219 gl_queue_redisplay(gl); 5220 }; 5221 return 0; 5222 } 5223 5224 /*....................................................................... 5225 * This is the action function that recalls the previous line in the 5226 * history buffer. 5227 */ 5228 static KT_KEY_FN(gl_up_history) 5229 { 5230 /* 5231 * In vi mode, switch to command mode, since the user is very 5232 * likely to want to move around newly recalled lines. 5233 */ 5234 gl_vi_command_mode(gl); 5235 /* 5236 * Forget any previous recall session. 5237 */ 5238 gl->preload_id = 0; 5239 /* 5240 * Record the key sequence number of this search action. 5241 */ 5242 gl->last_search = gl->keyseq_count; 5243 /* 5244 * We don't want a search prefix for this function. 5245 */ 5246 if(_glh_search_prefix(gl->glh, gl->line, 0)) { 5247 _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG); 5248 return 1; 5249 }; 5250 /* 5251 * Recall the count'th next older line in the history list. If the first one 5252 * fails we can return since nothing has changed, otherwise we must continue 5253 * and update the line state. 5254 */ 5255 if(_glh_find_backwards(gl->glh, gl->line, gl->linelen+1) == NULL) 5256 return 0; 5257 while(--count && _glh_find_backwards(gl->glh, gl->line, gl->linelen+1)) 5258 ; 5259 /* 5260 * Accomodate the new contents of gl->line[]. 5261 */ 5262 gl_update_buffer(gl); 5263 /* 5264 * Arrange to have the cursor placed at the end of the new line. 5265 */ 5266 gl->buff_curpos = gl->ntotal; 5267 /* 5268 * Erase and display the new line. 5269 */ 5270 gl_queue_redisplay(gl); 5271 return 0; 5272 } 5273 5274 /*....................................................................... 5275 * This is the action function that recalls the next line in the 5276 * history buffer. 5277 */ 5278 static KT_KEY_FN(gl_down_history) 5279 { 5280 /* 5281 * In vi mode, switch to command mode, since the user is very 5282 * likely to want to move around newly recalled lines. 5283 */ 5284 gl_vi_command_mode(gl); 5285 /* 5286 * Record the key sequence number of this search action. 5287 */ 5288 gl->last_search = gl->keyseq_count; 5289 /* 5290 * If no search is currently in progress continue a previous recall 5291 * session from a previous entered line if possible. 5292 */ 5293 if(_glh_line_id(gl->glh, 0) == 0 && gl->preload_id) { 5294 _glh_recall_line(gl->glh, gl->preload_id, gl->line, gl->linelen+1); 5295 gl->preload_id = 0; 5296 } else { 5297 /* 5298 * We don't want a search prefix for this function. 5299 */ 5300 if(_glh_search_prefix(gl->glh, gl->line, 0)) { 5301 _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG); 5302 return 1; 5303 }; 5304 /* 5305 * Recall the count'th next newer line in the history list. If the first one 5306 * fails we can return since nothing has changed otherwise we must continue 5307 * and update the line state. 5308 */ 5309 if(_glh_find_forwards(gl->glh, gl->line, gl->linelen+1) == NULL) 5310 return 0; 5311 while(--count && _glh_find_forwards(gl->glh, gl->line, gl->linelen+1)) 5312 ; 5313 }; 5314 /* 5315 * Accomodate the new contents of gl->line[]. 5316 */ 5317 gl_update_buffer(gl); 5318 /* 5319 * Arrange to have the cursor placed at the end of the new line. 5320 */ 5321 gl->buff_curpos = gl->ntotal; 5322 /* 5323 * Erase and display the new line. 5324 */ 5325 gl_queue_redisplay(gl); 5326 return 0; 5327 } 5328 5329 /*....................................................................... 5330 * This is the action function that recalls the previous line in the 5331 * history buffer whos prefix matches the characters that currently 5332 * precede the cursor. By setting count=-1, this can be used internally 5333 * to force searching for the prefix used in the last search. 5334 */ 5335 static KT_KEY_FN(gl_history_search_backward) 5336 { 5337 /* 5338 * In vi mode, switch to command mode, since the user is very 5339 * likely to want to move around newly recalled lines. 5340 */ 5341 gl_vi_command_mode(gl); 5342 /* 5343 * Forget any previous recall session. 5344 */ 5345 gl->preload_id = 0; 5346 /* 5347 * Record the key sequence number of this search action. 5348 */ 5349 gl->last_search = gl->keyseq_count; 5350 /* 5351 * If a prefix search isn't already in progress, replace the search 5352 * prefix to the string that precedes the cursor. In vi command mode 5353 * include the character that is under the cursor in the string. If 5354 * count<0 keep the previous search prefix regardless, so as to force 5355 * a repeat search even if the last command wasn't a history command. 5356 */ 5357 if(count >= 0 && !_glh_search_active(gl->glh) && 5358 _glh_search_prefix(gl->glh, gl->line, gl->buff_curpos + 5359 (gl->editor==GL_VI_MODE && gl->ntotal>0))) { 5360 _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG); 5361 return 1; 5362 }; 5363 /* 5364 * Search backwards for a match to the part of the line which precedes the 5365 * cursor. 5366 */ 5367 if(_glh_find_backwards(gl->glh, gl->line, gl->linelen+1) == NULL) 5368 return 0; 5369 /* 5370 * Accomodate the new contents of gl->line[]. 5371 */ 5372 gl_update_buffer(gl); 5373 /* 5374 * Arrange to have the cursor placed at the end of the new line. 5375 */ 5376 gl->buff_curpos = gl->ntotal; 5377 /* 5378 * Erase and display the new line. 5379 */ 5380 gl_queue_redisplay(gl); 5381 return 0; 5382 } 5383 5384 /*....................................................................... 5385 * This is the action function that recalls the previous line in the 5386 * history buffer who's prefix matches that specified in an earlier call 5387 * to gl_history_search_backward() or gl_history_search_forward(). 5388 */ 5389 static KT_KEY_FN(gl_history_re_search_backward) 5390 { 5391 return gl_history_search_backward(gl, -1, NULL); 5392 } 5393 5394 /*....................................................................... 5395 * This is the action function that recalls the next line in the 5396 * history buffer who's prefix matches that specified in the earlier call 5397 * to gl_history_search_backward) which started the history search. 5398 * By setting count=-1, this can be used internally to force searching 5399 * for the prefix used in the last search. 5400 */ 5401 static KT_KEY_FN(gl_history_search_forward) 5402 { 5403 /* 5404 * In vi mode, switch to command mode, since the user is very 5405 * likely to want to move around newly recalled lines. 5406 */ 5407 gl_vi_command_mode(gl); 5408 /* 5409 * Record the key sequence number of this search action. 5410 */ 5411 gl->last_search = gl->keyseq_count; 5412 /* 5413 * If a prefix search isn't already in progress, replace the search 5414 * prefix to the string that precedes the cursor. In vi command mode 5415 * include the character that is under the cursor in the string. If 5416 * count<0 keep the previous search prefix regardless, so as to force 5417 * a repeat search even if the last command wasn't a history command. 5418 */ 5419 if(count >= 0 && !_glh_search_active(gl->glh) && 5420 _glh_search_prefix(gl->glh, gl->line, gl->buff_curpos + 5421 (gl->editor==GL_VI_MODE && gl->ntotal>0))) { 5422 _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG); 5423 return 1; 5424 }; 5425 /* 5426 * Search forwards for the next matching line. 5427 */ 5428 if(_glh_find_forwards(gl->glh, gl->line, gl->linelen+1) == NULL) 5429 return 0; 5430 /* 5431 * Accomodate the new contents of gl->line[]. 5432 */ 5433 gl_update_buffer(gl); 5434 /* 5435 * Arrange for the cursor to be placed at the end of the new line. 5436 */ 5437 gl->buff_curpos = gl->ntotal; 5438 /* 5439 * Erase and display the new line. 5440 */ 5441 gl_queue_redisplay(gl); 5442 return 0; 5443 } 5444 5445 /*....................................................................... 5446 * This is the action function that recalls the next line in the 5447 * history buffer who's prefix matches that specified in an earlier call 5448 * to gl_history_search_backward() or gl_history_search_forward(). 5449 */ 5450 static KT_KEY_FN(gl_history_re_search_forward) 5451 { 5452 return gl_history_search_forward(gl, -1, NULL); 5453 } 5454 5455 #ifdef HIDE_FILE_SYSTEM 5456 /*....................................................................... 5457 * The following function is used as the default completion handler when 5458 * the filesystem is to be hidden. It simply reports no completions. 5459 */ 5460 static CPL_MATCH_FN(gl_no_completions) 5461 { 5462 return 0; 5463 } 5464 #endif 5465 5466 /*....................................................................... 5467 * This is the tab completion function that completes the filename that 5468 * precedes the cursor position. Its callback data argument must be a 5469 * pointer to a GlCplCallback containing the completion callback function 5470 * and its callback data, or NULL to use the builtin filename completer. 5471 */ 5472 static KT_KEY_FN(gl_complete_word) 5473 { 5474 CplMatches *matches; /* The possible completions */ 5475 int suffix_len; /* The length of the completion extension */ 5476 int cont_len; /* The length of any continuation suffix */ 5477 int nextra; /* The number of characters being added to the */ 5478 /* total length of the line. */ 5479 int buff_pos; /* The buffer index at which the completion is */ 5480 /* to be inserted. */ 5481 int waserr = 0; /* True after errors */ 5482 /* 5483 * Get the container of the completion callback and its callback data. 5484 */ 5485 GlCplCallback *cb = data ? (GlCplCallback *) data : &gl->cplfn; 5486 /* 5487 * In vi command mode, switch to append mode so that the character under 5488 * the cursor is included in the completion (otherwise people can't 5489 * complete at the end of the line). 5490 */ 5491 if(gl->vi.command && gl_vi_append(gl, 0, NULL)) 5492 return 1; 5493 /* 5494 * Get the cursor position at which the completion is to be inserted. 5495 */ 5496 buff_pos = gl->buff_curpos; 5497 /* 5498 * Perform the completion. 5499 */ 5500 matches = cpl_complete_word(gl->cpl, gl->line, gl->buff_curpos, cb->data, 5501 cb->fn); 5502 /* 5503 * No matching completions? 5504 */ 5505 if(!matches) { 5506 waserr = gl_print_info(gl, cpl_last_error(gl->cpl), GL_END_INFO); 5507 /* 5508 * Are there any completions? 5509 */ 5510 } else if(matches->nmatch >= 1) { 5511 /* 5512 * If there any ambiguous matches, report them, starting on a new line. 5513 */ 5514 if(matches->nmatch > 1 && gl->echo) { 5515 if(_gl_normal_io(gl) || 5516 _cpl_output_completions(matches, gl_write_fn, gl, gl->ncolumn)) 5517 waserr = 1; 5518 }; 5519 /* 5520 * Get the length of the suffix and any continuation suffix to add to it. 5521 */ 5522 suffix_len = strlen(matches->suffix); 5523 cont_len = strlen(matches->cont_suffix); 5524 /* 5525 * If there is an unambiguous match, and the continuation suffix ends in 5526 * a newline, strip that newline and arrange to have getline return 5527 * after this action function returns. 5528 */ 5529 if(matches->nmatch==1 && cont_len > 0 && 5530 matches->cont_suffix[cont_len - 1] == '\n') { 5531 cont_len--; 5532 if(gl_newline(gl, 1, NULL)) 5533 waserr = 1; 5534 }; 5535 /* 5536 * Work out the number of characters that are to be added. 5537 */ 5538 nextra = suffix_len + cont_len; 5539 /* 5540 * Is there anything to be added? 5541 */ 5542 if(!waserr && nextra) { 5543 /* 5544 * Will there be space for the expansion in the line buffer? 5545 */ 5546 if(gl->ntotal + nextra < gl->linelen) { 5547 /* 5548 * Make room to insert the filename extension. 5549 */ 5550 gl_make_gap_in_buffer(gl, gl->buff_curpos, nextra); 5551 /* 5552 * Insert the filename extension. 5553 */ 5554 gl_buffer_string(gl, matches->suffix, suffix_len, gl->buff_curpos); 5555 /* 5556 * Add the terminating characters. 5557 */ 5558 gl_buffer_string(gl, matches->cont_suffix, cont_len, 5559 gl->buff_curpos + suffix_len); 5560 /* 5561 * Place the cursor position at the end of the completion. 5562 */ 5563 gl->buff_curpos += nextra; 5564 /* 5565 * If we don't have to redisplay the whole line, redisplay the part 5566 * of the line which follows the original cursor position, and place 5567 * the cursor at the end of the completion. 5568 */ 5569 if(gl->displayed) { 5570 if(gl_truncate_display(gl) || 5571 gl_print_string(gl, gl->line + buff_pos, '\0') || 5572 gl_place_cursor(gl, gl->buff_curpos)) 5573 waserr = 1; 5574 }; 5575 } else { 5576 (void) gl_print_info(gl, 5577 "Insufficient room in line for file completion.", 5578 GL_END_INFO); 5579 waserr = 1; 5580 }; 5581 }; 5582 }; 5583 /* 5584 * If any output had to be written to the terminal, then editing will 5585 * have been suspended, make sure that we are back in raw line editing 5586 * mode before returning. 5587 */ 5588 if(_gl_raw_io(gl, 1)) 5589 waserr = 1; 5590 return 0; 5591 } 5592 5593 #ifndef HIDE_FILE_SYSTEM 5594 /*....................................................................... 5595 * This is the function that expands the filename that precedes the 5596 * cursor position. It expands ~user/ expressions, $envvar expressions, 5597 * and wildcards. 5598 */ 5599 static KT_KEY_FN(gl_expand_filename) 5600 { 5601 char *start_path; /* The pointer to the start of the pathname in */ 5602 /* gl->line[]. */ 5603 FileExpansion *result; /* The results of the filename expansion */ 5604 int pathlen; /* The length of the pathname being expanded */ 5605 int length; /* The number of characters needed to display the */ 5606 /* expanded files. */ 5607 int nextra; /* The number of characters to be added */ 5608 int i,j; 5609 /* 5610 * In vi command mode, switch to append mode so that the character under 5611 * the cursor is included in the completion (otherwise people can't 5612 * complete at the end of the line). 5613 */ 5614 if(gl->vi.command && gl_vi_append(gl, 0, NULL)) 5615 return 1; 5616 /* 5617 * Locate the start of the filename that precedes the cursor position. 5618 */ 5619 start_path = _pu_start_of_path(gl->line, gl->buff_curpos); 5620 if(!start_path) 5621 return 1; 5622 /* 5623 * Get the length of the string that is to be expanded. 5624 */ 5625 pathlen = gl->buff_curpos - (start_path - gl->line); 5626 /* 5627 * Attempt to expand it. 5628 */ 5629 result = ef_expand_file(gl->ef, start_path, pathlen); 5630 /* 5631 * If there was an error, report the error on a new line. 5632 */ 5633 if(!result) 5634 return gl_print_info(gl, ef_last_error(gl->ef), GL_END_INFO); 5635 /* 5636 * If no files matched, report this as well. 5637 */ 5638 if(result->nfile == 0 || !result->exists) 5639 return gl_print_info(gl, "No files match.", GL_END_INFO); 5640 /* 5641 * If in vi command mode, preserve the current line for potential use by 5642 * vi-undo. 5643 */ 5644 gl_save_for_undo(gl); 5645 /* 5646 * Work out how much space we will need to display all of the matching 5647 * filenames, taking account of the space that we need to place between 5648 * them, and the number of additional '\' characters needed to escape 5649 * spaces, tabs and backslash characters in the individual filenames. 5650 */ 5651 length = 0; 5652 for(i=0; i<result->nfile; i++) { 5653 char *file = result->files[i]; 5654 while(*file) { 5655 int c = *file++; 5656 switch(c) { 5657 case ' ': case '\t': case '\\': case '*': case '?': case '[': 5658 length++; /* Count extra backslash characters */ 5659 }; 5660 length++; /* Count the character itself */ 5661 }; 5662 length++; /* Count the space that follows each filename */ 5663 }; 5664 /* 5665 * Work out the number of characters that are to be added. 5666 */ 5667 nextra = length - pathlen; 5668 /* 5669 * Will there be space for the expansion in the line buffer? 5670 */ 5671 if(gl->ntotal + nextra >= gl->linelen) { 5672 return gl_print_info(gl, "Insufficient room in line for file expansion.", 5673 GL_END_INFO); 5674 } else { 5675 /* 5676 * Do we need to move the part of the line that followed the unexpanded 5677 * filename? 5678 */ 5679 if(nextra > 0) { 5680 gl_make_gap_in_buffer(gl, gl->buff_curpos, nextra); 5681 } else if(nextra < 0) { 5682 gl->buff_curpos += nextra; 5683 gl_remove_from_buffer(gl, gl->buff_curpos, -nextra); 5684 }; 5685 /* 5686 * Insert the filenames, separated by spaces, and with internal spaces, 5687 * tabs and backslashes escaped with backslashes. 5688 */ 5689 for(i=0,j=start_path - gl->line; i<result->nfile; i++) { 5690 char *file = result->files[i]; 5691 while(*file) { 5692 int c = *file++; 5693 switch(c) { 5694 case ' ': case '\t': case '\\': case '*': case '?': case '[': 5695 gl_buffer_char(gl, '\\', j++); 5696 }; 5697 gl_buffer_char(gl, c, j++); 5698 }; 5699 gl_buffer_char(gl, ' ', j++); 5700 }; 5701 }; 5702 /* 5703 * Redisplay the part of the line which follows the start of 5704 * the original filename. 5705 */ 5706 if(gl_place_cursor(gl, start_path - gl->line) || 5707 gl_truncate_display(gl) || 5708 gl_print_string(gl, start_path, start_path[length])) 5709 return 1; 5710 /* 5711 * Move the cursor to the end of the expansion. 5712 */ 5713 return gl_place_cursor(gl, (start_path - gl->line) + length); 5714 } 5715 #endif 5716 5717 #ifndef HIDE_FILE_SYSTEM 5718 /*....................................................................... 5719 * This is the action function that lists glob expansions of the 5720 * filename that precedes the cursor position. It expands ~user/ 5721 * expressions, $envvar expressions, and wildcards. 5722 */ 5723 static KT_KEY_FN(gl_list_glob) 5724 { 5725 char *start_path; /* The pointer to the start of the pathname in */ 5726 /* gl->line[]. */ 5727 FileExpansion *result; /* The results of the filename expansion */ 5728 int pathlen; /* The length of the pathname being expanded */ 5729 /* 5730 * Locate the start of the filename that precedes the cursor position. 5731 */ 5732 start_path = _pu_start_of_path(gl->line, gl->buff_curpos); 5733 if(!start_path) 5734 return 1; 5735 /* 5736 * Get the length of the string that is to be expanded. 5737 */ 5738 pathlen = gl->buff_curpos - (start_path - gl->line); 5739 /* 5740 * Attempt to expand it. 5741 */ 5742 result = ef_expand_file(gl->ef, start_path, pathlen); 5743 /* 5744 * If there was an error, report it. 5745 */ 5746 if(!result) { 5747 return gl_print_info(gl, ef_last_error(gl->ef), GL_END_INFO); 5748 /* 5749 * If no files matched, report this as well. 5750 */ 5751 } else if(result->nfile == 0 || !result->exists) { 5752 return gl_print_info(gl, "No files match.", GL_END_INFO); 5753 /* 5754 * List the matching expansions. 5755 */ 5756 } else if(gl->echo) { 5757 if(gl_start_newline(gl, 1) || 5758 _ef_output_expansions(result, gl_write_fn, gl, gl->ncolumn)) 5759 return 1; 5760 gl_queue_redisplay(gl); 5761 }; 5762 return 0; 5763 } 5764 #endif 5765 5766 /*....................................................................... 5767 * Return non-zero if a character should be considered a part of a word. 5768 * 5769 * Input: 5770 * c int The character to be tested. 5771 * Output: 5772 * return int True if the character should be considered part of a word. 5773 */ 5774 static int gl_is_word_char(int c) 5775 { 5776 return isalnum((int)(unsigned char)c) || strchr(GL_WORD_CHARS, c) != NULL; 5777 } 5778 5779 /*....................................................................... 5780 * Override the builtin file-completion callback that is bound to the 5781 * "complete_word" action function. 5782 * 5783 * Input: 5784 * gl GetLine * The resource object of the command-line input 5785 * module. 5786 * data void * This is passed to match_fn() whenever it is 5787 * called. It could, for example, point to a 5788 * symbol table where match_fn() could look 5789 * for possible completions. 5790 * match_fn CplMatchFn * The function that will identify the prefix 5791 * to be completed from the input line, and 5792 * report matching symbols. 5793 * Output: 5794 * return int 0 - OK. 5795 * 1 - Error. 5796 */ 5797 int gl_customize_completion(GetLine *gl, void *data, CplMatchFn *match_fn) 5798 { 5799 sigset_t oldset; /* The signals that were blocked on entry to this function */ 5800 /* 5801 * Check the arguments. 5802 */ 5803 if(!gl || !match_fn) { 5804 if(gl) 5805 _err_record_msg(gl->err, "NULL argument", END_ERR_MSG); 5806 errno = EINVAL; 5807 return 1; 5808 }; 5809 /* 5810 * Temporarily block all signals. 5811 */ 5812 gl_mask_signals(gl, &oldset); 5813 /* 5814 * Record the new completion function and its callback data. 5815 */ 5816 gl->cplfn.fn = match_fn; 5817 gl->cplfn.data = data; 5818 /* 5819 * Restore the process signal mask before returning. 5820 */ 5821 gl_unmask_signals(gl, &oldset); 5822 return 0; 5823 } 5824 5825 /*....................................................................... 5826 * Change the terminal (or stream) that getline interacts with. 5827 * 5828 * Input: 5829 * gl GetLine * The resource object of the command-line input 5830 * module. 5831 * input_fp FILE * The stdio stream to read from. 5832 * output_fp FILE * The stdio stream to write to. 5833 * term char * The terminal type. This can be NULL if 5834 * either or both of input_fp and output_fp don't 5835 * refer to a terminal. Otherwise it should refer 5836 * to an entry in the terminal information database. 5837 * Output: 5838 * return int 0 - OK. 5839 * 1 - Error. 5840 */ 5841 int gl_change_terminal(GetLine *gl, FILE *input_fp, FILE *output_fp, 5842 const char *term) 5843 { 5844 sigset_t oldset; /* The signals that were blocked on entry to this function */ 5845 int status; /* The return status of _gl_change_terminal() */ 5846 /* 5847 * Check the arguments. 5848 */ 5849 if(!gl) { 5850 errno = EINVAL; 5851 return 1; 5852 }; 5853 /* 5854 * Block all signals. 5855 */ 5856 if(gl_mask_signals(gl, &oldset)) 5857 return 1; 5858 /* 5859 * Execute the private body of the function while signals are blocked. 5860 */ 5861 status = _gl_change_terminal(gl, input_fp, output_fp, term); 5862 /* 5863 * Restore the process signal mask. 5864 */ 5865 gl_unmask_signals(gl, &oldset); 5866 return status; 5867 } 5868 5869 /*....................................................................... 5870 * This is the private body of the gl_change_terminal() function. It 5871 * assumes that the caller has checked its arguments and blocked the 5872 * delivery of signals. 5873 */ 5874 static int _gl_change_terminal(GetLine *gl, FILE *input_fp, FILE *output_fp, 5875 const char *term) 5876 { 5877 int is_term = 0; /* True if both input_fd and output_fd are associated */ 5878 /* with a terminal. */ 5879 /* 5880 * Require that input_fp and output_fp both be valid. 5881 */ 5882 if(!input_fp || !output_fp) { 5883 gl_print_info(gl, "Can't change terminal. Bad input/output stream(s).", 5884 GL_END_INFO); 5885 return 1; 5886 }; 5887 /* 5888 * Are we displacing an existing terminal (as opposed to setting the 5889 * initial terminal)? 5890 */ 5891 if(gl->input_fd >= 0) { 5892 /* 5893 * Make sure to leave the previous terminal in a usable state. 5894 */ 5895 if(_gl_normal_io(gl)) 5896 return 1; 5897 /* 5898 * Remove the displaced terminal from the list of fds to watch. 5899 */ 5900 #ifdef HAVE_SELECT 5901 FD_CLR(gl->input_fd, &gl->rfds); 5902 #endif 5903 }; 5904 /* 5905 * Record the file descriptors and streams. 5906 */ 5907 gl->input_fp = input_fp; 5908 gl->input_fd = fileno(input_fp); 5909 gl->output_fp = output_fp; 5910 gl->output_fd = fileno(output_fp); 5911 /* 5912 * If needed, expand the record of the maximum file-descriptor that might 5913 * need to be monitored with select(). 5914 */ 5915 #ifdef HAVE_SELECT 5916 if(gl->input_fd > gl->max_fd) 5917 gl->max_fd = gl->input_fd; 5918 #endif 5919 /* 5920 * Disable terminal interaction until we have enough info to interact 5921 * with the terminal. 5922 */ 5923 gl->is_term = 0; 5924 /* 5925 * For terminal editing, we need both output_fd and input_fd to refer to 5926 * a terminal. While we can't verify that they both point to the same 5927 * terminal, we can verify that they point to terminals. 5928 */ 5929 is_term = isatty(gl->input_fd) && isatty(gl->output_fd); 5930 /* 5931 * If we are interacting with a terminal and no terminal type has been 5932 * specified, treat it as a generic ANSI terminal. 5933 */ 5934 if(is_term && !term) 5935 term = "ansi"; 5936 /* 5937 * Make a copy of the terminal type string. 5938 */ 5939 if(term != gl->term) { 5940 /* 5941 * Delete any old terminal type string. 5942 */ 5943 if(gl->term) { 5944 free(gl->term); 5945 gl->term = NULL; 5946 }; 5947 /* 5948 * Make a copy of the new terminal-type string, if any. 5949 */ 5950 if(term) { 5951 size_t termsz = strlen(term)+1; 5952 5953 gl->term = (char *) malloc(termsz); 5954 if(gl->term) 5955 strlcpy(gl->term, term, termsz); 5956 }; 5957 }; 5958 /* 5959 * Clear any terminal-specific key bindings that were taken from the 5960 * settings of the last terminal. 5961 */ 5962 _kt_clear_bindings(gl->bindings, KTB_TERM); 5963 /* 5964 * If we have a terminal install new bindings for it. 5965 */ 5966 if(is_term) { 5967 /* 5968 * Get the current settings of the terminal. 5969 */ 5970 if(tcgetattr(gl->input_fd, &gl->oldattr)) { 5971 _err_record_msg(gl->err, "tcgetattr error", END_ERR_MSG); 5972 return 1; 5973 }; 5974 /* 5975 * If we don't set this now, gl_control_strings() won't know 5976 * that it is talking to a terminal. 5977 */ 5978 gl->is_term = 1; 5979 /* 5980 * Lookup the terminal control string and size information. 5981 */ 5982 if(gl_control_strings(gl, term)) { 5983 gl->is_term = 0; 5984 return 1; 5985 }; 5986 /* 5987 * Bind terminal-specific keys. 5988 */ 5989 if(gl_bind_terminal_keys(gl)) 5990 return 1; 5991 }; 5992 /* 5993 * Assume that the caller has given us a terminal in a sane state. 5994 */ 5995 gl->io_mode = GL_NORMAL_MODE; 5996 /* 5997 * Switch into the currently configured I/O mode. 5998 */ 5999 if(_gl_io_mode(gl, gl->io_mode)) 6000 return 1; 6001 return 0; 6002 } 6003 6004 /*....................................................................... 6005 * Set up terminal-specific key bindings. 6006 * 6007 * Input: 6008 * gl GetLine * The resource object of the command-line input 6009 * module. 6010 * Output: 6011 * return int 0 - OK. 6012 * 1 - Error. 6013 */ 6014 static int gl_bind_terminal_keys(GetLine *gl) 6015 { 6016 /* 6017 * Install key-bindings for the special terminal characters. 6018 */ 6019 if(gl_bind_control_char(gl, KTB_TERM, gl->oldattr.c_cc[VINTR], 6020 "user-interrupt") || 6021 gl_bind_control_char(gl, KTB_TERM, gl->oldattr.c_cc[VQUIT], "abort") || 6022 gl_bind_control_char(gl, KTB_TERM, gl->oldattr.c_cc[VSUSP], "suspend")) 6023 return 1; 6024 /* 6025 * In vi-mode, arrange for the above characters to be seen in command 6026 * mode. 6027 */ 6028 if(gl->editor == GL_VI_MODE) { 6029 if(gl_bind_control_char(gl, KTB_TERM, MAKE_META(gl->oldattr.c_cc[VINTR]), 6030 "user-interrupt") || 6031 gl_bind_control_char(gl, KTB_TERM, MAKE_META(gl->oldattr.c_cc[VQUIT]), 6032 "abort") || 6033 gl_bind_control_char(gl, KTB_TERM, MAKE_META(gl->oldattr.c_cc[VSUSP]), 6034 "suspend")) 6035 return 1; 6036 }; 6037 /* 6038 * Non-universal special keys. 6039 */ 6040 #ifdef VLNEXT 6041 if(gl_bind_control_char(gl, KTB_TERM, gl->oldattr.c_cc[VLNEXT], 6042 "literal-next")) 6043 return 1; 6044 #else 6045 if(_kt_set_keybinding(gl->bindings, KTB_TERM, "^V", "literal-next")) { 6046 _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG); 6047 return 1; 6048 }; 6049 #endif 6050 /* 6051 * Bind action functions to the terminal-specific arrow keys 6052 * looked up by gl_control_strings(). 6053 */ 6054 if(_gl_bind_arrow_keys(gl)) 6055 return 1; 6056 return 0; 6057 } 6058 6059 /*....................................................................... 6060 * This function is normally bound to control-D. When it is invoked within 6061 * a line it deletes the character which follows the cursor. When invoked 6062 * at the end of the line it lists possible file completions, and when 6063 * invoked on an empty line it causes gl_get_line() to return EOF. This 6064 * function emulates the one that is normally bound to control-D by tcsh. 6065 */ 6066 static KT_KEY_FN(gl_del_char_or_list_or_eof) 6067 { 6068 /* 6069 * If we have an empty line arrange to return EOF. 6070 */ 6071 if(gl->ntotal < 1) { 6072 gl_record_status(gl, GLR_EOF, 0); 6073 return 1; 6074 /* 6075 * If we are at the end of the line list possible completions. 6076 */ 6077 } else if(gl->buff_curpos >= gl->ntotal) { 6078 return gl_list_completions(gl, 1, NULL); 6079 /* 6080 * Within the line delete the character that follows the cursor. 6081 */ 6082 } else { 6083 /* 6084 * If in vi command mode, first preserve the current line for potential use 6085 * by vi-undo. 6086 */ 6087 gl_save_for_undo(gl); 6088 /* 6089 * Delete 'count' characters. 6090 */ 6091 return gl_forward_delete_char(gl, count, NULL); 6092 }; 6093 } 6094 6095 /*....................................................................... 6096 * This function is normally bound to control-D in vi mode. When it is 6097 * invoked within a line it lists possible file completions, and when 6098 * invoked on an empty line it causes gl_get_line() to return EOF. This 6099 * function emulates the one that is normally bound to control-D by tcsh. 6100 */ 6101 static KT_KEY_FN(gl_list_or_eof) 6102 { 6103 /* 6104 * If we have an empty line arrange to return EOF. 6105 */ 6106 if(gl->ntotal < 1) { 6107 gl_record_status(gl, GLR_EOF, 0); 6108 return 1; 6109 /* 6110 * Otherwise list possible completions. 6111 */ 6112 } else { 6113 return gl_list_completions(gl, 1, NULL); 6114 }; 6115 } 6116 6117 /*....................................................................... 6118 * List possible completions of the word that precedes the cursor. The 6119 * callback data argument must either be NULL to select the default 6120 * file completion callback, or be a GlCplCallback object containing the 6121 * completion callback function to call. 6122 */ 6123 static KT_KEY_FN(gl_list_completions) 6124 { 6125 int waserr = 0; /* True after errors */ 6126 /* 6127 * Get the container of the completion callback and its callback data. 6128 */ 6129 GlCplCallback *cb = data ? (GlCplCallback *) data : &gl->cplfn; 6130 /* 6131 * Get the list of possible completions. 6132 */ 6133 CplMatches *matches = cpl_complete_word(gl->cpl, gl->line, gl->buff_curpos, 6134 cb->data, cb->fn); 6135 /* 6136 * No matching completions? 6137 */ 6138 if(!matches) { 6139 waserr = gl_print_info(gl, cpl_last_error(gl->cpl), GL_END_INFO); 6140 /* 6141 * List the matches. 6142 */ 6143 } else if(matches->nmatch > 0 && gl->echo) { 6144 if(_gl_normal_io(gl) || 6145 _cpl_output_completions(matches, gl_write_fn, gl, gl->ncolumn)) 6146 waserr = 1; 6147 }; 6148 /* 6149 * If any output had to be written to the terminal, then editing will 6150 * have been suspended, make sure that we are back in raw line editing 6151 * mode before returning. 6152 */ 6153 if(_gl_raw_io(gl, 1)) 6154 waserr = 1; 6155 return waserr; 6156 } 6157 6158 /*....................................................................... 6159 * Where the user has used the symbolic arrow-key names to specify 6160 * arrow key bindings, bind the specified action functions to the default 6161 * and terminal specific arrow key sequences. 6162 * 6163 * Input: 6164 * gl GetLine * The getline resource object. 6165 * Output: 6166 * return int 0 - OK. 6167 * 1 - Error. 6168 */ 6169 static int _gl_bind_arrow_keys(GetLine *gl) 6170 { 6171 /* 6172 * Process each of the arrow keys. 6173 */ 6174 if(_gl_rebind_arrow_key(gl, "up", gl->u_arrow, "^[[A", "^[OA") || 6175 _gl_rebind_arrow_key(gl, "down", gl->d_arrow, "^[[B", "^[OB") || 6176 _gl_rebind_arrow_key(gl, "left", gl->l_arrow, "^[[D", "^[OD") || 6177 _gl_rebind_arrow_key(gl, "right", gl->r_arrow, "^[[C", "^[OC")) 6178 return 1; 6179 return 0; 6180 } 6181 6182 /*....................................................................... 6183 * Lookup the action function of a symbolic arrow-key binding, and bind 6184 * it to the terminal-specific and default arrow-key sequences. Note that 6185 * we don't trust the terminal-specified key sequences to be correct. 6186 * The main reason for this is that on some machines the xterm terminfo 6187 * entry is for hardware X-terminals, rather than xterm terminal emulators 6188 * and the two terminal types emit different character sequences when the 6189 * their cursor keys are pressed. As a result we also supply a couple 6190 * of default key sequences. 6191 * 6192 * Input: 6193 * gl GetLine * The resource object of gl_get_line(). 6194 * name char * The symbolic name of the arrow key. 6195 * term_seq char * The terminal-specific arrow-key sequence. 6196 * def_seq1 char * The first default arrow-key sequence. 6197 * def_seq2 char * The second arrow-key sequence. 6198 * Output: 6199 * return int 0 - OK. 6200 * 1 - Error. 6201 */ 6202 static int _gl_rebind_arrow_key(GetLine *gl, const char *name, 6203 const char *term_seq, const char *def_seq1, 6204 const char *def_seq2) 6205 { 6206 KeySym *keysym; /* The binding-table entry matching the arrow-key name */ 6207 int nsym; /* The number of ambiguous matches */ 6208 /* 6209 * Lookup the key binding for the symbolic name of the arrow key. This 6210 * will either be the default action, or a user provided one. 6211 */ 6212 if(_kt_lookup_keybinding(gl->bindings, name, strlen(name), &keysym, &nsym) 6213 == KT_EXACT_MATCH) { 6214 /* 6215 * Get the action function. 6216 */ 6217 KtAction *action = keysym->actions + keysym->binder; 6218 KtKeyFn *fn = action->fn; 6219 void *data = action->data; 6220 /* 6221 * Bind this to each of the specified key sequences. 6222 */ 6223 if((term_seq && 6224 _kt_set_keyfn(gl->bindings, KTB_TERM, term_seq, fn, data)) || 6225 (def_seq1 && 6226 _kt_set_keyfn(gl->bindings, KTB_NORM, def_seq1, fn, data)) || 6227 (def_seq2 && 6228 _kt_set_keyfn(gl->bindings, KTB_NORM, def_seq2, fn, data))) { 6229 _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG); 6230 return 1; 6231 }; 6232 }; 6233 return 0; 6234 } 6235 6236 /*....................................................................... 6237 * Read getline configuration information from a given file. 6238 * 6239 * Input: 6240 * gl GetLine * The getline resource object. 6241 * filename const char * The name of the file to read configuration 6242 * information from. The contents of this file 6243 * are as described in the gl_get_line(3) man 6244 * page for the default ~/.teclarc configuration 6245 * file. 6246 * who KtBinder Who bindings are to be installed for. 6247 * Output: 6248 * return int 0 - OK. 6249 * 1 - Irrecoverable error. 6250 */ 6251 static int _gl_read_config_file(GetLine *gl, const char *filename, KtBinder who) 6252 { 6253 /* 6254 * If filesystem access is to be excluded, configuration files can't 6255 * be read. 6256 */ 6257 #ifdef WITHOUT_FILE_SYSTEM 6258 _err_record_msg(gl->err, 6259 "Can't read configuration files without filesystem access", 6260 END_ERR_MSG); 6261 errno = EINVAL; 6262 return 1; 6263 #else 6264 FileExpansion *expansion; /* The expansion of the filename */ 6265 FILE *fp; /* The opened file */ 6266 int waserr = 0; /* True if an error occurred while reading */ 6267 int lineno = 1; /* The line number being processed */ 6268 /* 6269 * Check the arguments. 6270 */ 6271 if(!gl || !filename) { 6272 if(gl) 6273 _err_record_msg(gl->err, "NULL argument(s)", END_ERR_MSG); 6274 errno = EINVAL; 6275 return 1; 6276 }; 6277 /* 6278 * Expand the filename. 6279 */ 6280 expansion = ef_expand_file(gl->ef, filename, -1); 6281 if(!expansion) { 6282 gl_print_info(gl, "Unable to expand ", filename, " (", 6283 ef_last_error(gl->ef), ").", GL_END_INFO); 6284 return 1; 6285 }; 6286 /* 6287 * Attempt to open the file. 6288 */ 6289 fp = fopen(expansion->files[0], "r"); 6290 /* 6291 * It isn't an error for there to be no configuration file. 6292 */ 6293 if(!fp) 6294 return 0; 6295 /* 6296 * Parse the contents of the file. 6297 */ 6298 while(!waserr && !feof(fp)) 6299 waserr = _gl_parse_config_line(gl, fp, glc_file_getc, filename, who, 6300 &lineno); 6301 /* 6302 * Bind action functions to the terminal-specific arrow keys. 6303 */ 6304 if(_gl_bind_arrow_keys(gl)) 6305 return 1; 6306 /* 6307 * Clean up. 6308 */ 6309 (void) fclose(fp); 6310 return waserr; 6311 #endif 6312 } 6313 6314 /*....................................................................... 6315 * Read GetLine configuration information from a string. The contents of 6316 * the string are the same as those described in the gl_get_line(3) 6317 * man page for the contents of the ~/.teclarc configuration file. 6318 */ 6319 static int _gl_read_config_string(GetLine *gl, const char *buffer, KtBinder who) 6320 { 6321 const char *bptr; /* A pointer into buffer[] */ 6322 int waserr = 0; /* True if an error occurred while reading */ 6323 int lineno = 1; /* The line number being processed */ 6324 /* 6325 * Check the arguments. 6326 */ 6327 if(!gl || !buffer) { 6328 if(gl) 6329 _err_record_msg(gl->err, "NULL argument(s)", END_ERR_MSG); 6330 errno = EINVAL; 6331 return 1; 6332 }; 6333 /* 6334 * Get a pointer to the start of the buffer. 6335 */ 6336 bptr = buffer; 6337 /* 6338 * Parse the contents of the buffer. 6339 */ 6340 while(!waserr && *bptr) 6341 waserr = _gl_parse_config_line(gl, &bptr, glc_buff_getc, "", who, &lineno); 6342 /* 6343 * Bind action functions to the terminal-specific arrow keys. 6344 */ 6345 if(_gl_bind_arrow_keys(gl)) 6346 return 1; 6347 return waserr; 6348 } 6349 6350 /*....................................................................... 6351 * Parse the next line of a getline configuration file. 6352 * 6353 * Input: 6354 * gl GetLine * The getline resource object. 6355 * stream void * The pointer representing the stream to be read 6356 * by getc_fn(). 6357 * getc_fn GlcGetcFn * A callback function which when called with 6358 * 'stream' as its argument, returns the next 6359 * unread character from the stream. 6360 * origin const char * The name of the entity being read (eg. a 6361 * file name). 6362 * who KtBinder Who bindings are to be installed for. 6363 * Input/Output: 6364 * lineno int * The line number being processed is to be 6365 * maintained in *lineno. 6366 * Output: 6367 * return int 0 - OK. 6368 * 1 - Irrecoverable error. 6369 */ 6370 static int _gl_parse_config_line(GetLine *gl, void *stream, GlcGetcFn *getc_fn, 6371 const char *origin, KtBinder who, int *lineno) 6372 { 6373 char buffer[GL_CONF_BUFLEN+1]; /* The input line buffer */ 6374 char *argv[GL_CONF_MAXARG]; /* The argument list */ 6375 int argc = 0; /* The number of arguments in argv[] */ 6376 int c; /* A character from the file */ 6377 int escaped = 0; /* True if the next character is escaped */ 6378 int i; 6379 /* 6380 * Skip spaces and tabs. 6381 */ 6382 do c = getc_fn(stream); while(c==' ' || c=='\t'); 6383 /* 6384 * Comments extend to the end of the line. 6385 */ 6386 if(c=='#') 6387 do c = getc_fn(stream); while(c != '\n' && c != EOF); 6388 /* 6389 * Ignore empty lines. 6390 */ 6391 if(c=='\n' || c==EOF) { 6392 (*lineno)++; 6393 return 0; 6394 }; 6395 /* 6396 * Record the buffer location of the start of the first argument. 6397 */ 6398 argv[argc] = buffer; 6399 /* 6400 * Read the rest of the line, stopping early if a comment is seen, or 6401 * the buffer overflows, and replacing sequences of spaces with a 6402 * '\0', and recording the thus terminated string as an argument. 6403 */ 6404 i = 0; 6405 while(i<GL_CONF_BUFLEN) { 6406 /* 6407 * Did we hit the end of the latest argument? 6408 */ 6409 if(c==EOF || (!escaped && (c==' ' || c=='\n' || c=='\t' || c=='#'))) { 6410 /* 6411 * Terminate the argument. 6412 */ 6413 buffer[i++] = '\0'; 6414 argc++; 6415 /* 6416 * Skip spaces and tabs. 6417 */ 6418 while(c==' ' || c=='\t') 6419 c = getc_fn(stream); 6420 /* 6421 * If we hit the end of the line, or the start of a comment, exit the loop. 6422 */ 6423 if(c==EOF || c=='\n' || c=='#') 6424 break; 6425 /* 6426 * Start recording the next argument. 6427 */ 6428 if(argc >= GL_CONF_MAXARG) { 6429 gl_report_config_error(gl, origin, *lineno, "Too many arguments."); 6430 do c = getc_fn(stream); while(c!='\n' && c!=EOF); /* Skip past eol */ 6431 return 0; 6432 }; 6433 argv[argc] = buffer + i; 6434 /* 6435 * The next character was preceded by spaces, so it isn't escaped. 6436 */ 6437 escaped = 0; 6438 } else { 6439 /* 6440 * If we hit an unescaped backslash, this means that we should arrange 6441 * to treat the next character like a simple alphabetical character. 6442 */ 6443 if(c=='\\' && !escaped) { 6444 escaped = 1; 6445 /* 6446 * Splice lines where the newline is escaped. 6447 */ 6448 } else if(c=='\n' && escaped) { 6449 (*lineno)++; 6450 /* 6451 * Record a normal character, preserving any preceding backslash. 6452 */ 6453 } else { 6454 if(escaped) 6455 buffer[i++] = '\\'; 6456 if(i>=GL_CONF_BUFLEN) 6457 break; 6458 escaped = 0; 6459 buffer[i++] = c; 6460 }; 6461 /* 6462 * Get the next character. 6463 */ 6464 c = getc_fn(stream); 6465 }; 6466 }; 6467 /* 6468 * Did the buffer overflow? 6469 */ 6470 if(i>=GL_CONF_BUFLEN) { 6471 gl_report_config_error(gl, origin, *lineno, "Line too long."); 6472 return 0; 6473 }; 6474 /* 6475 * The first argument should be a command name. 6476 */ 6477 if(strcmp(argv[0], "bind") == 0) { 6478 const char *action = NULL; /* A NULL action removes a keybinding */ 6479 const char *keyseq = NULL; 6480 switch(argc) { 6481 case 3: 6482 action = argv[2]; 6483 case 2: /* Note the intentional fallthrough */ 6484 keyseq = argv[1]; 6485 /* 6486 * Attempt to record the new keybinding. 6487 */ 6488 if(_kt_set_keybinding(gl->bindings, who, keyseq, action)) { 6489 gl_report_config_error(gl, origin, *lineno, 6490 _kt_last_error(gl->bindings)); 6491 }; 6492 break; 6493 default: 6494 gl_report_config_error(gl, origin, *lineno, "Wrong number of arguments."); 6495 }; 6496 } else if(strcmp(argv[0], "edit-mode") == 0) { 6497 if(argc == 2 && strcmp(argv[1], "emacs") == 0) { 6498 gl_change_editor(gl, GL_EMACS_MODE); 6499 } else if(argc == 2 && strcmp(argv[1], "vi") == 0) { 6500 gl_change_editor(gl, GL_VI_MODE); 6501 } else if(argc == 2 && strcmp(argv[1], "none") == 0) { 6502 gl_change_editor(gl, GL_NO_EDITOR); 6503 } else { 6504 gl_report_config_error(gl, origin, *lineno, 6505 "The argument of editor should be vi or emacs."); 6506 }; 6507 } else if(strcmp(argv[0], "nobeep") == 0) { 6508 gl->silence_bell = 1; 6509 } else { 6510 gl_report_config_error(gl, origin, *lineno, "Unknown command name."); 6511 }; 6512 /* 6513 * Skip any trailing comment. 6514 */ 6515 while(c != '\n' && c != EOF) 6516 c = getc_fn(stream); 6517 (*lineno)++; 6518 return 0; 6519 } 6520 6521 /*....................................................................... 6522 * This is a private function of _gl_parse_config_line() which prints 6523 * out an error message about the contents of the line, prefixed by the 6524 * name of the origin of the line and its line number. 6525 * 6526 * Input: 6527 * gl GetLine * The resource object of gl_get_line(). 6528 * origin const char * The name of the entity being read (eg. a 6529 * file name). 6530 * lineno int The line number at which the error occurred. 6531 * errmsg const char * The error message. 6532 * Output: 6533 * return int 0 - OK. 6534 * 1 - Error. 6535 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 8937 static int gl_event_handler(GetLine *gl, int fd) 8938 { 8939 #if !defined(HAVE_SELECT) 8940 return 0; 8941 #else 8942 /* 8943 * Set up a zero-second timeout. 8944 */ 8945 struct timeval zero; 8946 zero.tv_sec = zero.tv_usec = 0; 8947 /* 8948 * If at any time no external callbacks remain, quit the loop return, 8949 * so that we can simply wait in read(). This is designed as an 8950 * optimization for when no callbacks have been registered on entry to 8951 * this function, but since callbacks can delete themselves, it can 8952 * also help later. 8953 */ 8954 while(gl->fd_nodes || gl->timer.fn) { 8955 int nready; /* The number of file descriptors that are ready for I/O */ 8956 /* 8957 * Get the set of descriptors to be watched. 8958 */ 8959 fd_set rfds = gl->rfds; 8960 fd_set wfds = gl->wfds; 8961 fd_set ufds = gl->ufds; 8962 /* 8963 * Get the appropriate timeout. 8964 */ 8965 struct timeval dt = gl->timer.fn ? gl->timer.dt : zero; 8966 /* 8967 * Add the specified user-input file descriptor tot he set that is to 8968 * be watched. 8969 */ 8970 FD_SET(fd, &rfds); 8971 /* 8972 * Unblock the signals that we are watching, while select is blocked 8973 * waiting for I/O. 8974 */ 8975 gl_catch_signals(gl); 8976 /* 8977 * Wait for activity on any of the file descriptors. 8978 */ 8979 nready = select(gl->max_fd+1, &rfds, &wfds, &ufds, 8980 (gl->timer.fn || gl->io_mode==GL_SERVER_MODE) ? &dt : NULL); 8981 /* 8982 * We don't want to do a longjmp in the middle of a callback that 8983 * might be modifying global or heap data, so block all the signals 8984 * that we are trapping before executing callback functions. Note that 8985 * the caller will unblock them again when it needs to, so there is 8986 * no need to undo this before returning. 8987 */ 8988 gl_mask_signals(gl, NULL); 8989 /* 8990 * If select() returns but none of the file descriptors are reported 8991 * to have activity, then select() timed out. 8992 */ 8993 if(nready == 0) { 8994 /* 8995 * Note that in non-blocking server mode, the inactivity timer is used 8996 * to allow I/O to block for a specified amount of time, so in this 8997 * mode we return the postponed blocked status when an abort is 8998 * requested. 8999 */ 9000 if(gl_call_timeout_handler(gl)) { 9001 return 1; 9002 } else if(gl->io_mode == GL_SERVER_MODE) { 9003 gl_record_status(gl, GLR_BLOCKED, BLOCKED_ERRNO); 9004 return 1; 9005 }; 9006 /* 9007 * If nready < 0, this means an error occurred. 9008 */ 9009 } else if(nready < 0) { 9010 if(errno != EINTR) { 9011 gl_record_status(gl, GLR_ERROR, errno); 9012 return 1; 9013 }; 9014 /* 9015 * If the user-input file descriptor has data available, return. 9016 */ 9017 } else if(FD_ISSET(fd, &rfds)) { 9018 return 0; 9019 /* 9020 * Check for activity on any of the file descriptors registered by the 9021 * calling application, and call the associated callback functions. 9022 */ 9023 } else { 9024 GlFdNode *node; /* The fd event node being checked */ 9025 /* 9026 * Search the list for the file descriptor that caused select() to return. 9027 */ 9028 for(node=gl->fd_nodes; node; node=node->next) { 9029 /* 9030 * Is there urgent out of band data waiting to be read on fd? 9031 */ 9032 if(node->ur.fn && FD_ISSET(node->fd, &ufds)) { 9033 if(gl_call_fd_handler(gl, &node->ur, node->fd, GLFD_URGENT)) 9034 return 1; 9035 break; /* The callback may have changed the list of nodes */ 9036 /* 9037 * Is the fd readable? 9038 */ 9039 } else if(node->rd.fn && FD_ISSET(node->fd, &rfds)) { 9040 if(gl_call_fd_handler(gl, &node->rd, node->fd, GLFD_READ)) 9041 return 1; 9042 break; /* The callback may have changed the list of nodes */ 9043 /* 9044 * Is the fd writable? 9045 */ 9046 } else if(node->wr.fn && FD_ISSET(node->fd, &wfds)) { 9047 if(gl_call_fd_handler(gl, &node->wr, node->fd, GLFD_WRITE)) 9048 return 1; 9049 break; /* The callback may have changed the list of nodes */ 9050 }; 9051 }; 9052 }; 9053 /* 9054 * Just in case the above event handlers asked for the input line to 9055 * be redrawn, flush any pending output. 9056 */ 9057 if(gl_flush_output(gl)) 9058 return 1; 9059 }; 9060 return 0; 9061 } 9062 #endif 9063 9064 #if defined(HAVE_SELECT) 9065 /*....................................................................... 9066 * This is a private function of gl_event_handler(), used to call a 9067 * file-descriptor callback. 9068 * 9069 * Input: 9070 * gl GetLine * The resource object of gl_get_line(). 9071 * gfh GlFdHandler * The I/O handler. 9072 * fd int The file-descriptor being reported. 9073 * event GlFdEvent The I/O event being reported. 9074 * Output: 9075 * return int 0 - OK. 9076 * 1 - Error. 9077 */ 9078 static int gl_call_fd_handler(GetLine *gl, GlFdHandler *gfh, int fd, 9079 GlFdEvent event) 9080 { 9081 Termios attr; /* The terminal attributes */ 9082 int waserr = 0; /* True after any error */ 9083 /* 9084 * Re-enable conversion of newline characters to carriage-return/linefeed, 9085 * so that the callback can write to the terminal without having to do 9086 * anything special. 9087 */ 9088 if(tcgetattr(gl->input_fd, &attr)) { 9089 _err_record_msg(gl->err, "tcgetattr error", END_ERR_MSG); 9090 return 1; 9091 }; 9092 attr.c_oflag |= OPOST; 9093 while(tcsetattr(gl->input_fd, TCSADRAIN, &attr)) { 9094 if(errno != EINTR) { 9095 _err_record_msg(gl->err, "tcsetattr error", END_ERR_MSG); 9096 return 1; 9097 }; 9098 }; 9099 /* 9100 * Invoke the application's callback function. 9101 */ 9102 switch(gfh->fn(gl, gfh->data, fd, event)) { 9103 default: 9104 case GLFD_ABORT: 9105 gl_record_status(gl, GLR_FDABORT, 0); 9106 waserr = 1; 9107 break; 9108 case GLFD_REFRESH: 9109 gl_queue_redisplay(gl); 9110 break; 9111 case GLFD_CONTINUE: 9112 break; 9113 }; 9114 /* 9115 * Disable conversion of newline characters to carriage-return/linefeed. 9116 */ 9117 attr.c_oflag &= ~(OPOST); 9118 while(tcsetattr(gl->input_fd, TCSADRAIN, &attr)) { 9119 if(errno != EINTR) { 9120 _err_record_msg(gl->err, "tcsetattr error", END_ERR_MSG); 9121 return 1; 9122 }; 9123 }; 9124 return waserr; 9125 } 9126 9127 /*....................................................................... 9128 * This is a private function of gl_event_handler(), used to call a 9129 * inactivity timer callbacks. 9130 * 9131 * Input: 9132 * gl GetLine * The resource object of gl_get_line(). 9133 * Output: 9134 * return int 0 - OK. 9135 * 1 - Error. 9136 */ 9137 static int gl_call_timeout_handler(GetLine *gl) 9138 { 9139 Termios attr; /* The terminal attributes */ 9140 int waserr = 0; /* True after any error */ 9141 /* 9142 * Make sure that there is an inactivity timeout callback. 9143 */ 9144 if(!gl->timer.fn) 9145 return 0; 9146 /* 9147 * Re-enable conversion of newline characters to carriage-return/linefeed, 9148 * so that the callback can write to the terminal without having to do 9149 * anything special. 9150 */ 9151 if(tcgetattr(gl->input_fd, &attr)) { 9152 _err_record_msg(gl->err, "tcgetattr error", END_ERR_MSG); 9153 return 1; 9154 }; 9155 attr.c_oflag |= OPOST; 9156 while(tcsetattr(gl->input_fd, TCSADRAIN, &attr)) { 9157 if(errno != EINTR) { 9158 _err_record_msg(gl->err, "tcsetattr error", END_ERR_MSG); 9159 return 1; 9160 }; 9161 }; 9162 /* 9163 * Invoke the application's callback function. 9164 */ 9165 switch(gl->timer.fn(gl, gl->timer.data)) { 9166 default: 9167 case GLTO_ABORT: 9168 gl_record_status(gl, GLR_TIMEOUT, 0); 9169 waserr = 1; 9170 break; 9171 case GLTO_REFRESH: 9172 gl_queue_redisplay(gl); 9173 break; 9174 case GLTO_CONTINUE: 9175 break; 9176 }; 9177 /* 9178 * Disable conversion of newline characters to carriage-return/linefeed. 9179 */ 9180 attr.c_oflag &= ~(OPOST); 9181 while(tcsetattr(gl->input_fd, TCSADRAIN, &attr)) { 9182 if(errno != EINTR) { 9183 _err_record_msg(gl->err, "tcsetattr error", END_ERR_MSG); 9184 return 1; 9185 }; 9186 }; 9187 return waserr; 9188 } 9189 #endif /* HAVE_SELECT */ 9190 9191 /*....................................................................... 9192 * Switch history groups. History groups represent separate history 9193 * lists recorded within a single history buffer. Different groups 9194 * are distinguished by integer identifiers chosen by the calling 9195 * appplicaton. Initially new_GetLine() sets the group identifier to 9196 * 0. Whenever a new line is appended to the history list, the current 9197 * group identifier is recorded with it, and history lookups only 9198 * consider lines marked with the current group identifier. 9199 * 9200 * Input: 9201 * gl GetLine * The resource object of gl_get_line(). 9202 * id unsigned The new history group identifier. 9203 * Output: 9204 * return int 0 - OK. 9205 * 1 - Error. 9206 */ 9207 int gl_group_history(GetLine *gl, unsigned id) 9208 { 9209 sigset_t oldset; /* The signals that were blocked on entry to this function */ 9210 int status; /* The return status of this function */ 9211 /* 9212 * Check the arguments. 9213 */ 9214 if(!gl) { 9215 errno = EINVAL; 9216 return 1; 9217 }; 9218 /* 9219 * Block all signals while we install the new configuration. 9220 */ 9221 if(gl_mask_signals(gl, &oldset)) 9222 return 1; 9223 /* 9224 * If the group isn't being changed, do nothing. 9225 */ 9226 if(_glh_get_group(gl->glh) == id) { 9227 status = 0; 9228 /* 9229 * Establish the new group. 9230 */ 9231 } else if(_glh_set_group(gl->glh, id)) { 9232 _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG); 9233 status = 1; 9234 /* 9235 * Prevent history information from the previous group being 9236 * inappropriately used by the next call to gl_get_line(). 9237 */ 9238 } else { 9239 gl->preload_history = 0; 9240 gl->last_search = -1; 9241 status = 0; 9242 }; 9243 /* 9244 * Restore the process signal mask. 9245 */ 9246 gl_unmask_signals(gl, &oldset); 9247 return status; 9248 } 9249 9250 /*....................................................................... 9251 * Display the contents of the history list. 9252 * 9253 * Input: 9254 * gl GetLine * The resource object of gl_get_line(). 9255 * fp FILE * The stdio output stream to write to. 9256 * fmt const char * A format string. This containing characters to be 9257 * written verbatim, plus any of the following 9258 * format directives: 9259 * %D - The date, formatted like 2001-11-20 9260 * %T - The time of day, formatted like 23:59:59 9261 * %N - The sequential entry number of the 9262 * line in the history buffer. 9263 * %G - The number of the history group that 9264 * the line belongs to. 9265 * %% - A literal % character. 9266 * %H - The history line itself. 9267 * Note that a '\n' newline character is not 9268 * appended by default. 9269 * all_groups int If true, display history lines from all 9270 * history groups. Otherwise only display 9271 * those of the current history group. 9272 * max_lines int If max_lines is < 0, all available lines 9273 * are displayed. Otherwise only the most 9274 * recent max_lines lines will be displayed. 9275 * Output: 9276 * return int 0 - OK. 9277 * 1 - Error. 9278 */ 9279 int gl_show_history(GetLine *gl, FILE *fp, const char *fmt, int all_groups, 9280 int max_lines) 9281 { 9282 sigset_t oldset; /* The signals that were blocked on entry to this function */ 9283 int status; /* The return status of this function */ 9284 /* 9285 * Check the arguments. 9286 */ 9287 if(!gl || !fp || !fmt) { 9288 if(gl) 9289 _err_record_msg(gl->err, "NULL argument(s)", END_ERR_MSG); 9290 errno = EINVAL; 9291 return 1; 9292 }; 9293 /* 9294 * Block all signals. 9295 */ 9296 if(gl_mask_signals(gl, &oldset)) 9297 return 1; 9298 /* 9299 * Display the specified history group(s) while signals are blocked. 9300 */ 9301 status = _glh_show_history(gl->glh, _io_write_stdio, fp, fmt, all_groups, 9302 max_lines) || fflush(fp)==EOF; 9303 if(!status) 9304 _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG); 9305 /* 9306 * Restore the process signal mask. 9307 */ 9308 gl_unmask_signals(gl, &oldset); 9309 return status; 9310 } 9311 9312 /*....................................................................... 9313 * Update if necessary, and return the current size of the terminal. 9314 * 9315 * Input: 9316 * gl GetLine * The resource object of gl_get_line(). 9317 * def_ncolumn int If the number of columns in the terminal 9318 * can't be determined, substitute this number. 9319 * def_nline int If the number of lines in the terminal can't 9320 * be determined, substitute this number. 9321 * Output: 9322 * return GlTerminalSize The current terminal size. 9323 */ 9324 GlTerminalSize gl_terminal_size(GetLine *gl, int def_ncolumn, int def_nline) 9325 { 9326 GlTerminalSize size; /* The object to be returned */ 9327 sigset_t oldset; /* The signals that were blocked on entry */ 9328 /* to this function */ 9329 /* 9330 * Block all signals while accessing gl. 9331 */ 9332 gl_mask_signals(gl, &oldset); 9333 /* 9334 * Lookup/configure the terminal size. 9335 */ 9336 _gl_terminal_size(gl, def_ncolumn, def_nline, &size); 9337 /* 9338 * Restore the process signal mask before returning. 9339 */ 9340 gl_unmask_signals(gl, &oldset); 9341 return size; 9342 } 9343 9344 /*....................................................................... 9345 * This is the private body of the gl_terminal_size() function. It 9346 * assumes that the caller has checked its arguments and blocked the 9347 * delivery of signals. 9348 */ 9349 static void _gl_terminal_size(GetLine *gl, int def_ncolumn, int def_nline, 9350 GlTerminalSize *size) 9351 { 9352 const char *env; /* The value of an environment variable */ 9353 int n; /* A number read from env[] */ 9354 /* 9355 * Set the number of lines and columns to non-sensical values so that 9356 * we know later if they have been set. 9357 */ 9358 gl->nline = 0; 9359 gl->ncolumn = 0; 9360 /* 9361 * Are we reading from a terminal? 9362 */ 9363 if(gl->is_term) { 9364 /* 9365 * Ask the terminal directly if possible. 9366 */ 9367 (void) _gl_update_size(gl); 9368 /* 9369 * If gl_update_size() couldn't ask the terminal, it will have 9370 * left gl->nrow and gl->ncolumn unchanged. If these values haven't 9371 * been changed from their initial values of zero, we need to find 9372 * a different method to get the terminal size. 9373 * 9374 * If the number of lines isn't known yet, first see if the 9375 * LINES environment ariable exists and specifies a believable number. 9376 * If this doesn't work, look up the default size in the terminal 9377 * information database. 9378 */ 9379 if(gl->nline < 1) { 9380 if((env = getenv("LINES")) && (n=atoi(env)) > 0) 9381 gl->nline = n; 9382 #ifdef USE_TERMINFO 9383 else 9384 gl->nline = tigetnum((char *)"lines"); 9385 #elif defined(USE_TERMCAP) 9386 else 9387 gl->nline = tgetnum("li"); 9388 #endif 9389 }; 9390 /* 9391 * If the number of lines isn't known yet, first see if the COLUMNS 9392 * environment ariable exists and specifies a believable number. If 9393 * this doesn't work, look up the default size in the terminal 9394 * information database. 9395 */ 9396 if(gl->ncolumn < 1) { 9397 if((env = getenv("COLUMNS")) && (n=atoi(env)) > 0) 9398 gl->ncolumn = n; 9399 #ifdef USE_TERMINFO 9400 else 9401 gl->ncolumn = tigetnum((char *)"cols"); 9402 #elif defined(USE_TERMCAP) 9403 else 9404 gl->ncolumn = tgetnum("co"); 9405 #endif 9406 }; 9407 }; 9408 /* 9409 * If we still haven't been able to acquire reasonable values, substitute 9410 * the default values specified by the caller. 9411 */ 9412 if(gl->nline <= 0) 9413 gl->nline = def_nline; 9414 if(gl->ncolumn <= 0) 9415 gl->ncolumn = def_ncolumn; 9416 /* 9417 * Copy the new size into the return value. 9418 */ 9419 if(size) { 9420 size->nline = gl->nline; 9421 size->ncolumn = gl->ncolumn; 9422 }; 9423 return; 9424 } 9425 9426 /*....................................................................... 9427 * Resize or delete the history buffer. 9428 * 9429 * Input: 9430 * gl GetLine * The resource object of gl_get_line(). 9431 * bufsize size_t The number of bytes in the history buffer, or 0 9432 * to delete the buffer completely. 9433 * Output: 9434 * return int 0 - OK. 9435 * 1 - Insufficient memory (the previous buffer 9436 * will have been retained). No error message 9437 * will be displayed. 9438 */ 9439 int gl_resize_history(GetLine *gl, size_t bufsize) 9440 { 9441 sigset_t oldset; /* The signals that were blocked on entry to this function */ 9442 int status; /* The return status of this function */ 9443 /* 9444 * Check the arguments. 9445 */ 9446 if(!gl) 9447 return 1; 9448 /* 9449 * Block all signals while modifying the contents of gl. 9450 */ 9451 if(gl_mask_signals(gl, &oldset)) 9452 return 1; 9453 /* 9454 * Perform the resize while signals are blocked. 9455 */ 9456 status = _glh_resize_history(gl->glh, bufsize); 9457 if(status) 9458 _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG); 9459 /* 9460 * Restore the process signal mask before returning. 9461 */ 9462 gl_unmask_signals(gl, &oldset); 9463 return status; 9464 } 9465 9466 /*....................................................................... 9467 * Set an upper limit to the number of lines that can be recorded in the 9468 * history list, or remove a previously specified limit. 9469 * 9470 * Input: 9471 * gl GetLine * The resource object of gl_get_line(). 9472 * max_lines int The maximum number of lines to allow, or -1 to 9473 * cancel a previous limit and allow as many lines 9474 * as will fit in the current history buffer size. 9475 */ 9476 void gl_limit_history(GetLine *gl, int max_lines) 9477 { 9478 if(gl) { 9479 sigset_t oldset; /* The signals that were blocked on entry to this block */ 9480 /* 9481 * Temporarily block all signals. 9482 */ 9483 gl_mask_signals(gl, &oldset); 9484 /* 9485 * Apply the limit while signals are blocked. 9486 */ 9487 _glh_limit_history(gl->glh, max_lines); 9488 /* 9489 * Restore the process signal mask before returning. 9490 */ 9491 gl_unmask_signals(gl, &oldset); 9492 }; 9493 } 9494 9495 /*....................................................................... 9496 * Discard either all historical lines, or just those associated with the 9497 * current history group. 9498 * 9499 * Input: 9500 * gl GetLine * The resource object of gl_get_line(). 9501 * all_groups int If true, clear all of the history. If false, 9502 * clear only the stored lines associated with the 9503 * currently selected history group. 9504 */ 9505 void gl_clear_history(GetLine *gl, int all_groups) 9506 { 9507 if(gl) { 9508 sigset_t oldset; /* The signals that were blocked on entry to this block */ 9509 /* 9510 * Temporarily block all signals. 9511 */ 9512 gl_mask_signals(gl, &oldset); 9513 /* 9514 * Clear the history buffer while signals are blocked. 9515 */ 9516 _glh_clear_history(gl->glh, all_groups); 9517 /* 9518 * Restore the process signal mask before returning. 9519 */ 9520 gl_unmask_signals(gl, &oldset); 9521 }; 9522 } 9523 9524 /*....................................................................... 9525 * Temporarily enable or disable the gl_get_line() history mechanism. 9526 * 9527 * Input: 9528 * gl GetLine * The resource object of gl_get_line(). 9529 * enable int If true, turn on the history mechanism. If 9530 * false, disable it. 9531 */ 9532 void gl_toggle_history(GetLine *gl, int enable) 9533 { 9534 if(gl) { 9535 sigset_t oldset; /* The signals that were blocked on entry to this block */ 9536 /* 9537 * Temporarily block all signals. 9538 */ 9539 gl_mask_signals(gl, &oldset); 9540 /* 9541 * Change the history recording mode while signals are blocked. 9542 */ 9543 _glh_toggle_history(gl->glh, enable); 9544 /* 9545 * Restore the process signal mask before returning. 9546 */ 9547 gl_unmask_signals(gl, &oldset); 9548 }; 9549 } 9550 9551 /*....................................................................... 9552 * Lookup a history line by its sequential number of entry in the 9553 * history buffer. 9554 * 9555 * Input: 9556 * gl GetLine * The resource object of gl_get_line(). 9557 * id unsigned long The identification number of the line to 9558 * be returned, where 0 denotes the first line 9559 * that was entered in the history list, and 9560 * each subsequently added line has a number 9561 * one greater than the previous one. For 9562 * the range of lines currently in the list, 9563 * see the gl_range_of_history() function. 9564 * Input/Output: 9565 * line GlHistoryLine * A pointer to the variable in which to 9566 * return the details of the line. 9567 * Output: 9568 * return int 0 - The line is no longer in the history 9569 * list, and *line has not been changed. 9570 * 1 - The requested line can be found in 9571 * *line. Note that line->line is part 9572 * of the history buffer, so a 9573 * private copy should be made if you 9574 * wish to use it after subsequent calls 9575 * to any functions that take *gl as an 9576 * argument. 9577 */ 9578 int gl_lookup_history(GetLine *gl, unsigned long id, GlHistoryLine *line) 9579 { 9580 sigset_t oldset; /* The signals that were blocked on entry to this function */ 9581 int status; /* The return status of this function */ 9582 /* 9583 * Check the arguments. 9584 */ 9585 if(!gl) 9586 return 0; 9587 /* 9588 * Block all signals while modifying the contents of gl. 9589 */ 9590 if(gl_mask_signals(gl, &oldset)) 9591 return 1; 9592 /* 9593 * Perform the lookup while signals are blocked. 9594 */ 9595 status = _glh_lookup_history(gl->glh, (GlhLineID) id, &line->line, 9596 &line->group, &line->timestamp); 9597 if(status) 9598 _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG); 9599 /* 9600 * Restore the process signal mask before returning. 9601 */ 9602 gl_unmask_signals(gl, &oldset); 9603 return status; 9604 } 9605 9606 /*....................................................................... 9607 * Query the state of the history list. Note that any of the input/output 9608 * pointers can be specified as NULL. 9609 * 9610 * Input: 9611 * gl GetLine * The resource object of gl_get_line(). 9612 * Input/Output: 9613 * state GlHistoryState * A pointer to the variable in which to record 9614 * the return values. 9615 */ 9616 void gl_state_of_history(GetLine *gl, GlHistoryState *state) 9617 { 9618 if(gl && state) { 9619 sigset_t oldset; /* The signals that were blocked on entry to this block */ 9620 /* 9621 * Temporarily block all signals. 9622 */ 9623 gl_mask_signals(gl, &oldset); 9624 /* 9625 * Lookup the status while signals are blocked. 9626 */ 9627 _glh_state_of_history(gl->glh, &state->enabled, &state->group, 9628 &state->max_lines); 9629 /* 9630 * Restore the process signal mask before returning. 9631 */ 9632 gl_unmask_signals(gl, &oldset); 9633 }; 9634 } 9635 9636 /*....................................................................... 9637 * Query the number and range of lines in the history buffer. 9638 * 9639 * Input: 9640 * gl GetLine * The resource object of gl_get_line(). 9641 * range GlHistoryRange * A pointer to the variable in which to record 9642 * the return values. If range->nline=0, the 9643 * range of lines will be given as 0-0. 9644 */ 9645 void gl_range_of_history(GetLine *gl, GlHistoryRange *range) 9646 { 9647 if(gl && range) { 9648 sigset_t oldset; /* The signals that were blocked on entry to this block */ 9649 /* 9650 * Temporarily block all signals. 9651 */ 9652 gl_mask_signals(gl, &oldset); 9653 /* 9654 * Lookup the information while signals are blocked. 9655 */ 9656 _glh_range_of_history(gl->glh, &range->oldest, &range->newest, 9657 &range->nlines); 9658 /* 9659 * Restore the process signal mask before returning. 9660 */ 9661 gl_unmask_signals(gl, &oldset); 9662 }; 9663 } 9664 9665 /*....................................................................... 9666 * Return the size of the history buffer and the amount of the 9667 * buffer that is currently in use. 9668 * 9669 * Input: 9670 * gl GetLine * The gl_get_line() resource object. 9671 * Input/Output: 9672 * GlHistorySize size * A pointer to the variable in which to return 9673 * the results. 9674 */ 9675 void gl_size_of_history(GetLine *gl, GlHistorySize *size) 9676 { 9677 if(gl && size) { 9678 sigset_t oldset; /* The signals that were blocked on entry to this block */ 9679 /* 9680 * Temporarily block all signals. 9681 */ 9682 gl_mask_signals(gl, &oldset); 9683 /* 9684 * Lookup the information while signals are blocked. 9685 */ 9686 _glh_size_of_history(gl->glh, &size->size, &size->used); 9687 /* 9688 * Restore the process signal mask before returning. 9689 */ 9690 gl_unmask_signals(gl, &oldset); 9691 }; 9692 } 9693 9694 /*....................................................................... 9695 * This is the action function that lists the contents of the history 9696 * list. 9697 */ 9698 static KT_KEY_FN(gl_list_history) 9699 { 9700 /* 9701 * Start a new line. 9702 */ 9703 if(gl_start_newline(gl, 1)) 9704 return 1; 9705 /* 9706 * List history lines that belong to the current group. 9707 */ 9708 _glh_show_history(gl->glh, gl_write_fn, gl, "%N %T %H\r\n", 0, 9709 count<=1 ? -1 : count); 9710 /* 9711 * Arrange for the input line to be redisplayed. 9712 */ 9713 gl_queue_redisplay(gl); 9714 return 0; 9715 } 9716 9717 /*....................................................................... 9718 * Specify whether text that users type should be displayed or hidden. 9719 * In the latter case, only the prompt is displayed, and the final 9720 * input line is not archived in the history list. 9721 * 9722 * Input: 9723 * gl GetLine * The gl_get_line() resource object. 9724 * enable int 0 - Disable echoing. 9725 * 1 - Enable echoing. 9726 * -1 - Just query the mode without changing it. 9727 * Output: 9728 * return int The echoing disposition that was in effect 9729 * before this function was called: 9730 * 0 - Echoing was disabled. 9731 * 1 - Echoing was enabled. 9732 */ 9733 int gl_echo_mode(GetLine *gl, int enable) 9734 { 9735 if(gl) { 9736 sigset_t oldset; /* The signals that were blocked on entry to this block */ 9737 int was_echoing; /* The echoing disposition on entry to this function */ 9738 /* 9739 * Temporarily block all signals. 9740 */ 9741 gl_mask_signals(gl, &oldset); 9742 /* 9743 * Install the new disposition while signals are blocked. 9744 */ 9745 was_echoing = gl->echo; 9746 if(enable >= 0) 9747 gl->echo = enable; 9748 /* 9749 * Restore the process signal mask before returning. 9750 */ 9751 gl_unmask_signals(gl, &oldset); 9752 /* 9753 * Return the original echoing disposition. 9754 */ 9755 return was_echoing; 9756 }; 9757 return 1; 9758 } 9759 9760 /*....................................................................... 9761 * Display the prompt. 9762 * 9763 * Input: 9764 * gl GetLine * The resource object of gl_get_line(). 9765 * Output: 9766 * return int 0 - OK. 9767 * 1 - Error. 9768 */ 9769 static int gl_display_prompt(GetLine *gl) 9770 { 9771 const char *pptr; /* A pointer into gl->prompt[] */ 9772 unsigned old_attr=0; /* The current text display attributes */ 9773 unsigned new_attr=0; /* The requested text display attributes */ 9774 /* 9775 * Temporarily switch to echoing output characters. 9776 */ 9777 int kept_echo = gl->echo; 9778 gl->echo = 1; 9779 /* 9780 * In case the screen got messed up, send a carriage return to 9781 * put the cursor at the beginning of the current terminal line. 9782 */ 9783 if(gl_print_control_sequence(gl, 1, gl->bol)) 9784 return 1; 9785 /* 9786 * Mark the line as partially displayed. 9787 */ 9788 gl->displayed = 1; 9789 /* 9790 * Write the prompt, using the currently selected prompt style. 9791 */ 9792 switch(gl->prompt_style) { 9793 case GL_LITERAL_PROMPT: 9794 if(gl_print_string(gl, gl->prompt, '\0')) 9795 return 1; 9796 break; 9797 case GL_FORMAT_PROMPT: 9798 for(pptr=gl->prompt; *pptr; pptr++) { 9799 /* 9800 * Does the latest character appear to be the start of a directive? 9801 */ 9802 if(*pptr == '%') { 9803 /* 9804 * Check for and act on attribute changing directives. 9805 */ 9806 switch(pptr[1]) { 9807 /* 9808 * Add or remove a text attribute from the new set of attributes. 9809 */ 9810 case 'B': case 'U': case 'S': case 'P': case 'F': case 'V': 9811 case 'b': case 'u': case 's': case 'p': case 'f': case 'v': 9812 switch(*++pptr) { 9813 case 'B': /* Switch to a bold font */ 9814 new_attr |= GL_TXT_BOLD; 9815 break; 9816 case 'b': /* Switch to a non-bold font */ 9817 new_attr &= ~GL_TXT_BOLD; 9818 break; 9819 case 'U': /* Start underlining */ 9820 new_attr |= GL_TXT_UNDERLINE; 9821 break; 9822 case 'u': /* Stop underlining */ 9823 new_attr &= ~GL_TXT_UNDERLINE; 9824 break; 9825 case 'S': /* Start highlighting */ 9826 new_attr |= GL_TXT_STANDOUT; 9827 break; 9828 case 's': /* Stop highlighting */ 9829 new_attr &= ~GL_TXT_STANDOUT; 9830 break; 9831 case 'P': /* Switch to a pale font */ 9832 new_attr |= GL_TXT_DIM; 9833 break; 9834 case 'p': /* Switch to a non-pale font */ 9835 new_attr &= ~GL_TXT_DIM; 9836 break; 9837 case 'F': /* Switch to a flashing font */ 9838 new_attr |= GL_TXT_BLINK; 9839 break; 9840 case 'f': /* Switch to a steady font */ 9841 new_attr &= ~GL_TXT_BLINK; 9842 break; 9843 case 'V': /* Switch to reverse video */ 9844 new_attr |= GL_TXT_REVERSE; 9845 break; 9846 case 'v': /* Switch out of reverse video */ 9847 new_attr &= ~GL_TXT_REVERSE; 9848 break; 9849 }; 9850 continue; 9851 /* 9852 * A literal % is represented by %%. Skip the leading %. 9853 */ 9854 case '%': 9855 pptr++; 9856 break; 9857 }; 9858 }; 9859 /* 9860 * Many terminals, when asked to turn off a single text attribute, turn 9861 * them all off, so the portable way to turn one off individually is to 9862 * explicitly turn them all off, then specify those that we want from 9863 * scratch. 9864 */ 9865 if(old_attr & ~new_attr) { 9866 if(gl_print_control_sequence(gl, 1, gl->text_attr_off)) 9867 return 1; 9868 old_attr = 0; 9869 }; 9870 /* 9871 * Install new text attributes? 9872 */ 9873 if(new_attr != old_attr) { 9874 if(new_attr & GL_TXT_BOLD && !(old_attr & GL_TXT_BOLD) && 9875 gl_print_control_sequence(gl, 1, gl->bold)) 9876 return 1; 9877 if(new_attr & GL_TXT_UNDERLINE && !(old_attr & GL_TXT_UNDERLINE) && 9878 gl_print_control_sequence(gl, 1, gl->underline)) 9879 return 1; 9880 if(new_attr & GL_TXT_STANDOUT && !(old_attr & GL_TXT_STANDOUT) && 9881 gl_print_control_sequence(gl, 1, gl->standout)) 9882 return 1; 9883 if(new_attr & GL_TXT_DIM && !(old_attr & GL_TXT_DIM) && 9884 gl_print_control_sequence(gl, 1, gl->dim)) 9885 return 1; 9886 if(new_attr & GL_TXT_REVERSE && !(old_attr & GL_TXT_REVERSE) && 9887 gl_print_control_sequence(gl, 1, gl->reverse)) 9888 return 1; 9889 if(new_attr & GL_TXT_BLINK && !(old_attr & GL_TXT_BLINK) && 9890 gl_print_control_sequence(gl, 1, gl->blink)) 9891 return 1; 9892 old_attr = new_attr; 9893 }; 9894 /* 9895 * Display the latest character. 9896 */ 9897 if(gl_print_char(gl, *pptr, pptr[1])) 9898 return 1; 9899 }; 9900 /* 9901 * Turn off all text attributes now that we have finished drawing 9902 * the prompt. 9903 */ 9904 if(gl_print_control_sequence(gl, 1, gl->text_attr_off)) 9905 return 1; 9906 break; 9907 }; 9908 /* 9909 * Restore the original echo mode. 9910 */ 9911 gl->echo = kept_echo; 9912 /* 9913 * The prompt has now been displayed at least once. 9914 */ 9915 gl->prompt_changed = 0; 9916 return 0; 9917 } 9918 9919 /*....................................................................... 9920 * This function can be called from gl_get_line() callbacks to have 9921 * the prompt changed when they return. It has no effect if gl_get_line() 9922 * is not currently being invoked. 9923 * 9924 * Input: 9925 * gl GetLine * The resource object of gl_get_line(). 9926 * prompt const char * The new prompt. 9927 */ 9928 void gl_replace_prompt(GetLine *gl, const char *prompt) 9929 { 9930 if(gl) { 9931 sigset_t oldset; /* The signals that were blocked on entry to this block */ 9932 /* 9933 * Temporarily block all signals. 9934 */ 9935 gl_mask_signals(gl, &oldset); 9936 /* 9937 * Replace the prompt. 9938 */ 9939 _gl_replace_prompt(gl, prompt); 9940 /* 9941 * Restore the process signal mask before returning. 9942 */ 9943 gl_unmask_signals(gl, &oldset); 9944 }; 9945 } 9946 9947 /*....................................................................... 9948 * This is the private body of the gl_replace_prompt() function. It 9949 * assumes that the caller has checked its arguments and blocked the 9950 * delivery of signals. 9951 */ 9952 static void _gl_replace_prompt(GetLine *gl, const char *prompt) 9953 { 9954 size_t size; 9955 9956 /* 9957 * Substitute an empty prompt? 9958 */ 9959 if(!prompt) 9960 prompt = ""; 9961 /* 9962 * Gaurd against aliasing between prompt and gl->prompt. 9963 */ 9964 if(gl->prompt != prompt) { 9965 /* 9966 * Get the length of the new prompt string. 9967 */ 9968 size_t slen = strlen(prompt); 9969 /* 9970 * If needed, allocate a new buffer for the prompt string. 9971 */ 9972 size = sizeof(char) * (slen + 1); 9973 if(!gl->prompt || slen > strlen(gl->prompt)) { 9974 char *new_prompt = gl->prompt ? realloc(gl->prompt, size) : malloc(size); 9975 if(!new_prompt) 9976 return; 9977 gl->prompt = new_prompt; 9978 }; 9979 /* 9980 * Make a copy of the new prompt. 9981 */ 9982 strlcpy(gl->prompt, prompt, size); 9983 }; 9984 /* 9985 * Record the statistics of the new prompt. 9986 */ 9987 gl->prompt_len = gl_displayed_prompt_width(gl); 9988 gl->prompt_changed = 1; 9989 gl_queue_redisplay(gl); 9990 return; 9991 } 9992 9993 /*....................................................................... 9994 * Work out the length of the current prompt on the terminal, according 9995 * to the current prompt formatting style. 9996 * 9997 * Input: 9998 * gl GetLine * The resource object of this library. 9999 * Output: 10000 * return int The number of displayed characters. 10001 */ 10002 static int gl_displayed_prompt_width(GetLine *gl) 10003 { 10004 int slen=0; /* The displayed number of characters */ 10005 const char *pptr; /* A pointer into prompt[] */ 10006 /* 10007 * The length differs according to the prompt display style. 10008 */ 10009 switch(gl->prompt_style) { 10010 case GL_LITERAL_PROMPT: 10011 return gl_displayed_string_width(gl, gl->prompt, -1, 0); 10012 break; 10013 case GL_FORMAT_PROMPT: 10014 /* 10015 * Add up the length of the displayed string, while filtering out 10016 * attribute directives. 10017 */ 10018 for(pptr=gl->prompt; *pptr; pptr++) { 10019 /* 10020 * Does the latest character appear to be the start of a directive? 10021 */ 10022 if(*pptr == '%') { 10023 /* 10024 * Check for and skip attribute changing directives. 10025 */ 10026 switch(pptr[1]) { 10027 case 'B': case 'b': case 'U': case 'u': case 'S': case 's': 10028 pptr++; 10029 continue; 10030 /* 10031 * A literal % is represented by %%. Skip the leading %. 10032 */ 10033 case '%': 10034 pptr++; 10035 break; 10036 }; 10037 }; 10038 slen += gl_displayed_char_width(gl, *pptr, slen); 10039 }; 10040 break; 10041 }; 10042 return slen; 10043 } 10044 10045 /*....................................................................... 10046 * Specify whether to heed text attribute directives within prompt 10047 * strings. 10048 * 10049 * Input: 10050 * gl GetLine * The resource object of gl_get_line(). 10051 * style GlPromptStyle The style of prompt (see the definition of 10052 * GlPromptStyle in libtecla.h for details). 10053 */ 10054 void gl_prompt_style(GetLine *gl, GlPromptStyle style) 10055 { 10056 if(gl) { 10057 sigset_t oldset; /* The signals that were blocked on entry to this block */ 10058 /* 10059 * Temporarily block all signals. 10060 */ 10061 gl_mask_signals(gl, &oldset); 10062 /* 10063 * Install the new style in gl while signals are blocked. 10064 */ 10065 if(style != gl->prompt_style) { 10066 gl->prompt_style = style; 10067 gl->prompt_len = gl_displayed_prompt_width(gl); 10068 gl->prompt_changed = 1; 10069 gl_queue_redisplay(gl); 10070 }; 10071 /* 10072 * Restore the process signal mask before returning. 10073 */ 10074 gl_unmask_signals(gl, &oldset); 10075 }; 10076 } 10077 10078 /*....................................................................... 10079 * Tell gl_get_line() how to respond to a given signal. This can be used 10080 * both to override the default responses to signals that gl_get_line() 10081 * normally catches and to add new signals to the list that are to be 10082 * caught. 10083 * 10084 * Input: 10085 * gl GetLine * The resource object of gl_get_line(). 10086 * signo int The number of the signal to be caught. 10087 * flags unsigned A bitwise union of GlSignalFlags enumerators. 10088 * after GlAfterSignal What to do after the application's signal 10089 * handler has been called. 10090 * errno_value int The value to set errno to. 10091 * Output: 10092 * return int 0 - OK. 10093 * 1 - Error. 10094 */ 10095 int gl_trap_signal(GetLine *gl, int signo, unsigned flags, 10096 GlAfterSignal after, int errno_value) 10097 { 10098 sigset_t oldset; /* The signals that were blocked on entry to this function */ 10099 int status; /* The return status of this function */ 10100 /* 10101 * Check the arguments. 10102 */ 10103 if(!gl) { 10104 errno = EINVAL; 10105 return 1; 10106 }; 10107 /* 10108 * Block all signals while modifying the contents of gl. 10109 */ 10110 if(gl_mask_signals(gl, &oldset)) 10111 return 1; 10112 /* 10113 * Perform the modification while signals are blocked. 10114 */ 10115 status = _gl_trap_signal(gl, signo, flags, after, errno_value); 10116 /* 10117 * Restore the process signal mask before returning. 10118 */ 10119 gl_unmask_signals(gl, &oldset); 10120 return status; 10121 } 10122 10123 /*....................................................................... 10124 * This is the private body of the gl_trap_signal() function. It 10125 * assumes that the caller has checked its arguments and blocked the 10126 * delivery of signals. 10127 */ 10128 static int _gl_trap_signal(GetLine *gl, int signo, unsigned flags, 10129 GlAfterSignal after, int errno_value) 10130 { 10131 GlSignalNode *sig; 10132 /* 10133 * Complain if an attempt is made to trap untrappable signals. 10134 * These would otherwise cause errors later in gl_mask_signals(). 10135 */ 10136 if(0 10137 #ifdef SIGKILL 10138 || signo==SIGKILL 10139 #endif 10140 #ifdef SIGBLOCK 10141 || signo==SIGBLOCK 10142 #endif 10143 ) { 10144 return 1; 10145 }; 10146 /* 10147 * See if the signal has already been registered. 10148 */ 10149 for(sig=gl->sigs; sig && sig->signo != signo; sig = sig->next) 10150 ; 10151 /* 10152 * If the signal hasn't already been registered, allocate a node for 10153 * it. 10154 */ 10155 if(!sig) { 10156 sig = (GlSignalNode *) _new_FreeListNode(gl->sig_mem); 10157 if(!sig) 10158 return 1; 10159 /* 10160 * Add the new node to the head of the list. 10161 */ 10162 sig->next = gl->sigs; 10163 gl->sigs = sig; 10164 /* 10165 * Record the signal number. 10166 */ 10167 sig->signo = signo; 10168 /* 10169 * Create a signal set that includes just this signal. 10170 */ 10171 sigemptyset(&sig->proc_mask); 10172 if(sigaddset(&sig->proc_mask, signo) == -1) { 10173 _err_record_msg(gl->err, "sigaddset error", END_ERR_MSG); 10174 sig = (GlSignalNode *) _del_FreeListNode(gl->sig_mem, sig); 10175 return 1; 10176 }; 10177 /* 10178 * Add the signal to the bit-mask of signals being trapped. 10179 */ 10180 sigaddset(&gl->all_signal_set, signo); 10181 }; 10182 /* 10183 * Record the new signal attributes. 10184 */ 10185 sig->flags = flags; 10186 sig->after = after; 10187 sig->errno_value = errno_value; 10188 return 0; 10189 } 10190 10191 /*....................................................................... 10192 * Remove a signal from the list of signals that gl_get_line() traps. 10193 * 10194 * Input: 10195 * gl GetLine * The resource object of gl_get_line(). 10196 * signo int The number of the signal to be ignored. 10197 * Output: 10198 * return int 0 - OK. 10199 * 1 - Error. 10200 */ 10201 int gl_ignore_signal(GetLine *gl, int signo) 10202 { 10203 GlSignalNode *sig; /* The gl->sigs list node of the specified signal */ 10204 GlSignalNode *prev; /* The node that precedes sig in the list */ 10205 sigset_t oldset; /* The signals that were blocked on entry to this */ 10206 /* function. */ 10207 /* 10208 * Check the arguments. 10209 */ 10210 if(!gl) { 10211 errno = EINVAL; 10212 return 1; 10213 }; 10214 /* 10215 * Block all signals while modifying the contents of gl. 10216 */ 10217 if(gl_mask_signals(gl, &oldset)) 10218 return 1; 10219 /* 10220 * Find the node of the gl->sigs list which records the disposition 10221 * of the specified signal. 10222 */ 10223 for(prev=NULL,sig=gl->sigs; sig && sig->signo != signo; 10224 prev=sig,sig=sig->next) 10225 ; 10226 if(sig) { 10227 /* 10228 * Remove the node from the list. 10229 */ 10230 if(prev) 10231 prev->next = sig->next; 10232 else 10233 gl->sigs = sig->next; 10234 /* 10235 * Return the node to the freelist. 10236 */ 10237 sig = (GlSignalNode *) _del_FreeListNode(gl->sig_mem, sig); 10238 /* 10239 * Remove the signal from the bit-mask union of signals being trapped. 10240 */ 10241 sigdelset(&gl->all_signal_set, signo); 10242 }; 10243 /* 10244 * Restore the process signal mask before returning. 10245 */ 10246 gl_unmask_signals(gl, &oldset); 10247 return 0; 10248 } 10249 10250 /*....................................................................... 10251 * This function is called when an input line has been completed. It 10252 * appends the specified newline character, terminates the line, 10253 * records the line in the history buffer if appropriate, and positions 10254 * the terminal cursor at the start of the next line. 10255 * 10256 * Input: 10257 * gl GetLine * The resource object of gl_get_line(). 10258 * newline_char int The newline character to add to the end 10259 * of the line. 10260 * Output: 10261 * return int 0 - OK. 10262 * 1 - Error. 10263 */ 10264 static int gl_line_ended(GetLine *gl, int newline_char) 10265 { 10266 /* 10267 * If the newline character is printable, display it at the end of 10268 * the line, and add it to the input line buffer. 10269 */ 10270 if(isprint((int)(unsigned char) newline_char)) { 10271 if(gl_end_of_line(gl, 1, NULL) || gl_add_char_to_line(gl, newline_char)) 10272 return 1; 10273 } else { 10274 /* 10275 * Otherwise just append a newline character to the input line buffer. 10276 */ 10277 newline_char = '\n'; 10278 gl_buffer_char(gl, newline_char, gl->ntotal); 10279 }; 10280 /* 10281 * Add the line to the history buffer if it was entered with a 10282 * newline character. 10283 */ 10284 if(gl->echo && gl->automatic_history && newline_char=='\n') 10285 (void) _gl_append_history(gl, gl->line); 10286 /* 10287 * Except when depending on the system-provided line editing, start a new 10288 * line after the end of the line that has just been entered. 10289 */ 10290 if(gl->editor != GL_NO_EDITOR && gl_start_newline(gl, 1)) 10291 return 1; 10292 /* 10293 * Record the successful return status. 10294 */ 10295 gl_record_status(gl, GLR_NEWLINE, 0); 10296 /* 10297 * Attempt to flush any pending output. 10298 */ 10299 (void) gl_flush_output(gl); 10300 /* 10301 * The next call to gl_get_line() will write the prompt for a new line 10302 * (or continue the above flush if incomplete), so if we manage to 10303 * flush the terminal now, report that we are waiting to write to the 10304 * terminal. 10305 */ 10306 gl->pending_io = GLP_WRITE; 10307 return 0; 10308 } 10309 10310 /*....................................................................... 10311 * Return the last signal that was caught by the most recent call to 10312 * gl_get_line(), or -1 if no signals were caught. This is useful if 10313 * gl_get_line() returns errno=EINTR and you need to find out what signal 10314 * caused it to abort. 10315 * 10316 * Input: 10317 * gl GetLine * The resource object of gl_get_line(). 10318 * Output: 10319 * return int The last signal caught by the most recent 10320 * call to gl_get_line(), or -1 if no signals 10321 * were caught. 10322 */ 10323 int gl_last_signal(GetLine *gl) 10324 { 10325 int signo = -1; /* The requested signal number */ 10326 if(gl) { 10327 sigset_t oldset; /* The signals that were blocked on entry to this block */ 10328 /* 10329 * Temporarily block all signals. 10330 */ 10331 gl_mask_signals(gl, &oldset); 10332 /* 10333 * Access gl now that signals are blocked. 10334 */ 10335 signo = gl->last_signal; 10336 /* 10337 * Restore the process signal mask before returning. 10338 */ 10339 gl_unmask_signals(gl, &oldset); 10340 }; 10341 return signo; 10342 } 10343 10344 /*....................................................................... 10345 * Prepare to edit a new line. 10346 * 10347 * Input: 10348 * gl GetLine * The resource object of this library. 10349 * prompt char * The prompt to prefix the line with, or NULL to 10350 * use the same prompt that was used by the previous 10351 * line. 10352 * start_line char * The initial contents of the input line, or NULL 10353 * if it should start out empty. 10354 * start_pos int If start_line isn't NULL, this specifies the 10355 * index of the character over which the cursor 10356 * should initially be positioned within the line. 10357 * If you just want it to follow the last character 10358 * of the line, send -1. 10359 * Output: 10360 * return int 0 - OK. 10361 * 1 - Error. 10362 */ 10363 static int gl_present_line(GetLine *gl, const char *prompt, 10364 const char *start_line, int start_pos) 10365 { 10366 /* 10367 * Reset the properties of the line. 10368 */ 10369 gl_reset_input_line(gl); 10370 /* 10371 * Record the new prompt and its displayed width. 10372 */ 10373 if(prompt) 10374 _gl_replace_prompt(gl, prompt); 10375 /* 10376 * Reset the history search pointers. 10377 */ 10378 if(_glh_cancel_search(gl->glh)) { 10379 _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG); 10380 return 1; 10381 }; 10382 /* 10383 * If the previous line was entered via the repeat-history action, 10384 * preload the specified history line. 10385 */ 10386 if(gl->preload_history) { 10387 gl->preload_history = 0; 10388 if(gl->preload_id) { 10389 if(_glh_recall_line(gl->glh, gl->preload_id, gl->line, gl->linelen+1)) { 10390 gl_update_buffer(gl); /* Compute gl->ntotal etc.. */ 10391 gl->buff_curpos = gl->ntotal; 10392 } else { 10393 gl_truncate_buffer(gl, 0); 10394 }; 10395 gl->preload_id = 0; 10396 }; 10397 /* 10398 * Present a specified initial line? 10399 */ 10400 } else if(start_line) { 10401 char *cptr; /* A pointer into gl->line[] */ 10402 /* 10403 * Measure the length of the starting line. 10404 */ 10405 int start_len = strlen(start_line); 10406 /* 10407 * If the length of the line is greater than the available space, 10408 * truncate it. 10409 */ 10410 if(start_len > gl->linelen) 10411 start_len = gl->linelen; 10412 /* 10413 * Load the line into the buffer. 10414 */ 10415 if(start_line != gl->line) 10416 gl_buffer_string(gl, start_line, start_len, 0); 10417 /* 10418 * Strip off any trailing newline and carriage return characters. 10419 */ 10420 for(cptr=gl->line + gl->ntotal - 1; cptr >= gl->line && 10421 (*cptr=='\n' || *cptr=='\r'); cptr--,gl->ntotal--) 10422 ; 10423 gl_truncate_buffer(gl, gl->ntotal < 0 ? 0 : gl->ntotal); 10424 /* 10425 * Where should the cursor be placed within the line? 10426 */ 10427 if(start_pos < 0 || start_pos > gl->ntotal) { 10428 if(gl_place_cursor(gl, gl->ntotal)) 10429 return 1; 10430 } else { 10431 if(gl_place_cursor(gl, start_pos)) 10432 return 1; 10433 }; 10434 /* 10435 * Clear the input line? 10436 */ 10437 } else { 10438 gl_truncate_buffer(gl, 0); 10439 }; 10440 /* 10441 * Arrange for the line to be displayed by gl_flush_output(). 10442 */ 10443 gl_queue_redisplay(gl); 10444 /* 10445 * Update the display. 10446 */ 10447 return gl_flush_output(gl); 10448 } 10449 10450 /*....................................................................... 10451 * Reset all line input parameters for a new input line. 10452 * 10453 * Input: 10454 * gl GetLine * The line editor resource object. 10455 */ 10456 static void gl_reset_input_line(GetLine *gl) 10457 { 10458 gl->ntotal = 0; 10459 gl->line[0] = '\0'; 10460 gl->buff_curpos = 0; 10461 gl->term_curpos = 0; 10462 gl->term_len = 0; 10463 gl->insert_curpos = 0; 10464 gl->number = -1; 10465 gl->displayed = 0; 10466 gl->endline = 0; 10467 gl->redisplay = 0; 10468 gl->postpone = 0; 10469 gl->nbuf = 0; 10470 gl->nread = 0; 10471 gl->vi.command = 0; 10472 gl->vi.undo.line[0] = '\0'; 10473 gl->vi.undo.ntotal = 0; 10474 gl->vi.undo.buff_curpos = 0; 10475 gl->vi.repeat.action.fn = 0; 10476 gl->vi.repeat.action.data = 0; 10477 gl->last_signal = -1; 10478 } 10479 10480 /*....................................................................... 10481 * Print an informational message to the terminal, after starting a new 10482 * line. 10483 * 10484 * Input: 10485 * gl GetLine * The line editor resource object. 10486 * ... const char * Zero or more strings to be printed. 10487 * ... void * The last argument must always be GL_END_INFO. 10488 * Output: 10489 * return int 0 - OK. 10490 * 1 - Error. 10491 */ 10492 static int gl_print_info(GetLine *gl, ...) 10493 { 10494 va_list ap; /* The variable argument list */ 10495 const char *s; /* The string being printed */ 10496 int waserr = 0; /* True after an error */ 10497 /* 10498 * Only display output when echoing is on. 10499 */ 10500 if(gl->echo) { 10501 /* 10502 * Skip to the start of the next empty line before displaying the message. 10503 */ 10504 if(gl_start_newline(gl, 1)) 10505 return 1; 10506 /* 10507 * Display the list of provided messages. 10508 */ 10509 va_start(ap, gl); 10510 while(!waserr && (s = va_arg(ap, const char *)) != GL_END_INFO) 10511 waserr = gl_print_raw_string(gl, 1, s, -1); 10512 va_end(ap); 10513 /* 10514 * Start a newline. 10515 */ 10516 waserr = waserr || gl_print_raw_string(gl, 1, "\n\r", -1); 10517 /* 10518 * Arrange for the input line to be redrawn. 10519 */ 10520 gl_queue_redisplay(gl); 10521 }; 10522 return waserr; 10523 } 10524 10525 /*....................................................................... 10526 * Go to the start of the next empty line, ready to output miscellaneous 10527 * text to the screen. 10528 * 10529 * Note that when async-signal safety is required, the 'buffered' 10530 * argument must be 0. 10531 * 10532 * Input: 10533 * gl GetLine * The line editor resource object. 10534 * buffered int If true, used buffered I/O when writing to 10535 * the terminal. Otherwise use async-signal-safe 10536 * unbuffered I/O. 10537 * Output: 10538 * return int 0 - OK. 10539 * 1 - Error. 10540 */ 10541 static int gl_start_newline(GetLine *gl, int buffered) 10542 { 10543 int waserr = 0; /* True after any I/O error */ 10544 /* 10545 * Move the cursor to the start of the terminal line that follows the 10546 * last line of the partially enterred line. In order that this 10547 * function remain async-signal safe when write_fn is signal safe, we 10548 * can't call our normal output functions, since they call tputs(), 10549 * who's signal saftey isn't defined. Fortunately, we can simply use 10550 * \r and \n to move the cursor to the right place. 10551 */ 10552 if(gl->displayed) { /* Is an input line currently displayed? */ 10553 /* 10554 * On which terminal lines are the cursor and the last character of the 10555 * input line? 10556 */ 10557 int curs_line = gl->term_curpos / gl->ncolumn; 10558 int last_line = gl->term_len / gl->ncolumn; 10559 /* 10560 * Move the cursor to the start of the line that follows the last 10561 * terminal line that is occupied by the input line. 10562 */ 10563 for( ; curs_line < last_line + 1; curs_line++) 10564 waserr = waserr || gl_print_raw_string(gl, buffered, "\n", 1); 10565 waserr = waserr || gl_print_raw_string(gl, buffered, "\r", 1); 10566 /* 10567 * Mark the line as no longer displayed. 10568 */ 10569 gl_line_erased(gl); 10570 }; 10571 return waserr; 10572 } 10573 10574 /*....................................................................... 10575 * The callback through which all terminal output is routed. 10576 * This simply appends characters to a queue buffer, which is 10577 * subsequently flushed to the output channel by gl_flush_output(). 10578 * 10579 * Input: 10580 * data void * The pointer to a GetLine line editor resource object 10581 * cast to (void *). 10582 * s const char * The string to be written. 10583 * n int The number of characters to write from s[]. 10584 * Output: 10585 * return int The number of characters written. This will always 10586 * be equal to 'n' unless an error occurs. 10587 */ 10588 static GL_WRITE_FN(gl_write_fn) 10589 { 10590 GetLine *gl = (GetLine *) data; 10591 int ndone = _glq_append_chars(gl->cq, s, n, gl->flush_fn, gl); 10592 if(ndone != n) 10593 _err_record_msg(gl->err, _glq_last_error(gl->cq), END_ERR_MSG); 10594 return ndone; 10595 } 10596 10597 /*....................................................................... 10598 * Ask gl_get_line() what caused it to return. 10599 * 10600 * Input: 10601 * gl GetLine * The line editor resource object. 10602 * Output: 10603 * return GlReturnStatus The return status of the last call to 10604 * gl_get_line(). 10605 */ 10606 GlReturnStatus gl_return_status(GetLine *gl) 10607 { 10608 GlReturnStatus rtn_status = GLR_ERROR; /* The requested status */ 10609 if(gl) { 10610 sigset_t oldset; /* The signals that were blocked on entry to this block */ 10611 /* 10612 * Temporarily block all signals. 10613 */ 10614 gl_mask_signals(gl, &oldset); 10615 /* 10616 * Access gl while signals are blocked. 10617 */ 10618 rtn_status = gl->rtn_status; 10619 /* 10620 * Restore the process signal mask before returning. 10621 */ 10622 gl_unmask_signals(gl, &oldset); 10623 }; 10624 return rtn_status; 10625 } 10626 10627 /*....................................................................... 10628 * In non-blocking server-I/O mode, this function should be called 10629 * from the application's external event loop to see what type of 10630 * terminal I/O is being waited for by gl_get_line(), and thus what 10631 * direction of I/O to wait for with select() or poll(). 10632 * 10633 * Input: 10634 * gl GetLine * The resource object of gl_get_line(). 10635 * Output: 10636 * return GlPendingIO The type of pending I/O being waited for. 10637 */ 10638 GlPendingIO gl_pending_io(GetLine *gl) 10639 { 10640 GlPendingIO pending_io = GLP_WRITE; /* The requested information */ 10641 if(gl) { 10642 sigset_t oldset; /* The signals that were blocked on entry to this block */ 10643 /* 10644 * Temporarily block all signals. 10645 */ 10646 gl_mask_signals(gl, &oldset); 10647 /* 10648 * Access gl while signals are blocked. 10649 */ 10650 pending_io = gl->pending_io; 10651 /* 10652 * Restore the process signal mask before returning. 10653 */ 10654 gl_unmask_signals(gl, &oldset); 10655 }; 10656 return pending_io; 10657 } 10658 10659 /*....................................................................... 10660 * In server mode, this function configures the terminal for non-blocking 10661 * raw terminal I/O. In normal I/O mode it does nothing. 10662 * 10663 * Callers of this function must be careful to trap all signals that 10664 * terminate or suspend the program, and call gl_normal_io() 10665 * from the corresponding signal handlers in order to restore the 10666 * terminal to its original settings before the program is terminated 10667 * or suspended. They should also trap the SIGCONT signal to detect 10668 * when the program resumes, and ensure that its signal handler 10669 * call gl_raw_io() to redisplay the line and resume editing. 10670 * 10671 * This function is async signal safe. 10672 * 10673 * Input: 10674 * gl GetLine * The line editor resource object. 10675 * Output: 10676 * return int 0 - OK. 10677 * 1 - Error. 10678 */ 10679 int gl_raw_io(GetLine *gl) 10680 { 10681 sigset_t oldset; /* The signals that were blocked on entry to this function */ 10682 int status; /* The return status of _gl_raw_io() */ 10683 /* 10684 * Check the arguments. 10685 */ 10686 if(!gl) { 10687 errno = EINVAL; 10688 return 1; 10689 }; 10690 /* 10691 * Block all signals. 10692 */ 10693 if(gl_mask_signals(gl, &oldset)) 10694 return 1; 10695 /* 10696 * Don't allow applications to switch into raw mode unless in server mode. 10697 */ 10698 if(gl->io_mode != GL_SERVER_MODE) { 10699 _err_record_msg(gl->err, "Can't switch to raw I/O unless in server mode", 10700 END_ERR_MSG); 10701 errno = EPERM; 10702 status = 1; 10703 } else { 10704 /* 10705 * Execute the private body of the function while signals are blocked. 10706 */ 10707 status = _gl_raw_io(gl, 1); 10708 }; 10709 /* 10710 * Restore the process signal mask. 10711 */ 10712 gl_unmask_signals(gl, &oldset); 10713 return status; 10714 } 10715 10716 /*....................................................................... 10717 * This is the private body of the public function, gl_raw_io(). 10718 * It assumes that the caller has checked its arguments and blocked the 10719 * delivery of signals. 10720 * 10721 * This function is async signal safe. 10722 */ 10723 static int _gl_raw_io(GetLine *gl, int redisplay) 10724 { 10725 /* 10726 * If we are already in the correct mode, do nothing. 10727 */ 10728 if(gl->raw_mode) 10729 return 0; 10730 /* 10731 * Switch the terminal to raw mode. 10732 */ 10733 if(gl->is_term && gl_raw_terminal_mode(gl)) 10734 return 1; 10735 /* 10736 * Switch to non-blocking I/O mode? 10737 */ 10738 if(gl->io_mode==GL_SERVER_MODE && 10739 (gl_nonblocking_io(gl, gl->input_fd) || 10740 gl_nonblocking_io(gl, gl->output_fd) || 10741 (gl->file_fp && gl_nonblocking_io(gl, fileno(gl->file_fp))))) { 10742 if(gl->is_term) 10743 gl_restore_terminal_attributes(gl); 10744 return 1; 10745 }; 10746 /* 10747 * If an input line is being entered, arrange for it to be 10748 * displayed. 10749 */ 10750 if(redisplay) { 10751 gl->postpone = 0; 10752 gl_queue_redisplay(gl); 10753 }; 10754 return 0; 10755 } 10756 10757 /*....................................................................... 10758 * Restore the terminal to the state that it had when 10759 * gl_raw_io() was last called. After calling 10760 * gl_raw_io(), this function must be called before 10761 * terminating or suspending the program, and before attempting other 10762 * uses of the terminal from within the program. See gl_raw_io() 10763 * for more details. 10764 * 10765 * Input: 10766 * gl GetLine * The line editor resource object. 10767 * Output: 10768 * return int 0 - OK. 10769 * 1 - Error. 10770 */ 10771 int gl_normal_io(GetLine *gl) 10772 { 10773 sigset_t oldset; /* The signals that were blocked on entry to this function */ 10774 int status; /* The return status of _gl_normal_io() */ 10775 /* 10776 * Check the arguments. 10777 */ 10778 if(!gl) { 10779 errno = EINVAL; 10780 return 1; 10781 }; 10782 /* 10783 * Block all signals. 10784 */ 10785 if(gl_mask_signals(gl, &oldset)) 10786 return 1; 10787 /* 10788 * Execute the private body of the function while signals are blocked. 10789 */ 10790 status = _gl_normal_io(gl); 10791 /* 10792 * Restore the process signal mask. 10793 */ 10794 gl_unmask_signals(gl, &oldset); 10795 return status; 10796 } 10797 10798 /*....................................................................... 10799 * This is the private body of the public function, gl_normal_io(). 10800 * It assumes that the caller has checked its arguments and blocked the 10801 * delivery of signals. 10802 */ 10803 static int _gl_normal_io(GetLine *gl) 10804 { 10805 /* 10806 * If we are already in normal mode, do nothing. 10807 */ 10808 if(!gl->raw_mode) 10809 return 0; 10810 /* 10811 * Postpone subsequent redisplays until after _gl_raw_io(gl, 1) 10812 * is next called. 10813 */ 10814 gl->postpone = 1; 10815 /* 10816 * Switch back to blocking I/O. Note that this is essential to do 10817 * here, because when using non-blocking I/O, the terminal output 10818 * buffering code can't always make room for new output without calling 10819 * malloc(), and a call to malloc() would mean that this function 10820 * couldn't safely be called from signal handlers. 10821 */ 10822 if(gl->io_mode==GL_SERVER_MODE && 10823 (gl_blocking_io(gl, gl->input_fd) || 10824 gl_blocking_io(gl, gl->output_fd) || 10825 (gl->file_fp && gl_blocking_io(gl, fileno(gl->file_fp))))) 10826 return 1; 10827 /* 10828 * Move the cursor to the next empty terminal line. Note that 10829 * unbuffered I/O is requested, to ensure that gl_start_newline() be 10830 * async-signal-safe. 10831 */ 10832 if(gl->is_term && gl_start_newline(gl, 0)) 10833 return 1; 10834 /* 10835 * Switch the terminal to normal mode. 10836 */ 10837 if(gl->is_term && gl_restore_terminal_attributes(gl)) { 10838 /* 10839 * On error, revert to non-blocking I/O if needed, so that on failure 10840 * we remain in raw mode. 10841 */ 10842 if(gl->io_mode==GL_SERVER_MODE) { 10843 gl_nonblocking_io(gl, gl->input_fd); 10844 gl_nonblocking_io(gl, gl->output_fd); 10845 if(gl->file_fp) 10846 gl_nonblocking_io(gl, fileno(gl->file_fp)); 10847 }; 10848 return 1; 10849 }; 10850 return 0; 10851 } 10852 10853 /*....................................................................... 10854 * This function allows you to install an additional completion 10855 * action, or to change the completion function of an existing 10856 * one. This should be called before the first call to gl_get_line() 10857 * so that the name of the action be defined before the user's 10858 * configuration file is read. 10859 * 10860 * Input: 10861 * gl GetLine * The resource object of the command-line input 10862 * module. 10863 * data void * This is passed to match_fn() whenever it is 10864 * called. It could, for example, point to a 10865 * symbol table that match_fn() would look up 10866 * matches in. 10867 * match_fn CplMatchFn * The function that will identify the prefix 10868 * to be completed from the input line, and 10869 * report matching symbols. 10870 * list_only int If non-zero, install an action that only lists 10871 * possible completions, rather than attempting 10872 * to perform the completion. 10873 * name const char * The name with which users can refer to the 10874 * binding in tecla configuration files. 10875 * keyseq const char * Either NULL, or a key sequence with which 10876 * to invoke the binding. This should be 10877 * specified in the same manner as key-sequences 10878 * in tecla configuration files (eg. "M-^I"). 10879 * Output: 10880 * return int 0 - OK. 10881 * 1 - Error. 10882 */ 10883 int gl_completion_action(GetLine *gl, void *data, CplMatchFn *match_fn, 10884 int list_only, const char *name, const char *keyseq) 10885 { 10886 sigset_t oldset; /* The signals that were blocked on entry to this function */ 10887 int status; /* The return status of _gl_completion_action() */ 10888 /* 10889 * Check the arguments. 10890 */ 10891 if(!gl || !name || !match_fn) { 10892 errno = EINVAL; 10893 return 1; 10894 }; 10895 /* 10896 * Block all signals. 10897 */ 10898 if(gl_mask_signals(gl, &oldset)) 10899 return 1; 10900 /* 10901 * Install the new action while signals are blocked. 10902 */ 10903 status = _gl_completion_action(gl, data, match_fn, list_only, name, keyseq); 10904 /* 10905 * Restore the process signal mask. 10906 */ 10907 gl_unmask_signals(gl, &oldset); 10908 return status; 10909 } 10910 10911 /*....................................................................... 10912 * This is the private body of the public function, gl_completion_action(). 10913 * It assumes that the caller has checked its arguments and blocked the 10914 * delivery of signals. 10915 */ 10916 static int _gl_completion_action(GetLine *gl, void *data, CplMatchFn *match_fn, 10917 int list_only, const char *name, 10918 const char *keyseq) 10919 { 10920 KtKeyFn *current_fn; /* An existing action function */ 10921 void *current_data; /* The action-function callback data */ 10922 /* 10923 * Which action function is desired? 10924 */ 10925 KtKeyFn *action_fn = list_only ? gl_list_completions : gl_complete_word; 10926 /* 10927 * Is there already an action of the specified name? 10928 */ 10929 if(_kt_lookup_action(gl->bindings, name, ¤t_fn, ¤t_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, ¤t_fn, ¤t_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