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