1 /* 2 * Copyright (c) 2000, 2001, 2002, 2003, 2004 by Martin C. Shepherd. 3 * 4 * All rights reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, and/or sell copies of the Software, and to permit persons 11 * to whom the Software is furnished to do so, provided that the above 12 * copyright notice(s) and this permission notice appear in all copies of 13 * the Software and that both the above copyright notice(s) and this 14 * permission notice appear in supporting documentation. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 19 * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 20 * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL 21 * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING 22 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 23 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 24 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 25 * 26 * Except as contained in this notice, the name of a copyright holder 27 * shall not be used in advertising or otherwise to promote the sale, use 28 * or other dealings in this Software without prior written authorization 29 * of the copyright holder. 30 */ 31 32 /* 33 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 34 * Use is subject to license terms. 35 */ 36 37 #pragma ident "%Z%%M% %I% %E% SMI" 38 39 /* 40 * Standard headers. 41 */ 42 #include <stdio.h> 43 #include <stdlib.h> 44 #include <signal.h> 45 #include <string.h> 46 #include <errno.h> 47 #include <ctype.h> 48 #include <setjmp.h> 49 #include <stdarg.h> 50 51 /* 52 * UNIX headers. 53 */ 54 #include <sys/ioctl.h> 55 #ifdef HAVE_SELECT 56 #ifdef HAVE_SYS_SELECT_H 57 #include <sys/select.h> 58 #endif 59 #include <sys/time.h> 60 #include <sys/types.h> 61 #endif 62 63 /* 64 * Handle the different sources of terminal control string and size 65 * information. Note that if no terminal information database is available, 66 * ANSI VT100 control sequences are used. 67 */ 68 #if defined(USE_TERMINFO) || defined(USE_TERMCAP) 69 /* 70 * Include curses.h or ncurses/curses.h depending on which is available. 71 */ 72 #ifdef HAVE_CURSES_H 73 #include <curses.h> 74 #elif defined(HAVE_NCURSES_CURSES_H) 75 #include <ncurses/curses.h> 76 #endif 77 /* 78 * Include term.h where available. 79 */ 80 #if defined(HAVE_TERM_H) 81 #include <term.h> 82 #elif defined(HAVE_NCURSES_TERM_H) 83 #include <ncurses/term.h> 84 #endif 85 /* 86 * When using termcap, include termcap.h on systems that have it. 87 * Otherwise assume that all prototypes are provided by curses.h. 88 */ 89 #if defined(USE_TERMCAP) && defined(HAVE_TERMCAP_H) 90 #include <termcap.h> 91 #endif 92 93 /* 94 * Under Solaris default Curses the output function that tputs takes is 95 * declared to have a char argument. On all other systems and on Solaris 96 * X/Open Curses (Issue 4, Version 2) it expects an int argument (using 97 * c89 or options -I /usr/xpg4/include -L /usr/xpg4/lib -R /usr/xpg4/lib 98 * selects XPG4v2 Curses on Solaris 2.6 and later). 99 * 100 * Similarly, under Mac OS X, the return value of the tputs output 101 * function is declared as void, whereas it is declared as int on 102 * other systems. 103 */ 104 #if defined __sun && defined __SVR4 && !defined _XOPEN_CURSES 105 typedef int TputsRetType; 106 typedef char TputsArgType; /* int tputs(char c, FILE *fp) */ 107 #define TPUTS_RETURNS_VALUE 1 108 #elif defined(__APPLE__) && defined(__MACH__) 109 typedef void TputsRetType; 110 typedef int TputsArgType; /* void tputs(int c, FILE *fp) */ 111 #define TPUTS_RETURNS_VALUE 0 112 #else 113 typedef int TputsRetType; 114 typedef int TputsArgType; /* int tputs(int c, FILE *fp) */ 115 #define TPUTS_RETURNS_VALUE 1 116 #endif 117 118 /* 119 * Use the above specifications to prototype our tputs callback function. 120 */ 121 static TputsRetType gl_tputs_putchar(TputsArgType c); 122 123 #endif /* defined(USE_TERMINFO) || defined(USE_TERMCAP) */ 124 125 /* 126 * If the library is being compiled without filesystem access facilities, 127 * ensure that none of the action functions that normally do access the 128 * filesystem are bound by default, and that it they do get bound, that 129 * they don't do anything. 130 */ 131 #if WITHOUT_FILE_SYSTEM 132 #define HIDE_FILE_SYSTEM 133 #endif 134 135 /* 136 * POSIX headers. 137 */ 138 #include <unistd.h> 139 #include <fcntl.h> 140 #include <termios.h> 141 142 /* 143 * Provide typedefs for standard POSIX structures. 144 */ 145 typedef struct sigaction SigAction; 146 typedef struct termios Termios; 147 148 /* 149 * Which flag is used to select non-blocking I/O with fcntl()? 150 */ 151 #undef NON_BLOCKING_FLAG 152 #if defined(O_NONBLOCK) 153 #define NON_BLOCKING_FLAG (O_NONBLOCK) 154 #elif defined(O_NDELAY) 155 #define NON_BLOCKING_FLAG (O_NDELAY) 156 #endif 157 158 /* 159 * What value should we give errno if I/O blocks when it shouldn't. 160 */ 161 #undef BLOCKED_ERRNO 162 #if defined(EAGAIN) 163 #define BLOCKED_ERRNO (EAGAIN) 164 #elif defined(EWOULDBLOCK) 165 #define BLOCKED_ERRNO (EWOULDBLOCK) 166 #elif defined(EIO) 167 #define BLOCKED_ERRNO (EIO) 168 #else 169 #define BLOCKED_ERRNO 0 170 #endif 171 172 /* 173 * Local headers. 174 */ 175 #ifndef WITHOUT_FILE_SYSTEM 176 #include "pathutil.h" 177 #endif 178 #include "libtecla.h" 179 #include "keytab.h" 180 #include "getline.h" 181 #include "ioutil.h" 182 #include "history.h" 183 #include "freelist.h" 184 #include "stringrp.h" 185 #include "chrqueue.h" 186 #include "cplmatch.h" 187 #ifndef WITHOUT_FILE_SYSTEM 188 #include "expand.h" 189 #endif 190 #include "errmsg.h" 191 192 /* 193 * Enumerate the available editing styles. 194 */ 195 typedef enum { 196 GL_EMACS_MODE, /* Emacs style editing */ 197 GL_VI_MODE, /* Vi style editing */ 198 GL_NO_EDITOR /* Fall back to the basic OS-provided editing */ 199 } GlEditor; 200 201 /* 202 * Set the largest key-sequence that can be handled. 203 */ 204 #define GL_KEY_MAX 64 205 206 /* 207 * In vi mode, the following datatype is used to implement the 208 * undo command. It records a copy of the input line from before 209 * the command-mode action which edited the input line. 210 */ 211 typedef struct { 212 char *line; /* A historical copy of the input line */ 213 int buff_curpos; /* The historical location of the cursor in */ 214 /* line[] when the line was modified. */ 215 int ntotal; /* The number of characters in line[] */ 216 int saved; /* True once a line has been saved after the */ 217 /* last call to gl_interpret_char(). */ 218 } ViUndo; 219 220 /* 221 * In vi mode, the following datatype is used to record information 222 * needed by the vi-repeat-change command. 223 */ 224 typedef struct { 225 KtAction action; /* The last action function that made a */ 226 /* change to the line. */ 227 int count; /* The repeat count that was passed to the */ 228 /* above command. */ 229 int input_curpos; /* Whenever vi command mode is entered, the */ 230 /* the position at which it was first left */ 231 /* is recorded here. */ 232 int command_curpos; /* Whenever vi command mode is entered, the */ 233 /* the location of the cursor is recorded */ 234 /* here. */ 235 char input_char; /* Commands that call gl_read_terminal() */ 236 /* record the character here, so that it can */ 237 /* used on repeating the function. */ 238 int saved; /* True if a function has been saved since the */ 239 /* last call to gl_interpret_char(). */ 240 int active; /* True while a function is being repeated. */ 241 } ViRepeat; 242 243 /* 244 * The following datatype is used to encapsulate information specific 245 * to vi mode. 246 */ 247 typedef struct { 248 ViUndo undo; /* Information needed to implement the vi */ 249 /* undo command. */ 250 ViRepeat repeat; /* Information needed to implement the vi */ 251 /* repeat command. */ 252 int command; /* True in vi command-mode */ 253 int find_forward; /* True if the last character search was in the */ 254 /* forward direction. */ 255 int find_onto; /* True if the last character search left the */ 256 /* on top of the located character, as opposed */ 257 /* to just before or after it. */ 258 char find_char; /* The last character sought, or '\0' if no */ 259 /* searches have been performed yet. */ 260 } ViMode; 261 262 #ifdef HAVE_SELECT 263 /* 264 * Define a type for recording a file-descriptor callback and its associated 265 * data. 266 */ 267 typedef struct { 268 GlFdEventFn *fn; /* The callback function */ 269 void *data; /* Anonymous data to pass to the callback function */ 270 } GlFdHandler; 271 272 /* 273 * A list of nodes of the following type is used to record file-activity 274 * event handlers, but only on systems that have the select() system call. 275 */ 276 typedef struct GlFdNode GlFdNode; 277 struct GlFdNode { 278 GlFdNode *next; /* The next in the list of nodes */ 279 int fd; /* The file descriptor being watched */ 280 GlFdHandler rd; /* The callback to call when fd is readable */ 281 GlFdHandler wr; /* The callback to call when fd is writable */ 282 GlFdHandler ur; /* The callback to call when fd has urgent data */ 283 }; 284 285 /* 286 * Set the number of the above structures to allocate every time that 287 * the freelist of GlFdNode's becomes exhausted. 288 */ 289 #define GLFD_FREELIST_BLOCKING 10 290 291 292 static int gl_call_fd_handler(GetLine *gl, GlFdHandler *gfh, int fd, 293 GlFdEvent event); 294 295 static int gl_call_timeout_handler(GetLine *gl); 296 297 #endif 298 299 /* 300 * Each signal that gl_get_line() traps is described by a list node 301 * of the following type. 302 */ 303 typedef struct GlSignalNode GlSignalNode; 304 struct GlSignalNode { 305 GlSignalNode *next; /* The next signal in the list */ 306 int signo; /* The number of the signal */ 307 sigset_t proc_mask; /* A process mask which only includes signo */ 308 SigAction original; /* The signal disposition of the calling program */ 309 /* for this signal. */ 310 unsigned flags; /* A bitwise union of GlSignalFlags enumerators */ 311 GlAfterSignal after; /* What to do after the signal has been handled */ 312 int errno_value; /* What to set errno to */ 313 }; 314 315 /* 316 * Set the number of the above structures to allocate every time that 317 * the freelist of GlSignalNode's becomes exhausted. 318 */ 319 #define GLS_FREELIST_BLOCKING 30 320 321 /* 322 * Completion handlers and their callback data are recorded in 323 * nodes of the following type. 324 */ 325 typedef struct GlCplCallback GlCplCallback; 326 struct GlCplCallback { 327 CplMatchFn *fn; /* The completion callback function */ 328 void *data; /* Arbitrary callback data */ 329 }; 330 331 /* 332 * The following function is used as the default completion handler when 333 * the filesystem is to be hidden. It simply reports no completions. 334 */ 335 #ifdef HIDE_FILE_SYSTEM 336 static CPL_MATCH_FN(gl_no_completions); 337 #endif 338 339 /* 340 * Specify how many GlCplCallback nodes are added to the GlCplCallback freelist 341 * whenever it becomes exhausted. 342 */ 343 #define GL_CPL_FREELIST_BLOCKING 10 344 345 /* 346 * External action functions and their callback data are recorded in 347 * nodes of the following type. 348 */ 349 typedef struct GlExternalAction GlExternalAction; 350 struct GlExternalAction { 351 GlActionFn *fn; /* The function which implements the action */ 352 void *data; /* Arbitrary callback data */ 353 }; 354 355 /* 356 * Specify how many GlExternalAction nodes are added to the 357 * GlExternalAction freelist whenever it becomes exhausted. 358 */ 359 #define GL_EXT_ACT_FREELIST_BLOCKING 10 360 361 /* 362 * Define the contents of the GetLine object. 363 * Note that the typedef for this object can be found in libtecla.h. 364 */ 365 struct GetLine { 366 ErrMsg *err; /* The error-reporting buffer */ 367 GlHistory *glh; /* The line-history buffer */ 368 WordCompletion *cpl; /* String completion resource object */ 369 GlCplCallback cplfn; /* The completion callback */ 370 #ifndef WITHOUT_FILE_SYSTEM 371 ExpandFile *ef; /* ~user/, $envvar and wildcard expansion */ 372 /* resource object. */ 373 #endif 374 StringGroup *capmem; /* Memory for recording terminal capability */ 375 /* strings. */ 376 GlCharQueue *cq; /* The terminal output character queue */ 377 int input_fd; /* The file descriptor to read on */ 378 int output_fd; /* The file descriptor to write to */ 379 FILE *input_fp; /* A stream wrapper around input_fd */ 380 FILE *output_fp; /* A stream wrapper around output_fd */ 381 FILE *file_fp; /* When input is being temporarily taken from */ 382 /* a file, this is its file-pointer. Otherwise */ 383 /* it is NULL. */ 384 char *term; /* The terminal type specified on the last call */ 385 /* to gl_change_terminal(). */ 386 int is_term; /* True if stdin is a terminal */ 387 GlWriteFn *flush_fn; /* The function to call to write to the terminal */ 388 GlIOMode io_mode; /* The I/O mode established by gl_io_mode() */ 389 int raw_mode; /* True while the terminal is in raw mode */ 390 GlPendingIO pending_io; /* The type of I/O that is currently pending */ 391 GlReturnStatus rtn_status; /* The reason why gl_get_line() returned */ 392 int rtn_errno; /* THe value of errno associated with rtn_status */ 393 size_t linelen; /* The max number of characters per line */ 394 char *line; /* A line-input buffer of allocated size */ 395 /* linelen+2. The extra 2 characters are */ 396 /* reserved for "\n\0". */ 397 char *cutbuf; /* A cut-buffer of the same size as line[] */ 398 char *prompt; /* The current prompt string */ 399 int prompt_len; /* The length of the prompt string */ 400 int prompt_changed; /* True after a callback changes the prompt */ 401 int prompt_style; /* How the prompt string is displayed */ 402 FreeList *cpl_mem; /* Memory for GlCplCallback objects */ 403 FreeList *ext_act_mem; /* Memory for GlExternalAction objects */ 404 FreeList *sig_mem; /* Memory for nodes of the signal list */ 405 GlSignalNode *sigs; /* The head of the list of signals */ 406 int signals_masked; /* True between calls to gl_mask_signals() and */ 407 /* gl_unmask_signals() */ 408 int signals_overriden; /* True between calls to gl_override_signals() */ 409 /* and gl_restore_signals() */ 410 sigset_t all_signal_set; /* The set of all signals that we are trapping */ 411 sigset_t old_signal_set; /* The set of blocked signals on entry to */ 412 /* gl_get_line(). */ 413 sigset_t use_signal_set; /* The subset of all_signal_set to unblock */ 414 /* while waiting for key-strokes */ 415 Termios oldattr; /* Saved terminal attributes. */ 416 KeyTab *bindings; /* A table of key-bindings */ 417 int ntotal; /* The number of characters in gl->line[] */ 418 int buff_curpos; /* The cursor position within gl->line[] */ 419 int term_curpos; /* The cursor position on the terminal */ 420 int term_len; /* The number of terminal characters used to */ 421 /* display the current input line. */ 422 int buff_mark; /* A marker location in the buffer */ 423 int insert_curpos; /* The cursor position at start of insert */ 424 int insert; /* True in insert mode */ 425 int number; /* If >= 0, a numeric argument is being read */ 426 int endline; /* True to tell gl_get_input_line() to return */ 427 /* the current contents of gl->line[] */ 428 int displayed; /* True if an input line is currently displayed */ 429 int redisplay; /* If true, the input line will be redrawn */ 430 /* either after the current action function */ 431 /* returns, or when gl_get_input_line() */ 432 /* is next called. */ 433 int postpone; /* _gl_normal_io() sets this flag, to */ 434 /* postpone any redisplays until */ 435 /* is next called, to resume line editing. */ 436 char keybuf[GL_KEY_MAX+1]; /* A buffer of currently unprocessed key presses */ 437 int nbuf; /* The number of characters in keybuf[] */ 438 int nread; /* The number of characters read from keybuf[] */ 439 KtAction current_action; /* The action function that is being invoked */ 440 int current_count; /* The repeat count passed to */ 441 /* current_acction.fn() */ 442 GlhLineID preload_id; /* When not zero, this should be the ID of a */ 443 /* line in the history buffer for potential */ 444 /* recall. */ 445 int preload_history; /* If true, preload the above history line when */ 446 /* gl_get_input_line() is next called. */ 447 long keyseq_count; /* The number of key sequences entered by the */ 448 /* the user since new_GetLine() was called. */ 449 long last_search; /* The value of keyseq_count during the last */ 450 /* history search operation. */ 451 GlEditor editor; /* The style of editing, (eg. vi or emacs) */ 452 int silence_bell; /* True if gl_ring_bell() should do nothing. */ 453 int automatic_history; /* True to automatically archive entered lines */ 454 /* in the history list. */ 455 ViMode vi; /* Parameters used when editing in vi mode */ 456 const char *left; /* The string that moves the cursor 1 character */ 457 /* left. */ 458 const char *right; /* The string that moves the cursor 1 character */ 459 /* right. */ 460 const char *up; /* The string that moves the cursor 1 character */ 461 /* up. */ 462 const char *down; /* The string that moves the cursor 1 character */ 463 /* down. */ 464 const char *home; /* The string that moves the cursor home */ 465 const char *bol; /* Move cursor to beginning of line */ 466 const char *clear_eol; /* The string that clears from the cursor to */ 467 /* the end of the line. */ 468 const char *clear_eod; /* The string that clears from the cursor to */ 469 /* the end of the display. */ 470 const char *u_arrow; /* The string returned by the up-arrow key */ 471 const char *d_arrow; /* The string returned by the down-arrow key */ 472 const char *l_arrow; /* The string returned by the left-arrow key */ 473 const char *r_arrow; /* The string returned by the right-arrow key */ 474 const char *sound_bell; /* The string needed to ring the terminal bell */ 475 const char *bold; /* Switch to the bold font */ 476 const char *underline; /* Underline subsequent characters */ 477 const char *standout; /* Turn on standout mode */ 478 const char *dim; /* Switch to a dim font */ 479 const char *reverse; /* Turn on reverse video */ 480 const char *blink; /* Switch to a blinking font */ 481 const char *text_attr_off; /* Turn off all text attributes */ 482 int nline; /* The height of the terminal in lines */ 483 int ncolumn; /* The width of the terminal in columns */ 484 #ifdef USE_TERMCAP 485 char *tgetent_buf; /* The buffer that is used by tgetent() to */ 486 /* store a terminal description. */ 487 char *tgetstr_buf; /* The buffer that is used by tgetstr() to */ 488 /* store terminal capabilities. */ 489 #endif 490 #ifdef USE_TERMINFO 491 const char *left_n; /* The parameter string that moves the cursor */ 492 /* n characters left. */ 493 const char *right_n; /* The parameter string that moves the cursor */ 494 /* n characters right. */ 495 #endif 496 char *app_file; /* The pathname of the application-specific */ 497 /* .teclarc configuration file, or NULL. */ 498 char *user_file; /* The pathname of the user-specific */ 499 /* .teclarc configuration file, or NULL. */ 500 int configured; /* True as soon as any teclarc configuration */ 501 /* file has been read. */ 502 int echo; /* True to display the line as it is being */ 503 /* entered. If 0, only the prompt will be */ 504 /* displayed, and the line will not be */ 505 /* archived in the history list. */ 506 int last_signal; /* The last signal that was caught by */ 507 /* the last call to gl_get_line(), or -1 */ 508 /* if no signal has been caught yet. */ 509 #ifdef HAVE_SELECT 510 FreeList *fd_node_mem; /* A freelist of GlFdNode structures */ 511 GlFdNode *fd_nodes; /* The list of fd event descriptions */ 512 fd_set rfds; /* The set of fds to watch for readability */ 513 fd_set wfds; /* The set of fds to watch for writability */ 514 fd_set ufds; /* The set of fds to watch for urgent data */ 515 int max_fd; /* The maximum file-descriptor being watched */ 516 struct { /* Inactivity timeout related data */ 517 struct timeval dt; /* The inactivity timeout when timer.fn() */ 518 /* isn't 0 */ 519 GlTimeoutFn *fn; /* The application callback to call when */ 520 /* the inactivity timer expires, or 0 if */ 521 /* timeouts are not required. */ 522 void *data; /* Application provided data to be passed to */ 523 /* timer.fn(). */ 524 } timer; 525 #endif 526 }; 527 528 /* 529 * Define the max amount of space needed to store a termcap terminal 530 * description. Unfortunately this has to be done by guesswork, so 531 * there is the potential for buffer overflows if we guess too small. 532 * Fortunately termcap has been replaced by terminfo on most 533 * platforms, and with terminfo this isn't an issue. The value that I 534 * am using here is the conventional value, as recommended by certain 535 * web references. 536 */ 537 #ifdef USE_TERMCAP 538 #define TERMCAP_BUF_SIZE 2048 539 #endif 540 541 /* 542 * Set the size of the string segments used to store terminal capability 543 * strings. 544 */ 545 #define CAPMEM_SEGMENT_SIZE 512 546 547 /* 548 * If no terminal size information is available, substitute the 549 * following vt100 default sizes. 550 */ 551 #define GL_DEF_NLINE 24 552 #define GL_DEF_NCOLUMN 80 553 554 /* 555 * Enumerate the attributes needed to classify different types of 556 * signals. These attributes reflect the standard default 557 * characteristics of these signals (according to Richard Steven's 558 * Advanced Programming in the UNIX Environment). Note that these values 559 * are all powers of 2, so that they can be combined in a bitwise union. 560 */ 561 typedef enum { 562 GLSA_TERM=1, /* A signal that terminates processes */ 563 GLSA_SUSP=2, /* A signal that suspends processes */ 564 GLSA_CONT=4, /* A signal that is sent when suspended processes resume */ 565 GLSA_IGN=8, /* A signal that is ignored */ 566 GLSA_CORE=16, /* A signal that generates a core dump */ 567 GLSA_HARD=32, /* A signal generated by a hardware exception */ 568 GLSA_SIZE=64 /* A signal indicating terminal size changes */ 569 } GlSigAttr; 570 571 /* 572 * List the signals that we need to catch. In general these are 573 * those that by default terminate or suspend the process, since 574 * in such cases we need to restore terminal settings. 575 */ 576 static const struct GlDefSignal { 577 int signo; /* The number of the signal */ 578 unsigned flags; /* A bitwise union of GlSignalFlags enumerators */ 579 GlAfterSignal after; /* What to do after the signal has been delivered */ 580 int attr; /* The default attributes of this signal, expressed */ 581 /* as a bitwise union of GlSigAttr enumerators */ 582 int errno_value; /* What to set errno to */ 583 } gl_signal_list[] = { 584 {SIGABRT, GLS_SUSPEND_INPUT, GLS_ABORT, GLSA_TERM|GLSA_CORE, EINTR}, 585 {SIGALRM, GLS_RESTORE_ENV, GLS_CONTINUE, GLSA_TERM, 0}, 586 {SIGCONT, GLS_RESTORE_ENV, GLS_CONTINUE, GLSA_CONT|GLSA_IGN, 0}, 587 #if defined(SIGHUP) 588 #ifdef ENOTTY 589 {SIGHUP, GLS_SUSPEND_INPUT, GLS_ABORT, GLSA_TERM, ENOTTY}, 590 #else 591 {SIGHUP, GLS_SUSPEND_INPUT, GLS_ABORT, GLSA_TERM, EINTR}, 592 #endif 593 #endif 594 {SIGINT, GLS_SUSPEND_INPUT, GLS_ABORT, GLSA_TERM, EINTR}, 595 #if defined(SIGPIPE) 596 #ifdef EPIPE 597 {SIGPIPE, GLS_SUSPEND_INPUT, GLS_ABORT, GLSA_TERM, EPIPE}, 598 #else 599 {SIGPIPE, GLS_SUSPEND_INPUT, GLS_ABORT, GLSA_TERM, EINTR}, 600 #endif 601 #endif 602 #ifdef SIGPOLL 603 {SIGPOLL, GLS_SUSPEND_INPUT, GLS_ABORT, GLSA_TERM, EINTR}, 604 #endif 605 #ifdef SIGPWR 606 {SIGPWR, GLS_RESTORE_ENV, GLS_CONTINUE, GLSA_IGN, 0}, 607 #endif 608 #ifdef SIGQUIT 609 {SIGQUIT, GLS_SUSPEND_INPUT, GLS_ABORT, GLSA_TERM|GLSA_CORE, EINTR}, 610 #endif 611 {SIGTERM, GLS_SUSPEND_INPUT, GLS_ABORT, GLSA_TERM, EINTR}, 612 #ifdef SIGTSTP 613 {SIGTSTP, GLS_SUSPEND_INPUT, GLS_CONTINUE, GLSA_SUSP, 0}, 614 #endif 615 #ifdef SIGTTIN 616 {SIGTTIN, GLS_SUSPEND_INPUT, GLS_CONTINUE, GLSA_SUSP, 0}, 617 #endif 618 #ifdef SIGTTOU 619 {SIGTTOU, GLS_SUSPEND_INPUT, GLS_CONTINUE, GLSA_SUSP, 0}, 620 #endif 621 #ifdef SIGUSR1 622 {SIGUSR1, GLS_RESTORE_ENV, GLS_CONTINUE, GLSA_TERM, 0}, 623 #endif 624 #ifdef SIGUSR2 625 {SIGUSR2, GLS_RESTORE_ENV, GLS_CONTINUE, GLSA_TERM, 0}, 626 #endif 627 #ifdef SIGVTALRM 628 {SIGVTALRM, GLS_RESTORE_ENV, GLS_CONTINUE, GLSA_TERM, 0}, 629 #endif 630 #ifdef SIGWINCH 631 {SIGWINCH, GLS_RESTORE_ENV, GLS_CONTINUE, GLSA_SIZE|GLSA_IGN, 0}, 632 #endif 633 #ifdef SIGXCPU 634 {SIGXCPU, GLS_RESTORE_ENV, GLS_CONTINUE, GLSA_TERM|GLSA_CORE, 0}, 635 #endif 636 #ifdef SIGXFSZ 637 {SIGXFSZ, GLS_RESTORE_ENV, GLS_CONTINUE, GLSA_TERM|GLSA_CORE, 0}, 638 #endif 639 }; 640 641 /* 642 * Define file-scope variables for use in signal handlers. 643 */ 644 static volatile sig_atomic_t gl_pending_signal = -1; 645 static sigjmp_buf gl_setjmp_buffer; 646 647 static void gl_signal_handler(int signo); 648 649 static int gl_check_caught_signal(GetLine *gl); 650 651 /* 652 * Respond to an externally caught process suspension or 653 * termination signal. 654 */ 655 static void gl_suspend_process(int signo, GetLine *gl, int ngl); 656 657 /* Return the default attributes of a given signal */ 658 659 static int gl_classify_signal(int signo); 660 661 /* 662 * Unfortunately both terminfo and termcap require one to use the tputs() 663 * function to output terminal control characters, and this function 664 * doesn't allow one to specify a file stream. As a result, the following 665 * file-scope variable is used to pass the current output file stream. 666 * This is bad, but there doesn't seem to be any alternative. 667 */ 668 static GetLine *tputs_gl = NULL; 669 670 /* 671 * Define a tab to be a string of 8 spaces. 672 */ 673 #define TAB_WIDTH 8 674 675 /* 676 * Lookup the current size of the terminal. 677 */ 678 static void gl_query_size(GetLine *gl, int *ncolumn, int *nline); 679 680 /* 681 * Getline calls this to temporarily override certain signal handlers 682 * of the calling program. 683 */ 684 static int gl_override_signal_handlers(GetLine *gl); 685 686 /* 687 * Getline calls this to restore the signal handlers of the calling 688 * program. 689 */ 690 static int gl_restore_signal_handlers(GetLine *gl); 691 692 /* 693 * Temporarily block the delivery of all signals that gl_get_line() 694 * is currently configured to trap. 695 */ 696 static int gl_mask_signals(GetLine *gl, sigset_t *oldset); 697 698 /* 699 * Restore the process signal mask that was overriden by a previous 700 * call to gl_mask_signals(). 701 */ 702 static int gl_unmask_signals(GetLine *gl, sigset_t *oldset); 703 704 /* 705 * Unblock the signals that gl_get_line() has been configured to catch. 706 */ 707 static int gl_catch_signals(GetLine *gl); 708 709 /* 710 * Return the set of all trappable signals. 711 */ 712 static void gl_list_trappable_signals(sigset_t *signals); 713 714 /* 715 * Put the terminal into raw input mode, after saving the original 716 * terminal attributes in gl->oldattr. 717 */ 718 static int gl_raw_terminal_mode(GetLine *gl); 719 720 /* 721 * Restore the terminal attributes from gl->oldattr. 722 */ 723 static int gl_restore_terminal_attributes(GetLine *gl); 724 725 /* 726 * Switch to non-blocking I/O if possible. 727 */ 728 static int gl_nonblocking_io(GetLine *gl, int fd); 729 730 /* 731 * Switch to blocking I/O if possible. 732 */ 733 static int gl_blocking_io(GetLine *gl, int fd); 734 735 /* 736 * Read a line from the user in raw mode. 737 */ 738 static int gl_get_input_line(GetLine *gl, const char *prompt, 739 const char *start_line, int start_pos); 740 741 /* 742 * Query the user for a single character. 743 */ 744 static int gl_get_query_char(GetLine *gl, const char *prompt, int defchar); 745 746 /* 747 * Read input from a non-interactive input stream. 748 */ 749 static int gl_read_stream_line(GetLine *gl); 750 751 /* 752 * Read a single character from a non-interactive input stream. 753 */ 754 static int gl_read_stream_char(GetLine *gl); 755 756 /* 757 * Prepare to edit a new line. 758 */ 759 static int gl_present_line(GetLine *gl, const char *prompt, 760 const char *start_line, int start_pos); 761 762 /* 763 * Reset all line input parameters for a new input line. 764 */ 765 static void gl_reset_input_line(GetLine *gl); 766 767 /* 768 * Handle the receipt of the potential start of a new key-sequence from 769 * the user. 770 */ 771 static int gl_interpret_char(GetLine *gl, char c); 772 773 /* 774 * Bind a single control or meta character to an action. 775 */ 776 static int gl_bind_control_char(GetLine *gl, KtBinder binder, 777 char c, const char *action); 778 779 /* 780 * Set up terminal-specific key bindings. 781 */ 782 static int gl_bind_terminal_keys(GetLine *gl); 783 784 /* 785 * Lookup terminal control string and size information. 786 */ 787 static int gl_control_strings(GetLine *gl, const char *term); 788 789 /* 790 * Wrappers around the terminfo and termcap functions that lookup 791 * strings in the terminal information databases. 792 */ 793 #ifdef USE_TERMINFO 794 static const char *gl_tigetstr(GetLine *gl, const char *name); 795 #elif defined(USE_TERMCAP) 796 static const char *gl_tgetstr(GetLine *gl, const char *name, char **bufptr); 797 #endif 798 799 /* 800 * Output a binary string directly to the terminal. 801 */ 802 static int gl_print_raw_string(GetLine *gl, int buffered, 803 const char *string, int n); 804 805 /* 806 * Print an informational message, starting and finishing on new lines. 807 * After the list of strings to be printed, the last argument MUST be 808 * GL_END_INFO. 809 */ 810 static int gl_print_info(GetLine *gl, ...); 811 #define GL_END_INFO ((const char *)0) 812 813 /* 814 * Start a newline and place the cursor at its start. 815 */ 816 static int gl_start_newline(GetLine *gl, int buffered); 817 818 /* 819 * Output a terminal control sequence. 820 */ 821 static int gl_print_control_sequence(GetLine *gl, int nline, 822 const char *string); 823 824 /* 825 * Output a character or string to the terminal after converting tabs 826 * to spaces and control characters to a caret followed by the modified 827 * character. 828 */ 829 static int gl_print_char(GetLine *gl, char c, char pad); 830 static int gl_print_string(GetLine *gl, const char *string, char pad); 831 832 /* 833 * Delete nc characters starting from the one under the cursor. 834 * Optionally copy the deleted characters to the cut buffer. 835 */ 836 static int gl_delete_chars(GetLine *gl, int nc, int cut); 837 838 /* 839 * Add a character to the line buffer at the current cursor position, 840 * inserting or overwriting according the current mode. 841 */ 842 static int gl_add_char_to_line(GetLine *gl, char c); 843 844 /* 845 * Insert/append a string to the line buffer and terminal at the current 846 * cursor position. 847 */ 848 static int gl_add_string_to_line(GetLine *gl, const char *s); 849 850 /* 851 * Record a new character in the input-line buffer. 852 */ 853 static int gl_buffer_char(GetLine *gl, char c, int bufpos); 854 855 /* 856 * Record a string in the input-line buffer. 857 */ 858 static int gl_buffer_string(GetLine *gl, const char *s, int n, int bufpos); 859 860 /* 861 * Make way to insert a string in the input-line buffer. 862 */ 863 static int gl_make_gap_in_buffer(GetLine *gl, int start, int n); 864 865 /* 866 * Remove characters from the input-line buffer, and move any characters 867 * that followed them to the start of the vacated space. 868 */ 869 static void gl_remove_from_buffer(GetLine *gl, int start, int n); 870 871 /* 872 * Terminate the input-line buffer after a specified number of characters. 873 */ 874 static int gl_truncate_buffer(GetLine *gl, int n); 875 876 /* 877 * Delete the displayed part of the input line that follows the current 878 * terminal cursor position. 879 */ 880 static int gl_truncate_display(GetLine *gl); 881 882 /* 883 * Accomodate changes to the contents of the input line buffer 884 * that weren't made by the above gl_*buffer functions. 885 */ 886 static void gl_update_buffer(GetLine *gl); 887 888 /* 889 * Read a single character from the terminal. 890 */ 891 static int gl_read_terminal(GetLine *gl, int keep, char *c); 892 893 /* 894 * Discard processed characters from the key-press lookahead buffer. 895 */ 896 static void gl_discard_chars(GetLine *gl, int nused); 897 898 /* 899 * Move the terminal cursor n positions to the left or right. 900 */ 901 static int gl_terminal_move_cursor(GetLine *gl, int n); 902 903 /* 904 * Move the terminal cursor to a given position. 905 */ 906 static int gl_set_term_curpos(GetLine *gl, int term_curpos); 907 908 /* 909 * Set the position of the cursor both in the line input buffer and on the 910 * terminal. 911 */ 912 static int gl_place_cursor(GetLine *gl, int buff_curpos); 913 914 /* 915 * How many characters are needed to write a number as an octal string? 916 */ 917 static int gl_octal_width(unsigned num); 918 919 /* 920 * Return the number of spaces needed to display a tab character at 921 * a given location of the terminal. 922 */ 923 static int gl_displayed_tab_width(GetLine *gl, int term_curpos); 924 925 /* 926 * Return the number of terminal characters needed to display a 927 * given raw character. 928 */ 929 static int gl_displayed_char_width(GetLine *gl, char c, int term_curpos); 930 931 /* 932 * Return the number of terminal characters needed to display a 933 * given substring. 934 */ 935 static int gl_displayed_string_width(GetLine *gl, const char *string, int nc, 936 int term_curpos); 937 938 /* 939 * Return non-zero if 'c' is to be considered part of a word. 940 */ 941 static int gl_is_word_char(int c); 942 943 /* 944 * Read a tecla configuration file. 945 */ 946 static int _gl_read_config_file(GetLine *gl, const char *filename, KtBinder who); 947 948 /* 949 * Read a tecla configuration string. 950 */ 951 static int _gl_read_config_string(GetLine *gl, const char *buffer, KtBinder who); 952 953 /* 954 * Define the callback function used by _gl_parse_config_line() to 955 * read the next character of a configuration stream. 956 */ 957 #define GLC_GETC_FN(fn) int (fn)(void *stream) 958 typedef GLC_GETC_FN(GlcGetcFn); 959 960 static GLC_GETC_FN(glc_file_getc); /* Read from a file */ 961 static GLC_GETC_FN(glc_buff_getc); /* Read from a string */ 962 963 /* 964 * Parse a single configuration command line. 965 */ 966 static int _gl_parse_config_line(GetLine *gl, void *stream, GlcGetcFn *getc_fn, 967 const char *origin, KtBinder who, int *lineno); 968 static int gl_report_config_error(GetLine *gl, const char *origin, int lineno, 969 const char *errmsg); 970 971 /* 972 * Bind the actual arrow key bindings to match those of the symbolic 973 * arrow-key bindings. 974 */ 975 static int _gl_bind_arrow_keys(GetLine *gl); 976 977 /* 978 * Copy the binding of the specified symbolic arrow-key binding to 979 * the terminal specific, and default arrow-key key-sequences. 980 */ 981 static int _gl_rebind_arrow_key(GetLine *gl, const char *name, 982 const char *term_seq, 983 const char *def_seq1, 984 const char *def_seq2); 985 986 /* 987 * After the gl_read_from_file() action has been used to tell gl_get_line() 988 * to temporarily read input from a file, gl_revert_input() arranges 989 * for input to be reverted to the input stream last registered with 990 * gl_change_terminal(). 991 */ 992 static void gl_revert_input(GetLine *gl); 993 994 /* 995 * Flush unwritten characters to the terminal. 996 */ 997 static int gl_flush_output(GetLine *gl); 998 999 /* 1000 * The callback through which all terminal output is routed. 1001 * This simply appends characters to a queue buffer, which is 1002 * subsequently flushed to the output channel by gl_flush_output(). 1003 */ 1004 static GL_WRITE_FN(gl_write_fn); 1005 1006 /* 1007 * The callback function which the output character queue object 1008 * calls to transfer characters to the output channel. 1009 */ 1010 static GL_WRITE_FN(gl_flush_terminal); 1011 1012 /* 1013 * Enumerate the possible return statuses of gl_read_input(). 1014 */ 1015 typedef enum { 1016 GL_READ_OK, /* A character was read successfully */ 1017 GL_READ_ERROR, /* A read-error occurred */ 1018 GL_READ_BLOCKED, /* The read would have blocked the caller */ 1019 GL_READ_EOF /* The end of the current input file was reached */ 1020 } GlReadStatus; 1021 1022 static GlReadStatus gl_read_input(GetLine *gl, char *c); 1023 /* 1024 * Private functions of gl_read_input(). 1025 */ 1026 static int gl_event_handler(GetLine *gl, int fd); 1027 static int gl_read_unmasked(GetLine *gl, int fd, char *c); 1028 1029 1030 /* 1031 * A private function of gl_tty_signals(). 1032 */ 1033 static int gl_set_tty_signal(int signo, void (*handler)(int)); 1034 1035 /* 1036 * Change the editor style being emulated. 1037 */ 1038 static int gl_change_editor(GetLine *gl, GlEditor editor); 1039 1040 /* 1041 * Searching in a given direction, return the index of a given (or 1042 * read) character in the input line, or the character that precedes 1043 * it in the specified search direction. Return -1 if not found. 1044 */ 1045 static int gl_find_char(GetLine *gl, int count, int forward, int onto, char c); 1046 1047 /* 1048 * Return the buffer index of the nth word ending after the cursor. 1049 */ 1050 static int gl_nth_word_end_forward(GetLine *gl, int n); 1051 1052 /* 1053 * Return the buffer index of the nth word start after the cursor. 1054 */ 1055 static int gl_nth_word_start_forward(GetLine *gl, int n); 1056 1057 /* 1058 * Return the buffer index of the nth word start before the cursor. 1059 */ 1060 static int gl_nth_word_start_backward(GetLine *gl, int n); 1061 1062 /* 1063 * When called when vi command mode is enabled, this function saves the 1064 * current line and cursor position for potential restoration later 1065 * by the vi undo command. 1066 */ 1067 static void gl_save_for_undo(GetLine *gl); 1068 1069 /* 1070 * If in vi mode, switch to vi command mode. 1071 */ 1072 static void gl_vi_command_mode(GetLine *gl); 1073 1074 /* 1075 * In vi mode this is used to delete up to or onto a given or read 1076 * character in the input line. Also switch to insert mode if requested 1077 * after the deletion. 1078 */ 1079 static int gl_delete_find(GetLine *gl, int count, char c, int forward, 1080 int onto, int change); 1081 1082 /* 1083 * Copy the characters between the cursor and the count'th instance of 1084 * a specified (or read) character in the input line, into the cut buffer. 1085 */ 1086 static int gl_copy_find(GetLine *gl, int count, char c, int forward, int onto); 1087 1088 /* 1089 * Return the line index of the parenthesis that either matches the one under 1090 * the cursor, or not over a parenthesis character, the index of the next 1091 * close parenthesis. Return -1 if not found. 1092 */ 1093 static int gl_index_of_matching_paren(GetLine *gl); 1094 1095 /* 1096 * Replace a malloc'd string (or NULL), with another malloc'd copy of 1097 * a string (or NULL). 1098 */ 1099 static int gl_record_string(char **sptr, const char *string); 1100 1101 /* 1102 * Enumerate text display attributes as powers of two, suitable for 1103 * use in a bit-mask. 1104 */ 1105 typedef enum { 1106 GL_TXT_STANDOUT=1, /* Display text highlighted */ 1107 GL_TXT_UNDERLINE=2, /* Display text underlined */ 1108 GL_TXT_REVERSE=4, /* Display text with reverse video */ 1109 GL_TXT_BLINK=8, /* Display blinking text */ 1110 GL_TXT_DIM=16, /* Display text in a dim font */ 1111 GL_TXT_BOLD=32 /* Display text using a bold font */ 1112 } GlTextAttr; 1113 1114 /* 1115 * Display the prompt regardless of the current visibility mode. 1116 */ 1117 static int gl_display_prompt(GetLine *gl); 1118 1119 /* 1120 * Return the number of characters used by the prompt on the terminal. 1121 */ 1122 static int gl_displayed_prompt_width(GetLine *gl); 1123 1124 /* 1125 * Prepare to return the current input line to the caller of gl_get_line(). 1126 */ 1127 static int gl_line_ended(GetLine *gl, int newline_char); 1128 1129 /* 1130 * Arrange for the input line to be redisplayed when the current contents 1131 * of the output queue have been flushed. 1132 */ 1133 static void gl_queue_redisplay(GetLine *gl); 1134 1135 /* 1136 * Erase the displayed representation of the input line, without 1137 * touching the buffered copy. 1138 */ 1139 static int gl_erase_line(GetLine *gl); 1140 1141 /* 1142 * This function is called whenever the input line has been erased. 1143 */ 1144 static void gl_line_erased(GetLine *gl); 1145 1146 /* 1147 * Arrange for the current input line to be discarded. 1148 */ 1149 void _gl_abandon_line(GetLine *gl); 1150 1151 /* 1152 * The following are private internally callable versions of pertinent 1153 * public functions. Unlike their public wrapper functions, they don't 1154 * block signals while running, and assume that their arguments are valid. 1155 * They are designed to be called from places where signals are already 1156 * blocked, and where simple sanity checks have already been applied to 1157 * their arguments. 1158 */ 1159 static char *_gl_get_line(GetLine *gl, const char *prompt, 1160 const char *start_line, int start_pos); 1161 static int _gl_query_char(GetLine *gl, const char *prompt, char defchar); 1162 static int _gl_read_char(GetLine *gl); 1163 static int _gl_update_size(GetLine *gl); 1164 /* 1165 * Redraw the current input line to account for a change in the terminal 1166 * size. Also install the new size in gl. 1167 */ 1168 static int gl_handle_tty_resize(GetLine *gl, int ncolumn, int nline); 1169 1170 static int _gl_change_terminal(GetLine *gl, FILE *input_fp, FILE *output_fp, 1171 const char *term); 1172 static int _gl_configure_getline(GetLine *gl, const char *app_string, 1173 const char *app_file, const char *user_file); 1174 static int _gl_save_history(GetLine *gl, const char *filename, 1175 const char *comment, int max_lines); 1176 static int _gl_load_history(GetLine *gl, const char *filename, 1177 const char *comment); 1178 static int _gl_watch_fd(GetLine *gl, int fd, GlFdEvent event, 1179 GlFdEventFn *callback, void *data); 1180 static void _gl_terminal_size(GetLine *gl, int def_ncolumn, int def_nline, 1181 GlTerminalSize *size); 1182 static void _gl_replace_prompt(GetLine *gl, const char *prompt); 1183 static int _gl_trap_signal(GetLine *gl, int signo, unsigned flags, 1184 GlAfterSignal after, int errno_value); 1185 static int _gl_raw_io(GetLine *gl, int redisplay); 1186 static int _gl_normal_io(GetLine *gl); 1187 static int _gl_completion_action(GetLine *gl, void *data, CplMatchFn *match_fn, 1188 int list_only, const char *name, 1189 const char *keyseq); 1190 static int _gl_register_action(GetLine *gl, void *data, GlActionFn *fn, 1191 const char *name, const char *keyseq); 1192 static int _gl_io_mode(GetLine *gl, GlIOMode mode); 1193 static int _gl_set_term_size(GetLine *gl, int ncolumn, int nline); 1194 static int _gl_append_history(GetLine *gl, const char *line); 1195 1196 /* 1197 * Reset the completion status and associated errno value in 1198 * gl->rtn_status and gl->rtn_errno. 1199 */ 1200 static void gl_clear_status(GetLine *gl); 1201 1202 /* 1203 * Record a completion status, unless a previous abnormal completion 1204 * status has already been recorded for the current call. 1205 */ 1206 static void gl_record_status(GetLine *gl, GlReturnStatus rtn_status, 1207 int rtn_errno); 1208 1209 /* 1210 * Set the maximum length of a line in a user's tecla configuration 1211 * file (not counting comments). 1212 */ 1213 #define GL_CONF_BUFLEN 100 1214 1215 /* 1216 * Set the maximum number of arguments supported by individual commands 1217 * in tecla configuration files. 1218 */ 1219 #define GL_CONF_MAXARG 10 1220 1221 /* 1222 * Prototype the available action functions. 1223 */ 1224 static KT_KEY_FN(gl_user_interrupt); 1225 static KT_KEY_FN(gl_abort); 1226 static KT_KEY_FN(gl_suspend); 1227 static KT_KEY_FN(gl_stop_output); 1228 static KT_KEY_FN(gl_start_output); 1229 static KT_KEY_FN(gl_literal_next); 1230 static KT_KEY_FN(gl_cursor_left); 1231 static KT_KEY_FN(gl_cursor_right); 1232 static KT_KEY_FN(gl_insert_mode); 1233 static KT_KEY_FN(gl_beginning_of_line); 1234 static KT_KEY_FN(gl_end_of_line); 1235 static KT_KEY_FN(gl_delete_line); 1236 static KT_KEY_FN(gl_kill_line); 1237 static KT_KEY_FN(gl_forward_word); 1238 static KT_KEY_FN(gl_backward_word); 1239 static KT_KEY_FN(gl_forward_delete_char); 1240 static KT_KEY_FN(gl_backward_delete_char); 1241 static KT_KEY_FN(gl_forward_delete_word); 1242 static KT_KEY_FN(gl_backward_delete_word); 1243 static KT_KEY_FN(gl_delete_refind); 1244 static KT_KEY_FN(gl_delete_invert_refind); 1245 static KT_KEY_FN(gl_delete_to_column); 1246 static KT_KEY_FN(gl_delete_to_parenthesis); 1247 static KT_KEY_FN(gl_forward_delete_find); 1248 static KT_KEY_FN(gl_backward_delete_find); 1249 static KT_KEY_FN(gl_forward_delete_to); 1250 static KT_KEY_FN(gl_backward_delete_to); 1251 static KT_KEY_FN(gl_upcase_word); 1252 static KT_KEY_FN(gl_downcase_word); 1253 static KT_KEY_FN(gl_capitalize_word); 1254 static KT_KEY_FN(gl_redisplay); 1255 static KT_KEY_FN(gl_clear_screen); 1256 static KT_KEY_FN(gl_transpose_chars); 1257 static KT_KEY_FN(gl_set_mark); 1258 static KT_KEY_FN(gl_exchange_point_and_mark); 1259 static KT_KEY_FN(gl_kill_region); 1260 static KT_KEY_FN(gl_copy_region_as_kill); 1261 static KT_KEY_FN(gl_yank); 1262 static KT_KEY_FN(gl_up_history); 1263 static KT_KEY_FN(gl_down_history); 1264 static KT_KEY_FN(gl_history_search_backward); 1265 static KT_KEY_FN(gl_history_re_search_backward); 1266 static KT_KEY_FN(gl_history_search_forward); 1267 static KT_KEY_FN(gl_history_re_search_forward); 1268 static KT_KEY_FN(gl_complete_word); 1269 #ifndef HIDE_FILE_SYSTEM 1270 static KT_KEY_FN(gl_expand_filename); 1271 static KT_KEY_FN(gl_read_from_file); 1272 static KT_KEY_FN(gl_read_init_files); 1273 static KT_KEY_FN(gl_list_glob); 1274 #endif 1275 static KT_KEY_FN(gl_del_char_or_list_or_eof); 1276 static KT_KEY_FN(gl_list_or_eof); 1277 static KT_KEY_FN(gl_beginning_of_history); 1278 static KT_KEY_FN(gl_end_of_history); 1279 static KT_KEY_FN(gl_digit_argument); 1280 static KT_KEY_FN(gl_newline); 1281 static KT_KEY_FN(gl_repeat_history); 1282 static KT_KEY_FN(gl_vi_insert); 1283 static KT_KEY_FN(gl_vi_overwrite); 1284 static KT_KEY_FN(gl_change_case); 1285 static KT_KEY_FN(gl_vi_insert_at_bol); 1286 static KT_KEY_FN(gl_vi_append_at_eol); 1287 static KT_KEY_FN(gl_vi_append); 1288 static KT_KEY_FN(gl_backward_kill_line); 1289 static KT_KEY_FN(gl_goto_column); 1290 static KT_KEY_FN(gl_forward_to_word); 1291 static KT_KEY_FN(gl_vi_replace_char); 1292 static KT_KEY_FN(gl_vi_change_rest_of_line); 1293 static KT_KEY_FN(gl_vi_change_line); 1294 static KT_KEY_FN(gl_vi_change_to_bol); 1295 static KT_KEY_FN(gl_vi_change_refind); 1296 static KT_KEY_FN(gl_vi_change_invert_refind); 1297 static KT_KEY_FN(gl_vi_change_to_column); 1298 static KT_KEY_FN(gl_vi_change_to_parenthesis); 1299 static KT_KEY_FN(gl_vi_forward_change_word); 1300 static KT_KEY_FN(gl_vi_backward_change_word); 1301 static KT_KEY_FN(gl_vi_forward_change_find); 1302 static KT_KEY_FN(gl_vi_backward_change_find); 1303 static KT_KEY_FN(gl_vi_forward_change_to); 1304 static KT_KEY_FN(gl_vi_backward_change_to); 1305 static KT_KEY_FN(gl_vi_forward_change_char); 1306 static KT_KEY_FN(gl_vi_backward_change_char); 1307 static KT_KEY_FN(gl_forward_copy_char); 1308 static KT_KEY_FN(gl_backward_copy_char); 1309 static KT_KEY_FN(gl_forward_find_char); 1310 static KT_KEY_FN(gl_backward_find_char); 1311 static KT_KEY_FN(gl_forward_to_char); 1312 static KT_KEY_FN(gl_backward_to_char); 1313 static KT_KEY_FN(gl_repeat_find_char); 1314 static KT_KEY_FN(gl_invert_refind_char); 1315 static KT_KEY_FN(gl_append_yank); 1316 static KT_KEY_FN(gl_backward_copy_word); 1317 static KT_KEY_FN(gl_forward_copy_word); 1318 static KT_KEY_FN(gl_copy_to_bol); 1319 static KT_KEY_FN(gl_copy_refind); 1320 static KT_KEY_FN(gl_copy_invert_refind); 1321 static KT_KEY_FN(gl_copy_to_column); 1322 static KT_KEY_FN(gl_copy_to_parenthesis); 1323 static KT_KEY_FN(gl_copy_rest_of_line); 1324 static KT_KEY_FN(gl_copy_line); 1325 static KT_KEY_FN(gl_backward_copy_find); 1326 static KT_KEY_FN(gl_forward_copy_find); 1327 static KT_KEY_FN(gl_backward_copy_to); 1328 static KT_KEY_FN(gl_forward_copy_to); 1329 static KT_KEY_FN(gl_vi_undo); 1330 static KT_KEY_FN(gl_emacs_editing_mode); 1331 static KT_KEY_FN(gl_vi_editing_mode); 1332 static KT_KEY_FN(gl_ring_bell); 1333 static KT_KEY_FN(gl_vi_repeat_change); 1334 static KT_KEY_FN(gl_find_parenthesis); 1335 static KT_KEY_FN(gl_list_history); 1336 static KT_KEY_FN(gl_list_completions); 1337 static KT_KEY_FN(gl_run_external_action); 1338 1339 /* 1340 * Name the available action functions. 1341 */ 1342 static const struct {const char *name; KT_KEY_FN(*fn);} gl_actions[] = { 1343 {"user-interrupt", gl_user_interrupt}, 1344 {"abort", gl_abort}, 1345 {"suspend", gl_suspend}, 1346 {"stop-output", gl_stop_output}, 1347 {"start-output", gl_start_output}, 1348 {"literal-next", gl_literal_next}, 1349 {"cursor-right", gl_cursor_right}, 1350 {"cursor-left", gl_cursor_left}, 1351 {"insert-mode", gl_insert_mode}, 1352 {"beginning-of-line", gl_beginning_of_line}, 1353 {"end-of-line", gl_end_of_line}, 1354 {"delete-line", gl_delete_line}, 1355 {"kill-line", gl_kill_line}, 1356 {"forward-word", gl_forward_word}, 1357 {"backward-word", gl_backward_word}, 1358 {"forward-delete-char", gl_forward_delete_char}, 1359 {"backward-delete-char", gl_backward_delete_char}, 1360 {"forward-delete-word", gl_forward_delete_word}, 1361 {"backward-delete-word", gl_backward_delete_word}, 1362 {"delete-refind", gl_delete_refind}, 1363 {"delete-invert-refind", gl_delete_invert_refind}, 1364 {"delete-to-column", gl_delete_to_column}, 1365 {"delete-to-parenthesis", gl_delete_to_parenthesis}, 1366 {"forward-delete-find", gl_forward_delete_find}, 1367 {"backward-delete-find", gl_backward_delete_find}, 1368 {"forward-delete-to", gl_forward_delete_to}, 1369 {"backward-delete-to", gl_backward_delete_to}, 1370 {"upcase-word", gl_upcase_word}, 1371 {"downcase-word", gl_downcase_word}, 1372 {"capitalize-word", gl_capitalize_word}, 1373 {"redisplay", gl_redisplay}, 1374 {"clear-screen", gl_clear_screen}, 1375 {"transpose-chars", gl_transpose_chars}, 1376 {"set-mark", gl_set_mark}, 1377 {"exchange-point-and-mark", gl_exchange_point_and_mark}, 1378 {"kill-region", gl_kill_region}, 1379 {"copy-region-as-kill", gl_copy_region_as_kill}, 1380 {"yank", gl_yank}, 1381 {"up-history", gl_up_history}, 1382 {"down-history", gl_down_history}, 1383 {"history-search-backward", gl_history_search_backward}, 1384 {"history-re-search-backward", gl_history_re_search_backward}, 1385 {"history-search-forward", gl_history_search_forward}, 1386 {"history-re-search-forward", gl_history_re_search_forward}, 1387 {"complete-word", gl_complete_word}, 1388 #ifndef HIDE_FILE_SYSTEM 1389 {"expand-filename", gl_expand_filename}, 1390 {"read-from-file", gl_read_from_file}, 1391 {"read-init-files", gl_read_init_files}, 1392 {"list-glob", gl_list_glob}, 1393 #endif 1394 {"del-char-or-list-or-eof", gl_del_char_or_list_or_eof}, 1395 {"beginning-of-history", gl_beginning_of_history}, 1396 {"end-of-history", gl_end_of_history}, 1397 {"digit-argument", gl_digit_argument}, 1398 {"newline", gl_newline}, 1399 {"repeat-history", gl_repeat_history}, 1400 {"vi-insert", gl_vi_insert}, 1401 {"vi-overwrite", gl_vi_overwrite}, 1402 {"vi-insert-at-bol", gl_vi_insert_at_bol}, 1403 {"vi-append-at-eol", gl_vi_append_at_eol}, 1404 {"vi-append", gl_vi_append}, 1405 {"change-case", gl_change_case}, 1406 {"backward-kill-line", gl_backward_kill_line}, 1407 {"goto-column", gl_goto_column}, 1408 {"forward-to-word", gl_forward_to_word}, 1409 {"vi-replace-char", gl_vi_replace_char}, 1410 {"vi-change-rest-of-line", gl_vi_change_rest_of_line}, 1411 {"vi-change-line", gl_vi_change_line}, 1412 {"vi-change-to-bol", gl_vi_change_to_bol}, 1413 {"vi-change-refind", gl_vi_change_refind}, 1414 {"vi-change-invert-refind", gl_vi_change_invert_refind}, 1415 {"vi-change-to-column", gl_vi_change_to_column}, 1416 {"vi-change-to-parenthesis", gl_vi_change_to_parenthesis}, 1417 {"forward-copy-char", gl_forward_copy_char}, 1418 {"backward-copy-char", gl_backward_copy_char}, 1419 {"forward-find-char", gl_forward_find_char}, 1420 {"backward-find-char", gl_backward_find_char}, 1421 {"forward-to-char", gl_forward_to_char}, 1422 {"backward-to-char", gl_backward_to_char}, 1423 {"repeat-find-char", gl_repeat_find_char}, 1424 {"invert-refind-char", gl_invert_refind_char}, 1425 {"append-yank", gl_append_yank}, 1426 {"backward-copy-word", gl_backward_copy_word}, 1427 {"forward-copy-word", gl_forward_copy_word}, 1428 {"copy-to-bol", gl_copy_to_bol}, 1429 {"copy-refind", gl_copy_refind}, 1430 {"copy-invert-refind", gl_copy_invert_refind}, 1431 {"copy-to-column", gl_copy_to_column}, 1432 {"copy-to-parenthesis", gl_copy_to_parenthesis}, 1433 {"copy-rest-of-line", gl_copy_rest_of_line}, 1434 {"copy-line", gl_copy_line}, 1435 {"backward-copy-find", gl_backward_copy_find}, 1436 {"forward-copy-find", gl_forward_copy_find}, 1437 {"backward-copy-to", gl_backward_copy_to}, 1438 {"forward-copy-to", gl_forward_copy_to}, 1439 {"list-or-eof", gl_list_or_eof}, 1440 {"vi-undo", gl_vi_undo}, 1441 {"vi-backward-change-word", gl_vi_backward_change_word}, 1442 {"vi-forward-change-word", gl_vi_forward_change_word}, 1443 {"vi-backward-change-find", gl_vi_backward_change_find}, 1444 {"vi-forward-change-find", gl_vi_forward_change_find}, 1445 {"vi-backward-change-to", gl_vi_backward_change_to}, 1446 {"vi-forward-change-to", gl_vi_forward_change_to}, 1447 {"vi-backward-change-char", gl_vi_backward_change_char}, 1448 {"vi-forward-change-char", gl_vi_forward_change_char}, 1449 {"emacs-mode", gl_emacs_editing_mode}, 1450 {"vi-mode", gl_vi_editing_mode}, 1451 {"ring-bell", gl_ring_bell}, 1452 {"vi-repeat-change", gl_vi_repeat_change}, 1453 {"find-parenthesis", gl_find_parenthesis}, 1454 {"list-history", gl_list_history}, 1455 }; 1456 1457 /* 1458 * Define the default key-bindings in emacs mode. 1459 */ 1460 static const KtKeyBinding gl_emacs_bindings[] = { 1461 {"right", "cursor-right"}, 1462 {"^F", "cursor-right"}, 1463 {"left", "cursor-left"}, 1464 {"^B", "cursor-left"}, 1465 {"M-i", "insert-mode"}, 1466 {"M-I", "insert-mode"}, 1467 {"^A", "beginning-of-line"}, 1468 {"^E", "end-of-line"}, 1469 {"^U", "delete-line"}, 1470 {"^K", "kill-line"}, 1471 {"M-f", "forward-word"}, 1472 {"M-F", "forward-word"}, 1473 {"M-b", "backward-word"}, 1474 {"M-B", "backward-word"}, 1475 {"^D", "del-char-or-list-or-eof"}, 1476 {"^H", "backward-delete-char"}, 1477 {"^?", "backward-delete-char"}, 1478 {"M-d", "forward-delete-word"}, 1479 {"M-D", "forward-delete-word"}, 1480 {"M-^H", "backward-delete-word"}, 1481 {"M-^?", "backward-delete-word"}, 1482 {"M-u", "upcase-word"}, 1483 {"M-U", "upcase-word"}, 1484 {"M-l", "downcase-word"}, 1485 {"M-L", "downcase-word"}, 1486 {"M-c", "capitalize-word"}, 1487 {"M-C", "capitalize-word"}, 1488 {"^R", "redisplay"}, 1489 {"^L", "clear-screen"}, 1490 {"^T", "transpose-chars"}, 1491 {"^@", "set-mark"}, 1492 {"^X^X", "exchange-point-and-mark"}, 1493 {"^W", "kill-region"}, 1494 {"M-w", "copy-region-as-kill"}, 1495 {"M-W", "copy-region-as-kill"}, 1496 {"^Y", "yank"}, 1497 {"^P", "up-history"}, 1498 {"up", "up-history"}, 1499 {"^N", "down-history"}, 1500 {"down", "down-history"}, 1501 {"M-p", "history-search-backward"}, 1502 {"M-P", "history-search-backward"}, 1503 {"M-n", "history-search-forward"}, 1504 {"M-N", "history-search-forward"}, 1505 {"\t", "complete-word"}, 1506 #ifndef HIDE_FILE_SYSTEM 1507 {"^X*", "expand-filename"}, 1508 {"^X^F", "read-from-file"}, 1509 {"^X^R", "read-init-files"}, 1510 {"^Xg", "list-glob"}, 1511 {"^XG", "list-glob"}, 1512 #endif 1513 {"^Xh", "list-history"}, 1514 {"^XH", "list-history"}, 1515 {"M-<", "beginning-of-history"}, 1516 {"M->", "end-of-history"}, 1517 {"M-0", "digit-argument"}, 1518 {"M-1", "digit-argument"}, 1519 {"M-2", "digit-argument"}, 1520 {"M-3", "digit-argument"}, 1521 {"M-4", "digit-argument"}, 1522 {"M-5", "digit-argument"}, 1523 {"M-6", "digit-argument"}, 1524 {"M-7", "digit-argument"}, 1525 {"M-8", "digit-argument"}, 1526 {"M-9", "digit-argument"}, 1527 {"\r", "newline"}, 1528 {"\n", "newline"}, 1529 {"M-o", "repeat-history"}, 1530 {"M-C-v", "vi-mode"}, 1531 }; 1532 1533 /* 1534 * Define the default key-bindings in vi mode. Note that in vi-mode 1535 * meta-key bindings are command-mode bindings. For example M-i first 1536 * switches to command mode if not already in that mode, then moves 1537 * the cursor one position right, as in vi. 1538 */ 1539 static const KtKeyBinding gl_vi_bindings[] = { 1540 {"^D", "list-or-eof"}, 1541 #ifndef HIDE_FILE_SYSTEM 1542 {"^G", "list-glob"}, 1543 #endif 1544 {"^H", "backward-delete-char"}, 1545 {"\t", "complete-word"}, 1546 {"\r", "newline"}, 1547 {"\n", "newline"}, 1548 {"^L", "clear-screen"}, 1549 {"^N", "down-history"}, 1550 {"^P", "up-history"}, 1551 {"^R", "redisplay"}, 1552 {"^U", "backward-kill-line"}, 1553 {"^W", "backward-delete-word"}, 1554 #ifndef HIDE_FILE_SYSTEM 1555 {"^X^F", "read-from-file"}, 1556 {"^X^R", "read-init-files"}, 1557 {"^X*", "expand-filename"}, 1558 #endif 1559 {"^?", "backward-delete-char"}, 1560 {"M- ", "cursor-right"}, 1561 {"M-$", "end-of-line"}, 1562 #ifndef HIDE_FILE_SYSTEM 1563 {"M-*", "expand-filename"}, 1564 #endif 1565 {"M-+", "down-history"}, 1566 {"M--", "up-history"}, 1567 {"M-<", "beginning-of-history"}, 1568 {"M->", "end-of-history"}, 1569 {"M-^", "beginning-of-line"}, 1570 {"M-;", "repeat-find-char"}, 1571 {"M-,", "invert-refind-char"}, 1572 {"M-|", "goto-column"}, 1573 {"M-~", "change-case"}, 1574 {"M-.", "vi-repeat-change"}, 1575 {"M-%", "find-parenthesis"}, 1576 {"M-0", "digit-argument"}, 1577 {"M-1", "digit-argument"}, 1578 {"M-2", "digit-argument"}, 1579 {"M-3", "digit-argument"}, 1580 {"M-4", "digit-argument"}, 1581 {"M-5", "digit-argument"}, 1582 {"M-6", "digit-argument"}, 1583 {"M-7", "digit-argument"}, 1584 {"M-8", "digit-argument"}, 1585 {"M-9", "digit-argument"}, 1586 {"M-a", "vi-append"}, 1587 {"M-A", "vi-append-at-eol"}, 1588 {"M-b", "backward-word"}, 1589 {"M-B", "backward-word"}, 1590 {"M-C", "vi-change-rest-of-line"}, 1591 {"M-cb", "vi-backward-change-word"}, 1592 {"M-cB", "vi-backward-change-word"}, 1593 {"M-cc", "vi-change-line"}, 1594 {"M-ce", "vi-forward-change-word"}, 1595 {"M-cE", "vi-forward-change-word"}, 1596 {"M-cw", "vi-forward-change-word"}, 1597 {"M-cW", "vi-forward-change-word"}, 1598 {"M-cF", "vi-backward-change-find"}, 1599 {"M-cf", "vi-forward-change-find"}, 1600 {"M-cT", "vi-backward-change-to"}, 1601 {"M-ct", "vi-forward-change-to"}, 1602 {"M-c;", "vi-change-refind"}, 1603 {"M-c,", "vi-change-invert-refind"}, 1604 {"M-ch", "vi-backward-change-char"}, 1605 {"M-c^H", "vi-backward-change-char"}, 1606 {"M-c^?", "vi-backward-change-char"}, 1607 {"M-cl", "vi-forward-change-char"}, 1608 {"M-c ", "vi-forward-change-char"}, 1609 {"M-c^", "vi-change-to-bol"}, 1610 {"M-c0", "vi-change-to-bol"}, 1611 {"M-c$", "vi-change-rest-of-line"}, 1612 {"M-c|", "vi-change-to-column"}, 1613 {"M-c%", "vi-change-to-parenthesis"}, 1614 {"M-dh", "backward-delete-char"}, 1615 {"M-d^H", "backward-delete-char"}, 1616 {"M-d^?", "backward-delete-char"}, 1617 {"M-dl", "forward-delete-char"}, 1618 {"M-d ", "forward-delete-char"}, 1619 {"M-dd", "delete-line"}, 1620 {"M-db", "backward-delete-word"}, 1621 {"M-dB", "backward-delete-word"}, 1622 {"M-de", "forward-delete-word"}, 1623 {"M-dE", "forward-delete-word"}, 1624 {"M-dw", "forward-delete-word"}, 1625 {"M-dW", "forward-delete-word"}, 1626 {"M-dF", "backward-delete-find"}, 1627 {"M-df", "forward-delete-find"}, 1628 {"M-dT", "backward-delete-to"}, 1629 {"M-dt", "forward-delete-to"}, 1630 {"M-d;", "delete-refind"}, 1631 {"M-d,", "delete-invert-refind"}, 1632 {"M-d^", "backward-kill-line"}, 1633 {"M-d0", "backward-kill-line"}, 1634 {"M-d$", "kill-line"}, 1635 {"M-D", "kill-line"}, 1636 {"M-d|", "delete-to-column"}, 1637 {"M-d%", "delete-to-parenthesis"}, 1638 {"M-e", "forward-word"}, 1639 {"M-E", "forward-word"}, 1640 {"M-f", "forward-find-char"}, 1641 {"M-F", "backward-find-char"}, 1642 {"M--", "up-history"}, 1643 {"M-h", "cursor-left"}, 1644 {"M-H", "beginning-of-history"}, 1645 {"M-i", "vi-insert"}, 1646 {"M-I", "vi-insert-at-bol"}, 1647 {"M-j", "down-history"}, 1648 {"M-J", "history-search-forward"}, 1649 {"M-k", "up-history"}, 1650 {"M-K", "history-search-backward"}, 1651 {"M-l", "cursor-right"}, 1652 {"M-L", "end-of-history"}, 1653 {"M-n", "history-re-search-forward"}, 1654 {"M-N", "history-re-search-backward"}, 1655 {"M-p", "append-yank"}, 1656 {"M-P", "yank"}, 1657 {"M-r", "vi-replace-char"}, 1658 {"M-R", "vi-overwrite"}, 1659 {"M-s", "vi-forward-change-char"}, 1660 {"M-S", "vi-change-line"}, 1661 {"M-t", "forward-to-char"}, 1662 {"M-T", "backward-to-char"}, 1663 {"M-u", "vi-undo"}, 1664 {"M-w", "forward-to-word"}, 1665 {"M-W", "forward-to-word"}, 1666 {"M-x", "forward-delete-char"}, 1667 {"M-X", "backward-delete-char"}, 1668 {"M-yh", "backward-copy-char"}, 1669 {"M-y^H", "backward-copy-char"}, 1670 {"M-y^?", "backward-copy-char"}, 1671 {"M-yl", "forward-copy-char"}, 1672 {"M-y ", "forward-copy-char"}, 1673 {"M-ye", "forward-copy-word"}, 1674 {"M-yE", "forward-copy-word"}, 1675 {"M-yw", "forward-copy-word"}, 1676 {"M-yW", "forward-copy-word"}, 1677 {"M-yb", "backward-copy-word"}, 1678 {"M-yB", "backward-copy-word"}, 1679 {"M-yf", "forward-copy-find"}, 1680 {"M-yF", "backward-copy-find"}, 1681 {"M-yt", "forward-copy-to"}, 1682 {"M-yT", "backward-copy-to"}, 1683 {"M-y;", "copy-refind"}, 1684 {"M-y,", "copy-invert-refind"}, 1685 {"M-y^", "copy-to-bol"}, 1686 {"M-y0", "copy-to-bol"}, 1687 {"M-y$", "copy-rest-of-line"}, 1688 {"M-yy", "copy-line"}, 1689 {"M-Y", "copy-line"}, 1690 {"M-y|", "copy-to-column"}, 1691 {"M-y%", "copy-to-parenthesis"}, 1692 {"M-^E", "emacs-mode"}, 1693 {"M-^H", "cursor-left"}, 1694 {"M-^?", "cursor-left"}, 1695 {"M-^L", "clear-screen"}, 1696 {"M-^N", "down-history"}, 1697 {"M-^P", "up-history"}, 1698 {"M-^R", "redisplay"}, 1699 {"M-^D", "list-or-eof"}, 1700 {"M-\r", "newline"}, 1701 {"M-\t", "complete-word"}, 1702 {"M-\n", "newline"}, 1703 #ifndef HIDE_FILE_SYSTEM 1704 {"M-^X^R", "read-init-files"}, 1705 #endif 1706 {"M-^Xh", "list-history"}, 1707 {"M-^XH", "list-history"}, 1708 {"down", "down-history"}, 1709 {"up", "up-history"}, 1710 {"left", "cursor-left"}, 1711 {"right", "cursor-right"}, 1712 }; 1713 1714 /*....................................................................... 1715 * Create a new GetLine object. 1716 * 1717 * Input: 1718 * linelen size_t The maximum line length to allow for. 1719 * histlen size_t The number of bytes to allocate for recording 1720 * a circular buffer of history lines. 1721 * Output: 1722 * return GetLine * The new object, or NULL on error. 1723 */ 1724 GetLine *new_GetLine(size_t linelen, size_t histlen) 1725 { 1726 GetLine *gl; /* The object to be returned */ 1727 int i; 1728 /* 1729 * Check the arguments. 1730 */ 1731 if(linelen < 10) { 1732 errno = ENOMEM; 1733 return NULL; 1734 }; 1735 /* 1736 * Allocate the container. 1737 */ 1738 gl = (GetLine *) malloc(sizeof(GetLine)); 1739 if(!gl) { 1740 errno = ENOMEM; 1741 return NULL; 1742 }; 1743 /* 1744 * Before attempting any operation that might fail, initialize the 1745 * container at least up to the point at which it can safely be passed 1746 * to del_GetLine(). 1747 */ 1748 gl->err = NULL; 1749 gl->glh = NULL; 1750 gl->cpl = NULL; 1751 #ifndef HIDE_FILE_SYSTEM 1752 gl->cplfn.fn = cpl_file_completions; 1753 #else 1754 gl->cplfn.fn = gl_no_completions; 1755 #endif 1756 gl->cplfn.data = NULL; 1757 #ifndef WITHOUT_FILE_SYSTEM 1758 gl->ef = NULL; 1759 #endif 1760 gl->capmem = NULL; 1761 gl->cq = NULL; 1762 gl->input_fd = -1; 1763 gl->output_fd = -1; 1764 gl->input_fp = NULL; 1765 gl->output_fp = NULL; 1766 gl->file_fp = NULL; 1767 gl->term = NULL; 1768 gl->is_term = 0; 1769 gl->flush_fn = gl_flush_terminal; 1770 gl->io_mode = GL_NORMAL_MODE; 1771 gl->raw_mode = 0; 1772 gl->pending_io = GLP_WRITE; /* We will start by writing the prompt */ 1773 gl_clear_status(gl); 1774 gl->linelen = linelen; 1775 gl->line = NULL; 1776 gl->cutbuf = NULL; 1777 gl->prompt = NULL; 1778 gl->prompt_len = 0; 1779 gl->prompt_changed = 0; 1780 gl->prompt_style = GL_LITERAL_PROMPT; 1781 gl->cpl_mem = NULL; 1782 gl->ext_act_mem = NULL; 1783 gl->sig_mem = NULL; 1784 gl->sigs = NULL; 1785 gl->signals_masked = 0; 1786 gl->signals_overriden = 0; 1787 sigemptyset(&gl->all_signal_set); 1788 sigemptyset(&gl->old_signal_set); 1789 sigemptyset(&gl->use_signal_set); 1790 gl->bindings = NULL; 1791 gl->ntotal = 0; 1792 gl->buff_curpos = 0; 1793 gl->term_curpos = 0; 1794 gl->term_len = 0; 1795 gl->buff_mark = 0; 1796 gl->insert_curpos = 0; 1797 gl->insert = 1; 1798 gl->number = -1; 1799 gl->endline = 1; 1800 gl->displayed = 0; 1801 gl->redisplay = 0; 1802 gl->postpone = 0; 1803 gl->keybuf[0]='\0'; 1804 gl->nbuf = 0; 1805 gl->nread = 0; 1806 gl->current_action.fn = 0; 1807 gl->current_action.data = NULL; 1808 gl->current_count = 0; 1809 gl->preload_id = 0; 1810 gl->preload_history = 0; 1811 gl->keyseq_count = 0; 1812 gl->last_search = -1; 1813 gl->editor = GL_EMACS_MODE; 1814 gl->silence_bell = 0; 1815 gl->automatic_history = 1; 1816 gl->vi.undo.line = NULL; 1817 gl->vi.undo.buff_curpos = 0; 1818 gl->vi.undo.ntotal = 0; 1819 gl->vi.undo.saved = 0; 1820 gl->vi.repeat.action.fn = 0; 1821 gl->vi.repeat.action.data = 0; 1822 gl->vi.repeat.count = 0; 1823 gl->vi.repeat.input_curpos = 0; 1824 gl->vi.repeat.command_curpos = 0; 1825 gl->vi.repeat.input_char = '\0'; 1826 gl->vi.repeat.saved = 0; 1827 gl->vi.repeat.active = 0; 1828 gl->vi.command = 0; 1829 gl->vi.find_forward = 0; 1830 gl->vi.find_onto = 0; 1831 gl->vi.find_char = '\0'; 1832 gl->left = NULL; 1833 gl->right = NULL; 1834 gl->up = NULL; 1835 gl->down = NULL; 1836 gl->home = NULL; 1837 gl->bol = 0; 1838 gl->clear_eol = NULL; 1839 gl->clear_eod = NULL; 1840 gl->u_arrow = NULL; 1841 gl->d_arrow = NULL; 1842 gl->l_arrow = NULL; 1843 gl->r_arrow = NULL; 1844 gl->sound_bell = NULL; 1845 gl->bold = NULL; 1846 gl->underline = NULL; 1847 gl->standout = NULL; 1848 gl->dim = NULL; 1849 gl->reverse = NULL; 1850 gl->blink = NULL; 1851 gl->text_attr_off = NULL; 1852 gl->nline = 0; 1853 gl->ncolumn = 0; 1854 #ifdef USE_TERMINFO 1855 gl->left_n = NULL; 1856 gl->right_n = NULL; 1857 #elif defined(USE_TERMCAP) 1858 gl->tgetent_buf = NULL; 1859 gl->tgetstr_buf = NULL; 1860 #endif 1861 gl->app_file = NULL; 1862 gl->user_file = NULL; 1863 gl->configured = 0; 1864 gl->echo = 1; 1865 gl->last_signal = -1; 1866 #ifdef HAVE_SELECT 1867 gl->fd_node_mem = NULL; 1868 gl->fd_nodes = NULL; 1869 FD_ZERO(&gl->rfds); 1870 FD_ZERO(&gl->wfds); 1871 FD_ZERO(&gl->ufds); 1872 gl->max_fd = 0; 1873 gl->timer.dt.tv_sec = 0; 1874 gl->timer.dt.tv_usec = 0; 1875 gl->timer.fn = 0; 1876 gl->timer.data = NULL; 1877 #endif 1878 /* 1879 * Allocate an error reporting buffer. 1880 */ 1881 gl->err = _new_ErrMsg(); 1882 if(!gl->err) 1883 return del_GetLine(gl); 1884 /* 1885 * Allocate the history buffer. 1886 */ 1887 gl->glh = _new_GlHistory(histlen); 1888 if(!gl->glh) 1889 return del_GetLine(gl); 1890 /* 1891 * Allocate the resource object for file-completion. 1892 */ 1893 gl->cpl = new_WordCompletion(); 1894 if(!gl->cpl) 1895 return del_GetLine(gl); 1896 /* 1897 * Allocate the resource object for file-completion. 1898 */ 1899 #ifndef WITHOUT_FILE_SYSTEM 1900 gl->ef = new_ExpandFile(); 1901 if(!gl->ef) 1902 return del_GetLine(gl); 1903 #endif 1904 /* 1905 * Allocate a string-segment memory allocator for use in storing terminal 1906 * capablity strings. 1907 */ 1908 gl->capmem = _new_StringGroup(CAPMEM_SEGMENT_SIZE); 1909 if(!gl->capmem) 1910 return del_GetLine(gl); 1911 /* 1912 * Allocate the character queue that is used to buffer terminal output. 1913 */ 1914 gl->cq = _new_GlCharQueue(); 1915 if(!gl->cq) 1916 return del_GetLine(gl); 1917 /* 1918 * Allocate a line buffer, leaving 2 extra characters for the terminating 1919 * '\n' and '\0' characters 1920 */ 1921 gl->line = (char *) malloc(linelen + 2); 1922 if(!gl->line) { 1923 errno = ENOMEM; 1924 return del_GetLine(gl); 1925 }; 1926 /* 1927 * Start with an empty input line. 1928 */ 1929 gl_truncate_buffer(gl, 0); 1930 /* 1931 * Allocate a cut buffer. 1932 */ 1933 gl->cutbuf = (char *) malloc(linelen + 2); 1934 if(!gl->cutbuf) { 1935 errno = ENOMEM; 1936 return del_GetLine(gl); 1937 }; 1938 gl->cutbuf[0] = '\0'; 1939 /* 1940 * Allocate an initial empty prompt. 1941 */ 1942 _gl_replace_prompt(gl, NULL); 1943 if(!gl->prompt) { 1944 errno = ENOMEM; 1945 return del_GetLine(gl); 1946 }; 1947 /* 1948 * Allocate a vi undo buffer. 1949 */ 1950 gl->vi.undo.line = (char *) malloc(linelen + 2); 1951 if(!gl->vi.undo.line) { 1952 errno = ENOMEM; 1953 return del_GetLine(gl); 1954 }; 1955 gl->vi.undo.line[0] = '\0'; 1956 /* 1957 * Allocate a freelist from which to allocate nodes for the list 1958 * of completion functions. 1959 */ 1960 gl->cpl_mem = _new_FreeList(sizeof(GlCplCallback), GL_CPL_FREELIST_BLOCKING); 1961 if(!gl->cpl_mem) 1962 return del_GetLine(gl); 1963 /* 1964 * Allocate a freelist from which to allocate nodes for the list 1965 * of external action functions. 1966 */ 1967 gl->ext_act_mem = _new_FreeList(sizeof(GlExternalAction), 1968 GL_EXT_ACT_FREELIST_BLOCKING); 1969 if(!gl->ext_act_mem) 1970 return del_GetLine(gl); 1971 /* 1972 * Allocate a freelist from which to allocate nodes for the list 1973 * of signals. 1974 */ 1975 gl->sig_mem = _new_FreeList(sizeof(GlSignalNode), GLS_FREELIST_BLOCKING); 1976 if(!gl->sig_mem) 1977 return del_GetLine(gl); 1978 /* 1979 * Install initial dispositions for the default list of signals that 1980 * gl_get_line() traps. 1981 */ 1982 for(i=0; i<sizeof(gl_signal_list)/sizeof(gl_signal_list[0]); i++) { 1983 const struct GlDefSignal *sig = gl_signal_list + i; 1984 if(_gl_trap_signal(gl, sig->signo, sig->flags, sig->after, 1985 sig->errno_value)) 1986 return del_GetLine(gl); 1987 }; 1988 /* 1989 * Allocate an empty table of key bindings. 1990 */ 1991 gl->bindings = _new_KeyTab(); 1992 if(!gl->bindings) 1993 return del_GetLine(gl); 1994 /* 1995 * Define the available actions that can be bound to key sequences. 1996 */ 1997 for(i=0; i<sizeof(gl_actions)/sizeof(gl_actions[0]); i++) { 1998 if(_kt_set_action(gl->bindings, gl_actions[i].name, gl_actions[i].fn, NULL)) 1999 return del_GetLine(gl); 2000 }; 2001 /* 2002 * Set up the default bindings. 2003 */ 2004 if(gl_change_editor(gl, gl->editor)) 2005 return del_GetLine(gl); 2006 /* 2007 * Allocate termcap buffers. 2008 */ 2009 #ifdef USE_TERMCAP 2010 gl->tgetent_buf = (char *) malloc(TERMCAP_BUF_SIZE); 2011 gl->tgetstr_buf = (char *) malloc(TERMCAP_BUF_SIZE); 2012 if(!gl->tgetent_buf || !gl->tgetstr_buf) { 2013 errno = ENOMEM; 2014 return del_GetLine(gl); 2015 }; 2016 #endif 2017 /* 2018 * Set up for I/O assuming stdin and stdout. 2019 */ 2020 if(_gl_change_terminal(gl, stdin, stdout, getenv("TERM"))) 2021 return del_GetLine(gl); 2022 /* 2023 * Create a freelist for use in allocating GlFdNode list nodes. 2024 */ 2025 #ifdef HAVE_SELECT 2026 gl->fd_node_mem = _new_FreeList(sizeof(GlFdNode), GLFD_FREELIST_BLOCKING); 2027 if(!gl->fd_node_mem) 2028 return del_GetLine(gl); 2029 #endif 2030 /* 2031 * We are done for now. 2032 */ 2033 return gl; 2034 } 2035 2036 /*....................................................................... 2037 * Delete a GetLine object. 2038 * 2039 * Input: 2040 * gl GetLine * The object to be deleted. 2041 * Output: 2042 * return GetLine * The deleted object (always NULL). 2043 */ 2044 GetLine *del_GetLine(GetLine *gl) 2045 { 2046 if(gl) { 2047 /* 2048 * If the terminal is in raw server mode, reset it. 2049 */ 2050 _gl_normal_io(gl); 2051 /* 2052 * Deallocate all objects contained by gl. 2053 */ 2054 gl->err = _del_ErrMsg(gl->err); 2055 gl->glh = _del_GlHistory(gl->glh); 2056 gl->cpl = del_WordCompletion(gl->cpl); 2057 #ifndef WITHOUT_FILE_SYSTEM 2058 gl->ef = del_ExpandFile(gl->ef); 2059 #endif 2060 gl->capmem = _del_StringGroup(gl->capmem); 2061 gl->cq = _del_GlCharQueue(gl->cq); 2062 if(gl->file_fp) 2063 fclose(gl->file_fp); 2064 if(gl->term) 2065 free(gl->term); 2066 if(gl->line) 2067 free(gl->line); 2068 if(gl->cutbuf) 2069 free(gl->cutbuf); 2070 if(gl->prompt) 2071 free(gl->prompt); 2072 gl->cpl_mem = _del_FreeList(gl->cpl_mem, 1); 2073 gl->ext_act_mem = _del_FreeList(gl->ext_act_mem, 1); 2074 gl->sig_mem = _del_FreeList(gl->sig_mem, 1); 2075 gl->sigs = NULL; /* Already freed by freeing sig_mem */ 2076 gl->bindings = _del_KeyTab(gl->bindings); 2077 if(gl->vi.undo.line) 2078 free(gl->vi.undo.line); 2079 #ifdef USE_TERMCAP 2080 if(gl->tgetent_buf) 2081 free(gl->tgetent_buf); 2082 if(gl->tgetstr_buf) 2083 free(gl->tgetstr_buf); 2084 #endif 2085 if(gl->app_file) 2086 free(gl->app_file); 2087 if(gl->user_file) 2088 free(gl->user_file); 2089 #ifdef HAVE_SELECT 2090 gl->fd_node_mem = _del_FreeList(gl->fd_node_mem, 1); 2091 gl->fd_nodes = NULL; /* Already freed by freeing gl->fd_node_mem */ 2092 #endif 2093 /* 2094 * Delete the now empty container. 2095 */ 2096 free(gl); 2097 }; 2098 return NULL; 2099 } 2100 2101 /*....................................................................... 2102 * Bind a control or meta character to an action. 2103 * 2104 * Input: 2105 * gl GetLine * The resource object of this program. 2106 * binder KtBinder The source of the binding. 2107 * c char The control or meta character. 2108 * If this is '\0', the call is ignored. 2109 * action const char * The action name to bind the key to. 2110 * Output: 2111 * return int 0 - OK. 2112 * 1 - Error. 2113 */ 2114 static int gl_bind_control_char(GetLine *gl, KtBinder binder, char c, 2115 const char *action) 2116 { 2117 char keyseq[2]; 2118 /* 2119 * Quietly reject binding to the NUL control character, since this 2120 * is an ambiguous prefix of all bindings. 2121 */ 2122 if(c == '\0') 2123 return 0; 2124 /* 2125 * Making sure not to bind characters which aren't either control or 2126 * meta characters. 2127 */ 2128 if(IS_CTRL_CHAR(c) || IS_META_CHAR(c)) { 2129 keyseq[0] = c; 2130 keyseq[1] = '\0'; 2131 } else { 2132 return 0; 2133 }; 2134 /* 2135 * Install the binding. 2136 */ 2137 if(_kt_set_keybinding(gl->bindings, binder, keyseq, action)) { 2138 _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG); 2139 return 1; 2140 }; 2141 return 0; 2142 } 2143 2144 /*....................................................................... 2145 * Read a line from the user. 2146 * 2147 * Input: 2148 * gl GetLine * A resource object returned by new_GetLine(). 2149 * prompt char * The prompt to prefix the line with. 2150 * start_line char * The initial contents of the input line, or NULL 2151 * if it should start out empty. 2152 * start_pos int If start_line isn't NULL, this specifies the 2153 * index of the character over which the cursor 2154 * should initially be positioned within the line. 2155 * If you just want it to follow the last character 2156 * of the line, send -1. 2157 * Output: 2158 * return char * An internal buffer containing the input line, or 2159 * NULL at the end of input. If the line fitted in 2160 * the buffer there will be a '\n' newline character 2161 * before the terminating '\0'. If it was truncated 2162 * there will be no newline character, and the remains 2163 * of the line should be retrieved via further calls 2164 * to this function. 2165 */ 2166 char *gl_get_line(GetLine *gl, const char *prompt, 2167 const char *start_line, int start_pos) 2168 { 2169 char *retval; /* The return value of _gl_get_line() */ 2170 /* 2171 * Check the arguments. 2172 */ 2173 if(!gl) { 2174 errno = EINVAL; 2175 return NULL; 2176 }; 2177 /* 2178 * Temporarily block all of the signals that we have been asked to trap. 2179 */ 2180 if(gl_mask_signals(gl, &gl->old_signal_set)) 2181 return NULL; 2182 /* 2183 * Perform the command-line editing task. 2184 */ 2185 retval = _gl_get_line(gl, prompt, start_line, start_pos); 2186 /* 2187 * Restore the process signal mask to how it was when this function was 2188 * first called. 2189 */ 2190 gl_unmask_signals(gl, &gl->old_signal_set); 2191 return retval; 2192 } 2193 2194 2195 /*....................................................................... 2196 * This is the main body of the public function gl_get_line(). 2197 */ 2198 static char *_gl_get_line(GetLine *gl, const char *prompt, 2199 const char *start_line, int start_pos) 2200 { 2201 int waserr = 0; /* True if an error occurs */ 2202 /* 2203 * Assume that this call will successfully complete the input 2204 * line until proven otherwise. 2205 */ 2206 gl_clear_status(gl); 2207 /* 2208 * If this is the first call to this function since new_GetLine(), 2209 * complete any postponed configuration. 2210 */ 2211 if(!gl->configured) { 2212 (void) _gl_configure_getline(gl, NULL, NULL, TECLA_CONFIG_FILE); 2213 gl->configured = 1; 2214 }; 2215 /* 2216 * Before installing our signal handler functions, record the fact 2217 * that there are no pending signals. 2218 */ 2219 gl_pending_signal = -1; 2220 /* 2221 * Temporarily override the signal handlers of the calling program, 2222 * so that we can intercept signals that would leave the terminal 2223 * in a bad state. 2224 */ 2225 waserr = gl_override_signal_handlers(gl); 2226 /* 2227 * After recording the current terminal settings, switch the terminal 2228 * into raw input mode. 2229 */ 2230 waserr = waserr || _gl_raw_io(gl, 1); 2231 /* 2232 * Attempt to read the line. This will require more than one attempt if 2233 * either a current temporary input file is opened by gl_get_input_line() 2234 * or the end of a temporary input file is reached by gl_read_stream_line(). 2235 */ 2236 while(!waserr) { 2237 /* 2238 * Read a line from a non-interactive stream? 2239 */ 2240 if(gl->file_fp || !gl->is_term) { 2241 if(gl_read_stream_line(gl)==0) { 2242 break; 2243 } else if(gl->file_fp) { 2244 gl_revert_input(gl); 2245 gl_record_status(gl, GLR_NEWLINE, 0); 2246 } else { 2247 waserr = 1; 2248 break; 2249 }; 2250 }; 2251 /* 2252 * Read from the terminal? Note that the above if() block may have 2253 * changed gl->file_fp, so it is necessary to retest it here, rather 2254 * than using an else statement. 2255 */ 2256 if(!gl->file_fp && gl->is_term) { 2257 if(gl_get_input_line(gl, prompt, start_line, start_pos)) 2258 waserr = 1; 2259 else 2260 break; 2261 }; 2262 }; 2263 /* 2264 * If an error occurred, but gl->rtn_status is still set to 2265 * GLR_NEWLINE, change the status to GLR_ERROR. Otherwise 2266 * leave it at whatever specific value was assigned by the function 2267 * that aborted input. This means that only functions that trap 2268 * non-generic errors have to remember to update gl->rtn_status 2269 * themselves. 2270 */ 2271 if(waserr && gl->rtn_status == GLR_NEWLINE) 2272 gl_record_status(gl, GLR_ERROR, errno); 2273 /* 2274 * Restore terminal settings. 2275 */ 2276 if(gl->io_mode != GL_SERVER_MODE) 2277 _gl_normal_io(gl); 2278 /* 2279 * Restore the signal handlers. 2280 */ 2281 gl_restore_signal_handlers(gl); 2282 /* 2283 * If gl_get_line() gets aborted early, the errno value associated 2284 * with the event that caused this to happen is recorded in 2285 * gl->rtn_errno. Since errno may have been overwritten by cleanup 2286 * functions after this, restore its value to the value that it had 2287 * when the error condition occured, so that the caller can examine it 2288 * to find out what happened. 2289 */ 2290 errno = gl->rtn_errno; 2291 /* 2292 * Check the completion status to see how to return. 2293 */ 2294 switch(gl->rtn_status) { 2295 case GLR_NEWLINE: /* Success */ 2296 return gl->line; 2297 case GLR_BLOCKED: /* These events abort the current input line, */ 2298 case GLR_SIGNAL: /* when in normal blocking I/O mode, but only */ 2299 case GLR_TIMEOUT: /* temporarily pause line editing when in */ 2300 case GLR_FDABORT: /* non-blocking server I/O mode. */ 2301 if(gl->io_mode != GL_SERVER_MODE) 2302 _gl_abandon_line(gl); 2303 return NULL; 2304 case GLR_ERROR: /* Unrecoverable errors abort the input line, */ 2305 case GLR_EOF: /* regardless of the I/O mode. */ 2306 default: 2307 _gl_abandon_line(gl); 2308 return NULL; 2309 }; 2310 } 2311 2312 /*....................................................................... 2313 * Read a single character from the user. 2314 * 2315 * Input: 2316 * gl GetLine * A resource object returned by new_GetLine(). 2317 * prompt char * The prompt to prefix the line with, or NULL if 2318 * no prompt is required. 2319 * defchar char The character to substitute if the 2320 * user simply hits return, or '\n' if you don't 2321 * need to substitute anything. 2322 * Output: 2323 * return int The character that was read, or EOF if the read 2324 * had to be aborted (in which case you can call 2325 * gl_return_status() to find out why). 2326 */ 2327 int gl_query_char(GetLine *gl, const char *prompt, char defchar) 2328 { 2329 int retval; /* The return value of _gl_query_char() */ 2330 /* 2331 * Check the arguments. 2332 */ 2333 if(!gl) { 2334 errno = EINVAL; 2335 return EOF; 2336 }; 2337 /* 2338 * Temporarily block all of the signals that we have been asked to trap. 2339 */ 2340 if(gl_mask_signals(gl, &gl->old_signal_set)) 2341 return EOF; 2342 /* 2343 * Perform the character reading task. 2344 */ 2345 retval = _gl_query_char(gl, prompt, defchar); 2346 /* 2347 * Restore the process signal mask to how it was when this function was 2348 * first called. 2349 */ 2350 gl_unmask_signals(gl, &gl->old_signal_set); 2351 return retval; 2352 } 2353 2354 /*....................................................................... 2355 * This is the main body of the public function gl_query_char(). 2356 */ 2357 static int _gl_query_char(GetLine *gl, const char *prompt, char defchar) 2358 { 2359 int c = EOF; /* The character to be returned */ 2360 int waserr = 0; /* True if an error occurs */ 2361 /* 2362 * Assume that this call will successfully complete the input operation 2363 * until proven otherwise. 2364 */ 2365 gl_clear_status(gl); 2366 /* 2367 * If this is the first call to this function or gl_get_line(), 2368 * since new_GetLine(), complete any postponed configuration. 2369 */ 2370 if(!gl->configured) { 2371 (void) _gl_configure_getline(gl, NULL, NULL, TECLA_CONFIG_FILE); 2372 gl->configured = 1; 2373 }; 2374 /* 2375 * Before installing our signal handler functions, record the fact 2376 * that there are no pending signals. 2377 */ 2378 gl_pending_signal = -1; 2379 /* 2380 * Temporarily override the signal handlers of the calling program, 2381 * so that we can intercept signals that would leave the terminal 2382 * in a bad state. 2383 */ 2384 waserr = gl_override_signal_handlers(gl); 2385 /* 2386 * After recording the current terminal settings, switch the terminal 2387 * into raw input mode without redisplaying any partially entered 2388 * input line. 2389 */ 2390 waserr = waserr || _gl_raw_io(gl, 0); 2391 /* 2392 * Attempt to read the line. This will require more than one attempt if 2393 * either a current temporary input file is opened by gl_get_input_line() 2394 * or the end of a temporary input file is reached by gl_read_stream_line(). 2395 */ 2396 while(!waserr) { 2397 /* 2398 * Read a line from a non-interactive stream? 2399 */ 2400 if(gl->file_fp || !gl->is_term) { 2401 c = gl_read_stream_char(gl); 2402 if(c != EOF) { /* Success? */ 2403 if(c=='\n') c = defchar; 2404 break; 2405 } else if(gl->file_fp) { /* End of temporary input file? */ 2406 gl_revert_input(gl); 2407 gl_record_status(gl, GLR_NEWLINE, 0); 2408 } else { /* An error? */ 2409 waserr = 1; 2410 break; 2411 }; 2412 }; 2413 /* 2414 * Read from the terminal? Note that the above if() block may have 2415 * changed gl->file_fp, so it is necessary to retest it here, rather 2416 * than using an else statement. 2417 */ 2418 if(!gl->file_fp && gl->is_term) { 2419 c = gl_get_query_char(gl, prompt, defchar); 2420 if(c==EOF) 2421 waserr = 1; 2422 else 2423 break; 2424 }; 2425 }; 2426 /* 2427 * If an error occurred, but gl->rtn_status is still set to 2428 * GLR_NEWLINE, change the status to GLR_ERROR. Otherwise 2429 * leave it at whatever specific value was assigned by the function 2430 * that aborted input. This means that only functions that trap 2431 * non-generic errors have to remember to update gl->rtn_status 2432 * themselves. 2433 */ 2434 if(waserr && gl->rtn_status == GLR_NEWLINE) 2435 gl_record_status(gl, GLR_ERROR, errno); 2436 /* 2437 * Restore terminal settings. 2438 */ 2439 if(gl->io_mode != GL_SERVER_MODE) 2440 _gl_normal_io(gl); 2441 /* 2442 * Restore the signal handlers. 2443 */ 2444 gl_restore_signal_handlers(gl); 2445 /* 2446 * If this function gets aborted early, the errno value associated 2447 * with the event that caused this to happen is recorded in 2448 * gl->rtn_errno. Since errno may have been overwritten by cleanup 2449 * functions after this, restore its value to the value that it had 2450 * when the error condition occured, so that the caller can examine it 2451 * to find out what happened. 2452 */ 2453 errno = gl->rtn_errno; 2454 /* 2455 * Error conditions are signalled to the caller, by setting the returned 2456 * character to EOF. 2457 */ 2458 if(gl->rtn_status != GLR_NEWLINE) 2459 c = EOF; 2460 /* 2461 * In this mode, every character that is read is a completed 2462 * transaction, just like reading a completed input line, so prepare 2463 * for the next input line or character. 2464 */ 2465 _gl_abandon_line(gl); 2466 /* 2467 * Return the acquired character. 2468 */ 2469 return c; 2470 } 2471 2472 /*....................................................................... 2473 * Record of the signal handlers of the calling program, so that they 2474 * can be restored later. 2475 * 2476 * Input: 2477 * gl GetLine * The resource object of this library. 2478 * Output: 2479 * return int 0 - OK. 2480 * 1 - Error. 2481 */ 2482 static int gl_override_signal_handlers(GetLine *gl) 2483 { 2484 GlSignalNode *sig; /* A node in the list of signals to be caught */ 2485 /* 2486 * Set up our signal handler. 2487 */ 2488 SigAction act; 2489 act.sa_handler = gl_signal_handler; 2490 memcpy(&act.sa_mask, &gl->all_signal_set, sizeof(sigset_t)); 2491 act.sa_flags = 0; 2492 /* 2493 * Get the subset of the signals that we are supposed to trap that 2494 * should actually be trapped. 2495 */ 2496 sigemptyset(&gl->use_signal_set); 2497 for(sig=gl->sigs; sig; sig=sig->next) { 2498 /* 2499 * Trap this signal? If it is blocked by the calling program and we 2500 * haven't been told to unblock it, don't arrange to trap this signal. 2501 */ 2502 if(sig->flags & GLS_UNBLOCK_SIG || 2503 !sigismember(&gl->old_signal_set, sig->signo)) { 2504 if(sigaddset(&gl->use_signal_set, sig->signo) == -1) { 2505 _err_record_msg(gl->err, "sigaddset error", END_ERR_MSG); 2506 return 1; 2507 }; 2508 }; 2509 }; 2510 /* 2511 * Override the actions of the signals that we are trapping. 2512 */ 2513 for(sig=gl->sigs; sig; sig=sig->next) { 2514 if(sigismember(&gl->use_signal_set, sig->signo)) { 2515 sigdelset(&act.sa_mask, sig->signo); 2516 if(sigaction(sig->signo, &act, &sig->original)) { 2517 _err_record_msg(gl->err, "sigaction error", END_ERR_MSG); 2518 return 1; 2519 }; 2520 sigaddset(&act.sa_mask, sig->signo); 2521 }; 2522 }; 2523 /* 2524 * Record the fact that the application's signal handlers have now 2525 * been overriden. 2526 */ 2527 gl->signals_overriden = 1; 2528 /* 2529 * Just in case a SIGWINCH signal was sent to the process while our 2530 * SIGWINCH signal handler wasn't in place, check to see if the terminal 2531 * size needs updating. 2532 */ 2533 if(_gl_update_size(gl)) 2534 return 1; 2535 return 0; 2536 } 2537 2538 /*....................................................................... 2539 * Restore the signal handlers of the calling program. 2540 * 2541 * Input: 2542 * gl GetLine * The resource object of this library. 2543 * Output: 2544 * return int 0 - OK. 2545 * 1 - Error. 2546 */ 2547 static int gl_restore_signal_handlers(GetLine *gl) 2548 { 2549 GlSignalNode *sig; /* A node in the list of signals to be caught */ 2550 /* 2551 * Restore application signal handlers that were overriden 2552 * by gl_override_signal_handlers(). 2553 */ 2554 for(sig=gl->sigs; sig; sig=sig->next) { 2555 if(sigismember(&gl->use_signal_set, sig->signo) && 2556 sigaction(sig->signo, &sig->original, NULL)) { 2557 _err_record_msg(gl->err, "sigaction error", END_ERR_MSG); 2558 return 1; 2559 }; 2560 }; 2561 /* 2562 * Record the fact that the application's signal handlers have now 2563 * been restored. 2564 */ 2565 gl->signals_overriden = 0; 2566 return 0; 2567 } 2568 2569 /*....................................................................... 2570 * This signal handler simply records the fact that a given signal was 2571 * caught in the file-scope gl_pending_signal variable. 2572 */ 2573 static void gl_signal_handler(int signo) 2574 { 2575 gl_pending_signal = signo; 2576 siglongjmp(gl_setjmp_buffer, 1); 2577 } 2578 2579 /*....................................................................... 2580 * Switch the terminal into raw mode after storing the previous terminal 2581 * settings in gl->attributes. 2582 * 2583 * Input: 2584 * gl GetLine * The resource object of this program. 2585 * Output: 2586 * return int 0 - OK. 2587 * 1 - Error. 2588 */ 2589 static int gl_raw_terminal_mode(GetLine *gl) 2590 { 2591 Termios newattr; /* The new terminal attributes */ 2592 /* 2593 * If the terminal is already in raw mode, do nothing. 2594 */ 2595 if(gl->raw_mode) 2596 return 0; 2597 /* 2598 * Record the current terminal attributes. 2599 */ 2600 if(tcgetattr(gl->input_fd, &gl->oldattr)) { 2601 _err_record_msg(gl->err, "tcgetattr error", END_ERR_MSG); 2602 return 1; 2603 }; 2604 /* 2605 * This function shouldn't do anything but record the current terminal 2606 * attritubes if editing has been disabled. 2607 */ 2608 if(gl->editor == GL_NO_EDITOR) 2609 return 0; 2610 /* 2611 * Modify the existing attributes. 2612 */ 2613 newattr = gl->oldattr; 2614 /* 2615 * Turn off local echo, canonical input mode and extended input processing. 2616 */ 2617 newattr.c_lflag &= ~(ECHO | ICANON | IEXTEN); 2618 /* 2619 * Don't translate carriage return to newline, turn off input parity 2620 * checking, don't strip off 8th bit, turn off output flow control. 2621 */ 2622 newattr.c_iflag &= ~(ICRNL | INPCK | ISTRIP); 2623 /* 2624 * Clear size bits, turn off parity checking, and allow 8-bit characters. 2625 */ 2626 newattr.c_cflag &= ~(CSIZE | PARENB); 2627 newattr.c_cflag |= CS8; 2628 /* 2629 * Turn off output processing. 2630 */ 2631 newattr.c_oflag &= ~(OPOST); 2632 /* 2633 * Request one byte at a time, without waiting. 2634 */ 2635 newattr.c_cc[VMIN] = gl->io_mode==GL_SERVER_MODE ? 0:1; 2636 newattr.c_cc[VTIME] = 0; 2637 /* 2638 * Install the new terminal modes. 2639 */ 2640 while(tcsetattr(gl->input_fd, TCSADRAIN, &newattr)) { 2641 if(errno != EINTR) { 2642 _err_record_msg(gl->err, "tcsetattr error", END_ERR_MSG); 2643 return 1; 2644 }; 2645 }; 2646 /* 2647 * Record the new terminal mode. 2648 */ 2649 gl->raw_mode = 1; 2650 return 0; 2651 } 2652 2653 /*....................................................................... 2654 * Restore the terminal attributes recorded in gl->oldattr. 2655 * 2656 * Input: 2657 * gl GetLine * The resource object of this library. 2658 * Output: 2659 * return int 0 - OK. 2660 * 1 - Error. 2661 */ 2662 static int gl_restore_terminal_attributes(GetLine *gl) 2663 { 2664 int waserr = 0; 2665 /* 2666 * If not in raw mode, do nothing. 2667 */ 2668 if(!gl->raw_mode) 2669 return 0; 2670 /* 2671 * Before changing the terminal attributes, make sure that all output 2672 * has been passed to the terminal. 2673 */ 2674 if(gl_flush_output(gl)) 2675 waserr = 1; 2676 /* 2677 * Reset the terminal attributes to the values that they had on 2678 * entry to gl_get_line(). 2679 */ 2680 while(tcsetattr(gl->input_fd, TCSADRAIN, &gl->oldattr)) { 2681 if(errno != EINTR) { 2682 _err_record_msg(gl->err, "tcsetattr error", END_ERR_MSG); 2683 waserr = 1; 2684 break; 2685 }; 2686 }; 2687 /* 2688 * Record the new terminal mode. 2689 */ 2690 gl->raw_mode = 0; 2691 return waserr; 2692 } 2693 2694 /*....................................................................... 2695 * Switch the terminal file descriptor to use non-blocking I/O. 2696 * 2697 * Input: 2698 * gl GetLine * The resource object of gl_get_line(). 2699 * fd int The file descriptor to make non-blocking. 2700 */ 2701 static int gl_nonblocking_io(GetLine *gl, int fd) 2702 { 2703 int fcntl_flags; /* The new file-descriptor control flags */ 2704 /* 2705 * Is non-blocking I/O supported on this system? Note that even 2706 * without non-blocking I/O, the terminal will probably still act as 2707 * though it was non-blocking, because we also set the terminal 2708 * attributes to return immediately if no input is available and we 2709 * use select() to wait to be able to write. If select() also isn't 2710 * available, then input will probably remain fine, but output could 2711 * block, depending on the behaviour of the terminal driver. 2712 */ 2713 #if defined(NON_BLOCKING_FLAG) 2714 /* 2715 * Query the current file-control flags, and add the 2716 * non-blocking I/O flag. 2717 */ 2718 fcntl_flags = fcntl(fd, F_GETFL) | NON_BLOCKING_FLAG; 2719 /* 2720 * Install the new control flags. 2721 */ 2722 if(fcntl(fd, F_SETFL, fcntl_flags) == -1) { 2723 _err_record_msg(gl->err, "fcntl error", END_ERR_MSG); 2724 return 1; 2725 }; 2726 #endif 2727 return 0; 2728 } 2729 2730 /*....................................................................... 2731 * Switch to blocking terminal I/O. 2732 * 2733 * Input: 2734 * gl GetLine * The resource object of gl_get_line(). 2735 * fd int The file descriptor to make blocking. 2736 */ 2737 static int gl_blocking_io(GetLine *gl, int fd) 2738 { 2739 int fcntl_flags; /* The new file-descriptor control flags */ 2740 /* 2741 * Is non-blocking I/O implemented on this system? 2742 */ 2743 #if defined(NON_BLOCKING_FLAG) 2744 /* 2745 * Query the current file control flags and remove the non-blocking 2746 * I/O flag. 2747 */ 2748 fcntl_flags = fcntl(fd, F_GETFL) & ~NON_BLOCKING_FLAG; 2749 /* 2750 * Install the modified control flags. 2751 */ 2752 if(fcntl(fd, F_SETFL, fcntl_flags) == -1) { 2753 _err_record_msg(gl->err, "fcntl error", END_ERR_MSG); 2754 return 1; 2755 }; 2756 #endif 2757 return 0; 2758 } 2759 2760 /*....................................................................... 2761 * Read a new input line from the user. 2762 * 2763 * Input: 2764 * gl GetLine * The resource object of this library. 2765 * prompt char * The prompt to prefix the line with, or NULL to 2766 * use the same prompt that was used by the previous 2767 * line. 2768 * start_line char * The initial contents of the input line, or NULL 2769 * if it should start out empty. 2770 * start_pos int If start_line isn't NULL, this specifies the 2771 * index of the character over which the cursor 2772 * should initially be positioned within the line. 2773 * If you just want it to follow the last character 2774 * of the line, send -1. 2775 * Output: 2776 * return int 0 - OK. 2777 * 1 - Error. 2778 */ 2779 static int gl_get_input_line(GetLine *gl, const char *prompt, 2780 const char *start_line, int start_pos) 2781 { 2782 char c; /* The character being read */ 2783 /* 2784 * Flush any pending output to the terminal. 2785 */ 2786 if(_glq_char_count(gl->cq) > 0 && gl_flush_output(gl)) 2787 return 1; 2788 /* 2789 * Are we starting a new line? 2790 */ 2791 if(gl->endline) { 2792 /* 2793 * Delete any incompletely enterred line. 2794 */ 2795 if(gl_erase_line(gl)) 2796 return 1; 2797 /* 2798 * Display the new line to be edited. 2799 */ 2800 if(gl_present_line(gl, prompt, start_line, start_pos)) 2801 return 1; 2802 }; 2803 /* 2804 * Read one character at a time. 2805 */ 2806 while(gl_read_terminal(gl, 1, &c) == 0) { 2807 /* 2808 * Increment the count of the number of key sequences entered. 2809 */ 2810 gl->keyseq_count++; 2811 /* 2812 * Interpret the character either as the start of a new key-sequence, 2813 * as a continuation of a repeat count, or as a printable character 2814 * to be added to the line. 2815 */ 2816 if(gl_interpret_char(gl, c)) 2817 break; 2818 /* 2819 * If we just ran an action function which temporarily asked for 2820 * input to be taken from a file, abort this call. 2821 */ 2822 if(gl->file_fp) 2823 return 0; 2824 /* 2825 * Has the line been completed? 2826 */ 2827 if(gl->endline) 2828 return gl_line_ended(gl, c); 2829 }; 2830 /* 2831 * To get here, gl_read_terminal() must have returned non-zero. See 2832 * whether a signal was caught that requested that the current line 2833 * be returned. 2834 */ 2835 if(gl->endline) 2836 return gl_line_ended(gl, '\n'); 2837 /* 2838 * If I/O blocked while attempting to get the latest character 2839 * of the key sequence, rewind the key buffer to allow interpretation of 2840 * the current key sequence to be restarted on the next call to this 2841 * function. 2842 */ 2843 if(gl->rtn_status == GLR_BLOCKED && gl->pending_io == GLP_READ) 2844 gl->nread = 0; 2845 return 1; 2846 } 2847 2848 /*....................................................................... 2849 * This is the private function of gl_query_char() that handles 2850 * prompting the user, reading a character from the terminal, and 2851 * displaying what the user entered. 2852 * 2853 * Input: 2854 * gl GetLine * The resource object of this library. 2855 * prompt char * The prompt to prefix the line with. 2856 * defchar char The character to substitute if the 2857 * user simply hits return, or '\n' if you don't 2858 * need to substitute anything. 2859 * Output: 2860 * return int The character that was read, or EOF if something 2861 * prevented a character from being read. 2862 */ 2863 static int gl_get_query_char(GetLine *gl, const char *prompt, int defchar) 2864 { 2865 char c; /* The character being read */ 2866 int retval; /* The return value of this function */ 2867 /* 2868 * Flush any pending output to the terminal. 2869 */ 2870 if(_glq_char_count(gl->cq) > 0 && gl_flush_output(gl)) 2871 return EOF; 2872 /* 2873 * Delete any incompletely entered line. 2874 */ 2875 if(gl_erase_line(gl)) 2876 return EOF; 2877 /* 2878 * Reset the line input parameters and display the prompt, if any. 2879 */ 2880 if(gl_present_line(gl, prompt, NULL, 0)) 2881 return EOF; 2882 /* 2883 * Read one character. 2884 */ 2885 if(gl_read_terminal(gl, 1, &c) == 0) { 2886 /* 2887 * In this mode, count each character as being a new key-sequence. 2888 */ 2889 gl->keyseq_count++; 2890 /* 2891 * Delete the character that was read, from the key-press buffer. 2892 */ 2893 gl_discard_chars(gl, gl->nread); 2894 /* 2895 * Convert carriage returns to newlines. 2896 */ 2897 if(c == '\r') 2898 c = '\n'; 2899 /* 2900 * If the user just hit return, subsitute the default character. 2901 */ 2902 if(c == '\n') 2903 c = defchar; 2904 /* 2905 * Display the entered character to the right of the prompt. 2906 */ 2907 if(c!='\n') { 2908 if(gl_end_of_line(gl, 1, NULL)==0) 2909 gl_print_char(gl, c, ' '); 2910 }; 2911 /* 2912 * Record the return character, and mark the call as successful. 2913 */ 2914 retval = c; 2915 gl_record_status(gl, GLR_NEWLINE, 0); 2916 /* 2917 * Was a signal caught whose disposition is to cause the current input 2918 * line to be returned? If so return a newline character. 2919 */ 2920 } else if(gl->endline) { 2921 retval = '\n'; 2922 gl_record_status(gl, GLR_NEWLINE, 0); 2923 } else { 2924 retval = EOF; 2925 }; 2926 /* 2927 * Start a new line. 2928 */ 2929 if(gl_start_newline(gl, 1)) 2930 return EOF; 2931 /* 2932 * Attempt to flush any pending output. 2933 */ 2934 (void) gl_flush_output(gl); 2935 /* 2936 * Return either the character that was read, or EOF if an error occurred. 2937 */ 2938 return retval; 2939 } 2940 2941 /*....................................................................... 2942 * Add a character to the line buffer at the current cursor position, 2943 * inserting or overwriting according the current mode. 2944 * 2945 * Input: 2946 * gl GetLine * The resource object of this library. 2947 * c char The character to be added. 2948 * Output: 2949 * return int 0 - OK. 2950 * 1 - Insufficient room. 2951 */ 2952 static int gl_add_char_to_line(GetLine *gl, char c) 2953 { 2954 /* 2955 * Keep a record of the current cursor position. 2956 */ 2957 int buff_curpos = gl->buff_curpos; 2958 int term_curpos = gl->term_curpos; 2959 /* 2960 * Work out the displayed width of the new character. 2961 */ 2962 int width = gl_displayed_char_width(gl, c, term_curpos); 2963 /* 2964 * If we are in insert mode, or at the end of the line, 2965 * check that we can accomodate a new character in the buffer. 2966 * If not, simply return, leaving it up to the calling program 2967 * to check for the absence of a newline character. 2968 */ 2969 if((gl->insert || buff_curpos >= gl->ntotal) && gl->ntotal >= gl->linelen) 2970 return 0; 2971 /* 2972 * Are we adding characters to the line (ie. inserting or appending)? 2973 */ 2974 if(gl->insert || buff_curpos >= gl->ntotal) { 2975 /* 2976 * If inserting, make room for the new character. 2977 */ 2978 if(buff_curpos < gl->ntotal) 2979 gl_make_gap_in_buffer(gl, buff_curpos, 1); 2980 /* 2981 * Copy the character into the buffer. 2982 */ 2983 gl_buffer_char(gl, c, buff_curpos); 2984 gl->buff_curpos++; 2985 /* 2986 * Redraw the line from the cursor position to the end of the line, 2987 * and move the cursor to just after the added character. 2988 */ 2989 if(gl_print_string(gl, gl->line + buff_curpos, '\0') || 2990 gl_set_term_curpos(gl, term_curpos + width)) 2991 return 1; 2992 /* 2993 * Are we overwriting an existing character? 2994 */ 2995 } else { 2996 /* 2997 * Get the width of the character being overwritten. 2998 */ 2999 int old_width = gl_displayed_char_width(gl, gl->line[buff_curpos], 3000 term_curpos); 3001 /* 3002 * Overwrite the character in the buffer. 3003 */ 3004 gl_buffer_char(gl, c, buff_curpos); 3005 /* 3006 * If we are replacing with a narrower character, we need to 3007 * redraw the terminal string to the end of the line, then 3008 * overwrite the trailing old_width - width characters 3009 * with spaces. 3010 */ 3011 if(old_width > width) { 3012 if(gl_print_string(gl, gl->line + buff_curpos, '\0')) 3013 return 1; 3014 /* 3015 * Clear to the end of the terminal. 3016 */ 3017 if(gl_truncate_display(gl)) 3018 return 1; 3019 /* 3020 * Move the cursor to the end of the new character. 3021 */ 3022 if(gl_set_term_curpos(gl, term_curpos + width)) 3023 return 1; 3024 gl->buff_curpos++; 3025 /* 3026 * If we are replacing with a wider character, then we will be 3027 * inserting new characters, and thus extending the line. 3028 */ 3029 } else if(width > old_width) { 3030 /* 3031 * Redraw the line from the cursor position to the end of the line, 3032 * and move the cursor to just after the added character. 3033 */ 3034 if(gl_print_string(gl, gl->line + buff_curpos, '\0') || 3035 gl_set_term_curpos(gl, term_curpos + width)) 3036 return 1; 3037 gl->buff_curpos++; 3038 /* 3039 * The original and replacement characters have the same width, 3040 * so simply overwrite. 3041 */ 3042 } else { 3043 /* 3044 * Copy the character into the buffer. 3045 */ 3046 gl_buffer_char(gl, c, buff_curpos); 3047 gl->buff_curpos++; 3048 /* 3049 * Overwrite the original character. 3050 */ 3051 if(gl_print_char(gl, c, gl->line[gl->buff_curpos])) 3052 return 1; 3053 }; 3054 }; 3055 return 0; 3056 } 3057 3058 /*....................................................................... 3059 * Insert/append a string to the line buffer and terminal at the current 3060 * cursor position. 3061 * 3062 * Input: 3063 * gl GetLine * The resource object of this library. 3064 * s char * The string to be added. 3065 * Output: 3066 * return int 0 - OK. 3067 * 1 - Insufficient room. 3068 */ 3069 static int gl_add_string_to_line(GetLine *gl, const char *s) 3070 { 3071 int buff_slen; /* The length of the string being added to line[] */ 3072 int term_slen; /* The length of the string being written to the terminal */ 3073 int buff_curpos; /* The original value of gl->buff_curpos */ 3074 int term_curpos; /* The original value of gl->term_curpos */ 3075 /* 3076 * Keep a record of the current cursor position. 3077 */ 3078 buff_curpos = gl->buff_curpos; 3079 term_curpos = gl->term_curpos; 3080 /* 3081 * How long is the string to be added? 3082 */ 3083 buff_slen = strlen(s); 3084 term_slen = gl_displayed_string_width(gl, s, buff_slen, term_curpos); 3085 /* 3086 * Check that we can accomodate the string in the buffer. 3087 * If not, simply return, leaving it up to the calling program 3088 * to check for the absence of a newline character. 3089 */ 3090 if(gl->ntotal + buff_slen > gl->linelen) 3091 return 0; 3092 /* 3093 * Move the characters that follow the cursor in the buffer by 3094 * buff_slen characters to the right. 3095 */ 3096 if(gl->ntotal > gl->buff_curpos) 3097 gl_make_gap_in_buffer(gl, gl->buff_curpos, buff_slen); 3098 /* 3099 * Copy the string into the buffer. 3100 */ 3101 gl_buffer_string(gl, s, buff_slen, gl->buff_curpos); 3102 gl->buff_curpos += buff_slen; 3103 /* 3104 * Write the modified part of the line to the terminal, then move 3105 * the terminal cursor to the end of the displayed input string. 3106 */ 3107 if(gl_print_string(gl, gl->line + buff_curpos, '\0') || 3108 gl_set_term_curpos(gl, term_curpos + term_slen)) 3109 return 1; 3110 return 0; 3111 } 3112 3113 /*....................................................................... 3114 * Read a single character from the terminal. 3115 * 3116 * Input: 3117 * gl GetLine * The resource object of this library. 3118 * keep int If true, the returned character will be kept in 3119 * the input buffer, for potential replays. It should 3120 * subsequently be removed from the buffer when the 3121 * key sequence that it belongs to has been fully 3122 * processed, by calling gl_discard_chars(). 3123 * Input/Output: 3124 * c char * The character that is read, is assigned to *c. 3125 * Output: 3126 * return int 0 - OK. 3127 * 1 - Either an I/O error occurred, or a signal was 3128 * caught who's disposition is to abort gl_get_line() 3129 * or to have gl_get_line() return the current line 3130 * as though the user had pressed return. In the 3131 * latter case gl->endline will be non-zero. 3132 */ 3133 static int gl_read_terminal(GetLine *gl, int keep, char *c) 3134 { 3135 /* 3136 * Before waiting for a new character to be input, flush unwritten 3137 * characters to the terminal. 3138 */ 3139 if(gl_flush_output(gl)) 3140 return 1; 3141 /* 3142 * Record the fact that we are about to read from the terminal. 3143 */ 3144 gl->pending_io = GLP_READ; 3145 /* 3146 * If there is already an unread character in the buffer, 3147 * return it. 3148 */ 3149 if(gl->nread < gl->nbuf) { 3150 *c = gl->keybuf[gl->nread]; 3151 /* 3152 * Retain the character in the key buffer, but mark it as having been read? 3153 */ 3154 if(keep) { 3155 gl->nread++; 3156 /* 3157 * Completely remove the character from the key buffer? 3158 */ 3159 } else { 3160 memmove(gl->keybuf + gl->nread, gl->keybuf + gl->nread + 1, 3161 gl->nbuf - gl->nread - 1); 3162 }; 3163 return 0; 3164 }; 3165 /* 3166 * Make sure that there is space in the key buffer for one more character. 3167 * This should always be true if gl_interpret_char() is called for each 3168 * new character added, since it will clear the buffer once it has recognized 3169 * or rejected a key sequence. 3170 */ 3171 if(gl->nbuf + 1 > GL_KEY_MAX) { 3172 gl_print_info(gl, "gl_read_terminal: Buffer overflow avoided.", 3173 GL_END_INFO); 3174 errno = EIO; 3175 return 1; 3176 }; 3177 /* 3178 * Read one character from the terminal. 3179 */ 3180 switch(gl_read_input(gl, c)) { 3181 case GL_READ_OK: 3182 break; 3183 case GL_READ_BLOCKED: 3184 gl_record_status(gl, GLR_BLOCKED, BLOCKED_ERRNO); 3185 return 1; 3186 break; 3187 default: 3188 return 1; 3189 break; 3190 }; 3191 /* 3192 * Append the character to the key buffer? 3193 */ 3194 if(keep) { 3195 gl->keybuf[gl->nbuf] = *c; 3196 gl->nread = ++gl->nbuf; 3197 }; 3198 return 0; 3199 } 3200 3201 /*....................................................................... 3202 * Read one or more keypresses from the terminal of an input stream. 3203 * 3204 * Input: 3205 * gl GetLine * The resource object of this module. 3206 * c char * The character that was read is assigned to *c. 3207 * Output: 3208 * return GlReadStatus The completion status of the read operation. 3209 */ 3210 static GlReadStatus gl_read_input(GetLine *gl, char *c) 3211 { 3212 /* 3213 * We may have to repeat the read if window change signals are received. 3214 */ 3215 for(;;) { 3216 /* 3217 * Which file descriptor should we read from? Mark this volatile, so 3218 * that siglongjmp() can't clobber it. 3219 */ 3220 volatile int fd = gl->file_fp ? fileno(gl->file_fp) : gl->input_fd; 3221 /* 3222 * If the endline flag becomes set, don't wait for another character. 3223 */ 3224 if(gl->endline) 3225 return GL_READ_ERROR; 3226 /* 3227 * Since the code in this function can block, trap signals. 3228 */ 3229 if(sigsetjmp(gl_setjmp_buffer, 1)==0) { 3230 /* 3231 * Handle the different I/O modes. 3232 */ 3233 switch(gl->io_mode) { 3234 /* 3235 * In normal I/O mode, we call the event handler before attempting 3236 * to read, since read() blocks. 3237 */ 3238 case GL_NORMAL_MODE: 3239 if(gl_event_handler(gl, fd)) 3240 return GL_READ_ERROR; 3241 return gl_read_unmasked(gl, fd, c); /* Read one character */ 3242 break; 3243 /* 3244 * In non-blocking server I/O mode, we attempt to read a character, 3245 * and only if this fails, call the event handler to wait for a any 3246 * user-configured timeout and any other user-configured events. In 3247 * addition, we turn off the fcntl() non-blocking flag when reading 3248 * from the terminal, to work around a bug in Solaris. We can do this 3249 * without causing the read() to block, because when in non-blocking 3250 * server-I/O mode, gl_raw_io() sets the VMIN terminal attribute to 0, 3251 * which tells the terminal driver to return immediately if no 3252 * characters are available to be read. 3253 */ 3254 case GL_SERVER_MODE: 3255 { 3256 GlReadStatus status; /* The return status */ 3257 if(isatty(fd)) /* If we reading from a terminal, */ 3258 gl_blocking_io(gl, fd); /* switch to blocking I/O */ 3259 status = gl_read_unmasked(gl, fd, c); /* Try reading */ 3260 if(status == GL_READ_BLOCKED) { /* Nothing readable yet */ 3261 if(gl_event_handler(gl, fd)) /* Wait for input */ 3262 status = GL_READ_ERROR; 3263 else 3264 status = gl_read_unmasked(gl, fd, c); /* Try reading again */ 3265 }; 3266 gl_nonblocking_io(gl, fd); /* Restore non-blocking I/O */ 3267 return status; 3268 }; 3269 break; 3270 }; 3271 }; 3272 /* 3273 * To get here, one of the signals that we are trapping must have 3274 * been received. Note that by using sigsetjmp() instead of setjmp() 3275 * the signal mask that was blocking these signals will have been 3276 * reinstated, so we can be sure that no more of these signals will 3277 * be received until we explicitly unblock them again. 3278 * 3279 * First, if non-blocking I/O was temporarily disabled, reinstate it. 3280 */ 3281 if(gl->io_mode == GL_SERVER_MODE) 3282 gl_nonblocking_io(gl, fd); 3283 /* 3284 * Now respond to the signal that was caught. 3285 */ 3286 if(gl_check_caught_signal(gl)) 3287 return GL_READ_ERROR; 3288 }; 3289 } 3290 3291 /*....................................................................... 3292 * This is a private function of gl_read_input(), which unblocks signals 3293 * temporarily while it reads a single character from the specified file 3294 * descriptor. 3295 * 3296 * Input: 3297 * gl GetLine * The resource object of this module. 3298 * fd int The file descriptor to read from. 3299 * c char * The character that was read is assigned to *c. 3300 * Output: 3301 * return GlReadStatus The completion status of the read. 3302 */ 3303 static int gl_read_unmasked(GetLine *gl, int fd, char *c) 3304 { 3305 int nread; /* The return value of read() */ 3306 /* 3307 * Unblock the signals that we are trapping, while waiting for I/O. 3308 */ 3309 gl_catch_signals(gl); 3310 /* 3311 * Attempt to read one character from the terminal, restarting the read 3312 * if any signals that we aren't trapping, are received. 3313 */ 3314 do { 3315 errno = 0; 3316 nread = read(fd, c, 1); 3317 } while(nread < 0 && errno==EINTR); 3318 /* 3319 * Block all of the signals that we are trapping. 3320 */ 3321 gl_mask_signals(gl, NULL); 3322 /* 3323 * Check the completion status of the read. 3324 */ 3325 switch(nread) { 3326 case 1: 3327 return GL_READ_OK; 3328 case 0: 3329 return (isatty(fd) || errno != 0) ? GL_READ_BLOCKED : GL_READ_EOF; 3330 default: 3331 return GL_READ_ERROR; 3332 }; 3333 } 3334 3335 /*....................................................................... 3336 * Remove a specified number of characters from the start of the 3337 * key-press lookahead buffer, gl->keybuf[], and arrange for the next 3338 * read to start from the character at the start of the shifted buffer. 3339 * 3340 * Input: 3341 * gl GetLine * The resource object of this module. 3342 * nused int The number of characters to discard from the start 3343 * of the buffer. 3344 */ 3345 static void gl_discard_chars(GetLine *gl, int nused) 3346 { 3347 int nkeep = gl->nbuf - nused; 3348 if(nkeep > 0) { 3349 memmove(gl->keybuf, gl->keybuf + nused, nkeep); 3350 gl->nbuf = nkeep; 3351 gl->nread = 0; 3352 } else { 3353 gl->nbuf = gl->nread = 0; 3354 }; 3355 } 3356 3357 /*....................................................................... 3358 * This function is called to handle signals caught between calls to 3359 * sigsetjmp() and siglongjmp(). 3360 * 3361 * Input: 3362 * gl GetLine * The resource object of this library. 3363 * Output: 3364 * return int 0 - Signal handled internally. 3365 * 1 - Signal requires gl_get_line() to abort. 3366 */ 3367 static int gl_check_caught_signal(GetLine *gl) 3368 { 3369 GlSignalNode *sig; /* The signal disposition */ 3370 SigAction keep_action; /* The signal disposition of tecla signal handlers */ 3371 unsigned flags; /* The signal processing flags to use */ 3372 int signo; /* The signal to be handled */ 3373 /* 3374 * Was no signal caught? 3375 */ 3376 if(gl_pending_signal == -1) 3377 return 0; 3378 /* 3379 * Get the signal to be handled. 3380 */ 3381 signo = gl_pending_signal; 3382 /* 3383 * Mark the signal as handled. Note that at this point, all of 3384 * the signals that we are trapping are blocked from delivery. 3385 */ 3386 gl_pending_signal = -1; 3387 /* 3388 * Record the signal that was caught, so that the user can query it later. 3389 */ 3390 gl->last_signal = signo; 3391 /* 3392 * In non-blocking server mode, the application is responsible for 3393 * responding to terminal signals, and we don't want gl_get_line()s 3394 * normal signal handling to clash with this, so whenever a signal 3395 * is caught, we arrange for gl_get_line() to abort and requeue the 3396 * signal while signals are still blocked. If the application 3397 * had the signal unblocked when gl_get_line() was called, the signal 3398 * will be delivered again as soon as gl_get_line() restores the 3399 * process signal mask, just before returning to the application. 3400 * Note that the caller of this function should set gl->pending_io 3401 * to the appropriate choice of GLP_READ and GLP_WRITE, before returning. 3402 */ 3403 if(gl->io_mode==GL_SERVER_MODE) { 3404 gl_record_status(gl, GLR_SIGNAL, EINTR); 3405 raise(signo); 3406 return 1; 3407 }; 3408 /* 3409 * Lookup the requested disposition of this signal. 3410 */ 3411 for(sig=gl->sigs; sig && sig->signo != signo; sig=sig->next) 3412 ; 3413 if(!sig) 3414 return 0; 3415 /* 3416 * Get the signal response flags for this signal. 3417 */ 3418 flags = sig->flags; 3419 /* 3420 * Did we receive a terminal size signal? 3421 */ 3422 #ifdef SIGWINCH 3423 if(signo == SIGWINCH && _gl_update_size(gl)) 3424 return 1; 3425 #endif 3426 /* 3427 * Start a fresh line? 3428 */ 3429 if(flags & GLS_RESTORE_LINE) { 3430 if(gl_start_newline(gl, 0)) 3431 return 1; 3432 }; 3433 /* 3434 * Restore terminal settings to how they were before gl_get_line() was 3435 * called? 3436 */ 3437 if(flags & GLS_RESTORE_TTY) 3438 gl_restore_terminal_attributes(gl); 3439 /* 3440 * Restore signal handlers to how they were before gl_get_line() was 3441 * called? If this hasn't been requested, only reinstate the signal 3442 * handler of the signal that we are handling. 3443 */ 3444 if(flags & GLS_RESTORE_SIG) { 3445 gl_restore_signal_handlers(gl); 3446 gl_unmask_signals(gl, &gl->old_signal_set); 3447 } else { 3448 (void) sigaction(sig->signo, &sig->original, &keep_action); 3449 (void) sigprocmask(SIG_UNBLOCK, &sig->proc_mask, NULL); 3450 }; 3451 /* 3452 * Forward the signal to the application's signal handler. 3453 */ 3454 if(!(flags & GLS_DONT_FORWARD)) 3455 raise(signo); 3456 /* 3457 * Reinstate our signal handlers. 3458 */ 3459 if(flags & GLS_RESTORE_SIG) { 3460 gl_mask_signals(gl, NULL); 3461 gl_override_signal_handlers(gl); 3462 } else { 3463 (void) sigaction(sig->signo, &keep_action, NULL); 3464 (void) sigprocmask(SIG_BLOCK, &sig->proc_mask, NULL); 3465 }; 3466 /* 3467 * Do we need to reinstate our terminal settings? 3468 */ 3469 if(flags & GLS_RESTORE_TTY) 3470 gl_raw_terminal_mode(gl); 3471 /* 3472 * Redraw the line? 3473 */ 3474 if(flags & GLS_REDRAW_LINE) 3475 gl_queue_redisplay(gl); 3476 /* 3477 * What next? 3478 */ 3479 switch(sig->after) { 3480 case GLS_RETURN: 3481 gl_newline(gl, 1, NULL); 3482 return gl_flush_output(gl); 3483 break; 3484 case GLS_ABORT: 3485 gl_record_status(gl, GLR_SIGNAL, sig->errno_value); 3486 return 1; 3487 break; 3488 case GLS_CONTINUE: 3489 return gl_flush_output(gl); 3490 break; 3491 }; 3492 return 0; 3493 } 3494 3495 /*....................................................................... 3496 * Get pertinent terminal control strings and the initial terminal size. 3497 * 3498 * Input: 3499 * gl GetLine * The resource object of this library. 3500 * term char * The type of the terminal. 3501 * Output: 3502 * return int 0 - OK. 3503 * 1 - Error. 3504 */ 3505 static int gl_control_strings(GetLine *gl, const char *term) 3506 { 3507 int bad_term = 0; /* True if term is unusable */ 3508 /* 3509 * Discard any existing control strings from a previous terminal. 3510 */ 3511 gl->left = NULL; 3512 gl->right = NULL; 3513 gl->up = NULL; 3514 gl->down = NULL; 3515 gl->home = NULL; 3516 gl->bol = 0; 3517 gl->clear_eol = NULL; 3518 gl->clear_eod = NULL; 3519 gl->u_arrow = NULL; 3520 gl->d_arrow = NULL; 3521 gl->l_arrow = NULL; 3522 gl->r_arrow = NULL; 3523 gl->sound_bell = NULL; 3524 gl->bold = NULL; 3525 gl->underline = NULL; 3526 gl->standout = NULL; 3527 gl->dim = NULL; 3528 gl->reverse = NULL; 3529 gl->blink = NULL; 3530 gl->text_attr_off = NULL; 3531 gl->nline = 0; 3532 gl->ncolumn = 0; 3533 #ifdef USE_TERMINFO 3534 gl->left_n = NULL; 3535 gl->right_n = NULL; 3536 #endif 3537 /* 3538 * If possible lookup the information in a terminal information 3539 * database. 3540 */ 3541 #ifdef USE_TERMINFO 3542 if(!term || setupterm((char *)term, gl->input_fd, NULL) == ERR) { 3543 bad_term = 1; 3544 } else { 3545 _clr_StringGroup(gl->capmem); 3546 gl->left = gl_tigetstr(gl, "cub1"); 3547 gl->right = gl_tigetstr(gl, "cuf1"); 3548 gl->up = gl_tigetstr(gl, "cuu1"); 3549 gl->down = gl_tigetstr(gl, "cud1"); 3550 gl->home = gl_tigetstr(gl, "home"); 3551 gl->clear_eol = gl_tigetstr(gl, "el"); 3552 gl->clear_eod = gl_tigetstr(gl, "ed"); 3553 gl->u_arrow = gl_tigetstr(gl, "kcuu1"); 3554 gl->d_arrow = gl_tigetstr(gl, "kcud1"); 3555 gl->l_arrow = gl_tigetstr(gl, "kcub1"); 3556 gl->r_arrow = gl_tigetstr(gl, "kcuf1"); 3557 gl->left_n = gl_tigetstr(gl, "cub"); 3558 gl->right_n = gl_tigetstr(gl, "cuf"); 3559 gl->sound_bell = gl_tigetstr(gl, "bel"); 3560 gl->bold = gl_tigetstr(gl, "bold"); 3561 gl->underline = gl_tigetstr(gl, "smul"); 3562 gl->standout = gl_tigetstr(gl, "smso"); 3563 gl->dim = gl_tigetstr(gl, "dim"); 3564 gl->reverse = gl_tigetstr(gl, "rev"); 3565 gl->blink = gl_tigetstr(gl, "blink"); 3566 gl->text_attr_off = gl_tigetstr(gl, "sgr0"); 3567 }; 3568 #elif defined(USE_TERMCAP) 3569 if(!term || tgetent(gl->tgetent_buf, (char *)term) < 0) { 3570 bad_term = 1; 3571 } else { 3572 char *tgetstr_buf_ptr = gl->tgetstr_buf; 3573 _clr_StringGroup(gl->capmem); 3574 gl->left = gl_tgetstr(gl, "le", &tgetstr_buf_ptr); 3575 gl->right = gl_tgetstr(gl, "nd", &tgetstr_buf_ptr); 3576 gl->up = gl_tgetstr(gl, "up", &tgetstr_buf_ptr); 3577 gl->down = gl_tgetstr(gl, "do", &tgetstr_buf_ptr); 3578 gl->home = gl_tgetstr(gl, "ho", &tgetstr_buf_ptr); 3579 gl->clear_eol = gl_tgetstr(gl, "ce", &tgetstr_buf_ptr); 3580 gl->clear_eod = gl_tgetstr(gl, "cd", &tgetstr_buf_ptr); 3581 gl->u_arrow = gl_tgetstr(gl, "ku", &tgetstr_buf_ptr); 3582 gl->d_arrow = gl_tgetstr(gl, "kd", &tgetstr_buf_ptr); 3583 gl->l_arrow = gl_tgetstr(gl, "kl", &tgetstr_buf_ptr); 3584 gl->r_arrow = gl_tgetstr(gl, "kr", &tgetstr_buf_ptr); 3585 gl->sound_bell = gl_tgetstr(gl, "bl", &tgetstr_buf_ptr); 3586 gl->bold = gl_tgetstr(gl, "md", &tgetstr_buf_ptr); 3587 gl->underline = gl_tgetstr(gl, "us", &tgetstr_buf_ptr); 3588 gl->standout = gl_tgetstr(gl, "so", &tgetstr_buf_ptr); 3589 gl->dim = gl_tgetstr(gl, "mh", &tgetstr_buf_ptr); 3590 gl->reverse = gl_tgetstr(gl, "mr", &tgetstr_buf_ptr); 3591 gl->blink = gl_tgetstr(gl, "mb", &tgetstr_buf_ptr); 3592 gl->text_attr_off = gl_tgetstr(gl, "me", &tgetstr_buf_ptr); 3593 }; 3594 #endif 3595 /* 3596 * Report term being unusable. 3597 */ 3598 if(bad_term) { 3599 gl_print_info(gl, "Bad terminal type: \"", term ? term : "(null)", 3600 "\". Will assume vt100.", GL_END_INFO); 3601 }; 3602 /* 3603 * Fill in missing information with ANSI VT100 strings. 3604 */ 3605 if(!gl->left) 3606 gl->left = "\b"; /* ^H */ 3607 if(!gl->right) 3608 gl->right = GL_ESC_STR "[C"; 3609 if(!gl->up) 3610 gl->up = GL_ESC_STR "[A"; 3611 if(!gl->down) 3612 gl->down = "\n"; 3613 if(!gl->home) 3614 gl->home = GL_ESC_STR "[H"; 3615 if(!gl->bol) 3616 gl->bol = "\r"; 3617 if(!gl->clear_eol) 3618 gl->clear_eol = GL_ESC_STR "[K"; 3619 if(!gl->clear_eod) 3620 gl->clear_eod = GL_ESC_STR "[J"; 3621 if(!gl->u_arrow) 3622 gl->u_arrow = GL_ESC_STR "[A"; 3623 if(!gl->d_arrow) 3624 gl->d_arrow = GL_ESC_STR "[B"; 3625 if(!gl->l_arrow) 3626 gl->l_arrow = GL_ESC_STR "[D"; 3627 if(!gl->r_arrow) 3628 gl->r_arrow = GL_ESC_STR "[C"; 3629 if(!gl->sound_bell) 3630 gl->sound_bell = "\a"; 3631 if(!gl->bold) 3632 gl->bold = GL_ESC_STR "[1m"; 3633 if(!gl->underline) 3634 gl->underline = GL_ESC_STR "[4m"; 3635 if(!gl->standout) 3636 gl->standout = GL_ESC_STR "[1;7m"; 3637 if(!gl->dim) 3638 gl->dim = ""; /* Not available */ 3639 if(!gl->reverse) 3640 gl->reverse = GL_ESC_STR "[7m"; 3641 if(!gl->blink) 3642 gl->blink = GL_ESC_STR "[5m"; 3643 if(!gl->text_attr_off) 3644 gl->text_attr_off = GL_ESC_STR "[m"; 3645 /* 3646 * Find out the current terminal size. 3647 */ 3648 (void) _gl_terminal_size(gl, GL_DEF_NCOLUMN, GL_DEF_NLINE, NULL); 3649 return 0; 3650 } 3651 3652 #ifdef USE_TERMINFO 3653 /*....................................................................... 3654 * This is a private function of gl_control_strings() used to look up 3655 * a termninal capability string from the terminfo database and make 3656 * a private copy of it. 3657 * 3658 * Input: 3659 * gl GetLine * The resource object of gl_get_line(). 3660 * name const char * The name of the terminfo string to look up. 3661 * Output: 3662 * return const char * The local copy of the capability, or NULL 3663 * if not available. 3664 */ 3665 static const char *gl_tigetstr(GetLine *gl, const char *name) 3666 { 3667 const char *value = tigetstr((char *)name); 3668 if(!value || value == (char *) -1) 3669 return NULL; 3670 return _sg_store_string(gl->capmem, value, 0); 3671 } 3672 #elif defined(USE_TERMCAP) 3673 /*....................................................................... 3674 * This is a private function of gl_control_strings() used to look up 3675 * a termninal capability string from the termcap database and make 3676 * a private copy of it. Note that some emulations of tgetstr(), such 3677 * as that used by Solaris, ignores the buffer pointer that is past to 3678 * it, so we can't assume that a private copy has been made that won't 3679 * be trashed by another call to gl_control_strings() by another 3680 * GetLine object. So we make what may be a redundant private copy 3681 * of the string in gl->capmem. 3682 * 3683 * Input: 3684 * gl GetLine * The resource object of gl_get_line(). 3685 * name const char * The name of the terminfo string to look up. 3686 * Input/Output: 3687 * bufptr char ** On input *bufptr points to the location in 3688 * gl->tgetstr_buf at which to record the 3689 * capability string. On output *bufptr is 3690 * incremented over the stored string. 3691 * Output: 3692 * return const char * The local copy of the capability, or NULL 3693 * on error. 3694 */ 3695 static const char *gl_tgetstr(GetLine *gl, const char *name, char **bufptr) 3696 { 3697 const char *value = tgetstr((char *)name, bufptr); 3698 if(!value || value == (char *) -1) 3699 return NULL; 3700 return _sg_store_string(gl->capmem, value, 0); 3701 } 3702 #endif 3703 3704 /*....................................................................... 3705 * This is an action function that implements a user interrupt (eg. ^C). 3706 */ 3707 static KT_KEY_FN(gl_user_interrupt) 3708 { 3709 raise(SIGINT); 3710 return 1; 3711 } 3712 3713 /*....................................................................... 3714 * This is an action function that implements the abort signal. 3715 */ 3716 static KT_KEY_FN(gl_abort) 3717 { 3718 raise(SIGABRT); 3719 return 1; 3720 } 3721 3722 /*....................................................................... 3723 * This is an action function that sends a suspend signal (eg. ^Z) to the 3724 * the parent process. 3725 */ 3726 static KT_KEY_FN(gl_suspend) 3727 { 3728 raise(SIGTSTP); 3729 return 0; 3730 } 3731 3732 /*....................................................................... 3733 * This is an action function that halts output to the terminal. 3734 */ 3735 static KT_KEY_FN(gl_stop_output) 3736 { 3737 tcflow(gl->output_fd, TCOOFF); 3738 return 0; 3739 } 3740 3741 /*....................................................................... 3742 * This is an action function that resumes halted terminal output. 3743 */ 3744 static KT_KEY_FN(gl_start_output) 3745 { 3746 tcflow(gl->output_fd, TCOON); 3747 return 0; 3748 } 3749 3750 /*....................................................................... 3751 * This is an action function that allows the next character to be accepted 3752 * without any interpretation as a special character. 3753 */ 3754 static KT_KEY_FN(gl_literal_next) 3755 { 3756 char c; /* The character to be added to the line */ 3757 int i; 3758 /* 3759 * Get the character to be inserted literally. 3760 */ 3761 if(gl_read_terminal(gl, 1, &c)) 3762 return 1; 3763 /* 3764 * Add the character to the line 'count' times. 3765 */ 3766 for(i=0; i<count; i++) 3767 gl_add_char_to_line(gl, c); 3768 return 0; 3769 } 3770 3771 /*....................................................................... 3772 * Return the width of a tab character at a given position when 3773 * displayed at a given position on the terminal. This is needed 3774 * because the width of tab characters depends on where they are, 3775 * relative to the preceding tab stops. 3776 * 3777 * Input: 3778 * gl GetLine * The resource object of this library. 3779 * term_curpos int The destination terminal location of the character. 3780 * Output: 3781 * return int The number of terminal charaters needed. 3782 */ 3783 static int gl_displayed_tab_width(GetLine *gl, int term_curpos) 3784 { 3785 return TAB_WIDTH - ((term_curpos % gl->ncolumn) % TAB_WIDTH); 3786 } 3787 3788 /*....................................................................... 3789 * Return the number of characters needed to display a given character 3790 * on the screen. Tab characters require eight spaces, and control 3791 * characters are represented by a caret followed by the modified 3792 * character. 3793 * 3794 * Input: 3795 * gl GetLine * The resource object of this library. 3796 * c char The character to be displayed. 3797 * term_curpos int The destination terminal location of the character. 3798 * This is needed because the width of tab characters 3799 * depends on where they are, relative to the 3800 * preceding tab stops. 3801 * Output: 3802 * return int The number of terminal charaters needed. 3803 */ 3804 static int gl_displayed_char_width(GetLine *gl, char c, int term_curpos) 3805 { 3806 if(c=='\t') 3807 return gl_displayed_tab_width(gl, term_curpos); 3808 if(IS_CTRL_CHAR(c)) 3809 return 2; 3810 if(!isprint((int)(unsigned char) c)) 3811 return gl_octal_width((int)(unsigned char)c) + 1; 3812 return 1; 3813 } 3814 3815 3816 /*....................................................................... 3817 * Work out the length of given string of characters on the terminal. 3818 * 3819 * Input: 3820 * gl GetLine * The resource object of this library. 3821 * string char * The string to be measured. 3822 * nc int The number of characters to be measured, or -1 3823 * to measure the whole string. 3824 * term_curpos int The destination terminal location of the character. 3825 * This is needed because the width of tab characters 3826 * depends on where they are, relative to the 3827 * preceding tab stops. 3828 * Output: 3829 * return int The number of displayed characters. 3830 */ 3831 static int gl_displayed_string_width(GetLine *gl, const char *string, int nc, 3832 int term_curpos) 3833 { 3834 int slen = 0; /* The displayed number of characters */ 3835 int i; 3836 /* 3837 * How many characters are to be measured? 3838 */ 3839 if(nc < 0) 3840 nc = strlen(string); 3841 /* 3842 * Add up the length of the displayed string. 3843 */ 3844 for(i=0; i<nc; i++) 3845 slen += gl_displayed_char_width(gl, string[i], term_curpos + slen); 3846 return slen; 3847 } 3848 3849 /*....................................................................... 3850 * Write a string verbatim to the current terminal or output stream. 3851 * 3852 * Note that when async-signal safety is required, the 'buffered' 3853 * argument must be 0, and n must not be -1. 3854 * 3855 * Input: 3856 * gl GetLine * The resource object of the gl_get_line(). 3857 * buffered int If true, used buffered I/O when writing to 3858 * the terminal. Otherwise use async-signal-safe 3859 * unbuffered I/O. 3860 * string const char * The string to be written (this need not be 3861 * '\0' terminated unless n<0). 3862 * n int The number of characters to write from the 3863 * prefix of string[], or -1 to request that 3864 * gl_print_raw_string() use strlen() to figure 3865 * out the length. 3866 * Output: 3867 * return int 0 - OK. 3868 * 1 - Error. 3869 */ 3870 static int gl_print_raw_string(GetLine *gl, int buffered, 3871 const char *string, int n) 3872 { 3873 GlWriteFn *write_fn = buffered ? gl_write_fn : gl->flush_fn; 3874 /* 3875 * Only display output when echoing is turned on. 3876 */ 3877 if(gl->echo) { 3878 int ndone = 0; /* The number of characters written so far */ 3879 /* 3880 * When using un-buffered I/O, flush pending output first. 3881 */ 3882 if(!buffered) { 3883 if(gl_flush_output(gl)) 3884 return 1; 3885 }; 3886 /* 3887 * If no length has been provided, measure the length of the string. 3888 */ 3889 if(n < 0) 3890 n = strlen(string); 3891 /* 3892 * Write the string. 3893 */ 3894 if(write_fn(gl, string + ndone, n-ndone) != n) 3895 return 1; 3896 }; 3897 return 0; 3898 } 3899 3900 /*....................................................................... 3901 * Output a terminal control sequence. When using terminfo, 3902 * this must be a sequence returned by tgetstr() or tigetstr() 3903 * respectively. 3904 * 3905 * Input: 3906 * gl GetLine * The resource object of this library. 3907 * nline int The number of lines affected by the operation, 3908 * or 1 if not relevant. 3909 * string char * The control sequence to be sent. 3910 * Output: 3911 * return int 0 - OK. 3912 * 1 - Error. 3913 */ 3914 static int gl_print_control_sequence(GetLine *gl, int nline, const char *string) 3915 { 3916 int waserr = 0; /* True if an error occurs */ 3917 /* 3918 * Only write characters to the terminal when echoing is enabled. 3919 */ 3920 if(gl->echo) { 3921 #if defined(USE_TERMINFO) || defined(USE_TERMCAP) 3922 tputs_gl = gl; 3923 errno = 0; 3924 tputs((char *)string, nline, gl_tputs_putchar); 3925 waserr = errno != 0; 3926 #else 3927 waserr = gl_print_raw_string(gl, 1, string, -1); 3928 #endif 3929 }; 3930 return waserr; 3931 } 3932 3933 #if defined(USE_TERMINFO) || defined(USE_TERMCAP) 3934 /*....................................................................... 3935 * The following callback function is called by tputs() to output a raw 3936 * control character to the terminal. 3937 */ 3938 static TputsRetType gl_tputs_putchar(TputsArgType c) 3939 { 3940 char ch = c; 3941 #if TPUTS_RETURNS_VALUE 3942 return gl_print_raw_string(tputs_gl, 1, &ch, 1); 3943 #else 3944 (void) gl_print_raw_string(tputs_gl, 1, &ch, 1); 3945 #endif 3946 } 3947 #endif 3948 3949 /*....................................................................... 3950 * Move the terminal cursor n characters to the left or right. 3951 * 3952 * Input: 3953 * gl GetLine * The resource object of this program. 3954 * n int number of positions to the right (> 0) or left (< 0). 3955 * Output: 3956 * return int 0 - OK. 3957 * 1 - Error. 3958 */ 3959 static int gl_terminal_move_cursor(GetLine *gl, int n) 3960 { 3961 int cur_row, cur_col; /* The current terminal row and column index of */ 3962 /* the cursor wrt the start of the input line. */ 3963 int new_row, new_col; /* The target terminal row and column index of */ 3964 /* the cursor wrt the start of the input line. */ 3965 /* 3966 * Do nothing if the input line isn't currently displayed. In this 3967 * case, the cursor will be moved to the right place when the line 3968 * is next redisplayed. 3969 */ 3970 if(!gl->displayed) 3971 return 0; 3972 /* 3973 * How far can we move left? 3974 */ 3975 if(gl->term_curpos + n < 0) 3976 n = gl->term_curpos; 3977 /* 3978 * Break down the current and target cursor locations into rows and columns. 3979 */ 3980 cur_row = gl->term_curpos / gl->ncolumn; 3981 cur_col = gl->term_curpos % gl->ncolumn; 3982 new_row = (gl->term_curpos + n) / gl->ncolumn; 3983 new_col = (gl->term_curpos + n) % gl->ncolumn; 3984 /* 3985 * Move down to the next line. 3986 */ 3987 for(; cur_row < new_row; cur_row++) { 3988 if(gl_print_control_sequence(gl, 1, gl->down)) 3989 return 1; 3990 }; 3991 /* 3992 * Move up to the previous line. 3993 */ 3994 for(; cur_row > new_row; cur_row--) { 3995 if(gl_print_control_sequence(gl, 1, gl->up)) 3996 return 1; 3997 }; 3998 /* 3999 * Move to the right within the target line? 4000 */ 4001 if(cur_col < new_col) { 4002 #ifdef USE_TERMINFO 4003 /* 4004 * Use a parameterized control sequence if it generates less control 4005 * characters (guess based on ANSI terminal termcap entry). 4006 */ 4007 if(gl->right_n != NULL && new_col - cur_col > 1) { 4008 if(gl_print_control_sequence(gl, 1, tparm((char *)gl->right_n, 4009 (long)(new_col - cur_col), 0l, 0l, 0l, 0l, 0l, 0l, 0l, 0l))) 4010 return 1; 4011 } else 4012 #endif 4013 { 4014 for(; cur_col < new_col; cur_col++) { 4015 if(gl_print_control_sequence(gl, 1, gl->right)) 4016 return 1; 4017 }; 4018 }; 4019 /* 4020 * Move to the left within the target line? 4021 */ 4022 } else if(cur_col > new_col) { 4023 #ifdef USE_TERMINFO 4024 /* 4025 * Use a parameterized control sequence if it generates less control 4026 * characters (guess based on ANSI terminal termcap entry). 4027 */ 4028 if(gl->left_n != NULL && cur_col - new_col > 3) { 4029 if(gl_print_control_sequence(gl, 1, tparm((char *)gl->left_n, 4030 (long)(cur_col - new_col), 0l, 0l, 0l, 0l, 0l, 0l, 0l, 0l))) 4031 return 1; 4032 } else 4033 #endif 4034 { 4035 for(; cur_col > new_col; cur_col--) { 4036 if(gl_print_control_sequence(gl, 1, gl->left)) 4037 return 1; 4038 }; 4039 }; 4040 } 4041 /* 4042 * Update the recorded position of the terminal cursor. 4043 */ 4044 gl->term_curpos += n; 4045 return 0; 4046 } 4047 4048 /*....................................................................... 4049 * Write a character to the terminal after expanding tabs and control 4050 * characters to their multi-character representations. 4051 * 4052 * Input: 4053 * gl GetLine * The resource object of this program. 4054 * c char The character to be output. 4055 * pad char Many terminals have the irritating feature that 4056 * when one writes a character in the last column of 4057 * of the terminal, the cursor isn't wrapped to the 4058 * start of the next line until one more character 4059 * is written. Some terminals don't do this, so 4060 * after such a write, we don't know where the 4061 * terminal is unless we output an extra character. 4062 * This argument specifies the character to write. 4063 * If at the end of the input line send '\0' or a 4064 * space, and a space will be written. Otherwise, 4065 * pass the next character in the input line 4066 * following the one being written. 4067 * Output: 4068 * return int 0 - OK. 4069 */ 4070 static int gl_print_char(GetLine *gl, char c, char pad) 4071 { 4072 char string[TAB_WIDTH + 4]; /* A work area for composing compound strings */ 4073 int nchar; /* The number of terminal characters */ 4074 int i; 4075 /* 4076 * Check for special characters. 4077 */ 4078 if(c == '\t') { 4079 /* 4080 * How many spaces do we need to represent a tab at the current terminal 4081 * column? 4082 */ 4083 nchar = gl_displayed_tab_width(gl, gl->term_curpos); 4084 /* 4085 * Compose the tab string. 4086 */ 4087 for(i=0; i<nchar; i++) 4088 string[i] = ' '; 4089 } else if(IS_CTRL_CHAR(c)) { 4090 string[0] = '^'; 4091 string[1] = CTRL_TO_CHAR(c); 4092 nchar = 2; 4093 } else if(!isprint((int)(unsigned char) c)) { 4094 snprintf(string, sizeof(string), "\\%o", (int)(unsigned char)c); 4095 nchar = strlen(string); 4096 } else { 4097 string[0] = c; 4098 nchar = 1; 4099 }; 4100 /* 4101 * Terminate the string. 4102 */ 4103 string[nchar] = '\0'; 4104 /* 4105 * Write the string to the terminal. 4106 */ 4107 if(gl_print_raw_string(gl, 1, string, -1)) 4108 return 1; 4109 /* 4110 * Except for one exception to be described in a moment, the cursor should 4111 * now have been positioned after the character that was just output. 4112 */ 4113 gl->term_curpos += nchar; 4114 /* 4115 * Keep a record of the number of characters in the terminal version 4116 * of the input line. 4117 */ 4118 if(gl->term_curpos > gl->term_len) 4119 gl->term_len = gl->term_curpos; 4120 /* 4121 * If the new character ended exactly at the end of a line, 4122 * most terminals won't move the cursor onto the next line until we 4123 * have written a character on the next line, so append an extra 4124 * space then move the cursor back. 4125 */ 4126 if(gl->term_curpos % gl->ncolumn == 0) { 4127 int term_curpos = gl->term_curpos; 4128 if(gl_print_char(gl, pad ? pad : ' ', ' ') || 4129 gl_set_term_curpos(gl, term_curpos)) 4130 return 1; 4131 }; 4132 return 0; 4133 } 4134 4135 /*....................................................................... 4136 * Write a string to the terminal after expanding tabs and control 4137 * characters to their multi-character representations. 4138 * 4139 * Input: 4140 * gl GetLine * The resource object of this program. 4141 * string char * The string to be output. 4142 * pad char Many terminals have the irritating feature that 4143 * when one writes a character in the last column of 4144 * of the terminal, the cursor isn't wrapped to the 4145 * start of the next line until one more character 4146 * is written. Some terminals don't do this, so 4147 * after such a write, we don't know where the 4148 * terminal is unless we output an extra character. 4149 * This argument specifies the character to write. 4150 * If at the end of the input line send '\0' or a 4151 * space, and a space will be written. Otherwise, 4152 * pass the next character in the input line 4153 * following the one being written. 4154 * Output: 4155 * return int 0 - OK. 4156 */ 4157 static int gl_print_string(GetLine *gl, const char *string, char pad) 4158 { 4159 const char *cptr; /* A pointer into string[] */ 4160 for(cptr=string; *cptr; cptr++) { 4161 char nextc = cptr[1]; 4162 if(gl_print_char(gl, *cptr, nextc ? nextc : pad)) 4163 return 1; 4164 }; 4165 return 0; 4166 } 4167 4168 /*....................................................................... 4169 * Move the terminal cursor position. 4170 * 4171 * Input: 4172 * gl GetLine * The resource object of this library. 4173 * term_curpos int The destination terminal cursor position. 4174 * Output: 4175 * return int 0 - OK. 4176 * 1 - Error. 4177 */ 4178 static int gl_set_term_curpos(GetLine *gl, int term_curpos) 4179 { 4180 return gl_terminal_move_cursor(gl, term_curpos - gl->term_curpos); 4181 } 4182 4183 /*....................................................................... 4184 * This is an action function that moves the buffer cursor one character 4185 * left, and updates the terminal cursor to match. 4186 */ 4187 static KT_KEY_FN(gl_cursor_left) 4188 { 4189 return gl_place_cursor(gl, gl->buff_curpos - count); 4190 } 4191 4192 /*....................................................................... 4193 * This is an action function that moves the buffer cursor one character 4194 * right, and updates the terminal cursor to match. 4195 */ 4196 static KT_KEY_FN(gl_cursor_right) 4197 { 4198 return gl_place_cursor(gl, gl->buff_curpos + count); 4199 } 4200 4201 /*....................................................................... 4202 * This is an action function that toggles between overwrite and insert 4203 * mode. 4204 */ 4205 static KT_KEY_FN(gl_insert_mode) 4206 { 4207 gl->insert = !gl->insert; 4208 return 0; 4209 } 4210 4211 /*....................................................................... 4212 * This is an action function which moves the cursor to the beginning of 4213 * the line. 4214 */ 4215 static KT_KEY_FN(gl_beginning_of_line) 4216 { 4217 return gl_place_cursor(gl, 0); 4218 } 4219 4220 /*....................................................................... 4221 * This is an action function which moves the cursor to the end of 4222 * the line. 4223 */ 4224 static KT_KEY_FN(gl_end_of_line) 4225 { 4226 return gl_place_cursor(gl, gl->ntotal); 4227 } 4228 4229 /*....................................................................... 4230 * This is an action function which deletes the entire contents of the 4231 * current line. 4232 */ 4233 static KT_KEY_FN(gl_delete_line) 4234 { 4235 /* 4236 * If in vi command mode, preserve the current line for potential 4237 * use by vi-undo. 4238 */ 4239 gl_save_for_undo(gl); 4240 /* 4241 * Copy the contents of the line to the cut buffer. 4242 */ 4243 strlcpy(gl->cutbuf, gl->line, gl->linelen); 4244 /* 4245 * Clear the buffer. 4246 */ 4247 gl_truncate_buffer(gl, 0); 4248 /* 4249 * Move the terminal cursor to just after the prompt. 4250 */ 4251 if(gl_place_cursor(gl, 0)) 4252 return 1; 4253 /* 4254 * Clear from the end of the prompt to the end of the terminal. 4255 */ 4256 if(gl_truncate_display(gl)) 4257 return 1; 4258 return 0; 4259 } 4260 4261 /*....................................................................... 4262 * This is an action function which deletes all characters between the 4263 * current cursor position and the end of the line. 4264 */ 4265 static KT_KEY_FN(gl_kill_line) 4266 { 4267 /* 4268 * If in vi command mode, preserve the current line for potential 4269 * use by vi-undo. 4270 */ 4271 gl_save_for_undo(gl); 4272 /* 4273 * Copy the part of the line that is about to be deleted to the cut buffer. 4274 */ 4275 strlcpy(gl->cutbuf, gl->line + gl->buff_curpos, gl->linelen); 4276 /* 4277 * Terminate the buffered line at the current cursor position. 4278 */ 4279 gl_truncate_buffer(gl, gl->buff_curpos); 4280 /* 4281 * Clear the part of the line that follows the cursor. 4282 */ 4283 if(gl_truncate_display(gl)) 4284 return 1; 4285 /* 4286 * Explicitly reset the cursor position to allow vi command mode 4287 * constraints on its position to be set. 4288 */ 4289 return gl_place_cursor(gl, gl->buff_curpos); 4290 } 4291 4292 /*....................................................................... 4293 * This is an action function which deletes all characters between the 4294 * start of the line and the current cursor position. 4295 */ 4296 static KT_KEY_FN(gl_backward_kill_line) 4297 { 4298 /* 4299 * How many characters are to be deleted from before the cursor? 4300 */ 4301 int nc = gl->buff_curpos - gl->insert_curpos; 4302 if (!nc) 4303 return 0; 4304 /* 4305 * Move the cursor to the start of the line, or in vi input mode, 4306 * the start of the sub-line at which insertion started, and delete 4307 * up to the old cursor position. 4308 */ 4309 return gl_place_cursor(gl, gl->insert_curpos) || 4310 gl_delete_chars(gl, nc, gl->editor == GL_EMACS_MODE || gl->vi.command); 4311 } 4312 4313 /*....................................................................... 4314 * This is an action function which moves the cursor forward by a word. 4315 */ 4316 static KT_KEY_FN(gl_forward_word) 4317 { 4318 return gl_place_cursor(gl, gl_nth_word_end_forward(gl, count) + 4319 (gl->editor==GL_EMACS_MODE)); 4320 } 4321 4322 /*....................................................................... 4323 * This is an action function which moves the cursor forward to the start 4324 * of the next word. 4325 */ 4326 static KT_KEY_FN(gl_forward_to_word) 4327 { 4328 return gl_place_cursor(gl, gl_nth_word_start_forward(gl, count)); 4329 } 4330 4331 /*....................................................................... 4332 * This is an action function which moves the cursor backward by a word. 4333 */ 4334 static KT_KEY_FN(gl_backward_word) 4335 { 4336 return gl_place_cursor(gl, gl_nth_word_start_backward(gl, count)); 4337 } 4338 4339 /*....................................................................... 4340 * Delete one or more characters, starting with the one under the cursor. 4341 * 4342 * Input: 4343 * gl GetLine * The resource object of this library. 4344 * nc int The number of characters to delete. 4345 * cut int If true, copy the characters to the cut buffer. 4346 * Output: 4347 * return int 0 - OK. 4348 * 1 - Error. 4349 */ 4350 static int gl_delete_chars(GetLine *gl, int nc, int cut) 4351 { 4352 /* 4353 * If in vi command mode, preserve the current line for potential 4354 * use by vi-undo. 4355 */ 4356 gl_save_for_undo(gl); 4357 /* 4358 * If there are fewer than nc characters following the cursor, limit 4359 * nc to the number available. 4360 */ 4361 if(gl->buff_curpos + nc > gl->ntotal) 4362 nc = gl->ntotal - gl->buff_curpos; 4363 /* 4364 * Copy the about to be deleted region to the cut buffer. 4365 */ 4366 if(cut) { 4367 memcpy(gl->cutbuf, gl->line + gl->buff_curpos, nc); 4368 gl->cutbuf[nc] = '\0'; 4369 } 4370 /* 4371 * Nothing to delete? 4372 */ 4373 if(nc <= 0) 4374 return 0; 4375 /* 4376 * In vi overwrite mode, restore any previously overwritten characters 4377 * from the undo buffer. 4378 */ 4379 if(gl->editor == GL_VI_MODE && !gl->vi.command && !gl->insert) { 4380 /* 4381 * How many of the characters being deleted can be restored from the 4382 * undo buffer? 4383 */ 4384 int nrestore = gl->buff_curpos + nc <= gl->vi.undo.ntotal ? 4385 nc : gl->vi.undo.ntotal - gl->buff_curpos; 4386 /* 4387 * Restore any available characters. 4388 */ 4389 if(nrestore > 0) { 4390 gl_buffer_string(gl, gl->vi.undo.line + gl->buff_curpos, nrestore, 4391 gl->buff_curpos); 4392 }; 4393 /* 4394 * If their were insufficient characters in the undo buffer, then this 4395 * implies that we are deleting from the end of the line, so we need 4396 * to terminate the line either where the undo buffer ran out, or if 4397 * we are deleting from beyond the end of the undo buffer, at the current 4398 * cursor position. 4399 */ 4400 if(nc != nrestore) { 4401 gl_truncate_buffer(gl, (gl->vi.undo.ntotal > gl->buff_curpos) ? 4402 gl->vi.undo.ntotal : gl->buff_curpos); 4403 }; 4404 } else { 4405 /* 4406 * Copy the remaining part of the line back over the deleted characters. 4407 */ 4408 gl_remove_from_buffer(gl, gl->buff_curpos, nc); 4409 }; 4410 /* 4411 * Redraw the remaining characters following the cursor. 4412 */ 4413 if(gl_print_string(gl, gl->line + gl->buff_curpos, '\0')) 4414 return 1; 4415 /* 4416 * Clear to the end of the terminal. 4417 */ 4418 if(gl_truncate_display(gl)) 4419 return 1; 4420 /* 4421 * Place the cursor at the start of where the deletion was performed. 4422 */ 4423 return gl_place_cursor(gl, gl->buff_curpos); 4424 } 4425 4426 /*....................................................................... 4427 * This is an action function which deletes character(s) under the 4428 * cursor without moving the cursor. 4429 */ 4430 static KT_KEY_FN(gl_forward_delete_char) 4431 { 4432 /* 4433 * Delete 'count' characters. 4434 */ 4435 return gl_delete_chars(gl, count, gl->vi.command); 4436 } 4437 4438 /*....................................................................... 4439 * This is an action function which deletes character(s) under the 4440 * cursor and moves the cursor back one character. 4441 */ 4442 static KT_KEY_FN(gl_backward_delete_char) 4443 { 4444 /* 4445 * Restrict the deletion count to the number of characters that 4446 * precede the insertion point. 4447 */ 4448 if(count > gl->buff_curpos - gl->insert_curpos) 4449 count = gl->buff_curpos - gl->insert_curpos; 4450 /* 4451 * If in vi command mode, preserve the current line for potential 4452 * use by vi-undo. 4453 */ 4454 gl_save_for_undo(gl); 4455 return gl_cursor_left(gl, count, NULL) || 4456 gl_delete_chars(gl, count, gl->vi.command); 4457 } 4458 4459 /*....................................................................... 4460 * Starting from the cursor position delete to the specified column. 4461 */ 4462 static KT_KEY_FN(gl_delete_to_column) 4463 { 4464 if (--count >= gl->buff_curpos) 4465 return gl_forward_delete_char(gl, count - gl->buff_curpos, NULL); 4466 else 4467 return gl_backward_delete_char(gl, gl->buff_curpos - count, NULL); 4468 } 4469 4470 /*....................................................................... 4471 * Starting from the cursor position delete characters to a matching 4472 * parenthesis. 4473 */ 4474 static KT_KEY_FN(gl_delete_to_parenthesis) 4475 { 4476 int curpos = gl_index_of_matching_paren(gl); 4477 if(curpos >= 0) { 4478 gl_save_for_undo(gl); 4479 if(curpos >= gl->buff_curpos) 4480 return gl_forward_delete_char(gl, curpos - gl->buff_curpos + 1, NULL); 4481 else 4482 return gl_backward_delete_char(gl, ++gl->buff_curpos - curpos + 1, NULL); 4483 }; 4484 return 0; 4485 } 4486 4487 /*....................................................................... 4488 * This is an action function which deletes from the cursor to the end 4489 * of the word that the cursor is either in or precedes. 4490 */ 4491 static KT_KEY_FN(gl_forward_delete_word) 4492 { 4493 /* 4494 * If in vi command mode, preserve the current line for potential 4495 * use by vi-undo. 4496 */ 4497 gl_save_for_undo(gl); 4498 /* 4499 * In emacs mode delete to the end of the word. In vi mode delete to the 4500 * start of the net word. 4501 */ 4502 if(gl->editor == GL_EMACS_MODE) { 4503 return gl_delete_chars(gl, 4504 gl_nth_word_end_forward(gl,count) - gl->buff_curpos + 1, 1); 4505 } else { 4506 return gl_delete_chars(gl, 4507 gl_nth_word_start_forward(gl,count) - gl->buff_curpos, 4508 gl->vi.command); 4509 }; 4510 } 4511 4512 /*....................................................................... 4513 * This is an action function which deletes the word that precedes the 4514 * cursor. 4515 */ 4516 static KT_KEY_FN(gl_backward_delete_word) 4517 { 4518 /* 4519 * Keep a record of the current cursor position. 4520 */ 4521 int buff_curpos = gl->buff_curpos; 4522 /* 4523 * If in vi command mode, preserve the current line for potential 4524 * use by vi-undo. 4525 */ 4526 gl_save_for_undo(gl); 4527 /* 4528 * Move back 'count' words. 4529 */ 4530 if(gl_backward_word(gl, count, NULL)) 4531 return 1; 4532 /* 4533 * Delete from the new cursor position to the original one. 4534 */ 4535 return gl_delete_chars(gl, buff_curpos - gl->buff_curpos, 4536 gl->editor == GL_EMACS_MODE || gl->vi.command); 4537 } 4538 4539 /*....................................................................... 4540 * Searching in a given direction, delete to the count'th 4541 * instance of a specified or queried character, in the input line. 4542 * 4543 * Input: 4544 * gl GetLine * The getline resource object. 4545 * count int The number of times to search. 4546 * c char The character to be searched for, or '\0' if 4547 * the character should be read from the user. 4548 * forward int True if searching forward. 4549 * onto int True if the search should end on top of the 4550 * character, false if the search should stop 4551 * one character before the character in the 4552 * specified search direction. 4553 * change int If true, this function is being called upon 4554 * to do a vi change command, in which case the 4555 * user will be left in insert mode after the 4556 * deletion. 4557 * Output: 4558 * return int 0 - OK. 4559 * 1 - Error. 4560 */ 4561 static int gl_delete_find(GetLine *gl, int count, char c, int forward, 4562 int onto, int change) 4563 { 4564 /* 4565 * Search for the character, and abort the deletion if not found. 4566 */ 4567 int pos = gl_find_char(gl, count, forward, onto, c); 4568 if(pos < 0) 4569 return 0; 4570 /* 4571 * If in vi command mode, preserve the current line for potential 4572 * use by vi-undo. 4573 */ 4574 gl_save_for_undo(gl); 4575 /* 4576 * Allow the cursor to be at the end of the line if this is a change 4577 * command. 4578 */ 4579 if(change) 4580 gl->vi.command = 0; 4581 /* 4582 * Delete the appropriate span of characters. 4583 */ 4584 if(forward) { 4585 if(gl_delete_chars(gl, pos - gl->buff_curpos + 1, 1)) 4586 return 1; 4587 } else { 4588 int buff_curpos = gl->buff_curpos; 4589 if(gl_place_cursor(gl, pos) || 4590 gl_delete_chars(gl, buff_curpos - gl->buff_curpos, 1)) 4591 return 1; 4592 }; 4593 /* 4594 * If this is a change operation, switch the insert mode. 4595 */ 4596 if(change && gl_vi_insert(gl, 0, NULL)) 4597 return 1; 4598 return 0; 4599 } 4600 4601 /*....................................................................... 4602 * This is an action function which deletes forward from the cursor up to and 4603 * including a specified character. 4604 */ 4605 static KT_KEY_FN(gl_forward_delete_find) 4606 { 4607 return gl_delete_find(gl, count, '\0', 1, 1, 0); 4608 } 4609 4610 /*....................................................................... 4611 * This is an action function which deletes backward from the cursor back to 4612 * and including a specified character. 4613 */ 4614 static KT_KEY_FN(gl_backward_delete_find) 4615 { 4616 return gl_delete_find(gl, count, '\0', 0, 1, 0); 4617 } 4618 4619 /*....................................................................... 4620 * This is an action function which deletes forward from the cursor up to but 4621 * not including a specified character. 4622 */ 4623 static KT_KEY_FN(gl_forward_delete_to) 4624 { 4625 return gl_delete_find(gl, count, '\0', 1, 0, 0); 4626 } 4627 4628 /*....................................................................... 4629 * This is an action function which deletes backward from the cursor back to 4630 * but not including a specified character. 4631 */ 4632 static KT_KEY_FN(gl_backward_delete_to) 4633 { 4634 return gl_delete_find(gl, count, '\0', 0, 0, 0); 4635 } 4636 4637 /*....................................................................... 4638 * This is an action function which deletes to a character specified by a 4639 * previous search. 4640 */ 4641 static KT_KEY_FN(gl_delete_refind) 4642 { 4643 return gl_delete_find(gl, count, gl->vi.find_char, gl->vi.find_forward, 4644 gl->vi.find_onto, 0); 4645 } 4646 4647 /*....................................................................... 4648 * This is an action function which deletes to a character specified by a 4649 * previous search, but in the opposite direction. 4650 */ 4651 static KT_KEY_FN(gl_delete_invert_refind) 4652 { 4653 return gl_delete_find(gl, count, gl->vi.find_char, 4654 !gl->vi.find_forward, gl->vi.find_onto, 0); 4655 } 4656 4657 /*....................................................................... 4658 * This is an action function which converts the characters in the word 4659 * following the cursor to upper case. 4660 */ 4661 static KT_KEY_FN(gl_upcase_word) 4662 { 4663 /* 4664 * Locate the count'th word ending after the cursor. 4665 */ 4666 int last = gl_nth_word_end_forward(gl, count); 4667 /* 4668 * If in vi command mode, preserve the current line for potential 4669 * use by vi-undo. 4670 */ 4671 gl_save_for_undo(gl); 4672 /* 4673 * Upcase characters from the current cursor position to 'last'. 4674 */ 4675 while(gl->buff_curpos <= last) { 4676 char *cptr = gl->line + gl->buff_curpos; 4677 /* 4678 * Convert the character to upper case? 4679 */ 4680 if(islower((int)(unsigned char) *cptr)) 4681 gl_buffer_char(gl, toupper((int) *cptr), gl->buff_curpos); 4682 gl->buff_curpos++; 4683 /* 4684 * Write the possibly modified character back. Note that for non-modified 4685 * characters we want to do this as well, so as to advance the cursor. 4686 */ 4687 if(gl_print_char(gl, *cptr, cptr[1])) 4688 return 1; 4689 }; 4690 return gl_place_cursor(gl, gl->buff_curpos); /* bounds check */ 4691 } 4692 4693 /*....................................................................... 4694 * This is an action function which converts the characters in the word 4695 * following the cursor to lower case. 4696 */ 4697 static KT_KEY_FN(gl_downcase_word) 4698 { 4699 /* 4700 * Locate the count'th word ending after the cursor. 4701 */ 4702 int last = gl_nth_word_end_forward(gl, count); 4703 /* 4704 * If in vi command mode, preserve the current line for potential 4705 * use by vi-undo. 4706 */ 4707 gl_save_for_undo(gl); 4708 /* 4709 * Upcase characters from the current cursor position to 'last'. 4710 */ 4711 while(gl->buff_curpos <= last) { 4712 char *cptr = gl->line + gl->buff_curpos; 4713 /* 4714 * Convert the character to upper case? 4715 */ 4716 if(isupper((int)(unsigned char) *cptr)) 4717 gl_buffer_char(gl, tolower((int) *cptr), gl->buff_curpos); 4718 gl->buff_curpos++; 4719 /* 4720 * Write the possibly modified character back. Note that for non-modified 4721 * characters we want to do this as well, so as to advance the cursor. 4722 */ 4723 if(gl_print_char(gl, *cptr, cptr[1])) 4724 return 1; 4725 }; 4726 return gl_place_cursor(gl, gl->buff_curpos); /* bounds check */ 4727 } 4728 4729 /*....................................................................... 4730 * This is an action function which converts the first character of the 4731 * following word to upper case, in order to capitalize the word, and 4732 * leaves the cursor at the end of the word. 4733 */ 4734 static KT_KEY_FN(gl_capitalize_word) 4735 { 4736 char *cptr; /* &gl->line[gl->buff_curpos] */ 4737 int first; /* True for the first letter of the word */ 4738 int i; 4739 /* 4740 * Keep a record of the current insert mode and the cursor position. 4741 */ 4742 int insert = gl->insert; 4743 /* 4744 * If in vi command mode, preserve the current line for potential 4745 * use by vi-undo. 4746 */ 4747 gl_save_for_undo(gl); 4748 /* 4749 * We want to overwrite the modified word. 4750 */ 4751 gl->insert = 0; 4752 /* 4753 * Capitalize 'count' words. 4754 */ 4755 for(i=0; i<count && gl->buff_curpos < gl->ntotal; i++) { 4756 int pos = gl->buff_curpos; 4757 /* 4758 * If we are not already within a word, skip to the start of the word. 4759 */ 4760 for(cptr = gl->line + pos ; pos<gl->ntotal && !gl_is_word_char((int) *cptr); 4761 pos++, cptr++) 4762 ; 4763 /* 4764 * Move the cursor to the new position. 4765 */ 4766 if(gl_place_cursor(gl, pos)) 4767 return 1; 4768 /* 4769 * While searching for the end of the word, change lower case letters 4770 * to upper case. 4771 */ 4772 for(first=1; gl->buff_curpos<gl->ntotal && gl_is_word_char((int) *cptr); 4773 gl->buff_curpos++, cptr++) { 4774 /* 4775 * Convert the character to upper case? 4776 */ 4777 if(first) { 4778 if(islower((int)(unsigned char) *cptr)) 4779 gl_buffer_char(gl, toupper((int) *cptr), cptr - gl->line); 4780 } else { 4781 if(isupper((int)(unsigned char) *cptr)) 4782 gl_buffer_char(gl, tolower((int) *cptr), cptr - gl->line); 4783 }; 4784 first = 0; 4785 /* 4786 * Write the possibly modified character back. Note that for non-modified 4787 * characters we want to do this as well, so as to advance the cursor. 4788 */ 4789 if(gl_print_char(gl, *cptr, cptr[1])) 4790 return 1; 4791 }; 4792 }; 4793 /* 4794 * Restore the insertion mode. 4795 */ 4796 gl->insert = insert; 4797 return gl_place_cursor(gl, gl->buff_curpos); /* bounds check */ 4798 } 4799 4800 /*....................................................................... 4801 * This is an action function which redraws the current line. 4802 */ 4803 static KT_KEY_FN(gl_redisplay) 4804 { 4805 /* 4806 * Keep a record of the current cursor position. 4807 */ 4808 int buff_curpos = gl->buff_curpos; 4809 /* 4810 * Do nothing if there is no line to be redisplayed. 4811 */ 4812 if(gl->endline) 4813 return 0; 4814 /* 4815 * Erase the current input line. 4816 */ 4817 if(gl_erase_line(gl)) 4818 return 1; 4819 /* 4820 * Display the current prompt. 4821 */ 4822 if(gl_display_prompt(gl)) 4823 return 1; 4824 /* 4825 * Render the part of the line that the user has typed in so far. 4826 */ 4827 if(gl_print_string(gl, gl->line, '\0')) 4828 return 1; 4829 /* 4830 * Restore the cursor position. 4831 */ 4832 if(gl_place_cursor(gl, buff_curpos)) 4833 return 1; 4834 /* 4835 * Mark the redisplay operation as having been completed. 4836 */ 4837 gl->redisplay = 0; 4838 /* 4839 * Flush the redisplayed line to the terminal. 4840 */ 4841 return gl_flush_output(gl); 4842 } 4843 4844 /*....................................................................... 4845 * This is an action function which clears the display and redraws the 4846 * input line from the home position. 4847 */ 4848 static KT_KEY_FN(gl_clear_screen) 4849 { 4850 /* 4851 * Home the cursor and clear from there to the end of the display. 4852 */ 4853 if(gl_print_control_sequence(gl, gl->nline, gl->home) || 4854 gl_print_control_sequence(gl, gl->nline, gl->clear_eod)) 4855 return 1; 4856 /* 4857 * The input line is no longer displayed. 4858 */ 4859 gl_line_erased(gl); 4860 /* 4861 * Arrange for the input line to be redisplayed. 4862 */ 4863 gl_queue_redisplay(gl); 4864 return 0; 4865 } 4866 4867 /*....................................................................... 4868 * This is an action function which swaps the character under the cursor 4869 * with the character to the left of the cursor. 4870 */ 4871 static KT_KEY_FN(gl_transpose_chars) 4872 { 4873 char from[3]; /* The original string of 2 characters */ 4874 char swap[3]; /* The swapped string of two characters */ 4875 /* 4876 * If we are at the beginning or end of the line, there aren't two 4877 * characters to swap. 4878 */ 4879 if(gl->buff_curpos < 1 || gl->buff_curpos >= gl->ntotal) 4880 return 0; 4881 /* 4882 * If in vi command mode, preserve the current line for potential 4883 * use by vi-undo. 4884 */ 4885 gl_save_for_undo(gl); 4886 /* 4887 * Get the original and swapped strings of the two characters. 4888 */ 4889 from[0] = gl->line[gl->buff_curpos - 1]; 4890 from[1] = gl->line[gl->buff_curpos]; 4891 from[2] = '\0'; 4892 swap[0] = gl->line[gl->buff_curpos]; 4893 swap[1] = gl->line[gl->buff_curpos - 1]; 4894 swap[2] = '\0'; 4895 /* 4896 * Move the cursor to the start of the two characters. 4897 */ 4898 if(gl_place_cursor(gl, gl->buff_curpos-1)) 4899 return 1; 4900 /* 4901 * Swap the two characters in the buffer. 4902 */ 4903 gl_buffer_char(gl, swap[0], gl->buff_curpos); 4904 gl_buffer_char(gl, swap[1], gl->buff_curpos+1); 4905 /* 4906 * If the sum of the displayed width of the two characters 4907 * in their current and final positions is the same, swapping can 4908 * be done by just overwriting with the two swapped characters. 4909 */ 4910 if(gl_displayed_string_width(gl, from, -1, gl->term_curpos) == 4911 gl_displayed_string_width(gl, swap, -1, gl->term_curpos)) { 4912 int insert = gl->insert; 4913 gl->insert = 0; 4914 if(gl_print_char(gl, swap[0], swap[1]) || 4915 gl_print_char(gl, swap[1], gl->line[gl->buff_curpos+2])) 4916 return 1; 4917 gl->insert = insert; 4918 /* 4919 * If the swapped substring has a different displayed size, we need to 4920 * redraw everything after the first of the characters. 4921 */ 4922 } else { 4923 if(gl_print_string(gl, gl->line + gl->buff_curpos, '\0') || 4924 gl_truncate_display(gl)) 4925 return 1; 4926 }; 4927 /* 4928 * Advance the cursor to the character after the swapped pair. 4929 */ 4930 return gl_place_cursor(gl, gl->buff_curpos + 2); 4931 } 4932 4933 /*....................................................................... 4934 * This is an action function which sets a mark at the current cursor 4935 * location. 4936 */ 4937 static KT_KEY_FN(gl_set_mark) 4938 { 4939 gl->buff_mark = gl->buff_curpos; 4940 return 0; 4941 } 4942 4943 /*....................................................................... 4944 * This is an action function which swaps the mark location for the 4945 * cursor location. 4946 */ 4947 static KT_KEY_FN(gl_exchange_point_and_mark) 4948 { 4949 /* 4950 * Get the old mark position, and limit to the extent of the input 4951 * line. 4952 */ 4953 int old_mark = gl->buff_mark <= gl->ntotal ? gl->buff_mark : gl->ntotal; 4954 /* 4955 * Make the current cursor position the new mark. 4956 */ 4957 gl->buff_mark = gl->buff_curpos; 4958 /* 4959 * Move the cursor to the old mark position. 4960 */ 4961 return gl_place_cursor(gl, old_mark); 4962 } 4963 4964 /*....................................................................... 4965 * This is an action function which deletes the characters between the 4966 * mark and the cursor, recording them in gl->cutbuf for later pasting. 4967 */ 4968 static KT_KEY_FN(gl_kill_region) 4969 { 4970 /* 4971 * If in vi command mode, preserve the current line for potential 4972 * use by vi-undo. 4973 */ 4974 gl_save_for_undo(gl); 4975 /* 4976 * Limit the mark to be within the line. 4977 */ 4978 if(gl->buff_mark > gl->ntotal) 4979 gl->buff_mark = gl->ntotal; 4980 /* 4981 * If there are no characters between the cursor and the mark, simply clear 4982 * the cut buffer. 4983 */ 4984 if(gl->buff_mark == gl->buff_curpos) { 4985 gl->cutbuf[0] = '\0'; 4986 return 0; 4987 }; 4988 /* 4989 * If the mark is before the cursor, swap the cursor and the mark. 4990 */ 4991 if(gl->buff_mark < gl->buff_curpos && gl_exchange_point_and_mark(gl,1,NULL)) 4992 return 1; 4993 /* 4994 * Delete the characters. 4995 */ 4996 if(gl_delete_chars(gl, gl->buff_mark - gl->buff_curpos, 1)) 4997 return 1; 4998 /* 4999 * Make the mark the same as the cursor position. 5000 */ 5001 gl->buff_mark = gl->buff_curpos; 5002 return 0; 5003 } 5004 5005 /*....................................................................... 5006 * This is an action function which records the characters between the 5007 * mark and the cursor, in gl->cutbuf for later pasting. 5008 */ 5009 static KT_KEY_FN(gl_copy_region_as_kill) 5010 { 5011 int ca, cb; /* The indexes of the first and last characters in the region */ 5012 int mark; /* The position of the mark */ 5013 /* 5014 * Get the position of the mark, limiting it to lie within the line. 5015 */ 5016 mark = gl->buff_mark > gl->ntotal ? gl->ntotal : gl->buff_mark; 5017 /* 5018 * If there are no characters between the cursor and the mark, clear 5019 * the cut buffer. 5020 */ 5021 if(mark == gl->buff_curpos) { 5022 gl->cutbuf[0] = '\0'; 5023 return 0; 5024 }; 5025 /* 5026 * Get the line indexes of the first and last characters in the region. 5027 */ 5028 if(mark < gl->buff_curpos) { 5029 ca = mark; 5030 cb = gl->buff_curpos - 1; 5031 } else { 5032 ca = gl->buff_curpos; 5033 cb = mark - 1; 5034 }; 5035 /* 5036 * Copy the region to the cut buffer. 5037 */ 5038 memcpy(gl->cutbuf, gl->line + ca, cb + 1 - ca); 5039 gl->cutbuf[cb + 1 - ca] = '\0'; 5040 return 0; 5041 } 5042 5043 /*....................................................................... 5044 * This is an action function which inserts the contents of the cut 5045 * buffer at the current cursor location. 5046 */ 5047 static KT_KEY_FN(gl_yank) 5048 { 5049 int i; 5050 /* 5051 * Set the mark at the current location. 5052 */ 5053 gl->buff_mark = gl->buff_curpos; 5054 /* 5055 * Do nothing else if the cut buffer is empty. 5056 */ 5057 if(gl->cutbuf[0] == '\0') 5058 return gl_ring_bell(gl, 1, NULL); 5059 /* 5060 * If in vi command mode, preserve the current line for potential 5061 * use by vi-undo. 5062 */ 5063 gl_save_for_undo(gl); 5064 /* 5065 * Insert the string count times. 5066 */ 5067 for(i=0; i<count; i++) { 5068 if(gl_add_string_to_line(gl, gl->cutbuf)) 5069 return 1; 5070 }; 5071 /* 5072 * gl_add_string_to_line() leaves the cursor after the last character that 5073 * was pasted, whereas vi leaves the cursor over the last character pasted. 5074 */ 5075 if(gl->editor == GL_VI_MODE && gl_cursor_left(gl, 1, NULL)) 5076 return 1; 5077 return 0; 5078 } 5079 5080 /*....................................................................... 5081 * This is an action function which inserts the contents of the cut 5082 * buffer one character beyond the current cursor location. 5083 */ 5084 static KT_KEY_FN(gl_append_yank) 5085 { 5086 int was_command = gl->vi.command; 5087 int i; 5088 /* 5089 * If the cut buffer is empty, ring the terminal bell. 5090 */ 5091 if(gl->cutbuf[0] == '\0') 5092 return gl_ring_bell(gl, 1, NULL); 5093 /* 5094 * Set the mark at the current location + 1. 5095 */ 5096 gl->buff_mark = gl->buff_curpos + 1; 5097 /* 5098 * If in vi command mode, preserve the current line for potential 5099 * use by vi-undo. 5100 */ 5101 gl_save_for_undo(gl); 5102 /* 5103 * Arrange to paste the text in insert mode after the current character. 5104 */ 5105 if(gl_vi_append(gl, 0, NULL)) 5106 return 1; 5107 /* 5108 * Insert the string count times. 5109 */ 5110 for(i=0; i<count; i++) { 5111 if(gl_add_string_to_line(gl, gl->cutbuf)) 5112 return 1; 5113 }; 5114 /* 5115 * Switch back to command mode if necessary. 5116 */ 5117 if(was_command) 5118 gl_vi_command_mode(gl); 5119 return 0; 5120 } 5121 5122 /*....................................................................... 5123 * Attempt to ask the terminal for its current size. On systems that 5124 * don't support the TIOCWINSZ ioctl() for querying the terminal size, 5125 * the current values of gl->ncolumn and gl->nrow are returned. 5126 * 5127 * Input: 5128 * gl GetLine * The resource object of gl_get_line(). 5129 * Input/Output: 5130 * ncolumn int * The number of columns will be assigned to *ncolumn. 5131 * nline int * The number of lines will be assigned to *nline. 5132 */ 5133 static void gl_query_size(GetLine *gl, int *ncolumn, int *nline) 5134 { 5135 #ifdef TIOCGWINSZ 5136 /* 5137 * Query the new terminal window size. Ignore invalid responses. 5138 */ 5139 struct winsize size; 5140 if(ioctl(gl->output_fd, TIOCGWINSZ, &size) == 0 && 5141 size.ws_row > 0 && size.ws_col > 0) { 5142 *ncolumn = size.ws_col; 5143 *nline = size.ws_row; 5144 return; 5145 }; 5146 #endif 5147 /* 5148 * Return the existing values. 5149 */ 5150 *ncolumn = gl->ncolumn; 5151 *nline = gl->nline; 5152 return; 5153 } 5154 5155 /*....................................................................... 5156 * Query the size of the terminal, and if it has changed, redraw the 5157 * current input line accordingly. 5158 * 5159 * Input: 5160 * gl GetLine * The resource object of gl_get_line(). 5161 * Output: 5162 * return int 0 - OK. 5163 * 1 - Error. 5164 */ 5165 static int _gl_update_size(GetLine *gl) 5166 { 5167 int ncolumn, nline; /* The new size of the terminal */ 5168 /* 5169 * Query the new terminal window size. 5170 */ 5171 gl_query_size(gl, &ncolumn, &nline); 5172 /* 5173 * Update gl and the displayed line to fit the new dimensions. 5174 */ 5175 return gl_handle_tty_resize(gl, ncolumn, nline); 5176 } 5177 5178 /*....................................................................... 5179 * Redraw the current input line to account for a change in the terminal 5180 * size. Also install the new size in gl. 5181 * 5182 * Input: 5183 * gl GetLine * The resource object of gl_get_line(). 5184 * ncolumn int The new number of columns. 5185 * nline int The new number of lines. 5186 * Output: 5187 * return int 0 - OK. 5188 * 1 - Error. 5189 */ 5190 static int gl_handle_tty_resize(GetLine *gl, int ncolumn, int nline) 5191 { 5192 /* 5193 * If the input device isn't a terminal, just record the new size. 5194 */ 5195 if(!gl->is_term) { 5196 gl->nline = nline; 5197 gl->ncolumn = ncolumn; 5198 /* 5199 * Has the size actually changed? 5200 */ 5201 } else if(ncolumn != gl->ncolumn || nline != gl->nline) { 5202 /* 5203 * If we are currently editing a line, erase it. 5204 */ 5205 if(gl_erase_line(gl)) 5206 return 1; 5207 /* 5208 * Update the recorded window size. 5209 */ 5210 gl->nline = nline; 5211 gl->ncolumn = ncolumn; 5212 /* 5213 * Arrange for the input line to be redrawn before the next character 5214 * is read from the terminal. 5215 */ 5216 gl_queue_redisplay(gl); 5217 }; 5218 return 0; 5219 } 5220 5221 /*....................................................................... 5222 * This is the action function that recalls the previous line in the 5223 * history buffer. 5224 */ 5225 static KT_KEY_FN(gl_up_history) 5226 { 5227 /* 5228 * In vi mode, switch to command mode, since the user is very 5229 * likely to want to move around newly recalled lines. 5230 */ 5231 gl_vi_command_mode(gl); 5232 /* 5233 * Forget any previous recall session. 5234 */ 5235 gl->preload_id = 0; 5236 /* 5237 * Record the key sequence number of this search action. 5238 */ 5239 gl->last_search = gl->keyseq_count; 5240 /* 5241 * We don't want a search prefix for this function. 5242 */ 5243 if(_glh_search_prefix(gl->glh, gl->line, 0)) { 5244 _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG); 5245 return 1; 5246 }; 5247 /* 5248 * Recall the count'th next older line in the history list. If the first one 5249 * fails we can return since nothing has changed, otherwise we must continue 5250 * and update the line state. 5251 */ 5252 if(_glh_find_backwards(gl->glh, gl->line, gl->linelen+1) == NULL) 5253 return 0; 5254 while(--count && _glh_find_backwards(gl->glh, gl->line, gl->linelen+1)) 5255 ; 5256 /* 5257 * Accomodate the new contents of gl->line[]. 5258 */ 5259 gl_update_buffer(gl); 5260 /* 5261 * Arrange to have the cursor placed at the end of the new line. 5262 */ 5263 gl->buff_curpos = gl->ntotal; 5264 /* 5265 * Erase and display the new line. 5266 */ 5267 gl_queue_redisplay(gl); 5268 return 0; 5269 } 5270 5271 /*....................................................................... 5272 * This is the action function that recalls the next line in the 5273 * history buffer. 5274 */ 5275 static KT_KEY_FN(gl_down_history) 5276 { 5277 /* 5278 * In vi mode, switch to command mode, since the user is very 5279 * likely to want to move around newly recalled lines. 5280 */ 5281 gl_vi_command_mode(gl); 5282 /* 5283 * Record the key sequence number of this search action. 5284 */ 5285 gl->last_search = gl->keyseq_count; 5286 /* 5287 * If no search is currently in progress continue a previous recall 5288 * session from a previous entered line if possible. 5289 */ 5290 if(_glh_line_id(gl->glh, 0) == 0 && gl->preload_id) { 5291 _glh_recall_line(gl->glh, gl->preload_id, gl->line, gl->linelen+1); 5292 gl->preload_id = 0; 5293 } else { 5294 /* 5295 * We don't want a search prefix for this function. 5296 */ 5297 if(_glh_search_prefix(gl->glh, gl->line, 0)) { 5298 _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG); 5299 return 1; 5300 }; 5301 /* 5302 * Recall the count'th next newer line in the history list. If the first one 5303 * fails we can return since nothing has changed otherwise we must continue 5304 * and update the line state. 5305 */ 5306 if(_glh_find_forwards(gl->glh, gl->line, gl->linelen+1) == NULL) 5307 return 0; 5308 while(--count && _glh_find_forwards(gl->glh, gl->line, gl->linelen+1)) 5309 ; 5310 }; 5311 /* 5312 * Accomodate the new contents of gl->line[]. 5313 */ 5314 gl_update_buffer(gl); 5315 /* 5316 * Arrange to have the cursor placed at the end of the new line. 5317 */ 5318 gl->buff_curpos = gl->ntotal; 5319 /* 5320 * Erase and display the new line. 5321 */ 5322 gl_queue_redisplay(gl); 5323 return 0; 5324 } 5325 5326 /*....................................................................... 5327 * This is the action function that recalls the previous line in the 5328 * history buffer whos prefix matches the characters that currently 5329 * precede the cursor. By setting count=-1, this can be used internally 5330 * to force searching for the prefix used in the last search. 5331 */ 5332 static KT_KEY_FN(gl_history_search_backward) 5333 { 5334 /* 5335 * In vi mode, switch to command mode, since the user is very 5336 * likely to want to move around newly recalled lines. 5337 */ 5338 gl_vi_command_mode(gl); 5339 /* 5340 * Forget any previous recall session. 5341 */ 5342 gl->preload_id = 0; 5343 /* 5344 * Record the key sequence number of this search action. 5345 */ 5346 gl->last_search = gl->keyseq_count; 5347 /* 5348 * If a prefix search isn't already in progress, replace the search 5349 * prefix to the string that precedes the cursor. In vi command mode 5350 * include the character that is under the cursor in the string. If 5351 * count<0 keep the previous search prefix regardless, so as to force 5352 * a repeat search even if the last command wasn't a history command. 5353 */ 5354 if(count >= 0 && !_glh_search_active(gl->glh) && 5355 _glh_search_prefix(gl->glh, gl->line, gl->buff_curpos + 5356 (gl->editor==GL_VI_MODE && gl->ntotal>0))) { 5357 _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG); 5358 return 1; 5359 }; 5360 /* 5361 * Search backwards for a match to the part of the line which precedes the 5362 * cursor. 5363 */ 5364 if(_glh_find_backwards(gl->glh, gl->line, gl->linelen+1) == NULL) 5365 return 0; 5366 /* 5367 * Accomodate the new contents of gl->line[]. 5368 */ 5369 gl_update_buffer(gl); 5370 /* 5371 * Arrange to have the cursor placed at the end of the new line. 5372 */ 5373 gl->buff_curpos = gl->ntotal; 5374 /* 5375 * Erase and display the new line. 5376 */ 5377 gl_queue_redisplay(gl); 5378 return 0; 5379 } 5380 5381 /*....................................................................... 5382 * This is the action function that recalls the previous line in the 5383 * history buffer who's prefix matches that specified in an earlier call 5384 * to gl_history_search_backward() or gl_history_search_forward(). 5385 */ 5386 static KT_KEY_FN(gl_history_re_search_backward) 5387 { 5388 return gl_history_search_backward(gl, -1, NULL); 5389 } 5390 5391 /*....................................................................... 5392 * This is the action function that recalls the next line in the 5393 * history buffer who's prefix matches that specified in the earlier call 5394 * to gl_history_search_backward) which started the history search. 5395 * By setting count=-1, this can be used internally to force searching 5396 * for the prefix used in the last search. 5397 */ 5398 static KT_KEY_FN(gl_history_search_forward) 5399 { 5400 /* 5401 * In vi mode, switch to command mode, since the user is very 5402 * likely to want to move around newly recalled lines. 5403 */ 5404 gl_vi_command_mode(gl); 5405 /* 5406 * Record the key sequence number of this search action. 5407 */ 5408 gl->last_search = gl->keyseq_count; 5409 /* 5410 * If a prefix search isn't already in progress, replace the search 5411 * prefix to the string that precedes the cursor. In vi command mode 5412 * include the character that is under the cursor in the string. If 5413 * count<0 keep the previous search prefix regardless, so as to force 5414 * a repeat search even if the last command wasn't a history command. 5415 */ 5416 if(count >= 0 && !_glh_search_active(gl->glh) && 5417 _glh_search_prefix(gl->glh, gl->line, gl->buff_curpos + 5418 (gl->editor==GL_VI_MODE && gl->ntotal>0))) { 5419 _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG); 5420 return 1; 5421 }; 5422 /* 5423 * Search forwards for the next matching line. 5424 */ 5425 if(_glh_find_forwards(gl->glh, gl->line, gl->linelen+1) == NULL) 5426 return 0; 5427 /* 5428 * Accomodate the new contents of gl->line[]. 5429 */ 5430 gl_update_buffer(gl); 5431 /* 5432 * Arrange for the cursor to be placed at the end of the new line. 5433 */ 5434 gl->buff_curpos = gl->ntotal; 5435 /* 5436 * Erase and display the new line. 5437 */ 5438 gl_queue_redisplay(gl); 5439 return 0; 5440 } 5441 5442 /*....................................................................... 5443 * This is the action function that recalls the next line in the 5444 * history buffer who's prefix matches that specified in an earlier call 5445 * to gl_history_search_backward() or gl_history_search_forward(). 5446 */ 5447 static KT_KEY_FN(gl_history_re_search_forward) 5448 { 5449 return gl_history_search_forward(gl, -1, NULL); 5450 } 5451 5452 #ifdef HIDE_FILE_SYSTEM 5453 /*....................................................................... 5454 * The following function is used as the default completion handler when 5455 * the filesystem is to be hidden. It simply reports no completions. 5456 */ 5457 static CPL_MATCH_FN(gl_no_completions) 5458 { 5459 return 0; 5460 } 5461 #endif 5462 5463 /*....................................................................... 5464 * This is the tab completion function that completes the filename that 5465 * precedes the cursor position. Its callback data argument must be a 5466 * pointer to a GlCplCallback containing the completion callback function 5467 * and its callback data, or NULL to use the builtin filename completer. 5468 */ 5469 static KT_KEY_FN(gl_complete_word) 5470 { 5471 CplMatches *matches; /* The possible completions */ 5472 int suffix_len; /* The length of the completion extension */ 5473 int cont_len; /* The length of any continuation suffix */ 5474 int nextra; /* The number of characters being added to the */ 5475 /* total length of the line. */ 5476 int buff_pos; /* The buffer index at which the completion is */ 5477 /* to be inserted. */ 5478 int waserr = 0; /* True after errors */ 5479 /* 5480 * Get the container of the completion callback and its callback data. 5481 */ 5482 GlCplCallback *cb = data ? (GlCplCallback *) data : &gl->cplfn; 5483 /* 5484 * In vi command mode, switch to append mode so that the character under 5485 * the cursor is included in the completion (otherwise people can't 5486 * complete at the end of the line). 5487 */ 5488 if(gl->vi.command && gl_vi_append(gl, 0, NULL)) 5489 return 1; 5490 /* 5491 * Get the cursor position at which the completion is to be inserted. 5492 */ 5493 buff_pos = gl->buff_curpos; 5494 /* 5495 * Perform the completion. 5496 */ 5497 matches = cpl_complete_word(gl->cpl, gl->line, gl->buff_curpos, cb->data, 5498 cb->fn); 5499 /* 5500 * No matching completions? 5501 */ 5502 if(!matches) { 5503 waserr = gl_print_info(gl, cpl_last_error(gl->cpl), GL_END_INFO); 5504 /* 5505 * Are there any completions? 5506 */ 5507 } else if(matches->nmatch >= 1) { 5508 /* 5509 * If there any ambiguous matches, report them, starting on a new line. 5510 */ 5511 if(matches->nmatch > 1 && gl->echo) { 5512 if(_gl_normal_io(gl) || 5513 _cpl_output_completions(matches, gl_write_fn, gl, gl->ncolumn)) 5514 waserr = 1; 5515 }; 5516 /* 5517 * Get the length of the suffix and any continuation suffix to add to it. 5518 */ 5519 suffix_len = strlen(matches->suffix); 5520 cont_len = strlen(matches->cont_suffix); 5521 /* 5522 * If there is an unambiguous match, and the continuation suffix ends in 5523 * a newline, strip that newline and arrange to have getline return 5524 * after this action function returns. 5525 */ 5526 if(matches->nmatch==1 && cont_len > 0 && 5527 matches->cont_suffix[cont_len - 1] == '\n') { 5528 cont_len--; 5529 if(gl_newline(gl, 1, NULL)) 5530 waserr = 1; 5531 }; 5532 /* 5533 * Work out the number of characters that are to be added. 5534 */ 5535 nextra = suffix_len + cont_len; 5536 /* 5537 * Is there anything to be added? 5538 */ 5539 if(!waserr && nextra) { 5540 /* 5541 * Will there be space for the expansion in the line buffer? 5542 */ 5543 if(gl->ntotal + nextra < gl->linelen) { 5544 /* 5545 * Make room to insert the filename extension. 5546 */ 5547 gl_make_gap_in_buffer(gl, gl->buff_curpos, nextra); 5548 /* 5549 * Insert the filename extension. 5550 */ 5551 gl_buffer_string(gl, matches->suffix, suffix_len, gl->buff_curpos); 5552 /* 5553 * Add the terminating characters. 5554 */ 5555 gl_buffer_string(gl, matches->cont_suffix, cont_len, 5556 gl->buff_curpos + suffix_len); 5557 /* 5558 * Place the cursor position at the end of the completion. 5559 */ 5560 gl->buff_curpos += nextra; 5561 /* 5562 * If we don't have to redisplay the whole line, redisplay the part 5563 * of the line which follows the original cursor position, and place 5564 * the cursor at the end of the completion. 5565 */ 5566 if(gl->displayed) { 5567 if(gl_truncate_display(gl) || 5568 gl_print_string(gl, gl->line + buff_pos, '\0') || 5569 gl_place_cursor(gl, gl->buff_curpos)) 5570 waserr = 1; 5571 }; 5572 } else { 5573 (void) gl_print_info(gl, 5574 "Insufficient room in line for file completion.", 5575 GL_END_INFO); 5576 waserr = 1; 5577 }; 5578 }; 5579 }; 5580 /* 5581 * If any output had to be written to the terminal, then editing will 5582 * have been suspended, make sure that we are back in raw line editing 5583 * mode before returning. 5584 */ 5585 if(_gl_raw_io(gl, 1)) 5586 waserr = 1; 5587 return 0; 5588 } 5589 5590 #ifndef HIDE_FILE_SYSTEM 5591 /*....................................................................... 5592 * This is the function that expands the filename that precedes the 5593 * cursor position. It expands ~user/ expressions, $envvar expressions, 5594 * and wildcards. 5595 */ 5596 static KT_KEY_FN(gl_expand_filename) 5597 { 5598 char *start_path; /* The pointer to the start of the pathname in */ 5599 /* gl->line[]. */ 5600 FileExpansion *result; /* The results of the filename expansion */ 5601 int pathlen; /* The length of the pathname being expanded */ 5602 int length; /* The number of characters needed to display the */ 5603 /* expanded files. */ 5604 int nextra; /* The number of characters to be added */ 5605 int i,j; 5606 /* 5607 * In vi command mode, switch to append mode so that the character under 5608 * the cursor is included in the completion (otherwise people can't 5609 * complete at the end of the line). 5610 */ 5611 if(gl->vi.command && gl_vi_append(gl, 0, NULL)) 5612 return 1; 5613 /* 5614 * Locate the start of the filename that precedes the cursor position. 5615 */ 5616 start_path = _pu_start_of_path(gl->line, gl->buff_curpos); 5617 if(!start_path) 5618 return 1; 5619 /* 5620 * Get the length of the string that is to be expanded. 5621 */ 5622 pathlen = gl->buff_curpos - (start_path - gl->line); 5623 /* 5624 * Attempt to expand it. 5625 */ 5626 result = ef_expand_file(gl->ef, start_path, pathlen); 5627 /* 5628 * If there was an error, report the error on a new line. 5629 */ 5630 if(!result) 5631 return gl_print_info(gl, ef_last_error(gl->ef), GL_END_INFO); 5632 /* 5633 * If no files matched, report this as well. 5634 */ 5635 if(result->nfile == 0 || !result->exists) 5636 return gl_print_info(gl, "No files match.", GL_END_INFO); 5637 /* 5638 * If in vi command mode, preserve the current line for potential use by 5639 * vi-undo. 5640 */ 5641 gl_save_for_undo(gl); 5642 /* 5643 * Work out how much space we will need to display all of the matching 5644 * filenames, taking account of the space that we need to place between 5645 * them, and the number of additional '\' characters needed to escape 5646 * spaces, tabs and backslash characters in the individual filenames. 5647 */ 5648 length = 0; 5649 for(i=0; i<result->nfile; i++) { 5650 char *file = result->files[i]; 5651 while(*file) { 5652 int c = *file++; 5653 switch(c) { 5654 case ' ': case '\t': case '\\': case '*': case '?': case '[': 5655 length++; /* Count extra backslash characters */ 5656 }; 5657 length++; /* Count the character itself */ 5658 }; 5659 length++; /* Count the space that follows each filename */ 5660 }; 5661 /* 5662 * Work out the number of characters that are to be added. 5663 */ 5664 nextra = length - pathlen; 5665 /* 5666 * Will there be space for the expansion in the line buffer? 5667 */ 5668 if(gl->ntotal + nextra >= gl->linelen) { 5669 return gl_print_info(gl, "Insufficient room in line for file expansion.", 5670 GL_END_INFO); 5671 } else { 5672 /* 5673 * Do we need to move the part of the line that followed the unexpanded 5674 * filename? 5675 */ 5676 if(nextra > 0) { 5677 gl_make_gap_in_buffer(gl, gl->buff_curpos, nextra); 5678 } else if(nextra < 0) { 5679 gl->buff_curpos += nextra; 5680 gl_remove_from_buffer(gl, gl->buff_curpos, -nextra); 5681 }; 5682 /* 5683 * Insert the filenames, separated by spaces, and with internal spaces, 5684 * tabs and backslashes escaped with backslashes. 5685 */ 5686 for(i=0,j=start_path - gl->line; i<result->nfile; i++) { 5687 char *file = result->files[i]; 5688 while(*file) { 5689 int c = *file++; 5690 switch(c) { 5691 case ' ': case '\t': case '\\': case '*': case '?': case '[': 5692 gl_buffer_char(gl, '\\', j++); 5693 }; 5694 gl_buffer_char(gl, c, j++); 5695 }; 5696 gl_buffer_char(gl, ' ', j++); 5697 }; 5698 }; 5699 /* 5700 * Redisplay the part of the line which follows the start of 5701 * the original filename. 5702 */ 5703 if(gl_place_cursor(gl, start_path - gl->line) || 5704 gl_truncate_display(gl) || 5705 gl_print_string(gl, start_path, start_path[length])) 5706 return 1; 5707 /* 5708 * Move the cursor to the end of the expansion. 5709 */ 5710 return gl_place_cursor(gl, (start_path - gl->line) + length); 5711 } 5712 #endif 5713 5714 #ifndef HIDE_FILE_SYSTEM 5715 /*....................................................................... 5716 * This is the action function that lists glob expansions of the 5717 * filename that precedes the cursor position. It expands ~user/ 5718 * expressions, $envvar expressions, and wildcards. 5719 */ 5720 static KT_KEY_FN(gl_list_glob) 5721 { 5722 char *start_path; /* The pointer to the start of the pathname in */ 5723 /* gl->line[]. */ 5724 FileExpansion *result; /* The results of the filename expansion */ 5725 int pathlen; /* The length of the pathname being expanded */ 5726 /* 5727 * Locate the start of the filename that precedes the cursor position. 5728 */ 5729 start_path = _pu_start_of_path(gl->line, gl->buff_curpos); 5730 if(!start_path) 5731 return 1; 5732 /* 5733 * Get the length of the string that is to be expanded. 5734 */ 5735 pathlen = gl->buff_curpos - (start_path - gl->line); 5736 /* 5737 * Attempt to expand it. 5738 */ 5739 result = ef_expand_file(gl->ef, start_path, pathlen); 5740 /* 5741 * If there was an error, report it. 5742 */ 5743 if(!result) { 5744 return gl_print_info(gl, ef_last_error(gl->ef), GL_END_INFO); 5745 /* 5746 * If no files matched, report this as well. 5747 */ 5748 } else if(result->nfile == 0 || !result->exists) { 5749 return gl_print_info(gl, "No files match.", GL_END_INFO); 5750 /* 5751 * List the matching expansions. 5752 */ 5753 } else if(gl->echo) { 5754 if(gl_start_newline(gl, 1) || 5755 _ef_output_expansions(result, gl_write_fn, gl, gl->ncolumn)) 5756 return 1; 5757 gl_queue_redisplay(gl); 5758 }; 5759 return 0; 5760 } 5761 #endif 5762 5763 /*....................................................................... 5764 * Return non-zero if a character should be considered a part of a word. 5765 * 5766 * Input: 5767 * c int The character to be tested. 5768 * Output: 5769 * return int True if the character should be considered part of a word. 5770 */ 5771 static int gl_is_word_char(int c) 5772 { 5773 return isalnum((int)(unsigned char)c) || strchr(GL_WORD_CHARS, c) != NULL; 5774 } 5775 5776 /*....................................................................... 5777 * Override the builtin file-completion callback that is bound to the 5778 * "complete_word" action function. 5779 * 5780 * Input: 5781 * gl GetLine * The resource object of the command-line input 5782 * module. 5783 * data void * This is passed to match_fn() whenever it is 5784 * called. It could, for example, point to a 5785 * symbol table where match_fn() could look 5786 * for possible completions. 5787 * match_fn CplMatchFn * The function that will identify the prefix 5788 * to be completed from the input line, and 5789 * report matching symbols. 5790 * Output: 5791 * return int 0 - OK. 5792 * 1 - Error. 5793 */ 5794 int gl_customize_completion(GetLine *gl, void *data, CplMatchFn *match_fn) 5795 { 5796 sigset_t oldset; /* The signals that were blocked on entry to this function */ 5797 /* 5798 * Check the arguments. 5799 */ 5800 if(!gl || !match_fn) { 5801 if(gl) 5802 _err_record_msg(gl->err, "NULL argument", END_ERR_MSG); 5803 errno = EINVAL; 5804 return 1; 5805 }; 5806 /* 5807 * Temporarily block all signals. 5808 */ 5809 gl_mask_signals(gl, &oldset); 5810 /* 5811 * Record the new completion function and its callback data. 5812 */ 5813 gl->cplfn.fn = match_fn; 5814 gl->cplfn.data = data; 5815 /* 5816 * Restore the process signal mask before returning. 5817 */ 5818 gl_unmask_signals(gl, &oldset); 5819 return 0; 5820 } 5821 5822 /*....................................................................... 5823 * Change the terminal (or stream) that getline interacts with. 5824 * 5825 * Input: 5826 * gl GetLine * The resource object of the command-line input 5827 * module. 5828 * input_fp FILE * The stdio stream to read from. 5829 * output_fp FILE * The stdio stream to write to. 5830 * term char * The terminal type. This can be NULL if 5831 * either or both of input_fp and output_fp don't 5832 * refer to a terminal. Otherwise it should refer 5833 * to an entry in the terminal information database. 5834 * Output: 5835 * return int 0 - OK. 5836 * 1 - Error. 5837 */ 5838 int gl_change_terminal(GetLine *gl, FILE *input_fp, FILE *output_fp, 5839 const char *term) 5840 { 5841 sigset_t oldset; /* The signals that were blocked on entry to this function */ 5842 int status; /* The return status of _gl_change_terminal() */ 5843 /* 5844 * Check the arguments. 5845 */ 5846 if(!gl) { 5847 errno = EINVAL; 5848 return 1; 5849 }; 5850 /* 5851 * Block all signals. 5852 */ 5853 if(gl_mask_signals(gl, &oldset)) 5854 return 1; 5855 /* 5856 * Execute the private body of the function while signals are blocked. 5857 */ 5858 status = _gl_change_terminal(gl, input_fp, output_fp, term); 5859 /* 5860 * Restore the process signal mask. 5861 */ 5862 gl_unmask_signals(gl, &oldset); 5863 return status; 5864 } 5865 5866 /*....................................................................... 5867 * This is the private body of the gl_change_terminal() function. It 5868 * assumes that the caller has checked its arguments and blocked the 5869 * delivery of signals. 5870 */ 5871 static int _gl_change_terminal(GetLine *gl, FILE *input_fp, FILE *output_fp, 5872 const char *term) 5873 { 5874 int is_term = 0; /* True if both input_fd and output_fd are associated */ 5875 /* with a terminal. */ 5876 /* 5877 * Require that input_fp and output_fp both be valid. 5878 */ 5879 if(!input_fp || !output_fp) { 5880 gl_print_info(gl, "Can't change terminal. Bad input/output stream(s).", 5881 GL_END_INFO); 5882 return 1; 5883 }; 5884 /* 5885 * Are we displacing an existing terminal (as opposed to setting the 5886 * initial terminal)? 5887 */ 5888 if(gl->input_fd >= 0) { 5889 /* 5890 * Make sure to leave the previous terminal in a usable state. 5891 */ 5892 if(_gl_normal_io(gl)) 5893 return 1; 5894 /* 5895 * Remove the displaced terminal from the list of fds to watch. 5896 */ 5897 #ifdef HAVE_SELECT 5898 FD_CLR(gl->input_fd, &gl->rfds); 5899 #endif 5900 }; 5901 /* 5902 * Record the file descriptors and streams. 5903 */ 5904 gl->input_fp = input_fp; 5905 gl->input_fd = fileno(input_fp); 5906 gl->output_fp = output_fp; 5907 gl->output_fd = fileno(output_fp); 5908 /* 5909 * If needed, expand the record of the maximum file-descriptor that might 5910 * need to be monitored with select(). 5911 */ 5912 #ifdef HAVE_SELECT 5913 if(gl->input_fd > gl->max_fd) 5914 gl->max_fd = gl->input_fd; 5915 #endif 5916 /* 5917 * Disable terminal interaction until we have enough info to interact 5918 * with the terminal. 5919 */ 5920 gl->is_term = 0; 5921 /* 5922 * For terminal editing, we need both output_fd and input_fd to refer to 5923 * a terminal. While we can't verify that they both point to the same 5924 * terminal, we can verify that they point to terminals. 5925 */ 5926 is_term = isatty(gl->input_fd) && isatty(gl->output_fd); 5927 /* 5928 * If we are interacting with a terminal and no terminal type has been 5929 * specified, treat it as a generic ANSI terminal. 5930 */ 5931 if(is_term && !term) 5932 term = "ansi"; 5933 /* 5934 * Make a copy of the terminal type string. 5935 */ 5936 if(term != gl->term) { 5937 /* 5938 * Delete any old terminal type string. 5939 */ 5940 if(gl->term) { 5941 free(gl->term); 5942 gl->term = NULL; 5943 }; 5944 /* 5945 * Make a copy of the new terminal-type string, if any. 5946 */ 5947 if(term) { 5948 size_t termsz = strlen(term)+1; 5949 5950 gl->term = (char *) malloc(termsz); 5951 if(gl->term) 5952 strlcpy(gl->term, term, termsz); 5953 }; 5954 }; 5955 /* 5956 * Clear any terminal-specific key bindings that were taken from the 5957 * settings of the last terminal. 5958 */ 5959 _kt_clear_bindings(gl->bindings, KTB_TERM); 5960 /* 5961 * If we have a terminal install new bindings for it. 5962 */ 5963 if(is_term) { 5964 /* 5965 * Get the current settings of the terminal. 5966 */ 5967 if(tcgetattr(gl->input_fd, &gl->oldattr)) { 5968 _err_record_msg(gl->err, "tcgetattr error", END_ERR_MSG); 5969 return 1; 5970 }; 5971 /* 5972 * If we don't set this now, gl_control_strings() won't know 5973 * that it is talking to a terminal. 5974 */ 5975 gl->is_term = 1; 5976 /* 5977 * Lookup the terminal control string and size information. 5978 */ 5979 if(gl_control_strings(gl, term)) { 5980 gl->is_term = 0; 5981 return 1; 5982 }; 5983 /* 5984 * Bind terminal-specific keys. 5985 */ 5986 if(gl_bind_terminal_keys(gl)) 5987 return 1; 5988 }; 5989 /* 5990 * Assume that the caller has given us a terminal in a sane state. 5991 */ 5992 gl->io_mode = GL_NORMAL_MODE; 5993 /* 5994 * Switch into the currently configured I/O mode. 5995 */ 5996 if(_gl_io_mode(gl, gl->io_mode)) 5997 return 1; 5998 return 0; 5999 } 6000 6001 /*....................................................................... 6002 * Set up terminal-specific key bindings. 6003 * 6004 * Input: 6005 * gl GetLine * The resource object of the command-line input 6006 * module. 6007 * Output: 6008 * return int 0 - OK. 6009 * 1 - Error. 6010 */ 6011 static int gl_bind_terminal_keys(GetLine *gl) 6012 { 6013 /* 6014 * Install key-bindings for the special terminal characters. 6015 */ 6016 if(gl_bind_control_char(gl, KTB_TERM, gl->oldattr.c_cc[VINTR], 6017 "user-interrupt") || 6018 gl_bind_control_char(gl, KTB_TERM, gl->oldattr.c_cc[VQUIT], "abort") || 6019 gl_bind_control_char(gl, KTB_TERM, gl->oldattr.c_cc[VSUSP], "suspend")) 6020 return 1; 6021 /* 6022 * In vi-mode, arrange for the above characters to be seen in command 6023 * mode. 6024 */ 6025 if(gl->editor == GL_VI_MODE) { 6026 if(gl_bind_control_char(gl, KTB_TERM, MAKE_META(gl->oldattr.c_cc[VINTR]), 6027 "user-interrupt") || 6028 gl_bind_control_char(gl, KTB_TERM, MAKE_META(gl->oldattr.c_cc[VQUIT]), 6029 "abort") || 6030 gl_bind_control_char(gl, KTB_TERM, MAKE_META(gl->oldattr.c_cc[VSUSP]), 6031 "suspend")) 6032 return 1; 6033 }; 6034 /* 6035 * Non-universal special keys. 6036 */ 6037 #ifdef VLNEXT 6038 if(gl_bind_control_char(gl, KTB_TERM, gl->oldattr.c_cc[VLNEXT], 6039 "literal-next")) 6040 return 1; 6041 #else 6042 if(_kt_set_keybinding(gl->bindings, KTB_TERM, "^V", "literal-next")) { 6043 _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG); 6044 return 1; 6045 }; 6046 #endif 6047 /* 6048 * Bind action functions to the terminal-specific arrow keys 6049 * looked up by gl_control_strings(). 6050 */ 6051 if(_gl_bind_arrow_keys(gl)) 6052 return 1; 6053 return 0; 6054 } 6055 6056 /*....................................................................... 6057 * This function is normally bound to control-D. When it is invoked within 6058 * a line it deletes the character which follows the cursor. When invoked 6059 * at the end of the line it lists possible file completions, and when 6060 * invoked on an empty line it causes gl_get_line() to return EOF. This 6061 * function emulates the one that is normally bound to control-D by tcsh. 6062 */ 6063 static KT_KEY_FN(gl_del_char_or_list_or_eof) 6064 { 6065 /* 6066 * If we have an empty line arrange to return EOF. 6067 */ 6068 if(gl->ntotal < 1) { 6069 gl_record_status(gl, GLR_EOF, 0); 6070 return 1; 6071 /* 6072 * If we are at the end of the line list possible completions. 6073 */ 6074 } else if(gl->buff_curpos >= gl->ntotal) { 6075 return gl_list_completions(gl, 1, NULL); 6076 /* 6077 * Within the line delete the character that follows the cursor. 6078 */ 6079 } else { 6080 /* 6081 * If in vi command mode, first preserve the current line for potential use 6082 * by vi-undo. 6083 */ 6084 gl_save_for_undo(gl); 6085 /* 6086 * Delete 'count' characters. 6087 */ 6088 return gl_forward_delete_char(gl, count, NULL); 6089 }; 6090 } 6091 6092 /*....................................................................... 6093 * This function is normally bound to control-D in vi mode. When it is 6094 * invoked within a line it lists possible file completions, and when 6095 * invoked on an empty line it causes gl_get_line() to return EOF. This 6096 * function emulates the one that is normally bound to control-D by tcsh. 6097 */ 6098 static KT_KEY_FN(gl_list_or_eof) 6099 { 6100 /* 6101 * If we have an empty line arrange to return EOF. 6102 */ 6103 if(gl->ntotal < 1) { 6104 gl_record_status(gl, GLR_EOF, 0); 6105 return 1; 6106 /* 6107 * Otherwise list possible completions. 6108 */ 6109 } else { 6110 return gl_list_completions(gl, 1, NULL); 6111 }; 6112 } 6113 6114 /*....................................................................... 6115 * List possible completions of the word that precedes the cursor. The 6116 * callback data argument must either be NULL to select the default 6117 * file completion callback, or be a GlCplCallback object containing the 6118 * completion callback function to call. 6119 */ 6120 static KT_KEY_FN(gl_list_completions) 6121 { 6122 int waserr = 0; /* True after errors */ 6123 /* 6124 * Get the container of the completion callback and its callback data. 6125 */ 6126 GlCplCallback *cb = data ? (GlCplCallback *) data : &gl->cplfn; 6127 /* 6128 * Get the list of possible completions. 6129 */ 6130 CplMatches *matches = cpl_complete_word(gl->cpl, gl->line, gl->buff_curpos, 6131 cb->data, cb->fn); 6132 /* 6133 * No matching completions? 6134 */ 6135 if(!matches) { 6136 waserr = gl_print_info(gl, cpl_last_error(gl->cpl), GL_END_INFO); 6137 /* 6138 * List the matches. 6139 */ 6140 } else if(matches->nmatch > 0 && gl->echo) { 6141 if(_gl_normal_io(gl) || 6142 _cpl_output_completions(matches, gl_write_fn, gl, gl->ncolumn)) 6143 waserr = 1; 6144 }; 6145 /* 6146 * If any output had to be written to the terminal, then editing will 6147 * have been suspended, make sure that we are back in raw line editing 6148 * mode before returning. 6149 */ 6150 if(_gl_raw_io(gl, 1)) 6151 waserr = 1; 6152 return waserr; 6153 } 6154 6155 /*....................................................................... 6156 * Where the user has used the symbolic arrow-key names to specify 6157 * arrow key bindings, bind the specified action functions to the default 6158 * and terminal specific arrow key sequences. 6159 * 6160 * Input: 6161 * gl GetLine * The getline resource object. 6162 * Output: 6163 * return int 0 - OK. 6164 * 1 - Error. 6165 */ 6166 static int _gl_bind_arrow_keys(GetLine *gl) 6167 { 6168 /* 6169 * Process each of the arrow keys. 6170 */ 6171 if(_gl_rebind_arrow_key(gl, "up", gl->u_arrow, "^[[A", "^[OA") || 6172 _gl_rebind_arrow_key(gl, "down", gl->d_arrow, "^[[B", "^[OB") || 6173 _gl_rebind_arrow_key(gl, "left", gl->l_arrow, "^[[D", "^[OD") || 6174 _gl_rebind_arrow_key(gl, "right", gl->r_arrow, "^[[C", "^[OC")) 6175 return 1; 6176 return 0; 6177 } 6178 6179 /*....................................................................... 6180 * Lookup the action function of a symbolic arrow-key binding, and bind 6181 * it to the terminal-specific and default arrow-key sequences. Note that 6182 * we don't trust the terminal-specified key sequences to be correct. 6183 * The main reason for this is that on some machines the xterm terminfo 6184 * entry is for hardware X-terminals, rather than xterm terminal emulators 6185 * and the two terminal types emit different character sequences when the 6186 * their cursor keys are pressed. As a result we also supply a couple 6187 * of default key sequences. 6188 * 6189 * Input: 6190 * gl GetLine * The resource object of gl_get_line(). 6191 * name char * The symbolic name of the arrow key. 6192 * term_seq char * The terminal-specific arrow-key sequence. 6193 * def_seq1 char * The first default arrow-key sequence. 6194 * def_seq2 char * The second arrow-key sequence. 6195 * Output: 6196 * return int 0 - OK. 6197 * 1 - Error. 6198 */ 6199 static int _gl_rebind_arrow_key(GetLine *gl, const char *name, 6200 const char *term_seq, const char *def_seq1, 6201 const char *def_seq2) 6202 { 6203 KeySym *keysym; /* The binding-table entry matching the arrow-key name */ 6204 int nsym; /* The number of ambiguous matches */ 6205 /* 6206 * Lookup the key binding for the symbolic name of the arrow key. This 6207 * will either be the default action, or a user provided one. 6208 */ 6209 if(_kt_lookup_keybinding(gl->bindings, name, strlen(name), &keysym, &nsym) 6210 == KT_EXACT_MATCH) { 6211 /* 6212 * Get the action function. 6213 */ 6214 KtAction *action = keysym->actions + keysym->binder; 6215 KtKeyFn *fn = action->fn; 6216 void *data = action->data; 6217 /* 6218 * Bind this to each of the specified key sequences. 6219 */ 6220 if((term_seq && 6221 _kt_set_keyfn(gl->bindings, KTB_TERM, term_seq, fn, data)) || 6222 (def_seq1 && 6223 _kt_set_keyfn(gl->bindings, KTB_NORM, def_seq1, fn, data)) || 6224 (def_seq2 && 6225 _kt_set_keyfn(gl->bindings, KTB_NORM, def_seq2, fn, data))) { 6226 _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG); 6227 return 1; 6228 }; 6229 }; 6230 return 0; 6231 } 6232 6233 /*....................................................................... 6234 * Read getline configuration information from a given file. 6235 * 6236 * Input: 6237 * gl GetLine * The getline resource object. 6238 * filename const char * The name of the file to read configuration 6239 * information from. The contents of this file 6240 * are as described in the gl_get_line(3) man 6241 * page for the default ~/.teclarc configuration 6242 * file. 6243 * who KtBinder Who bindings are to be installed for. 6244 * Output: 6245 * return int 0 - OK. 6246 * 1 - Irrecoverable error. 6247 */ 6248 static int _gl_read_config_file(GetLine *gl, const char *filename, KtBinder who) 6249 { 6250 /* 6251 * If filesystem access is to be excluded, configuration files can't 6252 * be read. 6253 */ 6254 #ifdef WITHOUT_FILE_SYSTEM 6255 _err_record_msg(gl->err, 6256 "Can't read configuration files without filesystem access", 6257 END_ERR_MSG); 6258 errno = EINVAL; 6259 return 1; 6260 #else 6261 FileExpansion *expansion; /* The expansion of the filename */ 6262 FILE *fp; /* The opened file */ 6263 int waserr = 0; /* True if an error occurred while reading */ 6264 int lineno = 1; /* The line number being processed */ 6265 /* 6266 * Check the arguments. 6267 */ 6268 if(!gl || !filename) { 6269 if(gl) 6270 _err_record_msg(gl->err, "NULL argument(s)", END_ERR_MSG); 6271 errno = EINVAL; 6272 return 1; 6273 }; 6274 /* 6275 * Expand the filename. 6276 */ 6277 expansion = ef_expand_file(gl->ef, filename, -1); 6278 if(!expansion) { 6279 gl_print_info(gl, "Unable to expand ", filename, " (", 6280 ef_last_error(gl->ef), ").", GL_END_INFO); 6281 return 1; 6282 }; 6283 /* 6284 * Attempt to open the file. 6285 */ 6286 fp = fopen(expansion->files[0], "r"); 6287 /* 6288 * It isn't an error for there to be no configuration file. 6289 */ 6290 if(!fp) 6291 return 0; 6292 /* 6293 * Parse the contents of the file. 6294 */ 6295 while(!waserr && !feof(fp)) 6296 waserr = _gl_parse_config_line(gl, fp, glc_file_getc, filename, who, 6297 &lineno); 6298 /* 6299 * Bind action functions to the terminal-specific arrow keys. 6300 */ 6301 if(_gl_bind_arrow_keys(gl)) 6302 return 1; 6303 /* 6304 * Clean up. 6305 */ 6306 (void) fclose(fp); 6307 return waserr; 6308 #endif 6309 } 6310 6311 /*....................................................................... 6312 * Read GetLine configuration information from a string. The contents of 6313 * the string are the same as those described in the gl_get_line(3) 6314 * man page for the contents of the ~/.teclarc configuration file. 6315 */ 6316 static int _gl_read_config_string(GetLine *gl, const char *buffer, KtBinder who) 6317 { 6318 const char *bptr; /* A pointer into buffer[] */ 6319 int waserr = 0; /* True if an error occurred while reading */ 6320 int lineno = 1; /* The line number being processed */ 6321 /* 6322 * Check the arguments. 6323 */ 6324 if(!gl || !buffer) { 6325 if(gl) 6326 _err_record_msg(gl->err, "NULL argument(s)", END_ERR_MSG); 6327 errno = EINVAL; 6328 return 1; 6329 }; 6330 /* 6331 * Get a pointer to the start of the buffer. 6332 */ 6333 bptr = buffer; 6334 /* 6335 * Parse the contents of the buffer. 6336 */ 6337 while(!waserr && *bptr) 6338 waserr = _gl_parse_config_line(gl, &bptr, glc_buff_getc, "", who, &lineno); 6339 /* 6340 * Bind action functions to the terminal-specific arrow keys. 6341 */ 6342 if(_gl_bind_arrow_keys(gl)) 6343 return 1; 6344 return waserr; 6345 } 6346 6347 /*....................................................................... 6348 * Parse the next line of a getline configuration file. 6349 * 6350 * Input: 6351 * gl GetLine * The getline resource object. 6352 * stream void * The pointer representing the stream to be read 6353 * by getc_fn(). 6354 * getc_fn GlcGetcFn * A callback function which when called with 6355 * 'stream' as its argument, returns the next 6356 * unread character from the stream. 6357 * origin const char * The name of the entity being read (eg. a 6358 * file name). 6359 * who KtBinder Who bindings are to be installed for. 6360 * Input/Output: 6361 * lineno int * The line number being processed is to be 6362 * maintained in *lineno. 6363 * Output: 6364 * return int 0 - OK. 6365 * 1 - Irrecoverable error. 6366 */ 6367 static int _gl_parse_config_line(GetLine *gl, void *stream, GlcGetcFn *getc_fn, 6368 const char *origin, KtBinder who, int *lineno) 6369 { 6370 char buffer[GL_CONF_BUFLEN+1]; /* The input line buffer */ 6371 char *argv[GL_CONF_MAXARG]; /* The argument list */ 6372 int argc = 0; /* The number of arguments in argv[] */ 6373 int c; /* A character from the file */ 6374 int escaped = 0; /* True if the next character is escaped */ 6375 int i; 6376 /* 6377 * Skip spaces and tabs. 6378 */ 6379 do c = getc_fn(stream); while(c==' ' || c=='\t'); 6380 /* 6381 * Comments extend to the end of the line. 6382 */ 6383 if(c=='#') 6384 do c = getc_fn(stream); while(c != '\n' && c != EOF); 6385 /* 6386 * Ignore empty lines. 6387 */ 6388 if(c=='\n' || c==EOF) { 6389 (*lineno)++; 6390 return 0; 6391 }; 6392 /* 6393 * Record the buffer location of the start of the first argument. 6394 */ 6395 argv[argc] = buffer; 6396 /* 6397 * Read the rest of the line, stopping early if a comment is seen, or 6398 * the buffer overflows, and replacing sequences of spaces with a 6399 * '\0', and recording the thus terminated string as an argument. 6400 */ 6401 i = 0; 6402 while(i<GL_CONF_BUFLEN) { 6403 /* 6404 * Did we hit the end of the latest argument? 6405 */ 6406 if(c==EOF || (!escaped && (c==' ' || c=='\n' || c=='\t' || c=='#'))) { 6407 /* 6408 * Terminate the argument. 6409 */ 6410 buffer[i++] = '\0'; 6411 argc++; 6412 /* 6413 * Skip spaces and tabs. 6414 */ 6415 while(c==' ' || c=='\t') 6416 c = getc_fn(stream); 6417 /* 6418 * If we hit the end of the line, or the start of a comment, exit the loop. 6419 */ 6420 if(c==EOF || c=='\n' || c=='#') 6421 break; 6422 /* 6423 * Start recording the next argument. 6424 */ 6425 if(argc >= GL_CONF_MAXARG) { 6426 gl_report_config_error(gl, origin, *lineno, "Too many arguments."); 6427 do c = getc_fn(stream); while(c!='\n' && c!=EOF); /* Skip past eol */ 6428 return 0; 6429 }; 6430 argv[argc] = buffer + i; 6431 /* 6432 * The next character was preceded by spaces, so it isn't escaped. 6433 */ 6434 escaped = 0; 6435 } else { 6436 /* 6437 * If we hit an unescaped backslash, this means that we should arrange 6438 * to treat the next character like a simple alphabetical character. 6439 */ 6440 if(c=='\\' && !escaped) { 6441 escaped = 1; 6442 /* 6443 * Splice lines where the newline is escaped. 6444 */ 6445 } else if(c=='\n' && escaped) { 6446 (*lineno)++; 6447 /* 6448 * Record a normal character, preserving any preceding backslash. 6449 */ 6450 } else { 6451 if(escaped) 6452 buffer[i++] = '\\'; 6453 if(i>=GL_CONF_BUFLEN) 6454 break; 6455 escaped = 0; 6456 buffer[i++] = c; 6457 }; 6458 /* 6459 * Get the next character. 6460 */ 6461 c = getc_fn(stream); 6462 }; 6463 }; 6464 /* 6465 * Did the buffer overflow? 6466 */ 6467 if(i>=GL_CONF_BUFLEN) { 6468 gl_report_config_error(gl, origin, *lineno, "Line too long."); 6469 return 0; 6470 }; 6471 /* 6472 * The first argument should be a command name. 6473 */ 6474 if(strcmp(argv[0], "bind") == 0) { 6475 const char *action = NULL; /* A NULL action removes a keybinding */ 6476 const char *keyseq = NULL; 6477 switch(argc) { 6478 case 3: 6479 action = argv[2]; 6480 case 2: /* Note the intentional fallthrough */ 6481 keyseq = argv[1]; 6482 /* 6483 * Attempt to record the new keybinding. 6484 */ 6485 if(_kt_set_keybinding(gl->bindings, who, keyseq, action)) { 6486 gl_report_config_error(gl, origin, *lineno, 6487 _kt_last_error(gl->bindings)); 6488 }; 6489 break; 6490 default: 6491 gl_report_config_error(gl, origin, *lineno, "Wrong number of arguments."); 6492 }; 6493 } else if(strcmp(argv[0], "edit-mode") == 0) { 6494 if(argc == 2 && strcmp(argv[1], "emacs") == 0) { 6495 gl_change_editor(gl, GL_EMACS_MODE); 6496 } else if(argc == 2 && strcmp(argv[1], "vi") == 0) { 6497 gl_change_editor(gl, GL_VI_MODE); 6498 } else if(argc == 2 && strcmp(argv[1], "none") == 0) { 6499 gl_change_editor(gl, GL_NO_EDITOR); 6500 } else { 6501 gl_report_config_error(gl, origin, *lineno, 6502 "The argument of editor should be vi or emacs."); 6503 }; 6504 } else if(strcmp(argv[0], "nobeep") == 0) { 6505 gl->silence_bell = 1; 6506 } else { 6507 gl_report_config_error(gl, origin, *lineno, "Unknown command name."); 6508 }; 6509 /* 6510 * Skip any trailing comment. 6511 */ 6512 while(c != '\n' && c != EOF) 6513 c = getc_fn(stream); 6514 (*lineno)++; 6515 return 0; 6516 } 6517 6518 /*....................................................................... 6519 * This is a private function of _gl_parse_config_line() which prints 6520 * out an error message about the contents of the line, prefixed by the 6521 * name of the origin of the line and its line number. 6522 * 6523 * Input: 6524 * gl GetLine * The resource object of gl_get_line(). 6525 * origin const char * The name of the entity being read (eg. a 6526 * file name). 6527 * lineno int The line number at which the error occurred. 6528 * errmsg const char * The error message. 6529 * Output: 6530 * return int 0 - OK. 6531 * 1 - Error. 6532 */ 6533 static int gl_report_config_error(GetLine *gl, const char *origin, int lineno, 6534 const char *errmsg) 6535 { 6536 char lnum[20]; /* A buffer in which to render a single integer */ 6537 /* 6538 * Convert the line number into a string. 6539 */ 6540 snprintf(lnum, sizeof(lnum), "%d", lineno); 6541 /* 6542 * Have the string printed on the terminal. 6543 */ 6544 return gl_print_info(gl, origin, ":", lnum, ": ", errmsg, GL_END_INFO); 6545 } 6546 6547 /*....................................................................... 6548 * This is the _gl_parse_config_line() callback function which reads the 6549 * next character from a configuration file. 6550 */ 6551 static GLC_GETC_FN(glc_file_getc) 6552 { 6553 return fgetc((FILE *) stream); 6554 } 6555 6556 /*....................................................................... 6557 * This is the _gl_parse_config_line() callback function which reads the 6558 * next character from a buffer. Its stream argument is a pointer to a 6559 * variable which is, in turn, a pointer into the buffer being read from. 6560 */ 6561 static GLC_GETC_FN(glc_buff_getc) 6562 { 6563 const char **lptr = (char const **) stream; 6564 return **lptr ? *(*lptr)++ : EOF; 6565 } 6566 6567 #ifndef HIDE_FILE_SYSTEM 6568 /*....................................................................... 6569 * When this action is triggered, it arranges to temporarily read command 6570 * lines from the regular file whos name precedes the cursor. 6571 * The current line is first discarded. 6572 */ 6573 static KT_KEY_FN(gl_read_from_file) 6574 { 6575 char *start_path; /* The pointer to the start of the pathname in */ 6576 /* gl->line[]. */ 6577 FileExpansion *result; /* The results of the filename expansion */ 6578 int pathlen; /* The length of the pathname being expanded */ 6579 /* 6580 * Locate the start of the filename that precedes the cursor position. 6581 */ 6582 start_path = _pu_start_of_path(gl->line, gl->buff_curpos); 6583 if(!start_path) 6584 return 1; 6585 /* 6586 * Get the length of the pathname string. 6587 */ 6588 pathlen = gl->buff_curpos - (start_path - gl->line); 6589 /* 6590 * Attempt to expand the pathname. 6591 */ 6592 result = ef_expand_file(gl->ef, start_path, pathlen); 6593 /* 6594 * If there was an error, report the error on a new line. 6595 */ 6596 if(!result) { 6597 return gl_print_info(gl, ef_last_error(gl->ef), GL_END_INFO); 6598 /* 6599 * If no files matched, report this as well. 6600 */ 6601 } else if(result->nfile == 0 || !result->exists) { 6602 return gl_print_info(gl, "No files match.", GL_END_INFO); 6603 /* 6604 * Complain if more than one file matches. 6605 */ 6606 } else if(result->nfile > 1) { 6607 return gl_print_info(gl, "More than one file matches.", GL_END_INFO); 6608 /* 6609 * Disallow input from anything but normal files. In principle we could 6610 * also support input from named pipes. Terminal files would be a problem 6611 * since we wouldn't know the terminal type, and other types of files 6612 * might cause the library to lock up. 6613 */ 6614 } else if(!_pu_path_is_file(result->files[0])) { 6615 return gl_print_info(gl, "Not a normal file.", GL_END_INFO); 6616 } else { 6617 /* 6618 * Attempt to open and install the specified file for reading. 6619 */ 6620 gl->file_fp = fopen(result->files[0], "r"); 6621 if(!gl->file_fp) { 6622 return gl_print_info(gl, "Unable to open: ", result->files[0], 6623 GL_END_INFO); 6624 }; 6625 /* 6626 * If needed, expand the record of the maximum file-descriptor that might 6627 * need to be monitored with select(). 6628 */ 6629 #ifdef HAVE_SELECT 6630 if(fileno(gl->file_fp) > gl->max_fd) 6631 gl->max_fd = fileno(gl->file_fp); 6632 #endif 6633 /* 6634 * Is non-blocking I/O needed? 6635 */ 6636 if(gl->raw_mode && gl->io_mode==GL_SERVER_MODE && 6637 gl_nonblocking_io(gl, fileno(gl->file_fp))) { 6638 gl_revert_input(gl); 6639 return gl_print_info(gl, "Can't read file %s with non-blocking I/O", 6640 result->files[0]); 6641 }; 6642 /* 6643 * Inform the user what is happening. 6644 */ 6645 if(gl_print_info(gl, "<Taking input from ", result->files[0], ">", 6646 GL_END_INFO)) 6647 return 1; 6648 }; 6649 return 0; 6650 } 6651 #endif 6652 6653 /*....................................................................... 6654 * Close any temporary file that is being used for input. 6655 * 6656 * Input: 6657 * gl GetLine * The getline resource object. 6658 */ 6659 static void gl_revert_input(GetLine *gl) 6660 { 6661 if(gl->file_fp) 6662 fclose(gl->file_fp); 6663 gl->file_fp = NULL; 6664 gl->endline = 1; 6665 } 6666 6667 /*....................................................................... 6668 * This is the action function that recalls the oldest line in the 6669 * history buffer. 6670 */ 6671 static KT_KEY_FN(gl_beginning_of_history) 6672 { 6673 /* 6674 * In vi mode, switch to command mode, since the user is very 6675 * likely to want to move around newly recalled lines. 6676 */ 6677 gl_vi_command_mode(gl); 6678 /* 6679 * Forget any previous recall session. 6680 */ 6681 gl->preload_id = 0; 6682 /* 6683 * Record the key sequence number of this search action. 6684 */ 6685 gl->last_search = gl->keyseq_count; 6686 /* 6687 * Recall the next oldest line in the history list. 6688 */ 6689 if(_glh_oldest_line(gl->glh, gl->line, gl->linelen+1) == NULL) 6690 return 0; 6691 /* 6692 * Accomodate the new contents of gl->line[]. 6693 */ 6694 gl_update_buffer(gl); 6695 /* 6696 * Arrange to have the cursor placed at the end of the new line. 6697 */ 6698 gl->buff_curpos = gl->ntotal; 6699 /* 6700 * Erase and display the new line. 6701 */ 6702 gl_queue_redisplay(gl); 6703 return 0; 6704 } 6705 6706 /*....................................................................... 6707 * If a history session is currently in progress, this action function 6708 * recalls the line that was being edited when the session started. If 6709 * no history session is in progress, it does nothing. 6710 */ 6711 static KT_KEY_FN(gl_end_of_history) 6712 { 6713 /* 6714 * In vi mode, switch to command mode, since the user is very 6715 * likely to want to move around newly recalled lines. 6716 */ 6717 gl_vi_command_mode(gl); 6718 /* 6719 * Forget any previous recall session. 6720 */ 6721 gl->preload_id = 0; 6722 /* 6723 * Record the key sequence number of this search action. 6724 */ 6725 gl->last_search = gl->keyseq_count; 6726 /* 6727 * Recall the next oldest line in the history list. 6728 */ 6729 if(_glh_current_line(gl->glh, gl->line, gl->linelen+1) == NULL) 6730 return 0; 6731 /* 6732 * Accomodate the new contents of gl->line[]. 6733 */ 6734 gl_update_buffer(gl); 6735 /* 6736 * Arrange to have the cursor placed at the end of the new line. 6737 */ 6738 gl->buff_curpos = gl->ntotal; 6739 /* 6740 * Erase and display the new line. 6741 */ 6742 gl_queue_redisplay(gl); 6743 return 0; 6744 } 6745 6746 /*....................................................................... 6747 * This action function is treated specially, in that its count argument 6748 * is set to the end keystroke of the keysequence that activated it. 6749 * It accumulates a numeric argument, adding one digit on each call in 6750 * which the last keystroke was a numeric digit. 6751 */ 6752 static KT_KEY_FN(gl_digit_argument) 6753 { 6754 /* 6755 * Was the last keystroke a digit? 6756 */ 6757 int is_digit = isdigit((int)(unsigned char) count); 6758 /* 6759 * In vi command mode, a lone '0' means goto-start-of-line. 6760 */ 6761 if(gl->vi.command && gl->number < 0 && count == '0') 6762 return gl_beginning_of_line(gl, count, NULL); 6763 /* 6764 * Are we starting to accumulate a new number? 6765 */ 6766 if(gl->number < 0 || !is_digit) 6767 gl->number = 0; 6768 /* 6769 * Was the last keystroke a digit? 6770 */ 6771 if(is_digit) { 6772 /* 6773 * Read the numeric value of the digit, without assuming ASCII. 6774 */ 6775 int n; 6776 char s[2]; s[0] = count; s[1] = '\0'; 6777 n = atoi(s); 6778 /* 6779 * Append the new digit. 6780 */ 6781 gl->number = gl->number * 10 + n; 6782 }; 6783 return 0; 6784 } 6785 6786 /*....................................................................... 6787 * The newline action function sets gl->endline to tell 6788 * gl_get_input_line() that the line is now complete. 6789 */ 6790 static KT_KEY_FN(gl_newline) 6791 { 6792 GlhLineID id; /* The last history line recalled while entering this line */ 6793 /* 6794 * Flag the line as ended. 6795 */ 6796 gl->endline = 1; 6797 /* 6798 * Record the next position in the history buffer, for potential 6799 * recall by an action function on the next call to gl_get_line(). 6800 */ 6801 id = _glh_line_id(gl->glh, 1); 6802 if(id) 6803 gl->preload_id = id; 6804 return 0; 6805 } 6806 6807 /*....................................................................... 6808 * The 'repeat' action function sets gl->endline to tell 6809 * gl_get_input_line() that the line is now complete, and records the 6810 * ID of the next history line in gl->preload_id so that the next call 6811 * to gl_get_input_line() will preload the line with that history line. 6812 */ 6813 static KT_KEY_FN(gl_repeat_history) 6814 { 6815 gl->endline = 1; 6816 gl->preload_id = _glh_line_id(gl->glh, 1); 6817 gl->preload_history = 1; 6818 return 0; 6819 } 6820 6821 /*....................................................................... 6822 * Flush unwritten characters to the terminal. 6823 * 6824 * Input: 6825 * gl GetLine * The getline resource object. 6826 * Output: 6827 * return int 0 - OK. 6828 * 1 - Either an error occured, or the output 6829 * blocked and non-blocking I/O is being used. 6830 * See gl->rtn_status for details. 6831 */ 6832 static int gl_flush_output(GetLine *gl) 6833 { 6834 /* 6835 * Record the fact that we are about to write to the terminal. 6836 */ 6837 gl->pending_io = GLP_WRITE; 6838 /* 6839 * Attempt to flush the output to the terminal. 6840 */ 6841 errno = 0; 6842 switch(_glq_flush_queue(gl->cq, gl->flush_fn, gl)) { 6843 case GLQ_FLUSH_DONE: 6844 return gl->redisplay && !gl->postpone && gl_redisplay(gl, 1, NULL); 6845 break; 6846 case GLQ_FLUSH_AGAIN: /* Output blocked */ 6847 gl_record_status(gl, GLR_BLOCKED, BLOCKED_ERRNO); 6848 return 1; 6849 break; 6850 default: /* Abort the line if an error occurs */ 6851 gl_record_status(gl, errno==EINTR ? GLR_SIGNAL : GLR_ERROR, errno); 6852 return 1; 6853 break; 6854 }; 6855 } 6856 6857 /*....................................................................... 6858 * This is the callback which _glq_flush_queue() uses to write buffered 6859 * characters to the terminal. 6860 */ 6861 static GL_WRITE_FN(gl_flush_terminal) 6862 { 6863 int ndone = 0; /* The number of characters written so far */ 6864 /* 6865 * Get the line-editor resource object. 6866 */ 6867 GetLine *gl = (GetLine *) data; 6868 /* 6869 * Transfer the latest array of characters to stdio. 6870 */ 6871 while(ndone < n) { 6872 int nnew = write(gl->output_fd, s, n-ndone); 6873 /* 6874 * If the write was successful, add to the recorded number of bytes 6875 * that have now been written. 6876 */ 6877 if(nnew > 0) { 6878 ndone += nnew; 6879 /* 6880 * If a signal interrupted the call, restart the write(), since all of 6881 * the signals that gl_get_line() has been told to watch for are 6882 * currently blocked. 6883 */ 6884 } else if(errno == EINTR) { 6885 continue; 6886 /* 6887 * If we managed to write something before an I/O error occurred, or 6888 * output blocked before anything was written, report the number of 6889 * bytes that were successfully written before this happened. 6890 */ 6891 } else if(ndone > 0 6892 #if defined(EAGAIN) 6893 || errno==EAGAIN 6894 #endif 6895 #if defined(EWOULDBLOCK) 6896 || errno==EWOULDBLOCK 6897 #endif 6898 ) { 6899 return ndone; 6900 6901 /* 6902 * To get here, an error must have occurred before anything new could 6903 * be written. 6904 */ 6905 } else { 6906 return -1; 6907 }; 6908 }; 6909 /* 6910 * To get here, we must have successfully written the number of 6911 * bytes that was specified. 6912 */ 6913 return n; 6914 } 6915 6916 /*....................................................................... 6917 * Change the style of editing to emulate a given editor. 6918 * 6919 * Input: 6920 * gl GetLine * The getline resource object. 6921 * editor GlEditor The type of editor to emulate. 6922 * Output: 6923 * return int 0 - OK. 6924 * 1 - Error. 6925 */ 6926 static int gl_change_editor(GetLine *gl, GlEditor editor) 6927 { 6928 /* 6929 * Install the default key-bindings of the requested editor. 6930 */ 6931 switch(editor) { 6932 case GL_EMACS_MODE: 6933 _kt_clear_bindings(gl->bindings, KTB_NORM); 6934 _kt_clear_bindings(gl->bindings, KTB_TERM); 6935 (void) _kt_add_bindings(gl->bindings, KTB_NORM, gl_emacs_bindings, 6936 sizeof(gl_emacs_bindings)/sizeof(gl_emacs_bindings[0])); 6937 break; 6938 case GL_VI_MODE: 6939 _kt_clear_bindings(gl->bindings, KTB_NORM); 6940 _kt_clear_bindings(gl->bindings, KTB_TERM); 6941 (void) _kt_add_bindings(gl->bindings, KTB_NORM, gl_vi_bindings, 6942 sizeof(gl_vi_bindings)/sizeof(gl_vi_bindings[0])); 6943 break; 6944 case GL_NO_EDITOR: 6945 break; 6946 default: 6947 _err_record_msg(gl->err, "Unknown editor", END_ERR_MSG); 6948 errno = EINVAL; 6949 return 1; 6950 }; 6951 /* 6952 * Record the new editing mode. 6953 */ 6954 gl->editor = editor; 6955 gl->vi.command = 0; /* Start in input mode */ 6956 gl->insert_curpos = 0; 6957 /* 6958 * Reinstate terminal-specific bindings. 6959 */ 6960 if(gl->editor != GL_NO_EDITOR && gl->input_fp) 6961 (void) gl_bind_terminal_keys(gl); 6962 return 0; 6963 } 6964 6965 /*....................................................................... 6966 * This is an action function that switches to editing using emacs bindings 6967 */ 6968 static KT_KEY_FN(gl_emacs_editing_mode) 6969 { 6970 return gl_change_editor(gl, GL_EMACS_MODE); 6971 } 6972 6973 /*....................................................................... 6974 * This is an action function that switches to editing using vi bindings 6975 */ 6976 static KT_KEY_FN(gl_vi_editing_mode) 6977 { 6978 return gl_change_editor(gl, GL_VI_MODE); 6979 } 6980 6981 /*....................................................................... 6982 * This is the action function that switches to insert mode. 6983 */ 6984 static KT_KEY_FN(gl_vi_insert) 6985 { 6986 /* 6987 * If in vi command mode, preserve the current line for potential 6988 * use by vi-undo. 6989 */ 6990 gl_save_for_undo(gl); 6991 /* 6992 * Switch to vi insert mode. 6993 */ 6994 gl->insert = 1; 6995 gl->vi.command = 0; 6996 gl->insert_curpos = gl->buff_curpos; 6997 return 0; 6998 } 6999 7000 /*....................................................................... 7001 * This is an action function that switches to overwrite mode. 7002 */ 7003 static KT_KEY_FN(gl_vi_overwrite) 7004 { 7005 /* 7006 * If in vi command mode, preserve the current line for potential 7007 * use by vi-undo. 7008 */ 7009 gl_save_for_undo(gl); 7010 /* 7011 * Switch to vi overwrite mode. 7012 */ 7013 gl->insert = 0; 7014 gl->vi.command = 0; 7015 gl->insert_curpos = gl->buff_curpos; 7016 return 0; 7017 } 7018 7019 /*....................................................................... 7020 * This action function toggles the case of the character under the 7021 * cursor. 7022 */ 7023 static KT_KEY_FN(gl_change_case) 7024 { 7025 int i; 7026 /* 7027 * Keep a record of the current insert mode and the cursor position. 7028 */ 7029 int insert = gl->insert; 7030 /* 7031 * If in vi command mode, preserve the current line for potential 7032 * use by vi-undo. 7033 */ 7034 gl_save_for_undo(gl); 7035 /* 7036 * We want to overwrite the modified word. 7037 */ 7038 gl->insert = 0; 7039 /* 7040 * Toggle the case of 'count' characters. 7041 */ 7042 for(i=0; i<count && gl->buff_curpos < gl->ntotal; i++) { 7043 char *cptr = gl->line + gl->buff_curpos++; 7044 /* 7045 * Convert the character to upper case? 7046 */ 7047 if(islower((int)(unsigned char) *cptr)) 7048 gl_buffer_char(gl, toupper((int) *cptr), cptr - gl->line); 7049 else if(isupper((int)(unsigned char) *cptr)) 7050 gl_buffer_char(gl, tolower((int) *cptr), cptr - gl->line); 7051 /* 7052 * Write the possibly modified character back. Note that for non-modified 7053 * characters we want to do this as well, so as to advance the cursor. 7054 */ 7055 if(gl_print_char(gl, *cptr, cptr[1])) 7056 return 1; 7057 }; 7058 /* 7059 * Restore the insertion mode. 7060 */ 7061 gl->insert = insert; 7062 return gl_place_cursor(gl, gl->buff_curpos); /* bounds check */ 7063 } 7064 7065 /*....................................................................... 7066 * This is the action function which implements the vi-style action which 7067 * moves the cursor to the start of the line, then switches to insert mode. 7068 */ 7069 static KT_KEY_FN(gl_vi_insert_at_bol) 7070 { 7071 gl_save_for_undo(gl); 7072 return gl_beginning_of_line(gl, 0, NULL) || 7073 gl_vi_insert(gl, 0, NULL); 7074 7075 } 7076 7077 /*....................................................................... 7078 * This is the action function which implements the vi-style action which 7079 * moves the cursor to the end of the line, then switches to insert mode 7080 * to allow text to be appended to the line. 7081 */ 7082 static KT_KEY_FN(gl_vi_append_at_eol) 7083 { 7084 gl_save_for_undo(gl); 7085 gl->vi.command = 0; /* Allow cursor at EOL */ 7086 return gl_end_of_line(gl, 0, NULL) || 7087 gl_vi_insert(gl, 0, NULL); 7088 } 7089 7090 /*....................................................................... 7091 * This is the action function which implements the vi-style action which 7092 * moves the cursor to right one then switches to insert mode, thus 7093 * allowing text to be appended after the next character. 7094 */ 7095 static KT_KEY_FN(gl_vi_append) 7096 { 7097 gl_save_for_undo(gl); 7098 gl->vi.command = 0; /* Allow cursor at EOL */ 7099 return gl_cursor_right(gl, 1, NULL) || 7100 gl_vi_insert(gl, 0, NULL); 7101 } 7102 7103 /*....................................................................... 7104 * This action function moves the cursor to the column specified by the 7105 * numeric argument. Column indexes start at 1. 7106 */ 7107 static KT_KEY_FN(gl_goto_column) 7108 { 7109 return gl_place_cursor(gl, count - 1); 7110 } 7111 7112 /*....................................................................... 7113 * Starting with the character under the cursor, replace 'count' 7114 * characters with the next character that the user types. 7115 */ 7116 static KT_KEY_FN(gl_vi_replace_char) 7117 { 7118 char c; /* The replacement character */ 7119 int i; 7120 /* 7121 * Keep a record of the current insert mode. 7122 */ 7123 int insert = gl->insert; 7124 /* 7125 * Get the replacement character. 7126 */ 7127 if(gl->vi.repeat.active) { 7128 c = gl->vi.repeat.input_char; 7129 } else { 7130 if(gl_read_terminal(gl, 1, &c)) 7131 return 1; 7132 gl->vi.repeat.input_char = c; 7133 }; 7134 /* 7135 * Are there 'count' characters to be replaced? 7136 */ 7137 if(gl->ntotal - gl->buff_curpos >= count) { 7138 /* 7139 * If in vi command mode, preserve the current line for potential 7140 * use by vi-undo. 7141 */ 7142 gl_save_for_undo(gl); 7143 /* 7144 * Temporarily switch to overwrite mode. 7145 */ 7146 gl->insert = 0; 7147 /* 7148 * Overwrite the current character plus count-1 subsequent characters 7149 * with the replacement character. 7150 */ 7151 for(i=0; i<count; i++) 7152 gl_add_char_to_line(gl, c); 7153 /* 7154 * Restore the original insert/overwrite mode. 7155 */ 7156 gl->insert = insert; 7157 }; 7158 return gl_place_cursor(gl, gl->buff_curpos); /* bounds check */ 7159 } 7160 7161 /*....................................................................... 7162 * This is an action function which changes all characters between the 7163 * current cursor position and the end of the line. 7164 */ 7165 static KT_KEY_FN(gl_vi_change_rest_of_line) 7166 { 7167 gl_save_for_undo(gl); 7168 gl->vi.command = 0; /* Allow cursor at EOL */ 7169 return gl_kill_line(gl, count, NULL) || gl_vi_insert(gl, 0, NULL); 7170 } 7171 7172 /*....................................................................... 7173 * This is an action function which changes all characters between the 7174 * start of the line and the current cursor position. 7175 */ 7176 static KT_KEY_FN(gl_vi_change_to_bol) 7177 { 7178 return gl_backward_kill_line(gl,count,NULL) || gl_vi_insert(gl,0,NULL); 7179 } 7180 7181 /*....................................................................... 7182 * This is an action function which deletes the entire contents of the 7183 * current line and switches to insert mode. 7184 */ 7185 static KT_KEY_FN(gl_vi_change_line) 7186 { 7187 return gl_delete_line(gl,count,NULL) || gl_vi_insert(gl,0,NULL); 7188 } 7189 7190 /*....................................................................... 7191 * Starting from the cursor position and looking towards the end of the 7192 * line, copy 'count' characters to the cut buffer. 7193 */ 7194 static KT_KEY_FN(gl_forward_copy_char) 7195 { 7196 /* 7197 * Limit the count to the number of characters available. 7198 */ 7199 if(gl->buff_curpos + count >= gl->ntotal) 7200 count = gl->ntotal - gl->buff_curpos; 7201 if(count < 0) 7202 count = 0; 7203 /* 7204 * Copy the characters to the cut buffer. 7205 */ 7206 memcpy(gl->cutbuf, gl->line + gl->buff_curpos, count); 7207 gl->cutbuf[count] = '\0'; 7208 return 0; 7209 } 7210 7211 /*....................................................................... 7212 * Starting from the character before the cursor position and looking 7213 * backwards towards the start of the line, copy 'count' characters to 7214 * the cut buffer. 7215 */ 7216 static KT_KEY_FN(gl_backward_copy_char) 7217 { 7218 /* 7219 * Limit the count to the number of characters available. 7220 */ 7221 if(count > gl->buff_curpos) 7222 count = gl->buff_curpos; 7223 if(count < 0) 7224 count = 0; 7225 gl_place_cursor(gl, gl->buff_curpos - count); 7226 /* 7227 * Copy the characters to the cut buffer. 7228 */ 7229 memcpy(gl->cutbuf, gl->line + gl->buff_curpos, count); 7230 gl->cutbuf[count] = '\0'; 7231 return 0; 7232 } 7233 7234 /*....................................................................... 7235 * Starting from the cursor position copy to the specified column into the 7236 * cut buffer. 7237 */ 7238 static KT_KEY_FN(gl_copy_to_column) 7239 { 7240 if (--count >= gl->buff_curpos) 7241 return gl_forward_copy_char(gl, count - gl->buff_curpos, NULL); 7242 else 7243 return gl_backward_copy_char(gl, gl->buff_curpos - count, NULL); 7244 } 7245 7246 /*....................................................................... 7247 * Starting from the cursor position copy characters up to a matching 7248 * parenthesis into the cut buffer. 7249 */ 7250 static KT_KEY_FN(gl_copy_to_parenthesis) 7251 { 7252 int curpos = gl_index_of_matching_paren(gl); 7253 if(curpos >= 0) { 7254 gl_save_for_undo(gl); 7255 if(curpos >= gl->buff_curpos) 7256 return gl_forward_copy_char(gl, curpos - gl->buff_curpos + 1, NULL); 7257 else 7258 return gl_backward_copy_char(gl, ++gl->buff_curpos - curpos + 1, NULL); 7259 }; 7260 return 0; 7261 } 7262 7263 /*....................................................................... 7264 * Starting from the cursor position copy the rest of the line into the 7265 * cut buffer. 7266 */ 7267 static KT_KEY_FN(gl_copy_rest_of_line) 7268 { 7269 /* 7270 * Copy the characters to the cut buffer. 7271 */ 7272 memcpy(gl->cutbuf, gl->line + gl->buff_curpos, gl->ntotal - gl->buff_curpos); 7273 gl->cutbuf[gl->ntotal - gl->buff_curpos] = '\0'; 7274 return 0; 7275 } 7276 7277 /*....................................................................... 7278 * Copy from the beginning of the line to the cursor position into the 7279 * cut buffer. 7280 */ 7281 static KT_KEY_FN(gl_copy_to_bol) 7282 { 7283 /* 7284 * Copy the characters to the cut buffer. 7285 */ 7286 memcpy(gl->cutbuf, gl->line, gl->buff_curpos); 7287 gl->cutbuf[gl->buff_curpos] = '\0'; 7288 gl_place_cursor(gl, 0); 7289 return 0; 7290 } 7291 7292 /*....................................................................... 7293 * Copy the entire line into the cut buffer. 7294 */ 7295 static KT_KEY_FN(gl_copy_line) 7296 { 7297 /* 7298 * Copy the characters to the cut buffer. 7299 */ 7300 memcpy(gl->cutbuf, gl->line, gl->ntotal); 7301 gl->cutbuf[gl->ntotal] = '\0'; 7302 return 0; 7303 } 7304 7305 /*....................................................................... 7306 * Search forwards for the next character that the user enters. 7307 */ 7308 static KT_KEY_FN(gl_forward_find_char) 7309 { 7310 int pos = gl_find_char(gl, count, 1, 1, '\0'); 7311 return pos >= 0 && gl_place_cursor(gl, pos); 7312 } 7313 7314 /*....................................................................... 7315 * Search backwards for the next character that the user enters. 7316 */ 7317 static KT_KEY_FN(gl_backward_find_char) 7318 { 7319 int pos = gl_find_char(gl, count, 0, 1, '\0'); 7320 return pos >= 0 && gl_place_cursor(gl, pos); 7321 } 7322 7323 /*....................................................................... 7324 * Search forwards for the next character that the user enters. Move up to, 7325 * but not onto, the found character. 7326 */ 7327 static KT_KEY_FN(gl_forward_to_char) 7328 { 7329 int pos = gl_find_char(gl, count, 1, 0, '\0'); 7330 return pos >= 0 && gl_place_cursor(gl, pos); 7331 } 7332 7333 /*....................................................................... 7334 * Search backwards for the next character that the user enters. Move back to, 7335 * but not onto, the found character. 7336 */ 7337 static KT_KEY_FN(gl_backward_to_char) 7338 { 7339 int pos = gl_find_char(gl, count, 0, 0, '\0'); 7340 return pos >= 0 && gl_place_cursor(gl, pos); 7341 } 7342 7343 /*....................................................................... 7344 * Searching in a given direction, return the index of a given (or 7345 * read) character in the input line, or the character that precedes 7346 * it in the specified search direction. Return -1 if not found. 7347 * 7348 * Input: 7349 * gl GetLine * The getline resource object. 7350 * count int The number of times to search. 7351 * forward int True if searching forward. 7352 * onto int True if the search should end on top of the 7353 * character, false if the search should stop 7354 * one character before the character in the 7355 * specified search direction. 7356 * c char The character to be sought, or '\0' if the 7357 * character should be read from the user. 7358 * Output: 7359 * return int The index of the character in gl->line[], or 7360 * -1 if not found. 7361 */ 7362 static int gl_find_char(GetLine *gl, int count, int forward, int onto, char c) 7363 { 7364 int pos; /* The index reached in searching the input line */ 7365 int i; 7366 /* 7367 * Get a character from the user? 7368 */ 7369 if(!c) { 7370 /* 7371 * If we are in the process of repeating a previous change command, substitute 7372 * the last find character. 7373 */ 7374 if(gl->vi.repeat.active) { 7375 c = gl->vi.find_char; 7376 } else { 7377 if(gl_read_terminal(gl, 1, &c)) 7378 return -1; 7379 /* 7380 * Record the details of the new search, for use by repeat finds. 7381 */ 7382 gl->vi.find_forward = forward; 7383 gl->vi.find_onto = onto; 7384 gl->vi.find_char = c; 7385 }; 7386 }; 7387 /* 7388 * Which direction should we search? 7389 */ 7390 if(forward) { 7391 /* 7392 * Search forwards 'count' times for the character, starting with the 7393 * character that follows the cursor. 7394 */ 7395 for(i=0, pos=gl->buff_curpos; i<count && pos < gl->ntotal; i++) { 7396 /* 7397 * Advance past the last match (or past the current cursor position 7398 * on the first search). 7399 */ 7400 pos++; 7401 /* 7402 * Search for the next instance of c. 7403 */ 7404 for( ; pos<gl->ntotal && c!=gl->line[pos]; pos++) 7405 ; 7406 }; 7407 /* 7408 * If the character was found and we have been requested to return the 7409 * position of the character that precedes the desired character, then 7410 * we have gone one character too far. 7411 */ 7412 if(!onto && pos<gl->ntotal) 7413 pos--; 7414 } else { 7415 /* 7416 * Search backwards 'count' times for the character, starting with the 7417 * character that precedes the cursor. 7418 */ 7419 for(i=0, pos=gl->buff_curpos; i<count && pos >= gl->insert_curpos; i++) { 7420 /* 7421 * Step back one from the last match (or from the current cursor 7422 * position on the first search). 7423 */ 7424 pos--; 7425 /* 7426 * Search for the next instance of c. 7427 */ 7428 for( ; pos>=gl->insert_curpos && c!=gl->line[pos]; pos--) 7429 ; 7430 }; 7431 /* 7432 * If the character was found and we have been requested to return the 7433 * position of the character that precedes the desired character, then 7434 * we have gone one character too far. 7435 */ 7436 if(!onto && pos>=gl->insert_curpos) 7437 pos++; 7438 }; 7439 /* 7440 * If found, return the cursor position of the count'th match. 7441 * Otherwise ring the terminal bell. 7442 */ 7443 if(pos >= gl->insert_curpos && pos < gl->ntotal) { 7444 return pos; 7445 } else { 7446 (void) gl_ring_bell(gl, 1, NULL); 7447 return -1; 7448 } 7449 } 7450 7451 /*....................................................................... 7452 * Repeat the last character search in the same direction as the last 7453 * search. 7454 */ 7455 static KT_KEY_FN(gl_repeat_find_char) 7456 { 7457 int pos = gl->vi.find_char ? 7458 gl_find_char(gl, count, gl->vi.find_forward, gl->vi.find_onto, 7459 gl->vi.find_char) : -1; 7460 return pos >= 0 && gl_place_cursor(gl, pos); 7461 } 7462 7463 /*....................................................................... 7464 * Repeat the last character search in the opposite direction as the last 7465 * search. 7466 */ 7467 static KT_KEY_FN(gl_invert_refind_char) 7468 { 7469 int pos = gl->vi.find_char ? 7470 gl_find_char(gl, count, !gl->vi.find_forward, gl->vi.find_onto, 7471 gl->vi.find_char) : -1; 7472 return pos >= 0 && gl_place_cursor(gl, pos); 7473 } 7474 7475 /*....................................................................... 7476 * Search forward from the current position of the cursor for 'count' 7477 * word endings, returning the index of the last one found, or the end of 7478 * the line if there were less than 'count' words. 7479 * 7480 * Input: 7481 * gl GetLine * The getline resource object. 7482 * n int The number of word boundaries to search for. 7483 * Output: 7484 * return int The buffer index of the located position. 7485 */ 7486 static int gl_nth_word_end_forward(GetLine *gl, int n) 7487 { 7488 int bufpos; /* The buffer index being checked. */ 7489 int i; 7490 /* 7491 * In order to guarantee forward motion to the next word ending, 7492 * we need to start from one position to the right of the cursor 7493 * position, since this may already be at the end of a word. 7494 */ 7495 bufpos = gl->buff_curpos + 1; 7496 /* 7497 * If we are at the end of the line, return the index of the last 7498 * real character on the line. Note that this will be -1 if the line 7499 * is empty. 7500 */ 7501 if(bufpos >= gl->ntotal) 7502 return gl->ntotal - 1; 7503 /* 7504 * Search 'n' times, unless the end of the input line is reached first. 7505 */ 7506 for(i=0; i<n && bufpos<gl->ntotal; i++) { 7507 /* 7508 * If we are not already within a word, skip to the start of the next word. 7509 */ 7510 for( ; bufpos<gl->ntotal && !gl_is_word_char((int)gl->line[bufpos]); 7511 bufpos++) 7512 ; 7513 /* 7514 * Find the end of the next word. 7515 */ 7516 for( ; bufpos<gl->ntotal && gl_is_word_char((int)gl->line[bufpos]); 7517 bufpos++) 7518 ; 7519 }; 7520 /* 7521 * We will have overshot. 7522 */ 7523 return bufpos > 0 ? bufpos-1 : bufpos; 7524 } 7525 7526 /*....................................................................... 7527 * Search forward from the current position of the cursor for 'count' 7528 * word starts, returning the index of the last one found, or the end of 7529 * the line if there were less than 'count' words. 7530 * 7531 * Input: 7532 * gl GetLine * The getline resource object. 7533 * n int The number of word boundaries to search for. 7534 * Output: 7535 * return int The buffer index of the located position. 7536 */ 7537 static int gl_nth_word_start_forward(GetLine *gl, int n) 7538 { 7539 int bufpos; /* The buffer index being checked. */ 7540 int i; 7541 /* 7542 * Get the current cursor position. 7543 */ 7544 bufpos = gl->buff_curpos; 7545 /* 7546 * Search 'n' times, unless the end of the input line is reached first. 7547 */ 7548 for(i=0; i<n && bufpos<gl->ntotal; i++) { 7549 /* 7550 * Find the end of the current word. 7551 */ 7552 for( ; bufpos<gl->ntotal && gl_is_word_char((int)gl->line[bufpos]); 7553 bufpos++) 7554 ; 7555 /* 7556 * Skip to the start of the next word. 7557 */ 7558 for( ; bufpos<gl->ntotal && !gl_is_word_char((int)gl->line[bufpos]); 7559 bufpos++) 7560 ; 7561 }; 7562 return bufpos; 7563 } 7564 7565 /*....................................................................... 7566 * Search backward from the current position of the cursor for 'count' 7567 * word starts, returning the index of the last one found, or the start 7568 * of the line if there were less than 'count' words. 7569 * 7570 * Input: 7571 * gl GetLine * The getline resource object. 7572 * n int The number of word boundaries to search for. 7573 * Output: 7574 * return int The buffer index of the located position. 7575 */ 7576 static int gl_nth_word_start_backward(GetLine *gl, int n) 7577 { 7578 int bufpos; /* The buffer index being checked. */ 7579 int i; 7580 /* 7581 * Get the current cursor position. 7582 */ 7583 bufpos = gl->buff_curpos; 7584 /* 7585 * Search 'n' times, unless the beginning of the input line (or vi insertion 7586 * point) is reached first. 7587 */ 7588 for(i=0; i<n && bufpos > gl->insert_curpos; i++) { 7589 /* 7590 * Starting one character back from the last search, so as not to keep 7591 * settling on the same word-start, search backwards until finding a 7592 * word character. 7593 */ 7594 while(--bufpos >= gl->insert_curpos && 7595 !gl_is_word_char((int)gl->line[bufpos])) 7596 ; 7597 /* 7598 * Find the start of the word. 7599 */ 7600 while(--bufpos >= gl->insert_curpos && 7601 gl_is_word_char((int)gl->line[bufpos])) 7602 ; 7603 /* 7604 * We will have gone one character too far. 7605 */ 7606 bufpos++; 7607 }; 7608 return bufpos >= gl->insert_curpos ? bufpos : gl->insert_curpos; 7609 } 7610 7611 /*....................................................................... 7612 * Copy one or more words into the cut buffer without moving the cursor 7613 * or deleting text. 7614 */ 7615 static KT_KEY_FN(gl_forward_copy_word) 7616 { 7617 /* 7618 * Find the location of the count'th start or end of a word 7619 * after the cursor, depending on whether in emacs or vi mode. 7620 */ 7621 int next = gl->editor == GL_EMACS_MODE ? 7622 gl_nth_word_end_forward(gl, count) : 7623 gl_nth_word_start_forward(gl, count); 7624 /* 7625 * How many characters are to be copied into the cut buffer? 7626 */ 7627 int n = next - gl->buff_curpos; 7628 /* 7629 * Copy the specified segment and terminate the string. 7630 */ 7631 memcpy(gl->cutbuf, gl->line + gl->buff_curpos, n); 7632 gl->cutbuf[n] = '\0'; 7633 return 0; 7634 } 7635 7636 /*....................................................................... 7637 * Copy one or more words preceding the cursor into the cut buffer, 7638 * without moving the cursor or deleting text. 7639 */ 7640 static KT_KEY_FN(gl_backward_copy_word) 7641 { 7642 /* 7643 * Find the location of the count'th start of word before the cursor. 7644 */ 7645 int next = gl_nth_word_start_backward(gl, count); 7646 /* 7647 * How many characters are to be copied into the cut buffer? 7648 */ 7649 int n = gl->buff_curpos - next; 7650 gl_place_cursor(gl, next); 7651 /* 7652 * Copy the specified segment and terminate the string. 7653 */ 7654 memcpy(gl->cutbuf, gl->line + next, n); 7655 gl->cutbuf[n] = '\0'; 7656 return 0; 7657 } 7658 7659 /*....................................................................... 7660 * Copy the characters between the cursor and the count'th instance of 7661 * a specified character in the input line, into the cut buffer. 7662 * 7663 * Input: 7664 * gl GetLine * The getline resource object. 7665 * count int The number of times to search. 7666 * c char The character to be searched for, or '\0' if 7667 * the character should be read from the user. 7668 * forward int True if searching forward. 7669 * onto int True if the search should end on top of the 7670 * character, false if the search should stop 7671 * one character before the character in the 7672 * specified search direction. 7673 * Output: 7674 * return int 0 - OK. 7675 * 1 - Error. 7676 * 7677 */ 7678 static int gl_copy_find(GetLine *gl, int count, char c, int forward, int onto) 7679 { 7680 int n; /* The number of characters in the cut buffer */ 7681 /* 7682 * Search for the character, and abort the operation if not found. 7683 */ 7684 int pos = gl_find_char(gl, count, forward, onto, c); 7685 if(pos < 0) 7686 return 0; 7687 /* 7688 * Copy the specified segment. 7689 */ 7690 if(forward) { 7691 n = pos + 1 - gl->buff_curpos; 7692 memcpy(gl->cutbuf, gl->line + gl->buff_curpos, n); 7693 } else { 7694 n = gl->buff_curpos - pos; 7695 memcpy(gl->cutbuf, gl->line + pos, n); 7696 if(gl->editor == GL_VI_MODE) 7697 gl_place_cursor(gl, pos); 7698 } 7699 /* 7700 * Terminate the copy. 7701 */ 7702 gl->cutbuf[n] = '\0'; 7703 return 0; 7704 } 7705 7706 /*....................................................................... 7707 * Copy a section up to and including a specified character into the cut 7708 * buffer without moving the cursor or deleting text. 7709 */ 7710 static KT_KEY_FN(gl_forward_copy_find) 7711 { 7712 return gl_copy_find(gl, count, '\0', 1, 1); 7713 } 7714 7715 /*....................................................................... 7716 * Copy a section back to and including a specified character into the cut 7717 * buffer without moving the cursor or deleting text. 7718 */ 7719 static KT_KEY_FN(gl_backward_copy_find) 7720 { 7721 return gl_copy_find(gl, count, '\0', 0, 1); 7722 } 7723 7724 /*....................................................................... 7725 * Copy a section up to and not including a specified character into the cut 7726 * buffer without moving the cursor or deleting text. 7727 */ 7728 static KT_KEY_FN(gl_forward_copy_to) 7729 { 7730 return gl_copy_find(gl, count, '\0', 1, 0); 7731 } 7732 7733 /*....................................................................... 7734 * Copy a section back to and not including a specified character into the cut 7735 * buffer without moving the cursor or deleting text. 7736 */ 7737 static KT_KEY_FN(gl_backward_copy_to) 7738 { 7739 return gl_copy_find(gl, count, '\0', 0, 0); 7740 } 7741 7742 /*....................................................................... 7743 * Copy to a character specified in a previous search into the cut 7744 * buffer without moving the cursor or deleting text. 7745 */ 7746 static KT_KEY_FN(gl_copy_refind) 7747 { 7748 return gl_copy_find(gl, count, gl->vi.find_char, gl->vi.find_forward, 7749 gl->vi.find_onto); 7750 } 7751 7752 /*....................................................................... 7753 * Copy to a character specified in a previous search, but in the opposite 7754 * direction, into the cut buffer without moving the cursor or deleting text. 7755 */ 7756 static KT_KEY_FN(gl_copy_invert_refind) 7757 { 7758 return gl_copy_find(gl, count, gl->vi.find_char, !gl->vi.find_forward, 7759 gl->vi.find_onto); 7760 } 7761 7762 /*....................................................................... 7763 * Set the position of the cursor in the line input buffer and the 7764 * terminal. 7765 * 7766 * Input: 7767 * gl GetLine * The getline resource object. 7768 * buff_curpos int The new buffer cursor position. 7769 * Output: 7770 * return int 0 - OK. 7771 * 1 - Error. 7772 */ 7773 static int gl_place_cursor(GetLine *gl, int buff_curpos) 7774 { 7775 /* 7776 * Don't allow the cursor position to go out of the bounds of the input 7777 * line. 7778 */ 7779 if(buff_curpos >= gl->ntotal) 7780 buff_curpos = gl->vi.command ? gl->ntotal-1 : gl->ntotal; 7781 if(buff_curpos < 0) 7782 buff_curpos = 0; 7783 /* 7784 * Record the new buffer position. 7785 */ 7786 gl->buff_curpos = buff_curpos; 7787 /* 7788 * Move the terminal cursor to the corresponding character. 7789 */ 7790 return gl_set_term_curpos(gl, gl->prompt_len + 7791 gl_displayed_string_width(gl, gl->line, buff_curpos, gl->prompt_len)); 7792 } 7793 7794 /*....................................................................... 7795 * In vi command mode, this function saves the current line to the 7796 * historical buffer needed by the undo command. In emacs mode it does 7797 * nothing. In order to allow action functions to call other action 7798 * functions, gl_interpret_char() sets gl->vi.undo.saved to 0 before 7799 * invoking an action, and thereafter once any call to this function 7800 * has set it to 1, further calls are ignored. 7801 * 7802 * Input: 7803 * gl GetLine * The getline resource object. 7804 */ 7805 static void gl_save_for_undo(GetLine *gl) 7806 { 7807 if(gl->vi.command && !gl->vi.undo.saved) { 7808 strlcpy(gl->vi.undo.line, gl->line, gl->linelen); 7809 gl->vi.undo.buff_curpos = gl->buff_curpos; 7810 gl->vi.undo.ntotal = gl->ntotal; 7811 gl->vi.undo.saved = 1; 7812 }; 7813 if(gl->vi.command && !gl->vi.repeat.saved && 7814 gl->current_action.fn != gl_vi_repeat_change) { 7815 gl->vi.repeat.action = gl->current_action; 7816 gl->vi.repeat.count = gl->current_count; 7817 gl->vi.repeat.saved = 1; 7818 }; 7819 return; 7820 } 7821 7822 /*....................................................................... 7823 * In vi mode, restore the line to the way it was before the last command 7824 * mode operation, storing the current line in the buffer so that the 7825 * undo operation itself can subsequently be undone. 7826 */ 7827 static KT_KEY_FN(gl_vi_undo) 7828 { 7829 /* 7830 * Get pointers into the two lines. 7831 */ 7832 char *undo_ptr = gl->vi.undo.line; 7833 char *line_ptr = gl->line; 7834 /* 7835 * Swap the characters of the two buffers up to the length of the shortest 7836 * line. 7837 */ 7838 while(*undo_ptr && *line_ptr) { 7839 char c = *undo_ptr; 7840 *undo_ptr++ = *line_ptr; 7841 *line_ptr++ = c; 7842 }; 7843 /* 7844 * Copy the rest directly. 7845 */ 7846 if(gl->ntotal > gl->vi.undo.ntotal) { 7847 strlcpy(undo_ptr, line_ptr, gl->linelen); 7848 *line_ptr = '\0'; 7849 } else { 7850 strlcpy(line_ptr, undo_ptr, gl->linelen); 7851 *undo_ptr = '\0'; 7852 }; 7853 /* 7854 * Record the length of the stored string. 7855 */ 7856 gl->vi.undo.ntotal = gl->ntotal; 7857 /* 7858 * Accomodate the new contents of gl->line[]. 7859 */ 7860 gl_update_buffer(gl); 7861 /* 7862 * Set both cursor positions to the leftmost of the saved and current 7863 * cursor positions to emulate what vi does. 7864 */ 7865 if(gl->buff_curpos < gl->vi.undo.buff_curpos) 7866 gl->vi.undo.buff_curpos = gl->buff_curpos; 7867 else 7868 gl->buff_curpos = gl->vi.undo.buff_curpos; 7869 /* 7870 * Since we have bipassed calling gl_save_for_undo(), record repeat 7871 * information inline. 7872 */ 7873 gl->vi.repeat.action.fn = gl_vi_undo; 7874 gl->vi.repeat.action.data = NULL; 7875 gl->vi.repeat.count = 1; 7876 /* 7877 * Display the restored line. 7878 */ 7879 gl_queue_redisplay(gl); 7880 return 0; 7881 } 7882 7883 /*....................................................................... 7884 * Delete the following word and leave the user in vi insert mode. 7885 */ 7886 static KT_KEY_FN(gl_vi_forward_change_word) 7887 { 7888 gl_save_for_undo(gl); 7889 gl->vi.command = 0; /* Allow cursor at EOL */ 7890 return gl_forward_delete_word(gl, count, NULL) || gl_vi_insert(gl, 0, NULL); 7891 } 7892 7893 /*....................................................................... 7894 * Delete the preceding word and leave the user in vi insert mode. 7895 */ 7896 static KT_KEY_FN(gl_vi_backward_change_word) 7897 { 7898 return gl_backward_delete_word(gl, count, NULL) || gl_vi_insert(gl, 0, NULL); 7899 } 7900 7901 /*....................................................................... 7902 * Delete the following section and leave the user in vi insert mode. 7903 */ 7904 static KT_KEY_FN(gl_vi_forward_change_find) 7905 { 7906 return gl_delete_find(gl, count, '\0', 1, 1, 1); 7907 } 7908 7909 /*....................................................................... 7910 * Delete the preceding section and leave the user in vi insert mode. 7911 */ 7912 static KT_KEY_FN(gl_vi_backward_change_find) 7913 { 7914 return gl_delete_find(gl, count, '\0', 0, 1, 1); 7915 } 7916 7917 /*....................................................................... 7918 * Delete the following section and leave the user in vi insert mode. 7919 */ 7920 static KT_KEY_FN(gl_vi_forward_change_to) 7921 { 7922 return gl_delete_find(gl, count, '\0', 1, 0, 1); 7923 } 7924 7925 /*....................................................................... 7926 * Delete the preceding section and leave the user in vi insert mode. 7927 */ 7928 static KT_KEY_FN(gl_vi_backward_change_to) 7929 { 7930 return gl_delete_find(gl, count, '\0', 0, 0, 1); 7931 } 7932 7933 /*....................................................................... 7934 * Delete to a character specified by a previous search and leave the user 7935 * in vi insert mode. 7936 */ 7937 static KT_KEY_FN(gl_vi_change_refind) 7938 { 7939 return gl_delete_find(gl, count, gl->vi.find_char, gl->vi.find_forward, 7940 gl->vi.find_onto, 1); 7941 } 7942 7943 /*....................................................................... 7944 * Delete to a character specified by a previous search, but in the opposite 7945 * direction, and leave the user in vi insert mode. 7946 */ 7947 static KT_KEY_FN(gl_vi_change_invert_refind) 7948 { 7949 return gl_delete_find(gl, count, gl->vi.find_char, !gl->vi.find_forward, 7950 gl->vi.find_onto, 1); 7951 } 7952 7953 /*....................................................................... 7954 * Delete the following character and leave the user in vi insert mode. 7955 */ 7956 static KT_KEY_FN(gl_vi_forward_change_char) 7957 { 7958 gl_save_for_undo(gl); 7959 gl->vi.command = 0; /* Allow cursor at EOL */ 7960 return gl_delete_chars(gl, count, 1) || gl_vi_insert(gl, 0, NULL); 7961 } 7962 7963 /*....................................................................... 7964 * Delete the preceding character and leave the user in vi insert mode. 7965 */ 7966 static KT_KEY_FN(gl_vi_backward_change_char) 7967 { 7968 return gl_backward_delete_char(gl, count, NULL) || gl_vi_insert(gl, 0, NULL); 7969 } 7970 7971 /*....................................................................... 7972 * Starting from the cursor position change characters to the specified column. 7973 */ 7974 static KT_KEY_FN(gl_vi_change_to_column) 7975 { 7976 if (--count >= gl->buff_curpos) 7977 return gl_vi_forward_change_char(gl, count - gl->buff_curpos, NULL); 7978 else 7979 return gl_vi_backward_change_char(gl, gl->buff_curpos - count, NULL); 7980 } 7981 7982 /*....................................................................... 7983 * Starting from the cursor position change characters to a matching 7984 * parenthesis. 7985 */ 7986 static KT_KEY_FN(gl_vi_change_to_parenthesis) 7987 { 7988 int curpos = gl_index_of_matching_paren(gl); 7989 if(curpos >= 0) { 7990 gl_save_for_undo(gl); 7991 if(curpos >= gl->buff_curpos) 7992 return gl_vi_forward_change_char(gl, curpos - gl->buff_curpos + 1, NULL); 7993 else 7994 return gl_vi_backward_change_char(gl, ++gl->buff_curpos - curpos + 1, 7995 NULL); 7996 }; 7997 return 0; 7998 } 7999 8000 /*....................................................................... 8001 * If in vi mode, switch to vi command mode. 8002 * 8003 * Input: 8004 * gl GetLine * The getline resource object. 8005 */ 8006 static void gl_vi_command_mode(GetLine *gl) 8007 { 8008 if(gl->editor == GL_VI_MODE && !gl->vi.command) { 8009 gl->insert = 1; 8010 gl->vi.command = 1; 8011 gl->vi.repeat.input_curpos = gl->insert_curpos; 8012 gl->vi.repeat.command_curpos = gl->buff_curpos; 8013 gl->insert_curpos = 0; /* unrestrict left motion boundary */ 8014 gl_cursor_left(gl, 1, NULL); /* Vi moves 1 left on entering command mode */ 8015 }; 8016 } 8017 8018 /*....................................................................... 8019 * This is an action function which rings the terminal bell. 8020 */ 8021 static KT_KEY_FN(gl_ring_bell) 8022 { 8023 return gl->silence_bell ? 0 : 8024 gl_print_control_sequence(gl, 1, gl->sound_bell); 8025 } 8026 8027 /*....................................................................... 8028 * This is the action function which implements the vi-repeat-change 8029 * action. 8030 */ 8031 static KT_KEY_FN(gl_vi_repeat_change) 8032 { 8033 int status; /* The return status of the repeated action function */ 8034 int i; 8035 /* 8036 * Nothing to repeat? 8037 */ 8038 if(!gl->vi.repeat.action.fn) 8039 return gl_ring_bell(gl, 1, NULL); 8040 /* 8041 * Provide a way for action functions to know whether they are being 8042 * called by us. 8043 */ 8044 gl->vi.repeat.active = 1; 8045 /* 8046 * Re-run the recorded function. 8047 */ 8048 status = gl->vi.repeat.action.fn(gl, gl->vi.repeat.count, 8049 gl->vi.repeat.action.data); 8050 /* 8051 * Mark the repeat as completed. 8052 */ 8053 gl->vi.repeat.active = 0; 8054 /* 8055 * Is we are repeating a function that has just switched to input 8056 * mode to allow the user to type, re-enter the text that the user 8057 * previously entered. 8058 */ 8059 if(status==0 && !gl->vi.command) { 8060 /* 8061 * Make sure that the current line has been saved. 8062 */ 8063 gl_save_for_undo(gl); 8064 /* 8065 * Repeat a previous insertion or overwrite? 8066 */ 8067 if(gl->vi.repeat.input_curpos >= 0 && 8068 gl->vi.repeat.input_curpos <= gl->vi.repeat.command_curpos && 8069 gl->vi.repeat.command_curpos <= gl->vi.undo.ntotal) { 8070 /* 8071 * Using the current line which is saved in the undo buffer, plus 8072 * the range of characters therein, as recorded by gl_vi_command_mode(), 8073 * add the characters that the user previously entered, to the input 8074 * line. 8075 */ 8076 for(i=gl->vi.repeat.input_curpos; i<gl->vi.repeat.command_curpos; i++) { 8077 if(gl_add_char_to_line(gl, gl->vi.undo.line[i])) 8078 return 1; 8079 }; 8080 }; 8081 /* 8082 * Switch back to command mode, now that the insertion has been repeated. 8083 */ 8084 gl_vi_command_mode(gl); 8085 }; 8086 return status; 8087 } 8088 8089 /*....................................................................... 8090 * If the cursor is currently over a parenthesis character, return the 8091 * index of its matching parenthesis. If not currently over a parenthesis 8092 * character, return the next close parenthesis character to the right of 8093 * the cursor. If the respective parenthesis character isn't found, 8094 * ring the terminal bell and return -1. 8095 * 8096 * Input: 8097 * gl GetLine * The getline resource object. 8098 * Output: 8099 * return int Either the index of the matching parenthesis, 8100 * or -1 if not found. 8101 */ 8102 static int gl_index_of_matching_paren(GetLine *gl) 8103 { 8104 int i; 8105 /* 8106 * List the recognized parentheses, and their matches. 8107 */ 8108 const char *o_paren = "([{"; 8109 const char *c_paren = ")]}"; 8110 const char *cptr; 8111 /* 8112 * Get the character that is currently under the cursor. 8113 */ 8114 char c = gl->line[gl->buff_curpos]; 8115 /* 8116 * If the character under the cursor is an open parenthesis, look forward 8117 * for the matching close parenthesis. 8118 */ 8119 if((cptr=strchr(o_paren, c))) { 8120 char match = c_paren[cptr - o_paren]; 8121 int matches_needed = 1; 8122 for(i=gl->buff_curpos+1; i<gl->ntotal; i++) { 8123 if(gl->line[i] == c) 8124 matches_needed++; 8125 else if(gl->line[i] == match && --matches_needed==0) 8126 return i; 8127 }; 8128 /* 8129 * If the character under the cursor is an close parenthesis, look forward 8130 * for the matching open parenthesis. 8131 */ 8132 } else if((cptr=strchr(c_paren, c))) { 8133 char match = o_paren[cptr - c_paren]; 8134 int matches_needed = 1; 8135 for(i=gl->buff_curpos-1; i>=0; i--) { 8136 if(gl->line[i] == c) 8137 matches_needed++; 8138 else if(gl->line[i] == match && --matches_needed==0) 8139 return i; 8140 }; 8141 /* 8142 * If not currently over a parenthesis character, search forwards for 8143 * the first close parenthesis (this is what the vi % binding does). 8144 */ 8145 } else { 8146 for(i=gl->buff_curpos+1; i<gl->ntotal; i++) 8147 if(strchr(c_paren, gl->line[i]) != NULL) 8148 return i; 8149 }; 8150 /* 8151 * Not found. 8152 */ 8153 (void) gl_ring_bell(gl, 1, NULL); 8154 return -1; 8155 } 8156 8157 /*....................................................................... 8158 * If the cursor is currently over a parenthesis character, this action 8159 * function moves the cursor to its matching parenthesis. 8160 */ 8161 static KT_KEY_FN(gl_find_parenthesis) 8162 { 8163 int curpos = gl_index_of_matching_paren(gl); 8164 if(curpos >= 0) 8165 return gl_place_cursor(gl, curpos); 8166 return 0; 8167 } 8168 8169 /*....................................................................... 8170 * Handle the receipt of the potential start of a new key-sequence from 8171 * the user. 8172 * 8173 * Input: 8174 * gl GetLine * The resource object of this library. 8175 * first_char char The first character of the sequence. 8176 * Output: 8177 * return int 0 - OK. 8178 * 1 - Error. 8179 */ 8180 static int gl_interpret_char(GetLine *gl, char first_char) 8181 { 8182 char keyseq[GL_KEY_MAX+1]; /* A special key sequence being read */ 8183 int nkey=0; /* The number of characters in the key sequence */ 8184 int count; /* The repeat count of an action function */ 8185 int ret; /* The return value of an action function */ 8186 int i; 8187 /* 8188 * Get the first character. 8189 */ 8190 char c = first_char; 8191 /* 8192 * If editing is disabled, just add newly entered characters to the 8193 * input line buffer, and watch for the end of the line. 8194 */ 8195 if(gl->editor == GL_NO_EDITOR) { 8196 gl_discard_chars(gl, 1); 8197 if(gl->ntotal >= gl->linelen) 8198 return 0; 8199 if(c == '\n' || c == '\r') 8200 return gl_newline(gl, 1, NULL); 8201 gl_buffer_char(gl, c, gl->ntotal); 8202 return 0; 8203 }; 8204 /* 8205 * If the user is in the process of specifying a repeat count and the 8206 * new character is a digit, increment the repeat count accordingly. 8207 */ 8208 if(gl->number >= 0 && isdigit((int)(unsigned char) c)) { 8209 gl_discard_chars(gl, 1); 8210 return gl_digit_argument(gl, c, NULL); 8211 /* 8212 * In vi command mode, all key-sequences entered need to be 8213 * either implicitly or explicitly prefixed with an escape character. 8214 */ 8215 } else if(gl->vi.command && c != GL_ESC_CHAR) { 8216 keyseq[nkey++] = GL_ESC_CHAR; 8217 /* 8218 * If the first character of the sequence is a printable character, 8219 * then to avoid confusion with the special "up", "down", "left" 8220 * or "right" cursor key bindings, we need to prefix the 8221 * printable character with a backslash escape before looking it up. 8222 */ 8223 } else if(!IS_META_CHAR(c) && !IS_CTRL_CHAR(c)) { 8224 keyseq[nkey++] = '\\'; 8225 }; 8226 /* 8227 * Compose a potentially multiple key-sequence in gl->keyseq. 8228 */ 8229 while(nkey < GL_KEY_MAX) { 8230 KtAction *action; /* An action function */ 8231 KeySym *keysym; /* The symbol-table entry of a key-sequence */ 8232 int nsym; /* The number of ambiguously matching key-sequences */ 8233 /* 8234 * If the character is an unprintable meta character, split it 8235 * into two characters, an escape character and the character 8236 * that was modified by the meta key. 8237 */ 8238 if(IS_META_CHAR(c)) { 8239 keyseq[nkey++] = GL_ESC_CHAR; 8240 c = META_TO_CHAR(c); 8241 continue; 8242 }; 8243 /* 8244 * Append the latest character to the key sequence. 8245 */ 8246 keyseq[nkey++] = c; 8247 /* 8248 * When doing vi-style editing, an escape at the beginning of any binding 8249 * switches to command mode. 8250 */ 8251 if(keyseq[0] == GL_ESC_CHAR && !gl->vi.command) 8252 gl_vi_command_mode(gl); 8253 /* 8254 * Lookup the key sequence. 8255 */ 8256 switch(_kt_lookup_keybinding(gl->bindings, keyseq, nkey, &keysym, &nsym)) { 8257 case KT_EXACT_MATCH: 8258 /* 8259 * Get the matching action function. 8260 */ 8261 action = keysym->actions + keysym->binder; 8262 /* 8263 * Get the repeat count, passing the last keystroke if executing the 8264 * digit-argument action. 8265 */ 8266 if(action->fn == gl_digit_argument) { 8267 count = c; 8268 } else { 8269 count = gl->number >= 0 ? gl->number : 1; 8270 }; 8271 /* 8272 * Record the function that is being invoked. 8273 */ 8274 gl->current_action = *action; 8275 gl->current_count = count; 8276 /* 8277 * Mark the current line as not yet preserved for use by the vi undo command. 8278 */ 8279 gl->vi.undo.saved = 0; 8280 gl->vi.repeat.saved = 0; 8281 /* 8282 * Execute the action function. Note the action function can tell 8283 * whether the provided repeat count was defaulted or specified 8284 * explicitly by looking at whether gl->number is -1 or not. If 8285 * it is negative, then no repeat count was specified by the user. 8286 */ 8287 ret = action->fn(gl, count, action->data); 8288 /* 8289 * In server mode, the action will return immediately if it tries to 8290 * read input from the terminal, and no input is currently available. 8291 * If this happens, abort. Note that gl_get_input_line() will rewind 8292 * the read-ahead buffer to allow the next call to redo the function 8293 * from scratch. 8294 */ 8295 if(gl->rtn_status == GLR_BLOCKED && gl->pending_io==GLP_READ) 8296 return 1; 8297 /* 8298 * Discard the now processed characters from the key sequence buffer. 8299 */ 8300 gl_discard_chars(gl, gl->nread); 8301 /* 8302 * If the latest action function wasn't a history action, cancel any 8303 * current history search. 8304 */ 8305 if(gl->last_search != gl->keyseq_count) 8306 _glh_cancel_search(gl->glh); 8307 /* 8308 * Reset the repeat count after running action functions. 8309 */ 8310 if(action->fn != gl_digit_argument) 8311 gl->number = -1; 8312 return ret ? 1 : 0; 8313 break; 8314 case KT_AMBIG_MATCH: /* Ambiguous match - so read the next character */ 8315 if(gl_read_terminal(gl, 1, &c)) 8316 return 1; 8317 break; 8318 case KT_NO_MATCH: 8319 /* 8320 * If the first character looked like it might be a prefix of a key-sequence 8321 * but it turned out not to be, ring the bell to tell the user that it 8322 * wasn't recognised. 8323 */ 8324 if(keyseq[0] != '\\' && keyseq[0] != '\t') { 8325 gl_ring_bell(gl, 1, NULL); 8326 } else { 8327 /* 8328 * The user typed a single printable character that doesn't match 8329 * the start of any keysequence, so add it to the line in accordance 8330 * with the current repeat count. 8331 */ 8332 count = gl->number >= 0 ? gl->number : 1; 8333 for(i=0; i<count; i++) 8334 gl_add_char_to_line(gl, first_char); 8335 gl->number = -1; 8336 }; 8337 gl_discard_chars(gl, 1); 8338 _glh_cancel_search(gl->glh); 8339 return 0; 8340 break; 8341 case KT_BAD_MATCH: 8342 gl_ring_bell(gl, 1, NULL); 8343 gl_discard_chars(gl, gl->nread); 8344 _glh_cancel_search(gl->glh); 8345 return 1; 8346 break; 8347 }; 8348 }; 8349 /* 8350 * If the key sequence was too long to match, ring the bell, then 8351 * discard the first character, so that the next attempt to match a 8352 * key-sequence continues with the next key press. In practice this 8353 * shouldn't happen, since one isn't allowed to bind action functions 8354 * to keysequences that are longer than GL_KEY_MAX. 8355 */ 8356 gl_ring_bell(gl, 1, NULL); 8357 gl_discard_chars(gl, 1); 8358 return 0; 8359 } 8360 8361 /*....................................................................... 8362 * Configure the application and/or user-specific behavior of 8363 * gl_get_line(). 8364 * 8365 * Note that calling this function between calling new_GetLine() and 8366 * the first call to gl_get_line(), disables the otherwise automatic 8367 * reading of ~/.teclarc on the first call to gl_get_line(). 8368 * 8369 * Input: 8370 * gl GetLine * The resource object of this library. 8371 * app_string const char * Either NULL, or a string containing one 8372 * or more .teclarc command lines, separated 8373 * by newline characters. This can be used to 8374 * establish an application-specific 8375 * configuration, without the need for an external 8376 * file. This is particularly useful in embedded 8377 * environments where there is no filesystem. 8378 * app_file const char * Either NULL, or the pathname of an 8379 * application-specific .teclarc file. The 8380 * contents of this file, if provided, are 8381 * read after the contents of app_string[]. 8382 * user_file const char * Either NULL, or the pathname of a 8383 * user-specific .teclarc file. Except in 8384 * embedded applications, this should 8385 * usually be "~/.teclarc". 8386 * Output: 8387 * return int 0 - OK. 8388 * 1 - Bad argument(s). 8389 */ 8390 int gl_configure_getline(GetLine *gl, const char *app_string, 8391 const char *app_file, const char *user_file) 8392 { 8393 sigset_t oldset; /* The signals that were blocked on entry to this function */ 8394 int status; /* The return status of _gl_configure_getline() */ 8395 /* 8396 * Check the arguments. 8397 */ 8398 if(!gl) { 8399 errno = EINVAL; 8400 return 1; 8401 }; 8402 /* 8403 * Block all signals. 8404 */ 8405 if(gl_mask_signals(gl, &oldset)) 8406 return 1; 8407 /* 8408 * Execute the private body of the function while signals are blocked. 8409 */ 8410 status = _gl_configure_getline(gl, app_string, app_file, user_file); 8411 /* 8412 * Restore the process signal mask. 8413 */ 8414 gl_unmask_signals(gl, &oldset); 8415 return status; 8416 } 8417 8418 /*....................................................................... 8419 * This is the private body of the gl_configure_getline() function. It 8420 * assumes that the caller has checked its arguments and blocked the 8421 * delivery of signals. 8422 */ 8423 static int _gl_configure_getline(GetLine *gl, const char *app_string, 8424 const char *app_file, const char *user_file) 8425 { 8426 /* 8427 * Mark getline as having been explicitly configured. 8428 */ 8429 gl->configured = 1; 8430 /* 8431 * Start by parsing the configuration string, if provided. 8432 */ 8433 if(app_string) 8434 (void) _gl_read_config_string(gl, app_string, KTB_NORM); 8435 /* 8436 * Now parse the application-specific configuration file, if provided. 8437 */ 8438 if(app_file) 8439 (void) _gl_read_config_file(gl, app_file, KTB_NORM); 8440 /* 8441 * Finally, parse the user-specific configuration file, if provided. 8442 */ 8443 if(user_file) 8444 (void) _gl_read_config_file(gl, user_file, KTB_USER); 8445 /* 8446 * Record the names of the configuration files to allow them to 8447 * be re-read if requested at a later time. 8448 */ 8449 if(gl_record_string(&gl->app_file, app_file) || 8450 gl_record_string(&gl->user_file, user_file)) { 8451 errno = ENOMEM; 8452 _err_record_msg(gl->err, 8453 "Insufficient memory to record tecla configuration file names", 8454 END_ERR_MSG); 8455 return 1; 8456 }; 8457 return 0; 8458 } 8459 8460 /*....................................................................... 8461 * Replace a malloc'd string (or NULL), with another malloc'd copy of 8462 * a string (or NULL). 8463 * 8464 * Input: 8465 * sptr char ** On input if *sptr!=NULL, *sptr will be 8466 * free'd and *sptr will be set to NULL. Then, 8467 * on output, if string!=NULL a malloc'd copy 8468 * of this string will be assigned to *sptr. 8469 * string const char * The string to be copied, or NULL to simply 8470 * discard any existing string. 8471 * Output: 8472 * return int 0 - OK. 8473 * 1 - Malloc failure (no error message is generated). 8474 */ 8475 static int gl_record_string(char **sptr, const char *string) 8476 { 8477 /* 8478 * If the original string is the same string, don't do anything. 8479 */ 8480 if(*sptr == string || (*sptr && string && strcmp(*sptr, string)==0)) 8481 return 0; 8482 /* 8483 * Discard any existing cached string. 8484 */ 8485 if(*sptr) { 8486 free(*sptr); 8487 *sptr = NULL; 8488 }; 8489 /* 8490 * Allocate memory for a copy of the specified string. 8491 */ 8492 if(string) { 8493 size_t ssz = strlen(string) + 1; 8494 *sptr = (char *) malloc(ssz); 8495 if(!*sptr) 8496 return 1; 8497 /* 8498 * Copy the string. 8499 */ 8500 strlcpy(*sptr, string, ssz); 8501 }; 8502 return 0; 8503 } 8504 8505 #ifndef HIDE_FILE_SYSTEM 8506 /*....................................................................... 8507 * Re-read any application-specific and user-specific files previously 8508 * specified via the gl_configure_getline() function. 8509 */ 8510 static KT_KEY_FN(gl_read_init_files) 8511 { 8512 return _gl_configure_getline(gl, NULL, gl->app_file, gl->user_file); 8513 } 8514 #endif 8515 8516 /*....................................................................... 8517 * Save the contents of the history buffer to a given new file. 8518 * 8519 * Input: 8520 * gl GetLine * The resource object of this library. 8521 * filename const char * The name of the new file to write to. 8522 * comment const char * Extra information such as timestamps will 8523 * be recorded on a line started with this 8524 * string, the idea being that the file can 8525 * double as a command file. Specify "" if 8526 * you don't care. 8527 * max_lines int The maximum number of lines to save, or -1 8528 * to save all of the lines in the history 8529 * list. 8530 * Output: 8531 * return int 0 - OK. 8532 * 1 - Error. 8533 */ 8534 int gl_save_history(GetLine *gl, const char *filename, const char *comment, 8535 int max_lines) 8536 { 8537 sigset_t oldset; /* The signals that were blocked on entry to this function */ 8538 int status; /* The return status of _gl_save_history() */ 8539 /* 8540 * Check the arguments. 8541 */ 8542 if(!gl || !filename || !comment) { 8543 if(gl) 8544 _err_record_msg(gl->err, "NULL argument(s)", END_ERR_MSG); 8545 errno = EINVAL; 8546 return 1; 8547 }; 8548 /* 8549 * Block all signals. 8550 */ 8551 if(gl_mask_signals(gl, &oldset)) 8552 return 1; 8553 /* 8554 * Execute the private body of the function while signals are blocked. 8555 */ 8556 status = _gl_save_history(gl, filename, comment, max_lines); 8557 /* 8558 * Restore the process signal mask. 8559 */ 8560 gl_unmask_signals(gl, &oldset); 8561 return status; 8562 } 8563 8564 /*....................................................................... 8565 * This is the private body of the gl_save_history() function. It 8566 * assumes that the caller has checked its arguments and blocked the 8567 * delivery of signals. 8568 */ 8569 static int _gl_save_history(GetLine *gl, const char *filename, 8570 const char *comment, int max_lines) 8571 { 8572 /* 8573 * If filesystem access is to be excluded, then history files can't 8574 * be written. 8575 */ 8576 #ifdef WITHOUT_FILE_SYSTEM 8577 _err_record_msg(gl->err, "Can't save history without filesystem access", 8578 END_ERR_MSG); 8579 errno = EINVAL; 8580 return 1; 8581 #else 8582 FileExpansion *expansion; /* The expansion of the filename */ 8583 /* 8584 * Expand the filename. 8585 */ 8586 expansion = ef_expand_file(gl->ef, filename, -1); 8587 if(!expansion) { 8588 gl_print_info(gl, "Unable to expand ", filename, " (", 8589 ef_last_error(gl->ef), ").", GL_END_INFO); 8590 return 1; 8591 }; 8592 /* 8593 * Attempt to save to the specified file. 8594 */ 8595 if(_glh_save_history(gl->glh, expansion->files[0], comment, max_lines)) { 8596 _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG); 8597 return 1; 8598 }; 8599 return 0; 8600 #endif 8601 } 8602 8603 /*....................................................................... 8604 * Restore the contents of the history buffer from a given new file. 8605 * 8606 * Input: 8607 * gl GetLine * The resource object of this library. 8608 * filename const char * The name of the new file to write to. 8609 * comment const char * This must be the same string that was 8610 * passed to gl_save_history() when the file 8611 * was written. 8612 * Output: 8613 * return int 0 - OK. 8614 * 1 - Error. 8615 */ 8616 int gl_load_history(GetLine *gl, const char *filename, const char *comment) 8617 { 8618 sigset_t oldset; /* The signals that were blocked on entry to this function */ 8619 int status; /* The return status of _gl_load_history() */ 8620 /* 8621 * Check the arguments. 8622 */ 8623 if(!gl || !filename || !comment) { 8624 if(gl) 8625 _err_record_msg(gl->err, "NULL argument(s)", END_ERR_MSG); 8626 errno = EINVAL; 8627 return 1; 8628 }; 8629 /* 8630 * Block all signals. 8631 */ 8632 if(gl_mask_signals(gl, &oldset)) 8633 return 1; 8634 /* 8635 * Execute the private body of the function while signals are blocked. 8636 */ 8637 status = _gl_load_history(gl, filename, comment); 8638 /* 8639 * Restore the process signal mask. 8640 */ 8641 gl_unmask_signals(gl, &oldset); 8642 return status; 8643 } 8644 8645 /*....................................................................... 8646 * This is the private body of the gl_load_history() function. It 8647 * assumes that the caller has checked its arguments and blocked the 8648 * delivery of signals. 8649 */ 8650 static int _gl_load_history(GetLine *gl, const char *filename, 8651 const char *comment) 8652 { 8653 /* 8654 * If filesystem access is to be excluded, then history files can't 8655 * be read. 8656 */ 8657 #ifdef WITHOUT_FILE_SYSTEM 8658 _err_record_msg(gl->err, "Can't load history without filesystem access", 8659 END_ERR_MSG); 8660 errno = EINVAL; 8661 return 1; 8662 #else 8663 FileExpansion *expansion; /* The expansion of the filename */ 8664 /* 8665 * Expand the filename. 8666 */ 8667 expansion = ef_expand_file(gl->ef, filename, -1); 8668 if(!expansion) { 8669 gl_print_info(gl, "Unable to expand ", filename, " (", 8670 ef_last_error(gl->ef), ").", GL_END_INFO); 8671 return 1; 8672 }; 8673 /* 8674 * Attempt to load from the specified file. 8675 */ 8676 if(_glh_load_history(gl->glh, expansion->files[0], comment, 8677 gl->cutbuf, gl->linelen+1)) { 8678 _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG); 8679 gl->cutbuf[0] = '\0'; 8680 return 1; 8681 }; 8682 gl->cutbuf[0] = '\0'; 8683 return 0; 8684 #endif 8685 } 8686 8687 /*....................................................................... 8688 * Where possible, register a function and associated data to be called 8689 * whenever a specified event is seen on a file descriptor. 8690 * 8691 * Input: 8692 * gl GetLine * The resource object of the command-line input 8693 * module. 8694 * fd int The file descriptor to watch. 8695 * event GlFdEvent The type of activity to watch for. 8696 * callback GlFdEventFn * The function to call when the specified 8697 * event occurs. Setting this to 0 removes 8698 * any existing callback. 8699 * data void * A pointer to arbitrary data to pass to the 8700 * callback function. 8701 * Output: 8702 * return int 0 - OK. 8703 * 1 - Either gl==NULL, or this facility isn't 8704 * available on the the host system 8705 * (ie. select() isn't available). No 8706 * error message is generated in the latter 8707 * case. 8708 */ 8709 int gl_watch_fd(GetLine *gl, int fd, GlFdEvent event, 8710 GlFdEventFn *callback, void *data) 8711 { 8712 sigset_t oldset; /* The signals that were blocked on entry to this function */ 8713 int status; /* The return status of _gl_watch_fd() */ 8714 /* 8715 * Check the arguments. 8716 */ 8717 if(!gl) { 8718 errno = EINVAL; 8719 return 1; 8720 }; 8721 if(fd < 0) { 8722 _err_record_msg(gl->err, "Error: fd < 0", END_ERR_MSG); 8723 errno = EINVAL; 8724 return 1; 8725 }; 8726 /* 8727 * Block all signals. 8728 */ 8729 if(gl_mask_signals(gl, &oldset)) 8730 return 1; 8731 /* 8732 * Execute the private body of the function while signals are blocked. 8733 */ 8734 status = _gl_watch_fd(gl, fd, event, callback, data); 8735 /* 8736 * Restore the process signal mask. 8737 */ 8738 gl_unmask_signals(gl, &oldset); 8739 return status; 8740 } 8741 8742 /*....................................................................... 8743 * This is the private body of the gl_watch_fd() function. It 8744 * assumes that the caller has checked its arguments and blocked the 8745 * delivery of signals. 8746 */ 8747 static int _gl_watch_fd(GetLine *gl, int fd, GlFdEvent event, 8748 GlFdEventFn *callback, void *data) 8749 #if !defined(HAVE_SELECT) 8750 {return 1;} /* The facility isn't supported on this system */ 8751 #else 8752 { 8753 GlFdNode *prev; /* The node that precedes 'node' in gl->fd_nodes */ 8754 GlFdNode *node; /* The file-descriptor node being checked */ 8755 /* 8756 * Search the list of already registered fd activity nodes for the specified 8757 * file descriptor. 8758 */ 8759 for(prev=NULL,node=gl->fd_nodes; node && node->fd != fd; 8760 prev=node, node=node->next) 8761 ; 8762 /* 8763 * Hasn't a node been allocated for this fd yet? 8764 */ 8765 if(!node) { 8766 /* 8767 * If there is no callback to record, just ignore the call. 8768 */ 8769 if(!callback) 8770 return 0; 8771 /* 8772 * Allocate the new node. 8773 */ 8774 node = (GlFdNode *) _new_FreeListNode(gl->fd_node_mem); 8775 if(!node) { 8776 errno = ENOMEM; 8777 _err_record_msg(gl->err, "Insufficient memory", END_ERR_MSG); 8778 return 1; 8779 }; 8780 /* 8781 * Prepend the node to the list. 8782 */ 8783 node->next = gl->fd_nodes; 8784 gl->fd_nodes = node; 8785 /* 8786 * Initialize the node. 8787 */ 8788 node->fd = fd; 8789 node->rd.fn = 0; 8790 node->rd.data = NULL; 8791 node->ur = node->wr = node->rd; 8792 }; 8793 /* 8794 * Record the new callback. 8795 */ 8796 switch(event) { 8797 case GLFD_READ: 8798 node->rd.fn = callback; 8799 node->rd.data = data; 8800 if(callback) 8801 FD_SET(fd, &gl->rfds); 8802 else 8803 FD_CLR(fd, &gl->rfds); 8804 break; 8805 case GLFD_WRITE: 8806 node->wr.fn = callback; 8807 node->wr.data = data; 8808 if(callback) 8809 FD_SET(fd, &gl->wfds); 8810 else 8811 FD_CLR(fd, &gl->wfds); 8812 break; 8813 case GLFD_URGENT: 8814 node->ur.fn = callback; 8815 node->ur.data = data; 8816 if(callback) 8817 FD_SET(fd, &gl->ufds); 8818 else 8819 FD_CLR(fd, &gl->ufds); 8820 break; 8821 }; 8822 /* 8823 * Keep a record of the largest file descriptor being watched. 8824 */ 8825 if(fd > gl->max_fd) 8826 gl->max_fd = fd; 8827 /* 8828 * If we are deleting an existing callback, also delete the parent 8829 * activity node if no callbacks are registered to the fd anymore. 8830 */ 8831 if(!callback) { 8832 if(!node->rd.fn && !node->wr.fn && !node->ur.fn) { 8833 if(prev) 8834 prev->next = node->next; 8835 else 8836 gl->fd_nodes = node->next; 8837 node = (GlFdNode *) _del_FreeListNode(gl->fd_node_mem, node); 8838 }; 8839 }; 8840 return 0; 8841 } 8842 #endif 8843 8844 /*....................................................................... 8845 * On systems with the select() system call, the gl_inactivity_timeout() 8846 * function provides the option of setting (or cancelling) an 8847 * inactivity timeout. Inactivity, in this case, refers both to 8848 * terminal input received from the user, and to I/O on any file 8849 * descriptors registered by calls to gl_watch_fd(). If at any time, 8850 * no activity is seen for the requested time period, the specified 8851 * timeout callback function is called. On returning, this callback 8852 * returns a code which tells gl_get_line() what to do next. Note that 8853 * each call to gl_inactivity_timeout() replaces any previously installed 8854 * timeout callback, and that specifying a callback of 0, turns off 8855 * inactivity timing. 8856 * 8857 * Beware that although the timeout argument includes a nano-second 8858 * component, few computer clocks presently have resolutions finer 8859 * than a few milliseconds, so asking for less than a few milliseconds 8860 * is equivalent to zero on a lot of systems. 8861 * 8862 * Input: 8863 * gl GetLine * The resource object of the command-line input 8864 * module. 8865 * callback GlTimeoutFn * The function to call when the inactivity 8866 * timeout is exceeded. To turn off 8867 * inactivity timeouts altogether, send 0. 8868 * data void * A pointer to arbitrary data to pass to the 8869 * callback function. 8870 * sec unsigned long The number of whole seconds in the timeout. 8871 * nsec unsigned long The fractional number of seconds in the 8872 * timeout, expressed in nano-seconds (see 8873 * the caveat above). 8874 * Output: 8875 * return int 0 - OK. 8876 * 1 - Either gl==NULL, or this facility isn't 8877 * available on the the host system 8878 * (ie. select() isn't available). No 8879 * error message is generated in the latter 8880 * case. 8881 */ 8882 int gl_inactivity_timeout(GetLine *gl, GlTimeoutFn *timeout_fn, void *data, 8883 unsigned long sec, unsigned long nsec) 8884 #if !defined(HAVE_SELECT) 8885 {return 1;} /* The facility isn't supported on this system */ 8886 #else 8887 { 8888 sigset_t oldset; /* The signals that were blocked on entry to this function */ 8889 /* 8890 * Check the arguments. 8891 */ 8892 if(!gl) { 8893 errno = EINVAL; 8894 return 1; 8895 }; 8896 /* 8897 * Block all signals. 8898 */ 8899 if(gl_mask_signals(gl, &oldset)) 8900 return 1; 8901 /* 8902 * Install a new timeout? 8903 */ 8904 if(timeout_fn) { 8905 gl->timer.dt.tv_sec = sec; 8906 gl->timer.dt.tv_usec = nsec / 1000; 8907 gl->timer.fn = timeout_fn; 8908 gl->timer.data = data; 8909 } else { 8910 gl->timer.fn = 0; 8911 gl->timer.data = NULL; 8912 }; 8913 /* 8914 * Restore the process signal mask. 8915 */ 8916 gl_unmask_signals(gl, &oldset); 8917 return 0; 8918 } 8919 #endif 8920 8921 /*....................................................................... 8922 * When select() is available, this is a private function of 8923 * gl_read_input() which responds to file-descriptor events registered by 8924 * the caller. Note that it assumes that it is being called from within 8925 * gl_read_input()'s sigsetjump() clause. 8926 * 8927 * Input: 8928 * gl GetLine * The resource object of this module. 8929 * fd int The file descriptor to be watched for user input. 8930 * Output: 8931 * return int 0 - OK. 8932 * 1 - An error occurred. 8933 */ 8934 static int gl_event_handler(GetLine *gl, int fd) 8935 { 8936 #if !defined(HAVE_SELECT) 8937 return 0; 8938 #else 8939 /* 8940 * Set up a zero-second timeout. 8941 */ 8942 struct timeval zero; 8943 zero.tv_sec = zero.tv_usec = 0; 8944 /* 8945 * If at any time no external callbacks remain, quit the loop return, 8946 * so that we can simply wait in read(). This is designed as an 8947 * optimization for when no callbacks have been registered on entry to 8948 * this function, but since callbacks can delete themselves, it can 8949 * also help later. 8950 */ 8951 while(gl->fd_nodes || gl->timer.fn) { 8952 int nready; /* The number of file descriptors that are ready for I/O */ 8953 /* 8954 * Get the set of descriptors to be watched. 8955 */ 8956 fd_set rfds = gl->rfds; 8957 fd_set wfds = gl->wfds; 8958 fd_set ufds = gl->ufds; 8959 /* 8960 * Get the appropriate timeout. 8961 */ 8962 struct timeval dt = gl->timer.fn ? gl->timer.dt : zero; 8963 /* 8964 * Add the specified user-input file descriptor tot he set that is to 8965 * be watched. 8966 */ 8967 FD_SET(fd, &rfds); 8968 /* 8969 * Unblock the signals that we are watching, while select is blocked 8970 * waiting for I/O. 8971 */ 8972 gl_catch_signals(gl); 8973 /* 8974 * Wait for activity on any of the file descriptors. 8975 */ 8976 nready = select(gl->max_fd+1, &rfds, &wfds, &ufds, 8977 (gl->timer.fn || gl->io_mode==GL_SERVER_MODE) ? &dt : NULL); 8978 /* 8979 * We don't want to do a longjmp in the middle of a callback that 8980 * might be modifying global or heap data, so block all the signals 8981 * that we are trapping before executing callback functions. Note that 8982 * the caller will unblock them again when it needs to, so there is 8983 * no need to undo this before returning. 8984 */ 8985 gl_mask_signals(gl, NULL); 8986 /* 8987 * If select() returns but none of the file descriptors are reported 8988 * to have activity, then select() timed out. 8989 */ 8990 if(nready == 0) { 8991 /* 8992 * Note that in non-blocking server mode, the inactivity timer is used 8993 * to allow I/O to block for a specified amount of time, so in this 8994 * mode we return the postponed blocked status when an abort is 8995 * requested. 8996 */ 8997 if(gl_call_timeout_handler(gl)) { 8998 return 1; 8999 } else if(gl->io_mode == GL_SERVER_MODE) { 9000 gl_record_status(gl, GLR_BLOCKED, BLOCKED_ERRNO); 9001 return 1; 9002 }; 9003 /* 9004 * If nready < 0, this means an error occurred. 9005 */ 9006 } else if(nready < 0) { 9007 if(errno != EINTR) { 9008 gl_record_status(gl, GLR_ERROR, errno); 9009 return 1; 9010 }; 9011 /* 9012 * If the user-input file descriptor has data available, return. 9013 */ 9014 } else if(FD_ISSET(fd, &rfds)) { 9015 return 0; 9016 /* 9017 * Check for activity on any of the file descriptors registered by the 9018 * calling application, and call the associated callback functions. 9019 */ 9020 } else { 9021 GlFdNode *node; /* The fd event node being checked */ 9022 /* 9023 * Search the list for the file descriptor that caused select() to return. 9024 */ 9025 for(node=gl->fd_nodes; node; node=node->next) { 9026 /* 9027 * Is there urgent out of band data waiting to be read on fd? 9028 */ 9029 if(node->ur.fn && FD_ISSET(node->fd, &ufds)) { 9030 if(gl_call_fd_handler(gl, &node->ur, node->fd, GLFD_URGENT)) 9031 return 1; 9032 break; /* The callback may have changed the list of nodes */ 9033 /* 9034 * Is the fd readable? 9035 */ 9036 } else if(node->rd.fn && FD_ISSET(node->fd, &rfds)) { 9037 if(gl_call_fd_handler(gl, &node->rd, node->fd, GLFD_READ)) 9038 return 1; 9039 break; /* The callback may have changed the list of nodes */ 9040 /* 9041 * Is the fd writable? 9042 */ 9043 } else if(node->wr.fn && FD_ISSET(node->fd, &wfds)) { 9044 if(gl_call_fd_handler(gl, &node->wr, node->fd, GLFD_WRITE)) 9045 return 1; 9046 break; /* The callback may have changed the list of nodes */ 9047 }; 9048 }; 9049 }; 9050 /* 9051 * Just in case the above event handlers asked for the input line to 9052 * be redrawn, flush any pending output. 9053 */ 9054 if(gl_flush_output(gl)) 9055 return 1; 9056 }; 9057 return 0; 9058 } 9059 #endif 9060 9061 #if defined(HAVE_SELECT) 9062 /*....................................................................... 9063 * This is a private function of gl_event_handler(), used to call a 9064 * file-descriptor callback. 9065 * 9066 * Input: 9067 * gl GetLine * The resource object of gl_get_line(). 9068 * gfh GlFdHandler * The I/O handler. 9069 * fd int The file-descriptor being reported. 9070 * event GlFdEvent The I/O event being reported. 9071 * Output: 9072 * return int 0 - OK. 9073 * 1 - Error. 9074 */ 9075 static int gl_call_fd_handler(GetLine *gl, GlFdHandler *gfh, int fd, 9076 GlFdEvent event) 9077 { 9078 Termios attr; /* The terminal attributes */ 9079 int waserr = 0; /* True after any error */ 9080 /* 9081 * Re-enable conversion of newline characters to carriage-return/linefeed, 9082 * so that the callback can write to the terminal without having to do 9083 * anything special. 9084 */ 9085 if(tcgetattr(gl->input_fd, &attr)) { 9086 _err_record_msg(gl->err, "tcgetattr error", END_ERR_MSG); 9087 return 1; 9088 }; 9089 attr.c_oflag |= OPOST; 9090 while(tcsetattr(gl->input_fd, TCSADRAIN, &attr)) { 9091 if(errno != EINTR) { 9092 _err_record_msg(gl->err, "tcsetattr error", END_ERR_MSG); 9093 return 1; 9094 }; 9095 }; 9096 /* 9097 * Invoke the application's callback function. 9098 */ 9099 switch(gfh->fn(gl, gfh->data, fd, event)) { 9100 default: 9101 case GLFD_ABORT: 9102 gl_record_status(gl, GLR_FDABORT, 0); 9103 waserr = 1; 9104 break; 9105 case GLFD_REFRESH: 9106 gl_queue_redisplay(gl); 9107 break; 9108 case GLFD_CONTINUE: 9109 break; 9110 }; 9111 /* 9112 * Disable conversion of newline characters to carriage-return/linefeed. 9113 */ 9114 attr.c_oflag &= ~(OPOST); 9115 while(tcsetattr(gl->input_fd, TCSADRAIN, &attr)) { 9116 if(errno != EINTR) { 9117 _err_record_msg(gl->err, "tcsetattr error", END_ERR_MSG); 9118 return 1; 9119 }; 9120 }; 9121 return waserr; 9122 } 9123 9124 /*....................................................................... 9125 * This is a private function of gl_event_handler(), used to call a 9126 * inactivity timer callbacks. 9127 * 9128 * Input: 9129 * gl GetLine * The resource object of gl_get_line(). 9130 * Output: 9131 * return int 0 - OK. 9132 * 1 - Error. 9133 */ 9134 static int gl_call_timeout_handler(GetLine *gl) 9135 { 9136 Termios attr; /* The terminal attributes */ 9137 int waserr = 0; /* True after any error */ 9138 /* 9139 * Make sure that there is an inactivity timeout callback. 9140 */ 9141 if(!gl->timer.fn) 9142 return 0; 9143 /* 9144 * Re-enable conversion of newline characters to carriage-return/linefeed, 9145 * so that the callback can write to the terminal without having to do 9146 * anything special. 9147 */ 9148 if(tcgetattr(gl->input_fd, &attr)) { 9149 _err_record_msg(gl->err, "tcgetattr error", END_ERR_MSG); 9150 return 1; 9151 }; 9152 attr.c_oflag |= OPOST; 9153 while(tcsetattr(gl->input_fd, TCSADRAIN, &attr)) { 9154 if(errno != EINTR) { 9155 _err_record_msg(gl->err, "tcsetattr error", END_ERR_MSG); 9156 return 1; 9157 }; 9158 }; 9159 /* 9160 * Invoke the application's callback function. 9161 */ 9162 switch(gl->timer.fn(gl, gl->timer.data)) { 9163 default: 9164 case GLTO_ABORT: 9165 gl_record_status(gl, GLR_TIMEOUT, 0); 9166 waserr = 1; 9167 break; 9168 case GLTO_REFRESH: 9169 gl_queue_redisplay(gl); 9170 break; 9171 case GLTO_CONTINUE: 9172 break; 9173 }; 9174 /* 9175 * Disable conversion of newline characters to carriage-return/linefeed. 9176 */ 9177 attr.c_oflag &= ~(OPOST); 9178 while(tcsetattr(gl->input_fd, TCSADRAIN, &attr)) { 9179 if(errno != EINTR) { 9180 _err_record_msg(gl->err, "tcsetattr error", END_ERR_MSG); 9181 return 1; 9182 }; 9183 }; 9184 return waserr; 9185 } 9186 #endif /* HAVE_SELECT */ 9187 9188 /*....................................................................... 9189 * Switch history groups. History groups represent separate history 9190 * lists recorded within a single history buffer. Different groups 9191 * are distinguished by integer identifiers chosen by the calling 9192 * appplicaton. Initially new_GetLine() sets the group identifier to 9193 * 0. Whenever a new line is appended to the history list, the current 9194 * group identifier is recorded with it, and history lookups only 9195 * consider lines marked with the current group identifier. 9196 * 9197 * Input: 9198 * gl GetLine * The resource object of gl_get_line(). 9199 * id unsigned The new history group identifier. 9200 * Output: 9201 * return int 0 - OK. 9202 * 1 - Error. 9203 */ 9204 int gl_group_history(GetLine *gl, unsigned id) 9205 { 9206 sigset_t oldset; /* The signals that were blocked on entry to this function */ 9207 int status; /* The return status of this function */ 9208 /* 9209 * Check the arguments. 9210 */ 9211 if(!gl) { 9212 errno = EINVAL; 9213 return 1; 9214 }; 9215 /* 9216 * Block all signals while we install the new configuration. 9217 */ 9218 if(gl_mask_signals(gl, &oldset)) 9219 return 1; 9220 /* 9221 * If the group isn't being changed, do nothing. 9222 */ 9223 if(_glh_get_group(gl->glh) == id) { 9224 status = 0; 9225 /* 9226 * Establish the new group. 9227 */ 9228 } else if(_glh_set_group(gl->glh, id)) { 9229 _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG); 9230 status = 1; 9231 /* 9232 * Prevent history information from the previous group being 9233 * inappropriately used by the next call to gl_get_line(). 9234 */ 9235 } else { 9236 gl->preload_history = 0; 9237 gl->last_search = -1; 9238 status = 0; 9239 }; 9240 /* 9241 * Restore the process signal mask. 9242 */ 9243 gl_unmask_signals(gl, &oldset); 9244 return status; 9245 } 9246 9247 /*....................................................................... 9248 * Display the contents of the history list. 9249 * 9250 * Input: 9251 * gl GetLine * The resource object of gl_get_line(). 9252 * fp FILE * The stdio output stream to write to. 9253 * fmt const char * A format string. This containing characters to be 9254 * written verbatim, plus any of the following 9255 * format directives: 9256 * %D - The date, formatted like 2001-11-20 9257 * %T - The time of day, formatted like 23:59:59 9258 * %N - The sequential entry number of the 9259 * line in the history buffer. 9260 * %G - The number of the history group that 9261 * the line belongs to. 9262 * %% - A literal % character. 9263 * %H - The history line itself. 9264 * Note that a '\n' newline character is not 9265 * appended by default. 9266 * all_groups int If true, display history lines from all 9267 * history groups. Otherwise only display 9268 * those of the current history group. 9269 * max_lines int If max_lines is < 0, all available lines 9270 * are displayed. Otherwise only the most 9271 * recent max_lines lines will be displayed. 9272 * Output: 9273 * return int 0 - OK. 9274 * 1 - Error. 9275 */ 9276 int gl_show_history(GetLine *gl, FILE *fp, const char *fmt, int all_groups, 9277 int max_lines) 9278 { 9279 sigset_t oldset; /* The signals that were blocked on entry to this function */ 9280 int status; /* The return status of this function */ 9281 /* 9282 * Check the arguments. 9283 */ 9284 if(!gl || !fp || !fmt) { 9285 if(gl) 9286 _err_record_msg(gl->err, "NULL argument(s)", END_ERR_MSG); 9287 errno = EINVAL; 9288 return 1; 9289 }; 9290 /* 9291 * Block all signals. 9292 */ 9293 if(gl_mask_signals(gl, &oldset)) 9294 return 1; 9295 /* 9296 * Display the specified history group(s) while signals are blocked. 9297 */ 9298 status = _glh_show_history(gl->glh, _io_write_stdio, fp, fmt, all_groups, 9299 max_lines) || fflush(fp)==EOF; 9300 if(!status) 9301 _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG); 9302 /* 9303 * Restore the process signal mask. 9304 */ 9305 gl_unmask_signals(gl, &oldset); 9306 return status; 9307 } 9308 9309 /*....................................................................... 9310 * Update if necessary, and return the current size of the terminal. 9311 * 9312 * Input: 9313 * gl GetLine * The resource object of gl_get_line(). 9314 * def_ncolumn int If the number of columns in the terminal 9315 * can't be determined, substitute this number. 9316 * def_nline int If the number of lines in the terminal can't 9317 * be determined, substitute this number. 9318 * Output: 9319 * return GlTerminalSize The current terminal size. 9320 */ 9321 GlTerminalSize gl_terminal_size(GetLine *gl, int def_ncolumn, int def_nline) 9322 { 9323 GlTerminalSize size; /* The object to be returned */ 9324 sigset_t oldset; /* The signals that were blocked on entry */ 9325 /* to this function */ 9326 /* 9327 * Block all signals while accessing gl. 9328 */ 9329 gl_mask_signals(gl, &oldset); 9330 /* 9331 * Lookup/configure the terminal size. 9332 */ 9333 _gl_terminal_size(gl, def_ncolumn, def_nline, &size); 9334 /* 9335 * Restore the process signal mask before returning. 9336 */ 9337 gl_unmask_signals(gl, &oldset); 9338 return size; 9339 } 9340 9341 /*....................................................................... 9342 * This is the private body of the gl_terminal_size() function. It 9343 * assumes that the caller has checked its arguments and blocked the 9344 * delivery of signals. 9345 */ 9346 static void _gl_terminal_size(GetLine *gl, int def_ncolumn, int def_nline, 9347 GlTerminalSize *size) 9348 { 9349 const char *env; /* The value of an environment variable */ 9350 int n; /* A number read from env[] */ 9351 /* 9352 * Set the number of lines and columns to non-sensical values so that 9353 * we know later if they have been set. 9354 */ 9355 gl->nline = 0; 9356 gl->ncolumn = 0; 9357 /* 9358 * Are we reading from a terminal? 9359 */ 9360 if(gl->is_term) { 9361 /* 9362 * Ask the terminal directly if possible. 9363 */ 9364 (void) _gl_update_size(gl); 9365 /* 9366 * If gl_update_size() couldn't ask the terminal, it will have 9367 * left gl->nrow and gl->ncolumn unchanged. If these values haven't 9368 * been changed from their initial values of zero, we need to find 9369 * a different method to get the terminal size. 9370 * 9371 * If the number of lines isn't known yet, first see if the 9372 * LINES environment ariable exists and specifies a believable number. 9373 * If this doesn't work, look up the default size in the terminal 9374 * information database. 9375 */ 9376 if(gl->nline < 1) { 9377 if((env = getenv("LINES")) && (n=atoi(env)) > 0) 9378 gl->nline = n; 9379 #ifdef USE_TERMINFO 9380 else 9381 gl->nline = tigetnum((char *)"lines"); 9382 #elif defined(USE_TERMCAP) 9383 else 9384 gl->nline = tgetnum("li"); 9385 #endif 9386 }; 9387 /* 9388 * If the number of lines isn't known yet, first see if the COLUMNS 9389 * environment ariable exists and specifies a believable number. If 9390 * this doesn't work, look up the default size in the terminal 9391 * information database. 9392 */ 9393 if(gl->ncolumn < 1) { 9394 if((env = getenv("COLUMNS")) && (n=atoi(env)) > 0) 9395 gl->ncolumn = n; 9396 #ifdef USE_TERMINFO 9397 else 9398 gl->ncolumn = tigetnum((char *)"cols"); 9399 #elif defined(USE_TERMCAP) 9400 else 9401 gl->ncolumn = tgetnum("co"); 9402 #endif 9403 }; 9404 }; 9405 /* 9406 * If we still haven't been able to acquire reasonable values, substitute 9407 * the default values specified by the caller. 9408 */ 9409 if(gl->nline <= 0) 9410 gl->nline = def_nline; 9411 if(gl->ncolumn <= 0) 9412 gl->ncolumn = def_ncolumn; 9413 /* 9414 * Copy the new size into the return value. 9415 */ 9416 if(size) { 9417 size->nline = gl->nline; 9418 size->ncolumn = gl->ncolumn; 9419 }; 9420 return; 9421 } 9422 9423 /*....................................................................... 9424 * Resize or delete the history buffer. 9425 * 9426 * Input: 9427 * gl GetLine * The resource object of gl_get_line(). 9428 * bufsize size_t The number of bytes in the history buffer, or 0 9429 * to delete the buffer completely. 9430 * Output: 9431 * return int 0 - OK. 9432 * 1 - Insufficient memory (the previous buffer 9433 * will have been retained). No error message 9434 * will be displayed. 9435 */ 9436 int gl_resize_history(GetLine *gl, size_t bufsize) 9437 { 9438 sigset_t oldset; /* The signals that were blocked on entry to this function */ 9439 int status; /* The return status of this function */ 9440 /* 9441 * Check the arguments. 9442 */ 9443 if(!gl) 9444 return 1; 9445 /* 9446 * Block all signals while modifying the contents of gl. 9447 */ 9448 if(gl_mask_signals(gl, &oldset)) 9449 return 1; 9450 /* 9451 * Perform the resize while signals are blocked. 9452 */ 9453 status = _glh_resize_history(gl->glh, bufsize); 9454 if(status) 9455 _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG); 9456 /* 9457 * Restore the process signal mask before returning. 9458 */ 9459 gl_unmask_signals(gl, &oldset); 9460 return status; 9461 } 9462 9463 /*....................................................................... 9464 * Set an upper limit to the number of lines that can be recorded in the 9465 * history list, or remove a previously specified limit. 9466 * 9467 * Input: 9468 * gl GetLine * The resource object of gl_get_line(). 9469 * max_lines int The maximum number of lines to allow, or -1 to 9470 * cancel a previous limit and allow as many lines 9471 * as will fit in the current history buffer size. 9472 */ 9473 void gl_limit_history(GetLine *gl, int max_lines) 9474 { 9475 if(gl) { 9476 sigset_t oldset; /* The signals that were blocked on entry to this block */ 9477 /* 9478 * Temporarily block all signals. 9479 */ 9480 gl_mask_signals(gl, &oldset); 9481 /* 9482 * Apply the limit while signals are blocked. 9483 */ 9484 _glh_limit_history(gl->glh, max_lines); 9485 /* 9486 * Restore the process signal mask before returning. 9487 */ 9488 gl_unmask_signals(gl, &oldset); 9489 }; 9490 } 9491 9492 /*....................................................................... 9493 * Discard either all historical lines, or just those associated with the 9494 * current history group. 9495 * 9496 * Input: 9497 * gl GetLine * The resource object of gl_get_line(). 9498 * all_groups int If true, clear all of the history. If false, 9499 * clear only the stored lines associated with the 9500 * currently selected history group. 9501 */ 9502 void gl_clear_history(GetLine *gl, int all_groups) 9503 { 9504 if(gl) { 9505 sigset_t oldset; /* The signals that were blocked on entry to this block */ 9506 /* 9507 * Temporarily block all signals. 9508 */ 9509 gl_mask_signals(gl, &oldset); 9510 /* 9511 * Clear the history buffer while signals are blocked. 9512 */ 9513 _glh_clear_history(gl->glh, all_groups); 9514 /* 9515 * Restore the process signal mask before returning. 9516 */ 9517 gl_unmask_signals(gl, &oldset); 9518 }; 9519 } 9520 9521 /*....................................................................... 9522 * Temporarily enable or disable the gl_get_line() history mechanism. 9523 * 9524 * Input: 9525 * gl GetLine * The resource object of gl_get_line(). 9526 * enable int If true, turn on the history mechanism. If 9527 * false, disable it. 9528 */ 9529 void gl_toggle_history(GetLine *gl, int enable) 9530 { 9531 if(gl) { 9532 sigset_t oldset; /* The signals that were blocked on entry to this block */ 9533 /* 9534 * Temporarily block all signals. 9535 */ 9536 gl_mask_signals(gl, &oldset); 9537 /* 9538 * Change the history recording mode while signals are blocked. 9539 */ 9540 _glh_toggle_history(gl->glh, enable); 9541 /* 9542 * Restore the process signal mask before returning. 9543 */ 9544 gl_unmask_signals(gl, &oldset); 9545 }; 9546 } 9547 9548 /*....................................................................... 9549 * Lookup a history line by its sequential number of entry in the 9550 * history buffer. 9551 * 9552 * Input: 9553 * gl GetLine * The resource object of gl_get_line(). 9554 * id unsigned long The identification number of the line to 9555 * be returned, where 0 denotes the first line 9556 * that was entered in the history list, and 9557 * each subsequently added line has a number 9558 * one greater than the previous one. For 9559 * the range of lines currently in the list, 9560 * see the gl_range_of_history() function. 9561 * Input/Output: 9562 * line GlHistoryLine * A pointer to the variable in which to 9563 * return the details of the line. 9564 * Output: 9565 * return int 0 - The line is no longer in the history 9566 * list, and *line has not been changed. 9567 * 1 - The requested line can be found in 9568 * *line. Note that line->line is part 9569 * of the history buffer, so a 9570 * private copy should be made if you 9571 * wish to use it after subsequent calls 9572 * to any functions that take *gl as an 9573 * argument. 9574 */ 9575 int gl_lookup_history(GetLine *gl, unsigned long id, GlHistoryLine *line) 9576 { 9577 sigset_t oldset; /* The signals that were blocked on entry to this function */ 9578 int status; /* The return status of this function */ 9579 /* 9580 * Check the arguments. 9581 */ 9582 if(!gl) 9583 return 0; 9584 /* 9585 * Block all signals while modifying the contents of gl. 9586 */ 9587 if(gl_mask_signals(gl, &oldset)) 9588 return 1; 9589 /* 9590 * Perform the lookup while signals are blocked. 9591 */ 9592 status = _glh_lookup_history(gl->glh, (GlhLineID) id, &line->line, 9593 &line->group, &line->timestamp); 9594 if(status) 9595 _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG); 9596 /* 9597 * Restore the process signal mask before returning. 9598 */ 9599 gl_unmask_signals(gl, &oldset); 9600 return status; 9601 } 9602 9603 /*....................................................................... 9604 * Query the state of the history list. Note that any of the input/output 9605 * pointers can be specified as NULL. 9606 * 9607 * Input: 9608 * gl GetLine * The resource object of gl_get_line(). 9609 * Input/Output: 9610 * state GlHistoryState * A pointer to the variable in which to record 9611 * the return values. 9612 */ 9613 void gl_state_of_history(GetLine *gl, GlHistoryState *state) 9614 { 9615 if(gl && state) { 9616 sigset_t oldset; /* The signals that were blocked on entry to this block */ 9617 /* 9618 * Temporarily block all signals. 9619 */ 9620 gl_mask_signals(gl, &oldset); 9621 /* 9622 * Lookup the status while signals are blocked. 9623 */ 9624 _glh_state_of_history(gl->glh, &state->enabled, &state->group, 9625 &state->max_lines); 9626 /* 9627 * Restore the process signal mask before returning. 9628 */ 9629 gl_unmask_signals(gl, &oldset); 9630 }; 9631 } 9632 9633 /*....................................................................... 9634 * Query the number and range of lines in the history buffer. 9635 * 9636 * Input: 9637 * gl GetLine * The resource object of gl_get_line(). 9638 * range GlHistoryRange * A pointer to the variable in which to record 9639 * the return values. If range->nline=0, the 9640 * range of lines will be given as 0-0. 9641 */ 9642 void gl_range_of_history(GetLine *gl, GlHistoryRange *range) 9643 { 9644 if(gl && range) { 9645 sigset_t oldset; /* The signals that were blocked on entry to this block */ 9646 /* 9647 * Temporarily block all signals. 9648 */ 9649 gl_mask_signals(gl, &oldset); 9650 /* 9651 * Lookup the information while signals are blocked. 9652 */ 9653 _glh_range_of_history(gl->glh, &range->oldest, &range->newest, 9654 &range->nlines); 9655 /* 9656 * Restore the process signal mask before returning. 9657 */ 9658 gl_unmask_signals(gl, &oldset); 9659 }; 9660 } 9661 9662 /*....................................................................... 9663 * Return the size of the history buffer and the amount of the 9664 * buffer that is currently in use. 9665 * 9666 * Input: 9667 * gl GetLine * The gl_get_line() resource object. 9668 * Input/Output: 9669 * GlHistorySize size * A pointer to the variable in which to return 9670 * the results. 9671 */ 9672 void gl_size_of_history(GetLine *gl, GlHistorySize *size) 9673 { 9674 if(gl && size) { 9675 sigset_t oldset; /* The signals that were blocked on entry to this block */ 9676 /* 9677 * Temporarily block all signals. 9678 */ 9679 gl_mask_signals(gl, &oldset); 9680 /* 9681 * Lookup the information while signals are blocked. 9682 */ 9683 _glh_size_of_history(gl->glh, &size->size, &size->used); 9684 /* 9685 * Restore the process signal mask before returning. 9686 */ 9687 gl_unmask_signals(gl, &oldset); 9688 }; 9689 } 9690 9691 /*....................................................................... 9692 * This is the action function that lists the contents of the history 9693 * list. 9694 */ 9695 static KT_KEY_FN(gl_list_history) 9696 { 9697 /* 9698 * Start a new line. 9699 */ 9700 if(gl_start_newline(gl, 1)) 9701 return 1; 9702 /* 9703 * List history lines that belong to the current group. 9704 */ 9705 _glh_show_history(gl->glh, gl_write_fn, gl, "%N %T %H\r\n", 0, 9706 count<=1 ? -1 : count); 9707 /* 9708 * Arrange for the input line to be redisplayed. 9709 */ 9710 gl_queue_redisplay(gl); 9711 return 0; 9712 } 9713 9714 /*....................................................................... 9715 * Specify whether text that users type should be displayed or hidden. 9716 * In the latter case, only the prompt is displayed, and the final 9717 * input line is not archived in the history list. 9718 * 9719 * Input: 9720 * gl GetLine * The gl_get_line() resource object. 9721 * enable int 0 - Disable echoing. 9722 * 1 - Enable echoing. 9723 * -1 - Just query the mode without changing it. 9724 * Output: 9725 * return int The echoing disposition that was in effect 9726 * before this function was called: 9727 * 0 - Echoing was disabled. 9728 * 1 - Echoing was enabled. 9729 */ 9730 int gl_echo_mode(GetLine *gl, int enable) 9731 { 9732 if(gl) { 9733 sigset_t oldset; /* The signals that were blocked on entry to this block */ 9734 int was_echoing; /* The echoing disposition on entry to this function */ 9735 /* 9736 * Temporarily block all signals. 9737 */ 9738 gl_mask_signals(gl, &oldset); 9739 /* 9740 * Install the new disposition while signals are blocked. 9741 */ 9742 was_echoing = gl->echo; 9743 if(enable >= 0) 9744 gl->echo = enable; 9745 /* 9746 * Restore the process signal mask before returning. 9747 */ 9748 gl_unmask_signals(gl, &oldset); 9749 /* 9750 * Return the original echoing disposition. 9751 */ 9752 return was_echoing; 9753 }; 9754 return 1; 9755 } 9756 9757 /*....................................................................... 9758 * Display the prompt. 9759 * 9760 * Input: 9761 * gl GetLine * The resource object of gl_get_line(). 9762 * Output: 9763 * return int 0 - OK. 9764 * 1 - Error. 9765 */ 9766 static int gl_display_prompt(GetLine *gl) 9767 { 9768 const char *pptr; /* A pointer into gl->prompt[] */ 9769 unsigned old_attr=0; /* The current text display attributes */ 9770 unsigned new_attr=0; /* The requested text display attributes */ 9771 /* 9772 * Temporarily switch to echoing output characters. 9773 */ 9774 int kept_echo = gl->echo; 9775 gl->echo = 1; 9776 /* 9777 * In case the screen got messed up, send a carriage return to 9778 * put the cursor at the beginning of the current terminal line. 9779 */ 9780 if(gl_print_control_sequence(gl, 1, gl->bol)) 9781 return 1; 9782 /* 9783 * Mark the line as partially displayed. 9784 */ 9785 gl->displayed = 1; 9786 /* 9787 * Write the prompt, using the currently selected prompt style. 9788 */ 9789 switch(gl->prompt_style) { 9790 case GL_LITERAL_PROMPT: 9791 if(gl_print_string(gl, gl->prompt, '\0')) 9792 return 1; 9793 break; 9794 case GL_FORMAT_PROMPT: 9795 for(pptr=gl->prompt; *pptr; pptr++) { 9796 /* 9797 * Does the latest character appear to be the start of a directive? 9798 */ 9799 if(*pptr == '%') { 9800 /* 9801 * Check for and act on attribute changing directives. 9802 */ 9803 switch(pptr[1]) { 9804 /* 9805 * Add or remove a text attribute from the new set of attributes. 9806 */ 9807 case 'B': case 'U': case 'S': case 'P': case 'F': case 'V': 9808 case 'b': case 'u': case 's': case 'p': case 'f': case 'v': 9809 switch(*++pptr) { 9810 case 'B': /* Switch to a bold font */ 9811 new_attr |= GL_TXT_BOLD; 9812 break; 9813 case 'b': /* Switch to a non-bold font */ 9814 new_attr &= ~GL_TXT_BOLD; 9815 break; 9816 case 'U': /* Start underlining */ 9817 new_attr |= GL_TXT_UNDERLINE; 9818 break; 9819 case 'u': /* Stop underlining */ 9820 new_attr &= ~GL_TXT_UNDERLINE; 9821 break; 9822 case 'S': /* Start highlighting */ 9823 new_attr |= GL_TXT_STANDOUT; 9824 break; 9825 case 's': /* Stop highlighting */ 9826 new_attr &= ~GL_TXT_STANDOUT; 9827 break; 9828 case 'P': /* Switch to a pale font */ 9829 new_attr |= GL_TXT_DIM; 9830 break; 9831 case 'p': /* Switch to a non-pale font */ 9832 new_attr &= ~GL_TXT_DIM; 9833 break; 9834 case 'F': /* Switch to a flashing font */ 9835 new_attr |= GL_TXT_BLINK; 9836 break; 9837 case 'f': /* Switch to a steady font */ 9838 new_attr &= ~GL_TXT_BLINK; 9839 break; 9840 case 'V': /* Switch to reverse video */ 9841 new_attr |= GL_TXT_REVERSE; 9842 break; 9843 case 'v': /* Switch out of reverse video */ 9844 new_attr &= ~GL_TXT_REVERSE; 9845 break; 9846 }; 9847 continue; 9848 /* 9849 * A literal % is represented by %%. Skip the leading %. 9850 */ 9851 case '%': 9852 pptr++; 9853 break; 9854 }; 9855 }; 9856 /* 9857 * Many terminals, when asked to turn off a single text attribute, turn 9858 * them all off, so the portable way to turn one off individually is to 9859 * explicitly turn them all off, then specify those that we want from 9860 * scratch. 9861 */ 9862 if(old_attr & ~new_attr) { 9863 if(gl_print_control_sequence(gl, 1, gl->text_attr_off)) 9864 return 1; 9865 old_attr = 0; 9866 }; 9867 /* 9868 * Install new text attributes? 9869 */ 9870 if(new_attr != old_attr) { 9871 if(new_attr & GL_TXT_BOLD && !(old_attr & GL_TXT_BOLD) && 9872 gl_print_control_sequence(gl, 1, gl->bold)) 9873 return 1; 9874 if(new_attr & GL_TXT_UNDERLINE && !(old_attr & GL_TXT_UNDERLINE) && 9875 gl_print_control_sequence(gl, 1, gl->underline)) 9876 return 1; 9877 if(new_attr & GL_TXT_STANDOUT && !(old_attr & GL_TXT_STANDOUT) && 9878 gl_print_control_sequence(gl, 1, gl->standout)) 9879 return 1; 9880 if(new_attr & GL_TXT_DIM && !(old_attr & GL_TXT_DIM) && 9881 gl_print_control_sequence(gl, 1, gl->dim)) 9882 return 1; 9883 if(new_attr & GL_TXT_REVERSE && !(old_attr & GL_TXT_REVERSE) && 9884 gl_print_control_sequence(gl, 1, gl->reverse)) 9885 return 1; 9886 if(new_attr & GL_TXT_BLINK && !(old_attr & GL_TXT_BLINK) && 9887 gl_print_control_sequence(gl, 1, gl->blink)) 9888 return 1; 9889 old_attr = new_attr; 9890 }; 9891 /* 9892 * Display the latest character. 9893 */ 9894 if(gl_print_char(gl, *pptr, pptr[1])) 9895 return 1; 9896 }; 9897 /* 9898 * Turn off all text attributes now that we have finished drawing 9899 * the prompt. 9900 */ 9901 if(gl_print_control_sequence(gl, 1, gl->text_attr_off)) 9902 return 1; 9903 break; 9904 }; 9905 /* 9906 * Restore the original echo mode. 9907 */ 9908 gl->echo = kept_echo; 9909 /* 9910 * The prompt has now been displayed at least once. 9911 */ 9912 gl->prompt_changed = 0; 9913 return 0; 9914 } 9915 9916 /*....................................................................... 9917 * This function can be called from gl_get_line() callbacks to have 9918 * the prompt changed when they return. It has no effect if gl_get_line() 9919 * is not currently being invoked. 9920 * 9921 * Input: 9922 * gl GetLine * The resource object of gl_get_line(). 9923 * prompt const char * The new prompt. 9924 */ 9925 void gl_replace_prompt(GetLine *gl, const char *prompt) 9926 { 9927 if(gl) { 9928 sigset_t oldset; /* The signals that were blocked on entry to this block */ 9929 /* 9930 * Temporarily block all signals. 9931 */ 9932 gl_mask_signals(gl, &oldset); 9933 /* 9934 * Replace the prompt. 9935 */ 9936 _gl_replace_prompt(gl, prompt); 9937 /* 9938 * Restore the process signal mask before returning. 9939 */ 9940 gl_unmask_signals(gl, &oldset); 9941 }; 9942 } 9943 9944 /*....................................................................... 9945 * This is the private body of the gl_replace_prompt() function. It 9946 * assumes that the caller has checked its arguments and blocked the 9947 * delivery of signals. 9948 */ 9949 static void _gl_replace_prompt(GetLine *gl, const char *prompt) 9950 { 9951 size_t size; 9952 9953 /* 9954 * Substitute an empty prompt? 9955 */ 9956 if(!prompt) 9957 prompt = ""; 9958 /* 9959 * Gaurd against aliasing between prompt and gl->prompt. 9960 */ 9961 if(gl->prompt != prompt) { 9962 /* 9963 * Get the length of the new prompt string. 9964 */ 9965 size_t slen = strlen(prompt); 9966 /* 9967 * If needed, allocate a new buffer for the prompt string. 9968 */ 9969 size = sizeof(char) * (slen + 1); 9970 if(!gl->prompt || slen > strlen(gl->prompt)) { 9971 char *new_prompt = gl->prompt ? realloc(gl->prompt, size) : malloc(size); 9972 if(!new_prompt) 9973 return; 9974 gl->prompt = new_prompt; 9975 }; 9976 /* 9977 * Make a copy of the new prompt. 9978 */ 9979 strlcpy(gl->prompt, prompt, size); 9980 }; 9981 /* 9982 * Record the statistics of the new prompt. 9983 */ 9984 gl->prompt_len = gl_displayed_prompt_width(gl); 9985 gl->prompt_changed = 1; 9986 gl_queue_redisplay(gl); 9987 return; 9988 } 9989 9990 /*....................................................................... 9991 * Work out the length of the current prompt on the terminal, according 9992 * to the current prompt formatting style. 9993 * 9994 * Input: 9995 * gl GetLine * The resource object of this library. 9996 * Output: 9997 * return int The number of displayed characters. 9998 */ 9999 static int gl_displayed_prompt_width(GetLine *gl) 10000 { 10001 int slen=0; /* The displayed number of characters */ 10002 const char *pptr; /* A pointer into prompt[] */ 10003 /* 10004 * The length differs according to the prompt display style. 10005 */ 10006 switch(gl->prompt_style) { 10007 case GL_LITERAL_PROMPT: 10008 return gl_displayed_string_width(gl, gl->prompt, -1, 0); 10009 break; 10010 case GL_FORMAT_PROMPT: 10011 /* 10012 * Add up the length of the displayed string, while filtering out 10013 * attribute directives. 10014 */ 10015 for(pptr=gl->prompt; *pptr; pptr++) { 10016 /* 10017 * Does the latest character appear to be the start of a directive? 10018 */ 10019 if(*pptr == '%') { 10020 /* 10021 * Check for and skip attribute changing directives. 10022 */ 10023 switch(pptr[1]) { 10024 case 'B': case 'b': case 'U': case 'u': case 'S': case 's': 10025 pptr++; 10026 continue; 10027 /* 10028 * A literal % is represented by %%. Skip the leading %. 10029 */ 10030 case '%': 10031 pptr++; 10032 break; 10033 }; 10034 }; 10035 slen += gl_displayed_char_width(gl, *pptr, slen); 10036 }; 10037 break; 10038 }; 10039 return slen; 10040 } 10041 10042 /*....................................................................... 10043 * Specify whether to heed text attribute directives within prompt 10044 * strings. 10045 * 10046 * Input: 10047 * gl GetLine * The resource object of gl_get_line(). 10048 * style GlPromptStyle The style of prompt (see the definition of 10049 * GlPromptStyle in libtecla.h for details). 10050 */ 10051 void gl_prompt_style(GetLine *gl, GlPromptStyle style) 10052 { 10053 if(gl) { 10054 sigset_t oldset; /* The signals that were blocked on entry to this block */ 10055 /* 10056 * Temporarily block all signals. 10057 */ 10058 gl_mask_signals(gl, &oldset); 10059 /* 10060 * Install the new style in gl while signals are blocked. 10061 */ 10062 if(style != gl->prompt_style) { 10063 gl->prompt_style = style; 10064 gl->prompt_len = gl_displayed_prompt_width(gl); 10065 gl->prompt_changed = 1; 10066 gl_queue_redisplay(gl); 10067 }; 10068 /* 10069 * Restore the process signal mask before returning. 10070 */ 10071 gl_unmask_signals(gl, &oldset); 10072 }; 10073 } 10074 10075 /*....................................................................... 10076 * Tell gl_get_line() how to respond to a given signal. This can be used 10077 * both to override the default responses to signals that gl_get_line() 10078 * normally catches and to add new signals to the list that are to be 10079 * caught. 10080 * 10081 * Input: 10082 * gl GetLine * The resource object of gl_get_line(). 10083 * signo int The number of the signal to be caught. 10084 * flags unsigned A bitwise union of GlSignalFlags enumerators. 10085 * after GlAfterSignal What to do after the application's signal 10086 * handler has been called. 10087 * errno_value int The value to set errno to. 10088 * Output: 10089 * return int 0 - OK. 10090 * 1 - Error. 10091 */ 10092 int gl_trap_signal(GetLine *gl, int signo, unsigned flags, 10093 GlAfterSignal after, int errno_value) 10094 { 10095 sigset_t oldset; /* The signals that were blocked on entry to this function */ 10096 int status; /* The return status of this function */ 10097 /* 10098 * Check the arguments. 10099 */ 10100 if(!gl) { 10101 errno = EINVAL; 10102 return 1; 10103 }; 10104 /* 10105 * Block all signals while modifying the contents of gl. 10106 */ 10107 if(gl_mask_signals(gl, &oldset)) 10108 return 1; 10109 /* 10110 * Perform the modification while signals are blocked. 10111 */ 10112 status = _gl_trap_signal(gl, signo, flags, after, errno_value); 10113 /* 10114 * Restore the process signal mask before returning. 10115 */ 10116 gl_unmask_signals(gl, &oldset); 10117 return status; 10118 } 10119 10120 /*....................................................................... 10121 * This is the private body of the gl_trap_signal() function. It 10122 * assumes that the caller has checked its arguments and blocked the 10123 * delivery of signals. 10124 */ 10125 static int _gl_trap_signal(GetLine *gl, int signo, unsigned flags, 10126 GlAfterSignal after, int errno_value) 10127 { 10128 GlSignalNode *sig; 10129 /* 10130 * Complain if an attempt is made to trap untrappable signals. 10131 * These would otherwise cause errors later in gl_mask_signals(). 10132 */ 10133 if(0 10134 #ifdef SIGKILL 10135 || signo==SIGKILL 10136 #endif 10137 #ifdef SIGBLOCK 10138 || signo==SIGBLOCK 10139 #endif 10140 ) { 10141 return 1; 10142 }; 10143 /* 10144 * See if the signal has already been registered. 10145 */ 10146 for(sig=gl->sigs; sig && sig->signo != signo; sig = sig->next) 10147 ; 10148 /* 10149 * If the signal hasn't already been registered, allocate a node for 10150 * it. 10151 */ 10152 if(!sig) { 10153 sig = (GlSignalNode *) _new_FreeListNode(gl->sig_mem); 10154 if(!sig) 10155 return 1; 10156 /* 10157 * Add the new node to the head of the list. 10158 */ 10159 sig->next = gl->sigs; 10160 gl->sigs = sig; 10161 /* 10162 * Record the signal number. 10163 */ 10164 sig->signo = signo; 10165 /* 10166 * Create a signal set that includes just this signal. 10167 */ 10168 sigemptyset(&sig->proc_mask); 10169 if(sigaddset(&sig->proc_mask, signo) == -1) { 10170 _err_record_msg(gl->err, "sigaddset error", END_ERR_MSG); 10171 sig = (GlSignalNode *) _del_FreeListNode(gl->sig_mem, sig); 10172 return 1; 10173 }; 10174 /* 10175 * Add the signal to the bit-mask of signals being trapped. 10176 */ 10177 sigaddset(&gl->all_signal_set, signo); 10178 }; 10179 /* 10180 * Record the new signal attributes. 10181 */ 10182 sig->flags = flags; 10183 sig->after = after; 10184 sig->errno_value = errno_value; 10185 return 0; 10186 } 10187 10188 /*....................................................................... 10189 * Remove a signal from the list of signals that gl_get_line() traps. 10190 * 10191 * Input: 10192 * gl GetLine * The resource object of gl_get_line(). 10193 * signo int The number of the signal to be ignored. 10194 * Output: 10195 * return int 0 - OK. 10196 * 1 - Error. 10197 */ 10198 int gl_ignore_signal(GetLine *gl, int signo) 10199 { 10200 GlSignalNode *sig; /* The gl->sigs list node of the specified signal */ 10201 GlSignalNode *prev; /* The node that precedes sig in the list */ 10202 sigset_t oldset; /* The signals that were blocked on entry to this */ 10203 /* function. */ 10204 /* 10205 * Check the arguments. 10206 */ 10207 if(!gl) { 10208 errno = EINVAL; 10209 return 1; 10210 }; 10211 /* 10212 * Block all signals while modifying the contents of gl. 10213 */ 10214 if(gl_mask_signals(gl, &oldset)) 10215 return 1; 10216 /* 10217 * Find the node of the gl->sigs list which records the disposition 10218 * of the specified signal. 10219 */ 10220 for(prev=NULL,sig=gl->sigs; sig && sig->signo != signo; 10221 prev=sig,sig=sig->next) 10222 ; 10223 if(sig) { 10224 /* 10225 * Remove the node from the list. 10226 */ 10227 if(prev) 10228 prev->next = sig->next; 10229 else 10230 gl->sigs = sig->next; 10231 /* 10232 * Return the node to the freelist. 10233 */ 10234 sig = (GlSignalNode *) _del_FreeListNode(gl->sig_mem, sig); 10235 /* 10236 * Remove the signal from the bit-mask union of signals being trapped. 10237 */ 10238 sigdelset(&gl->all_signal_set, signo); 10239 }; 10240 /* 10241 * Restore the process signal mask before returning. 10242 */ 10243 gl_unmask_signals(gl, &oldset); 10244 return 0; 10245 } 10246 10247 /*....................................................................... 10248 * This function is called when an input line has been completed. It 10249 * appends the specified newline character, terminates the line, 10250 * records the line in the history buffer if appropriate, and positions 10251 * the terminal cursor at the start of the next line. 10252 * 10253 * Input: 10254 * gl GetLine * The resource object of gl_get_line(). 10255 * newline_char int The newline character to add to the end 10256 * of the line. 10257 * Output: 10258 * return int 0 - OK. 10259 * 1 - Error. 10260 */ 10261 static int gl_line_ended(GetLine *gl, int newline_char) 10262 { 10263 /* 10264 * If the newline character is printable, display it at the end of 10265 * the line, and add it to the input line buffer. 10266 */ 10267 if(isprint((int)(unsigned char) newline_char)) { 10268 if(gl_end_of_line(gl, 1, NULL) || gl_add_char_to_line(gl, newline_char)) 10269 return 1; 10270 } else { 10271 /* 10272 * Otherwise just append a newline character to the input line buffer. 10273 */ 10274 newline_char = '\n'; 10275 gl_buffer_char(gl, newline_char, gl->ntotal); 10276 }; 10277 /* 10278 * Add the line to the history buffer if it was entered with a 10279 * newline character. 10280 */ 10281 if(gl->echo && gl->automatic_history && newline_char=='\n') 10282 (void) _gl_append_history(gl, gl->line); 10283 /* 10284 * Except when depending on the system-provided line editing, start a new 10285 * line after the end of the line that has just been entered. 10286 */ 10287 if(gl->editor != GL_NO_EDITOR && gl_start_newline(gl, 1)) 10288 return 1; 10289 /* 10290 * Record the successful return status. 10291 */ 10292 gl_record_status(gl, GLR_NEWLINE, 0); 10293 /* 10294 * Attempt to flush any pending output. 10295 */ 10296 (void) gl_flush_output(gl); 10297 /* 10298 * The next call to gl_get_line() will write the prompt for a new line 10299 * (or continue the above flush if incomplete), so if we manage to 10300 * flush the terminal now, report that we are waiting to write to the 10301 * terminal. 10302 */ 10303 gl->pending_io = GLP_WRITE; 10304 return 0; 10305 } 10306 10307 /*....................................................................... 10308 * Return the last signal that was caught by the most recent call to 10309 * gl_get_line(), or -1 if no signals were caught. This is useful if 10310 * gl_get_line() returns errno=EINTR and you need to find out what signal 10311 * caused it to abort. 10312 * 10313 * Input: 10314 * gl GetLine * The resource object of gl_get_line(). 10315 * Output: 10316 * return int The last signal caught by the most recent 10317 * call to gl_get_line(), or -1 if no signals 10318 * were caught. 10319 */ 10320 int gl_last_signal(GetLine *gl) 10321 { 10322 int signo = -1; /* The requested signal number */ 10323 if(gl) { 10324 sigset_t oldset; /* The signals that were blocked on entry to this block */ 10325 /* 10326 * Temporarily block all signals. 10327 */ 10328 gl_mask_signals(gl, &oldset); 10329 /* 10330 * Access gl now that signals are blocked. 10331 */ 10332 signo = gl->last_signal; 10333 /* 10334 * Restore the process signal mask before returning. 10335 */ 10336 gl_unmask_signals(gl, &oldset); 10337 }; 10338 return signo; 10339 } 10340 10341 /*....................................................................... 10342 * Prepare to edit a new line. 10343 * 10344 * Input: 10345 * gl GetLine * The resource object of this library. 10346 * prompt char * The prompt to prefix the line with, or NULL to 10347 * use the same prompt that was used by the previous 10348 * line. 10349 * start_line char * The initial contents of the input line, or NULL 10350 * if it should start out empty. 10351 * start_pos int If start_line isn't NULL, this specifies the 10352 * index of the character over which the cursor 10353 * should initially be positioned within the line. 10354 * If you just want it to follow the last character 10355 * of the line, send -1. 10356 * Output: 10357 * return int 0 - OK. 10358 * 1 - Error. 10359 */ 10360 static int gl_present_line(GetLine *gl, const char *prompt, 10361 const char *start_line, int start_pos) 10362 { 10363 /* 10364 * Reset the properties of the line. 10365 */ 10366 gl_reset_input_line(gl); 10367 /* 10368 * Record the new prompt and its displayed width. 10369 */ 10370 if(prompt) 10371 _gl_replace_prompt(gl, prompt); 10372 /* 10373 * Reset the history search pointers. 10374 */ 10375 if(_glh_cancel_search(gl->glh)) { 10376 _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG); 10377 return 1; 10378 }; 10379 /* 10380 * If the previous line was entered via the repeat-history action, 10381 * preload the specified history line. 10382 */ 10383 if(gl->preload_history) { 10384 gl->preload_history = 0; 10385 if(gl->preload_id) { 10386 if(_glh_recall_line(gl->glh, gl->preload_id, gl->line, gl->linelen+1)) { 10387 gl_update_buffer(gl); /* Compute gl->ntotal etc.. */ 10388 gl->buff_curpos = gl->ntotal; 10389 } else { 10390 gl_truncate_buffer(gl, 0); 10391 }; 10392 gl->preload_id = 0; 10393 }; 10394 /* 10395 * Present a specified initial line? 10396 */ 10397 } else if(start_line) { 10398 char *cptr; /* A pointer into gl->line[] */ 10399 /* 10400 * Measure the length of the starting line. 10401 */ 10402 int start_len = strlen(start_line); 10403 /* 10404 * If the length of the line is greater than the available space, 10405 * truncate it. 10406 */ 10407 if(start_len > gl->linelen) 10408 start_len = gl->linelen; 10409 /* 10410 * Load the line into the buffer. 10411 */ 10412 if(start_line != gl->line) 10413 gl_buffer_string(gl, start_line, start_len, 0); 10414 /* 10415 * Strip off any trailing newline and carriage return characters. 10416 */ 10417 for(cptr=gl->line + gl->ntotal - 1; cptr >= gl->line && 10418 (*cptr=='\n' || *cptr=='\r'); cptr--,gl->ntotal--) 10419 ; 10420 gl_truncate_buffer(gl, gl->ntotal < 0 ? 0 : gl->ntotal); 10421 /* 10422 * Where should the cursor be placed within the line? 10423 */ 10424 if(start_pos < 0 || start_pos > gl->ntotal) { 10425 if(gl_place_cursor(gl, gl->ntotal)) 10426 return 1; 10427 } else { 10428 if(gl_place_cursor(gl, start_pos)) 10429 return 1; 10430 }; 10431 /* 10432 * Clear the input line? 10433 */ 10434 } else { 10435 gl_truncate_buffer(gl, 0); 10436 }; 10437 /* 10438 * Arrange for the line to be displayed by gl_flush_output(). 10439 */ 10440 gl_queue_redisplay(gl); 10441 /* 10442 * Update the display. 10443 */ 10444 return gl_flush_output(gl); 10445 } 10446 10447 /*....................................................................... 10448 * Reset all line input parameters for a new input line. 10449 * 10450 * Input: 10451 * gl GetLine * The line editor resource object. 10452 */ 10453 static void gl_reset_input_line(GetLine *gl) 10454 { 10455 gl->ntotal = 0; 10456 gl->line[0] = '\0'; 10457 gl->buff_curpos = 0; 10458 gl->term_curpos = 0; 10459 gl->term_len = 0; 10460 gl->insert_curpos = 0; 10461 gl->number = -1; 10462 gl->displayed = 0; 10463 gl->endline = 0; 10464 gl->redisplay = 0; 10465 gl->postpone = 0; 10466 gl->nbuf = 0; 10467 gl->nread = 0; 10468 gl->vi.command = 0; 10469 gl->vi.undo.line[0] = '\0'; 10470 gl->vi.undo.ntotal = 0; 10471 gl->vi.undo.buff_curpos = 0; 10472 gl->vi.repeat.action.fn = 0; 10473 gl->vi.repeat.action.data = 0; 10474 gl->last_signal = -1; 10475 } 10476 10477 /*....................................................................... 10478 * Print an informational message to the terminal, after starting a new 10479 * line. 10480 * 10481 * Input: 10482 * gl GetLine * The line editor resource object. 10483 * ... const char * Zero or more strings to be printed. 10484 * ... void * The last argument must always be GL_END_INFO. 10485 * Output: 10486 * return int 0 - OK. 10487 * 1 - Error. 10488 */ 10489 static int gl_print_info(GetLine *gl, ...) 10490 { 10491 va_list ap; /* The variable argument list */ 10492 const char *s; /* The string being printed */ 10493 int waserr = 0; /* True after an error */ 10494 /* 10495 * Only display output when echoing is on. 10496 */ 10497 if(gl->echo) { 10498 /* 10499 * Skip to the start of the next empty line before displaying the message. 10500 */ 10501 if(gl_start_newline(gl, 1)) 10502 return 1; 10503 /* 10504 * Display the list of provided messages. 10505 */ 10506 va_start(ap, gl); 10507 while(!waserr && (s = va_arg(ap, const char *)) != GL_END_INFO) 10508 waserr = gl_print_raw_string(gl, 1, s, -1); 10509 va_end(ap); 10510 /* 10511 * Start a newline. 10512 */ 10513 waserr = waserr || gl_print_raw_string(gl, 1, "\n\r", -1); 10514 /* 10515 * Arrange for the input line to be redrawn. 10516 */ 10517 gl_queue_redisplay(gl); 10518 }; 10519 return waserr; 10520 } 10521 10522 /*....................................................................... 10523 * Go to the start of the next empty line, ready to output miscellaneous 10524 * text to the screen. 10525 * 10526 * Note that when async-signal safety is required, the 'buffered' 10527 * argument must be 0. 10528 * 10529 * Input: 10530 * gl GetLine * The line editor resource object. 10531 * buffered int If true, used buffered I/O when writing to 10532 * the terminal. Otherwise use async-signal-safe 10533 * unbuffered I/O. 10534 * Output: 10535 * return int 0 - OK. 10536 * 1 - Error. 10537 */ 10538 static int gl_start_newline(GetLine *gl, int buffered) 10539 { 10540 int waserr = 0; /* True after any I/O error */ 10541 /* 10542 * Move the cursor to the start of the terminal line that follows the 10543 * last line of the partially enterred line. In order that this 10544 * function remain async-signal safe when write_fn is signal safe, we 10545 * can't call our normal output functions, since they call tputs(), 10546 * who's signal saftey isn't defined. Fortunately, we can simply use 10547 * \r and \n to move the cursor to the right place. 10548 */ 10549 if(gl->displayed) { /* Is an input line currently displayed? */ 10550 /* 10551 * On which terminal lines are the cursor and the last character of the 10552 * input line? 10553 */ 10554 int curs_line = gl->term_curpos / gl->ncolumn; 10555 int last_line = gl->term_len / gl->ncolumn; 10556 /* 10557 * Move the cursor to the start of the line that follows the last 10558 * terminal line that is occupied by the input line. 10559 */ 10560 for( ; curs_line < last_line + 1; curs_line++) 10561 waserr = waserr || gl_print_raw_string(gl, buffered, "\n", 1); 10562 waserr = waserr || gl_print_raw_string(gl, buffered, "\r", 1); 10563 /* 10564 * Mark the line as no longer displayed. 10565 */ 10566 gl_line_erased(gl); 10567 }; 10568 return waserr; 10569 } 10570 10571 /*....................................................................... 10572 * The callback through which all terminal output is routed. 10573 * This simply appends characters to a queue buffer, which is 10574 * subsequently flushed to the output channel by gl_flush_output(). 10575 * 10576 * Input: 10577 * data void * The pointer to a GetLine line editor resource object 10578 * cast to (void *). 10579 * s const char * The string to be written. 10580 * n int The number of characters to write from s[]. 10581 * Output: 10582 * return int The number of characters written. This will always 10583 * be equal to 'n' unless an error occurs. 10584 */ 10585 static GL_WRITE_FN(gl_write_fn) 10586 { 10587 GetLine *gl = (GetLine *) data; 10588 int ndone = _glq_append_chars(gl->cq, s, n, gl->flush_fn, gl); 10589 if(ndone != n) 10590 _err_record_msg(gl->err, _glq_last_error(gl->cq), END_ERR_MSG); 10591 return ndone; 10592 } 10593 10594 /*....................................................................... 10595 * Ask gl_get_line() what caused it to return. 10596 * 10597 * Input: 10598 * gl GetLine * The line editor resource object. 10599 * Output: 10600 * return GlReturnStatus The return status of the last call to 10601 * gl_get_line(). 10602 */ 10603 GlReturnStatus gl_return_status(GetLine *gl) 10604 { 10605 GlReturnStatus rtn_status = GLR_ERROR; /* The requested status */ 10606 if(gl) { 10607 sigset_t oldset; /* The signals that were blocked on entry to this block */ 10608 /* 10609 * Temporarily block all signals. 10610 */ 10611 gl_mask_signals(gl, &oldset); 10612 /* 10613 * Access gl while signals are blocked. 10614 */ 10615 rtn_status = gl->rtn_status; 10616 /* 10617 * Restore the process signal mask before returning. 10618 */ 10619 gl_unmask_signals(gl, &oldset); 10620 }; 10621 return rtn_status; 10622 } 10623 10624 /*....................................................................... 10625 * In non-blocking server-I/O mode, this function should be called 10626 * from the application's external event loop to see what type of 10627 * terminal I/O is being waited for by gl_get_line(), and thus what 10628 * direction of I/O to wait for with select() or poll(). 10629 * 10630 * Input: 10631 * gl GetLine * The resource object of gl_get_line(). 10632 * Output: 10633 * return GlPendingIO The type of pending I/O being waited for. 10634 */ 10635 GlPendingIO gl_pending_io(GetLine *gl) 10636 { 10637 GlPendingIO pending_io = GLP_WRITE; /* The requested information */ 10638 if(gl) { 10639 sigset_t oldset; /* The signals that were blocked on entry to this block */ 10640 /* 10641 * Temporarily block all signals. 10642 */ 10643 gl_mask_signals(gl, &oldset); 10644 /* 10645 * Access gl while signals are blocked. 10646 */ 10647 pending_io = gl->pending_io; 10648 /* 10649 * Restore the process signal mask before returning. 10650 */ 10651 gl_unmask_signals(gl, &oldset); 10652 }; 10653 return pending_io; 10654 } 10655 10656 /*....................................................................... 10657 * In server mode, this function configures the terminal for non-blocking 10658 * raw terminal I/O. In normal I/O mode it does nothing. 10659 * 10660 * Callers of this function must be careful to trap all signals that 10661 * terminate or suspend the program, and call gl_normal_io() 10662 * from the corresponding signal handlers in order to restore the 10663 * terminal to its original settings before the program is terminated 10664 * or suspended. They should also trap the SIGCONT signal to detect 10665 * when the program resumes, and ensure that its signal handler 10666 * call gl_raw_io() to redisplay the line and resume editing. 10667 * 10668 * This function is async signal safe. 10669 * 10670 * Input: 10671 * gl GetLine * The line editor resource object. 10672 * Output: 10673 * return int 0 - OK. 10674 * 1 - Error. 10675 */ 10676 int gl_raw_io(GetLine *gl) 10677 { 10678 sigset_t oldset; /* The signals that were blocked on entry to this function */ 10679 int status; /* The return status of _gl_raw_io() */ 10680 /* 10681 * Check the arguments. 10682 */ 10683 if(!gl) { 10684 errno = EINVAL; 10685 return 1; 10686 }; 10687 /* 10688 * Block all signals. 10689 */ 10690 if(gl_mask_signals(gl, &oldset)) 10691 return 1; 10692 /* 10693 * Don't allow applications to switch into raw mode unless in server mode. 10694 */ 10695 if(gl->io_mode != GL_SERVER_MODE) { 10696 _err_record_msg(gl->err, "Can't switch to raw I/O unless in server mode", 10697 END_ERR_MSG); 10698 errno = EPERM; 10699 status = 1; 10700 } else { 10701 /* 10702 * Execute the private body of the function while signals are blocked. 10703 */ 10704 status = _gl_raw_io(gl, 1); 10705 }; 10706 /* 10707 * Restore the process signal mask. 10708 */ 10709 gl_unmask_signals(gl, &oldset); 10710 return status; 10711 } 10712 10713 /*....................................................................... 10714 * This is the private body of the public function, gl_raw_io(). 10715 * It assumes that the caller has checked its arguments and blocked the 10716 * delivery of signals. 10717 * 10718 * This function is async signal safe. 10719 */ 10720 static int _gl_raw_io(GetLine *gl, int redisplay) 10721 { 10722 /* 10723 * If we are already in the correct mode, do nothing. 10724 */ 10725 if(gl->raw_mode) 10726 return 0; 10727 /* 10728 * Switch the terminal to raw mode. 10729 */ 10730 if(gl->is_term && gl_raw_terminal_mode(gl)) 10731 return 1; 10732 /* 10733 * Switch to non-blocking I/O mode? 10734 */ 10735 if(gl->io_mode==GL_SERVER_MODE && 10736 (gl_nonblocking_io(gl, gl->input_fd) || 10737 gl_nonblocking_io(gl, gl->output_fd) || 10738 (gl->file_fp && gl_nonblocking_io(gl, fileno(gl->file_fp))))) { 10739 if(gl->is_term) 10740 gl_restore_terminal_attributes(gl); 10741 return 1; 10742 }; 10743 /* 10744 * If an input line is being entered, arrange for it to be 10745 * displayed. 10746 */ 10747 if(redisplay) { 10748 gl->postpone = 0; 10749 gl_queue_redisplay(gl); 10750 }; 10751 return 0; 10752 } 10753 10754 /*....................................................................... 10755 * Restore the terminal to the state that it had when 10756 * gl_raw_io() was last called. After calling 10757 * gl_raw_io(), this function must be called before 10758 * terminating or suspending the program, and before attempting other 10759 * uses of the terminal from within the program. See gl_raw_io() 10760 * for more details. 10761 * 10762 * Input: 10763 * gl GetLine * The line editor resource object. 10764 * Output: 10765 * return int 0 - OK. 10766 * 1 - Error. 10767 */ 10768 int gl_normal_io(GetLine *gl) 10769 { 10770 sigset_t oldset; /* The signals that were blocked on entry to this function */ 10771 int status; /* The return status of _gl_normal_io() */ 10772 /* 10773 * Check the arguments. 10774 */ 10775 if(!gl) { 10776 errno = EINVAL; 10777 return 1; 10778 }; 10779 /* 10780 * Block all signals. 10781 */ 10782 if(gl_mask_signals(gl, &oldset)) 10783 return 1; 10784 /* 10785 * Execute the private body of the function while signals are blocked. 10786 */ 10787 status = _gl_normal_io(gl); 10788 /* 10789 * Restore the process signal mask. 10790 */ 10791 gl_unmask_signals(gl, &oldset); 10792 return status; 10793 } 10794 10795 /*....................................................................... 10796 * This is the private body of the public function, gl_normal_io(). 10797 * It assumes that the caller has checked its arguments and blocked the 10798 * delivery of signals. 10799 */ 10800 static int _gl_normal_io(GetLine *gl) 10801 { 10802 /* 10803 * If we are already in normal mode, do nothing. 10804 */ 10805 if(!gl->raw_mode) 10806 return 0; 10807 /* 10808 * Postpone subsequent redisplays until after _gl_raw_io(gl, 1) 10809 * is next called. 10810 */ 10811 gl->postpone = 1; 10812 /* 10813 * Switch back to blocking I/O. Note that this is essential to do 10814 * here, because when using non-blocking I/O, the terminal output 10815 * buffering code can't always make room for new output without calling 10816 * malloc(), and a call to malloc() would mean that this function 10817 * couldn't safely be called from signal handlers. 10818 */ 10819 if(gl->io_mode==GL_SERVER_MODE && 10820 (gl_blocking_io(gl, gl->input_fd) || 10821 gl_blocking_io(gl, gl->output_fd) || 10822 (gl->file_fp && gl_blocking_io(gl, fileno(gl->file_fp))))) 10823 return 1; 10824 /* 10825 * Move the cursor to the next empty terminal line. Note that 10826 * unbuffered I/O is requested, to ensure that gl_start_newline() be 10827 * async-signal-safe. 10828 */ 10829 if(gl->is_term && gl_start_newline(gl, 0)) 10830 return 1; 10831 /* 10832 * Switch the terminal to normal mode. 10833 */ 10834 if(gl->is_term && gl_restore_terminal_attributes(gl)) { 10835 /* 10836 * On error, revert to non-blocking I/O if needed, so that on failure 10837 * we remain in raw mode. 10838 */ 10839 if(gl->io_mode==GL_SERVER_MODE) { 10840 gl_nonblocking_io(gl, gl->input_fd); 10841 gl_nonblocking_io(gl, gl->output_fd); 10842 if(gl->file_fp) 10843 gl_nonblocking_io(gl, fileno(gl->file_fp)); 10844 }; 10845 return 1; 10846 }; 10847 return 0; 10848 } 10849 10850 /*....................................................................... 10851 * This function allows you to install an additional completion 10852 * action, or to change the completion function of an existing 10853 * one. This should be called before the first call to gl_get_line() 10854 * so that the name of the action be defined before the user's 10855 * configuration file is read. 10856 * 10857 * Input: 10858 * gl GetLine * The resource object of the command-line input 10859 * module. 10860 * data void * This is passed to match_fn() whenever it is 10861 * called. It could, for example, point to a 10862 * symbol table that match_fn() would look up 10863 * matches in. 10864 * match_fn CplMatchFn * The function that will identify the prefix 10865 * to be completed from the input line, and 10866 * report matching symbols. 10867 * list_only int If non-zero, install an action that only lists 10868 * possible completions, rather than attempting 10869 * to perform the completion. 10870 * name const char * The name with which users can refer to the 10871 * binding in tecla configuration files. 10872 * keyseq const char * Either NULL, or a key sequence with which 10873 * to invoke the binding. This should be 10874 * specified in the same manner as key-sequences 10875 * in tecla configuration files (eg. "M-^I"). 10876 * Output: 10877 * return int 0 - OK. 10878 * 1 - Error. 10879 */ 10880 int gl_completion_action(GetLine *gl, void *data, CplMatchFn *match_fn, 10881 int list_only, const char *name, const char *keyseq) 10882 { 10883 sigset_t oldset; /* The signals that were blocked on entry to this function */ 10884 int status; /* The return status of _gl_completion_action() */ 10885 /* 10886 * Check the arguments. 10887 */ 10888 if(!gl || !name || !match_fn) { 10889 errno = EINVAL; 10890 return 1; 10891 }; 10892 /* 10893 * Block all signals. 10894 */ 10895 if(gl_mask_signals(gl, &oldset)) 10896 return 1; 10897 /* 10898 * Install the new action while signals are blocked. 10899 */ 10900 status = _gl_completion_action(gl, data, match_fn, list_only, name, keyseq); 10901 /* 10902 * Restore the process signal mask. 10903 */ 10904 gl_unmask_signals(gl, &oldset); 10905 return status; 10906 } 10907 10908 /*....................................................................... 10909 * This is the private body of the public function, gl_completion_action(). 10910 * It assumes that the caller has checked its arguments and blocked the 10911 * delivery of signals. 10912 */ 10913 static int _gl_completion_action(GetLine *gl, void *data, CplMatchFn *match_fn, 10914 int list_only, const char *name, 10915 const char *keyseq) 10916 { 10917 KtKeyFn *current_fn; /* An existing action function */ 10918 void *current_data; /* The action-function callback data */ 10919 /* 10920 * Which action function is desired? 10921 */ 10922 KtKeyFn *action_fn = list_only ? gl_list_completions : gl_complete_word; 10923 /* 10924 * Is there already an action of the specified name? 10925 */ 10926 if(_kt_lookup_action(gl->bindings, name, ¤t_fn, ¤t_data) == 0) { 10927 /* 10928 * If the action has the same type as the one being requested, 10929 * simply change the contents of its GlCplCallback callback data. 10930 */ 10931 if(current_fn == action_fn) { 10932 GlCplCallback *cb = (GlCplCallback *) current_data; 10933 cb->fn = match_fn; 10934 cb->data = data; 10935 } else { 10936 errno = EINVAL; 10937 _err_record_msg(gl->err, 10938 "Illegal attempt to change the type of an existing completion action", 10939 END_ERR_MSG); 10940 return 1; 10941 }; 10942 /* 10943 * No existing action has the specified name. 10944 */ 10945 } else { 10946 /* 10947 * Allocate a new GlCplCallback callback object. 10948 */ 10949 GlCplCallback *cb = (GlCplCallback *) _new_FreeListNode(gl->cpl_mem); 10950 if(!cb) { 10951 errno = ENOMEM; 10952 _err_record_msg(gl->err, "Insufficient memory to add completion action", 10953 END_ERR_MSG); 10954 return 1; 10955 }; 10956 /* 10957 * Record the completion callback data. 10958 */ 10959 cb->fn = match_fn; 10960 cb->data = data; 10961 /* 10962 * Attempt to register the new action. 10963 */ 10964 if(_kt_set_action(gl->bindings, name, action_fn, cb)) { 10965 _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG); 10966 _del_FreeListNode(gl->cpl_mem, (void *) cb); 10967 return 1; 10968 }; 10969 }; 10970 /* 10971 * Bind the action to a given key-sequence? 10972 */ 10973 if(keyseq && _kt_set_keybinding(gl->bindings, KTB_NORM, keyseq, name)) { 10974 _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG); 10975 return 1; 10976 }; 10977 return 0; 10978 } 10979 10980 /*....................................................................... 10981 * Register an application-provided function as an action function. 10982 * This should preferably be called before the first call to gl_get_line() 10983 * so that the name of the action becomes defined before the user's 10984 * configuration file is read. 10985 * 10986 * Input: 10987 * gl GetLine * The resource object of the command-line input 10988 * module. 10989 * data void * Arbitrary application-specific callback 10990 * data to be passed to the callback 10991 * function, fn(). 10992 * fn GlActionFn * The application-specific function that 10993 * implements the action. This will be invoked 10994 * whenever the user presses any 10995 * key-sequence which is bound to this action. 10996 * name const char * The name with which users can refer to the 10997 * binding in tecla configuration files. 10998 * keyseq const char * The key sequence with which to invoke 10999 * the binding. This should be specified in the 11000 * same manner as key-sequences in tecla 11001 * configuration files (eg. "M-^I"). 11002 * Output: 11003 * return int 0 - OK. 11004 * 1 - Error. 11005 */ 11006 int gl_register_action(GetLine *gl, void *data, GlActionFn *fn, 11007 const char *name, const char *keyseq) 11008 { 11009 sigset_t oldset; /* The signals that were blocked on entry to this function */ 11010 int status; /* The return status of _gl_register_action() */ 11011 /* 11012 * Check the arguments. 11013 */ 11014 if(!gl || !name || !fn) { 11015 errno = EINVAL; 11016 return 1; 11017 }; 11018 /* 11019 * Block all signals. 11020 */ 11021 if(gl_mask_signals(gl, &oldset)) 11022 return 1; 11023 /* 11024 * Install the new action while signals are blocked. 11025 */ 11026 status = _gl_register_action(gl, data, fn, name, keyseq); 11027 /* 11028 * Restore the process signal mask. 11029 */ 11030 gl_unmask_signals(gl, &oldset); 11031 return status; 11032 } 11033 11034 /*....................................................................... 11035 * This is the private body of the public function, gl_register_action(). 11036 * It assumes that the caller has checked its arguments and blocked the 11037 * delivery of signals. 11038 */ 11039 static int _gl_register_action(GetLine *gl, void *data, GlActionFn *fn, 11040 const char *name, const char *keyseq) 11041 { 11042 KtKeyFn *current_fn; /* An existing action function */ 11043 void *current_data; /* The action-function callback data */ 11044 /* 11045 * Get the action function which actually runs the application-provided 11046 * function. 11047 */ 11048 KtKeyFn *action_fn = gl_run_external_action; 11049 /* 11050 * Is there already an action of the specified name? 11051 */ 11052 if(_kt_lookup_action(gl->bindings, name, ¤t_fn, ¤t_data) == 0) { 11053 /* 11054 * If the action has the same type as the one being requested, 11055 * simply change the contents of its GlCplCallback callback data. 11056 */ 11057 if(current_fn == action_fn) { 11058 GlExternalAction *a = (GlExternalAction *) current_data; 11059 a->fn = fn; 11060 a->data = data; 11061 } else { 11062 errno = EINVAL; 11063 _err_record_msg(gl->err, 11064 "Illegal attempt to change the type of an existing action", 11065 END_ERR_MSG); 11066 return 1; 11067 }; 11068 /* 11069 * No existing action has the specified name. 11070 */ 11071 } else { 11072 /* 11073 * Allocate a new GlCplCallback callback object. 11074 */ 11075 GlExternalAction *a = 11076 (GlExternalAction *) _new_FreeListNode(gl->ext_act_mem); 11077 if(!a) { 11078 errno = ENOMEM; 11079 _err_record_msg(gl->err, "Insufficient memory to add completion action", 11080 END_ERR_MSG); 11081 return 1; 11082 }; 11083 /* 11084 * Record the completion callback data. 11085 */ 11086 a->fn = fn; 11087 a->data = data; 11088 /* 11089 * Attempt to register the new action. 11090 */ 11091 if(_kt_set_action(gl->bindings, name, action_fn, a)) { 11092 _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG); 11093 _del_FreeListNode(gl->cpl_mem, (void *) a); 11094 return 1; 11095 }; 11096 }; 11097 /* 11098 * Bind the action to a given key-sequence? 11099 */ 11100 if(keyseq && _kt_set_keybinding(gl->bindings, KTB_NORM, keyseq, name)) { 11101 _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG); 11102 return 1; 11103 }; 11104 return 0; 11105 } 11106 11107 /*....................................................................... 11108 * Invoke an action function previously registered by a call to 11109 * gl_register_action(). 11110 */ 11111 static KT_KEY_FN(gl_run_external_action) 11112 { 11113 GlAfterAction status; /* The return value of the action function */ 11114 /* 11115 * Get the container of the action function and associated callback data. 11116 */ 11117 GlExternalAction *a = (GlExternalAction *) data; 11118 /* 11119 * Invoke the action function. 11120 */ 11121 status = a->fn(gl, a->data, count, gl->buff_curpos, gl->line); 11122 /* 11123 * If the callback took us out of raw (possibly non-blocking) input 11124 * mode, restore this mode, and queue a redisplay of the input line. 11125 */ 11126 if(_gl_raw_io(gl, 1)) 11127 return 1; 11128 /* 11129 * Finally, check to see what the action function wants us to do next. 11130 */ 11131 switch(status) { 11132 default: 11133 case GLA_ABORT: 11134 gl_record_status(gl, GLR_ERROR, errno); 11135 return 1; 11136 break; 11137 case GLA_RETURN: 11138 return gl_newline(gl, 1, NULL); 11139 break; 11140 case GLA_CONTINUE: 11141 break; 11142 }; 11143 return 0; 11144 } 11145 11146 /*....................................................................... 11147 * In server-I/O mode the terminal is left in raw mode between calls 11148 * to gl_get_line(), so it is necessary for the application to install 11149 * terminal restoring signal handlers for signals that could terminate 11150 * or suspend the process, plus a terminal reconfiguration handler to 11151 * be called when a process resumption signal is received, and finally 11152 * a handler to be called when a terminal-resize signal is received. 11153 * 11154 * Since there are many signals that by default terminate or suspend 11155 * processes, and different systems support different sub-sets of 11156 * these signals, this function provides a convenient wrapper around 11157 * sigaction() for assigning the specified handlers to all appropriate 11158 * signals. It also arranges that when any one of these signals is 11159 * being handled, all other catchable signals are blocked. This is 11160 * necessary so that the specified signal handlers can safely call 11161 * gl_raw_io(), gl_normal_io() and gl_update_size() without 11162 * reentrancy issues. 11163 * 11164 * Input: 11165 * term_handler void (*)(int) The signal handler to invoke when 11166 * a process terminating signal is 11167 * received. 11168 * susp_handler void (*)(int) The signal handler to invoke when 11169 * a process suspending signal is 11170 * received. 11171 * cont_handler void (*)(int) The signal handler to invoke when 11172 * a process resumption signal is 11173 * received (ie. SIGCONT). 11174 * size_handler void (*)(int) The signal handler to invoke when 11175 * a terminal-resize signal (ie. SIGWINCH) 11176 * is received. 11177 * Output: 11178 * return int 0 - OK. 11179 * 1 - Error. 11180 */ 11181 int gl_tty_signals(void (*term_handler)(int), void (*susp_handler)(int), 11182 void (*cont_handler)(int), void (*size_handler)(int)) 11183 { 11184 int i; 11185 /* 11186 * Search for signals of the specified classes, and assign the 11187 * associated signal handler to them. 11188 */ 11189 for(i=0; i<sizeof(gl_signal_list)/sizeof(gl_signal_list[0]); i++) { 11190 const struct GlDefSignal *sig = gl_signal_list + i; 11191 if(sig->attr & GLSA_SUSP) { 11192 if(gl_set_tty_signal(sig->signo, term_handler)) 11193 return 1; 11194 } else if(sig->attr & GLSA_TERM) { 11195 if(gl_set_tty_signal(sig->signo, susp_handler)) 11196 return 1; 11197 } else if(sig->attr & GLSA_CONT) { 11198 if(gl_set_tty_signal(sig->signo, cont_handler)) 11199 return 1; 11200 } else if(sig->attr & GLSA_SIZE) { 11201 if(gl_set_tty_signal(sig->signo, size_handler)) 11202 return 1; 11203 }; 11204 }; 11205 return 0; 11206 } 11207 11208 /*....................................................................... 11209 * This is a private function of gl_tty_signals(). It installs a given 11210 * signal handler, and arranges that when that signal handler is being 11211 * invoked other signals are blocked. The latter is important to allow 11212 * functions like gl_normal_io(), gl_raw_io() and gl_update_size() 11213 * to be called from signal handlers. 11214 * 11215 * Input: 11216 * signo int The signal to be trapped. 11217 * handler void (*)(int) The signal handler to assign to the signal. 11218 */ 11219 static int gl_set_tty_signal(int signo, void (*handler)(int)) 11220 { 11221 SigAction act; /* The signal handler configuation */ 11222 /* 11223 * Arrange to block all trappable signals except the one that is being 11224 * assigned (the trapped signal will be blocked automatically by the 11225 * system). 11226 */ 11227 gl_list_trappable_signals(&act.sa_mask); 11228 sigdelset(&act.sa_mask, signo); 11229 /* 11230 * Assign the signal handler. 11231 */ 11232 act.sa_handler = handler; 11233 /* 11234 * There is only one portable signal handling flag, and it isn't 11235 * relevant to us, so don't specify any flags. 11236 */ 11237 act.sa_flags = 0; 11238 /* 11239 * Register the signal handler. 11240 */ 11241 if(sigaction(signo, &act, NULL)) 11242 return 1; 11243 return 0; 11244 } 11245 11246 /*....................................................................... 11247 * Display a left-justified string over multiple terminal lines, 11248 * taking account of the current width of the terminal. Optional 11249 * indentation and an optional prefix string can be specified to be 11250 * displayed at the start of each new terminal line used. Similarly, 11251 * an optional suffix can be specified to be displayed at the end of 11252 * each terminal line. If needed, a single paragraph can be broken 11253 * across multiple calls. Note that literal newlines in the input 11254 * string can be used to force a newline at any point and that you 11255 * should use this feature to explicitly end all paragraphs, including 11256 * at the end of the last string that you write. Note that when a new 11257 * line is started between two words that are separated by spaces, 11258 * those spaces are not output, whereas when a new line is started 11259 * because a newline character was found in the string, only the 11260 * spaces before the newline character are discarded. 11261 * 11262 * Input: 11263 * gl GetLine * The resource object of gl_get_line(). 11264 * indentation int The number of spaces of indentation to write 11265 * at the beginning of each new terminal line. 11266 * prefix const char * An optional prefix string to write after the 11267 * indentation margin at the start of each new 11268 * terminal line. You can specify NULL if no 11269 * prefix is required. 11270 * suffix const char * An optional suffix string to draw at the end 11271 * of the terminal line. Spaces will be added 11272 * where necessary to ensure that the suffix ends 11273 * in the last column of the terminal line. If 11274 * no suffix is desired, specify NULL. 11275 * fill_char int The padding character to use when indenting 11276 * the line or padding up to the suffix. 11277 * def_width int If the terminal width isn't known, such as when 11278 * writing to a pipe or redirecting to a file, 11279 * this number specifies what width to assume. 11280 * start int The number of characters already written to 11281 * the start of the current terminal line. This 11282 * is primarily used to allow individual 11283 * paragraphs to be written over multiple calls 11284 * to this function, but can also be used to 11285 * allow you to start the first line of a 11286 * paragraph with a different prefix or 11287 * indentation than those specified above. 11288 * string const char * The string to be written. 11289 * Output: 11290 * return int On error -1 is returned. Otherwise the 11291 * return value is the terminal column index at 11292 * which the cursor was left after writing the 11293 * final word in the string. Successful return 11294 * values can thus be passed verbatim to the 11295 * 'start' arguments of subsequent calls to 11296 * gl_display_text() to allow the printing of a 11297 * paragraph to be broken across multiple calls 11298 * to gl_display_text(). 11299 */ 11300 int gl_display_text(GetLine *gl, int indentation, const char *prefix, 11301 const char *suffix, int fill_char, 11302 int def_width, int start, const char *string) 11303 { 11304 sigset_t oldset; /* The signals that were blocked on entry to this function */ 11305 int status; /* The return status of _gl_completion_action() */ 11306 /* 11307 * Check the arguments? 11308 */ 11309 if(!gl || !string) { 11310 errno = EINVAL; 11311 return -1; 11312 }; 11313 /* 11314 * Block all signals. 11315 */ 11316 if(gl_mask_signals(gl, &oldset)) 11317 return -1; 11318 /* 11319 * Display the text while signals are blocked. 11320 */ 11321 status = _io_display_text(_io_write_stdio, gl->output_fp, indentation, 11322 prefix, suffix, fill_char, 11323 gl->ncolumn > 0 ? gl->ncolumn : def_width, 11324 start, string); 11325 /* 11326 * Restore the process signal mask. 11327 */ 11328 gl_unmask_signals(gl, &oldset); 11329 return status; 11330 } 11331 11332 /*....................................................................... 11333 * Block all of the signals that we are currently trapping. 11334 * 11335 * Input: 11336 * gl GetLine * The resource object of gl_get_line(). 11337 * Input/Output: 11338 * oldset sigset_t * The superseded process signal mask 11339 * will be return in *oldset unless oldset is 11340 * NULL. 11341 * Output: 11342 * return int 0 - OK. 11343 * 1 - Error. 11344 */ 11345 static int gl_mask_signals(GetLine *gl, sigset_t *oldset) 11346 { 11347 /* 11348 * Block all signals in all_signal_set, along with any others that are 11349 * already blocked by the application. 11350 */ 11351 if(sigprocmask(SIG_BLOCK, &gl->all_signal_set, oldset) >= 0) { 11352 gl->signals_masked = 1; 11353 return 0; 11354 }; 11355 /* 11356 * On error attempt to query the current process signal mask, so 11357 * that oldset be the correct process signal mask to restore later 11358 * if the caller of this function ignores the error return value. 11359 */ 11360 if(oldset) 11361 (void) sigprocmask(SIG_SETMASK, NULL, oldset); 11362 gl->signals_masked = 0; 11363 return 1; 11364 } 11365 11366 /*....................................................................... 11367 * Restore a process signal mask that was previously returned via the 11368 * oldset argument of gl_mask_signals(). 11369 * 11370 * Input: 11371 * gl GetLine * The resource object of gl_get_line(). 11372 * Input/Output: 11373 * oldset sigset_t * The process signal mask to be restored. 11374 * Output: 11375 * return int 0 - OK. 11376 * 1 - Error. 11377 */ 11378 static int gl_unmask_signals(GetLine *gl, sigset_t *oldset) 11379 { 11380 gl->signals_masked = 0; 11381 return sigprocmask(SIG_SETMASK, oldset, NULL) < 0; 11382 } 11383 11384 /*....................................................................... 11385 * Arrange to temporarily catch the signals marked in gl->use_signal_set. 11386 * 11387 * Input: 11388 * gl GetLine * The resource object of gl_get_line(). 11389 * Output: 11390 * return int 0 - OK. 11391 * 1 - Error. 11392 */ 11393 static int gl_catch_signals(GetLine *gl) 11394 { 11395 return sigprocmask(SIG_UNBLOCK, &gl->use_signal_set, NULL) < 0; 11396 } 11397 11398 /*....................................................................... 11399 * Select the I/O mode to be used by gl_get_line(). 11400 * 11401 * Input: 11402 * gl GetLine * The resource object of gl_get_line(). 11403 * mode GlIOMode The I/O mode to establish. 11404 * Output: 11405 * return int 0 - OK. 11406 * 1 - Error. 11407 */ 11408 int gl_io_mode(GetLine *gl, GlIOMode mode) 11409 { 11410 sigset_t oldset; /* The signals that were blocked on entry to this function */ 11411 int status; /* The return status of _gl_io_mode() */ 11412 /* 11413 * Check the arguments. 11414 */ 11415 if(!gl) { 11416 errno = EINVAL; 11417 return 1; 11418 }; 11419 /* 11420 * Check that the requested mode is known. 11421 */ 11422 switch(mode) { 11423 case GL_NORMAL_MODE: 11424 case GL_SERVER_MODE: 11425 break; 11426 default: 11427 errno = EINVAL; 11428 _err_record_msg(gl->err, "Unknown gl_get_line() I/O mode requested.", 11429 END_ERR_MSG); 11430 return 1; 11431 }; 11432 /* 11433 * Block all signals. 11434 */ 11435 if(gl_mask_signals(gl, &oldset)) 11436 return 1; 11437 /* 11438 * Invoke the private body of this function. 11439 */ 11440 status = _gl_io_mode(gl, mode); 11441 /* 11442 * Restore the process signal mask. 11443 */ 11444 gl_unmask_signals(gl, &oldset); 11445 return status; 11446 } 11447 11448 /*....................................................................... 11449 * This is the private body of the public function, gl_io_mode(). 11450 * It assumes that the caller has checked its arguments and blocked the 11451 * delivery of signals. 11452 */ 11453 static int _gl_io_mode(GetLine *gl, GlIOMode mode) 11454 { 11455 /* 11456 * Are we already in the specified mode? 11457 */ 11458 if(mode == gl->io_mode) 11459 return 0; 11460 /* 11461 * First revert to normal I/O in the current I/O mode. 11462 */ 11463 _gl_normal_io(gl); 11464 /* 11465 * Record the new mode. 11466 */ 11467 gl->io_mode = mode; 11468 /* 11469 * Perform any actions needed by the new mode. 11470 */ 11471 if(mode==GL_SERVER_MODE) { 11472 if(_gl_raw_io(gl, 1)) 11473 return 1; 11474 }; 11475 return 0; 11476 } 11477 11478 /*....................................................................... 11479 * Return extra information (ie. in addition to that provided by errno) 11480 * about the last error to occur in either gl_get_line() or its 11481 * associated public functions. 11482 * 11483 * Input: 11484 * gl GetLine * The resource object of gl_get_line(). 11485 * Input/Output: 11486 * buff char * An optional output buffer. Note that if the 11487 * calling application calls any gl_*() 11488 * functions from signal handlers, it should 11489 * provide a buffer here, so that a copy of 11490 * the latest error message can safely be made 11491 * while signals are blocked. 11492 * n size_t The allocated size of buff[]. 11493 * Output: 11494 * return const char * A pointer to the error message. This will 11495 * be the buff argument, unless buff==NULL, in 11496 * which case it will be a pointer to an 11497 * internal error buffer. In the latter case, 11498 * note that the contents of the returned buffer 11499 * will change on subsequent calls to any gl_*() 11500 * functions. 11501 */ 11502 const char *gl_error_message(GetLine *gl, char *buff, size_t n) 11503 { 11504 if(!gl) { 11505 static const char *msg = "NULL GetLine argument"; 11506 if(buff) { 11507 strncpy(buff, msg, n); 11508 buff[n-1] = '\0'; 11509 } else { 11510 return msg; 11511 }; 11512 } else if(buff) { 11513 sigset_t oldset; /* The signals that were blocked on entry to this block */ 11514 /* 11515 * Temporarily block all signals. 11516 */ 11517 gl_mask_signals(gl, &oldset); 11518 /* 11519 * Copy the error message into the specified buffer. 11520 */ 11521 if(buff && n > 0) { 11522 strncpy(buff, _err_get_msg(gl->err), n); 11523 buff[n-1] = '\0'; 11524 }; 11525 /* 11526 * Restore the process signal mask before returning. 11527 */ 11528 gl_unmask_signals(gl, &oldset); 11529 } else { 11530 return _err_get_msg(gl->err); 11531 }; 11532 return buff; 11533 } 11534 11535 /*....................................................................... 11536 * Return the signal mask used by gl_get_line(). This is the set of 11537 * signals that gl_get_line() is currently configured to trap. 11538 * 11539 * Input: 11540 * gl GetLine * The resource object of gl_get_line(). 11541 * Input/Output: 11542 * set sigset_t * The set of signals will be returned in *set, 11543 * in the form of a signal process mask, as 11544 * used by sigaction(), sigprocmask(), 11545 * sigpending(), sigsuspend(), sigsetjmp() and 11546 * other standard POSIX signal-aware 11547 * functions. 11548 * Output: 11549 * return int 0 - OK. 11550 * 1 - Error (examine errno for reason). 11551 */ 11552 int gl_list_signals(GetLine *gl, sigset_t *set) 11553 { 11554 /* 11555 * Check the arguments. 11556 */ 11557 if(!gl || !set) { 11558 if(gl) 11559 _err_record_msg(gl->err, "NULL argument(s)", END_ERR_MSG); 11560 errno = EINVAL; 11561 return 1; 11562 }; 11563 /* 11564 * Copy the signal mask into *set. 11565 */ 11566 memcpy(set, &gl->all_signal_set, sizeof(*set)); 11567 return 0; 11568 } 11569 11570 /*....................................................................... 11571 * By default, gl_get_line() doesn't trap signals that are blocked 11572 * when it is called. This default can be changed either on a 11573 * per-signal basis by calling gl_trap_signal(), or on a global basis 11574 * by calling this function. What this function does is add the 11575 * GLS_UNBLOCK_SIG flag to all signals that are currently configured 11576 * to be trapped by gl_get_line(), such that when subsequent calls to 11577 * gl_get_line() wait for I/O, these signals are temporarily 11578 * unblocked. This behavior is useful in non-blocking server-I/O mode, 11579 * where it is used to avoid race conditions related to handling these 11580 * signals externally to gl_get_line(). See the demonstration code in 11581 * demo3.c, or the gl_handle_signal() man page for further 11582 * information. 11583 * 11584 * Input: 11585 * gl GetLine * The resource object of gl_get_line(). 11586 */ 11587 void gl_catch_blocked(GetLine *gl) 11588 { 11589 sigset_t oldset; /* The process signal mask to restore */ 11590 GlSignalNode *sig; /* A signal node in gl->sigs */ 11591 /* 11592 * Check the arguments. 11593 */ 11594 if(!gl) { 11595 errno = EINVAL; 11596 return; 11597 }; 11598 /* 11599 * Temporarily block all signals while we modify the contents of gl. 11600 */ 11601 gl_mask_signals(gl, &oldset); 11602 /* 11603 * Add the GLS_UNBLOCK_SIG flag to all configured signals. 11604 */ 11605 for(sig=gl->sigs; sig; sig=sig->next) 11606 sig->flags |= GLS_UNBLOCK_SIG; 11607 /* 11608 * Restore the process signal mask that was superseded by the call 11609 * to gl_mask_signals(). 11610 */ 11611 gl_unmask_signals(gl, &oldset); 11612 return; 11613 } 11614 11615 /*....................................................................... 11616 * Respond to signals who's default effects have important 11617 * consequences to gl_get_line(). This is intended for use in 11618 * non-blocking server mode, where the external event loop is 11619 * responsible for catching signals. Signals that are handled include 11620 * those that by default terminate or suspend the process, and the 11621 * signal that indicates that the terminal size has changed. Note that 11622 * this function is not signal safe and should thus not be called from 11623 * a signal handler itself. See the gl_io_mode() man page for how it 11624 * should be used. 11625 * 11626 * In the case of signals that by default terminate or suspend 11627 * processes, command-line editing will be suspended, the terminal 11628 * returned to a usable state, then the default disposition of the 11629 * signal restored and the signal resent, in order to suspend or 11630 * terminate the process. If the process subsequently resumes, 11631 * command-line editing is resumed. 11632 * 11633 * In the case of signals that indicate that the terminal has been 11634 * resized, the new size will be queried, and any input line that is 11635 * being edited will be redrawn to fit the new dimensions of the 11636 * terminal. 11637 * 11638 * Input: 11639 * signo int The number of the signal to respond to. 11640 * gl GetLine * The first element of an array of 'ngl' GetLine 11641 * objects. 11642 * ngl int The number of elements in the gl[] array. Normally 11643 * this will be one. 11644 */ 11645 void gl_handle_signal(int signo, GetLine *gl, int ngl) 11646 { 11647 int attr; /* The attributes of the specified signal */ 11648 sigset_t all_signals; /* The set of trappable signals */ 11649 sigset_t oldset; /* The process signal mask to restore */ 11650 int i; 11651 /* 11652 * NULL operation? 11653 */ 11654 if(ngl < 1 || !gl) 11655 return; 11656 /* 11657 * Look up the default attributes of the specified signal. 11658 */ 11659 attr = gl_classify_signal(signo); 11660 /* 11661 * If the signal isn't known, we are done. 11662 */ 11663 if(!attr) 11664 return; 11665 /* 11666 * Temporarily block all signals while we modify the gl objects. 11667 */ 11668 gl_list_trappable_signals(&all_signals); 11669 sigprocmask(SIG_BLOCK, &all_signals, &oldset); 11670 /* 11671 * Suspend or terminate the process? 11672 */ 11673 if(attr & (GLSA_SUSP | GLSA_TERM)) { 11674 gl_suspend_process(signo, gl, ngl); 11675 /* 11676 * Resize the terminal? Note that ioctl() isn't defined as being 11677 * signal safe, so we can't call gl_update_size() here. However, 11678 * gl_get_line() checks for resizes on each call, so simply arrange 11679 * for the application's event loop to call gl_get_line() as soon as 11680 * it becomes possible to write to the terminal. Note that if the 11681 * caller is calling select() or poll when this happens, these functions 11682 * get interrupted, since a signal has been caught. 11683 */ 11684 } else if(attr & GLSA_SIZE) { 11685 for(i=0; i<ngl; i++) 11686 gl[i].pending_io = GLP_WRITE; 11687 }; 11688 /* 11689 * Restore the process signal mask that was superseded by the call 11690 * to gl_mask_signals(). 11691 */ 11692 sigprocmask(SIG_SETMASK, &oldset, NULL); 11693 return; 11694 } 11695 11696 /*....................................................................... 11697 * Respond to an externally caught process suspension or 11698 * termination signal. 11699 * 11700 * After restoring the terminal to a usable state, suspend or 11701 * terminate the calling process, using the original signal with its 11702 * default disposition restored to do so. If the process subsequently 11703 * resumes, resume editing any input lines that were being entered. 11704 * 11705 * Input: 11706 * signo int The signal number to suspend the process with. Note 11707 * that the default disposition of this signal will be 11708 * restored before the signal is sent, so provided 11709 * that the default disposition of this signal is to 11710 * either suspend or terminate the application, 11711 * that is what wil happen, regardless of what signal 11712 * handler is currently assigned to this signal. 11713 * gl GetLine * The first element of an array of 'ngl' GetLine objects 11714 * whose terminals should be restored to a sane state 11715 * while the application is suspended. 11716 * ngl int The number of elements in the gl[] array. 11717 */ 11718 static void gl_suspend_process(int signo, GetLine *gl, int ngl) 11719 { 11720 sigset_t only_signo; /* A signal set containing just signo */ 11721 sigset_t oldset; /* The signal mask on entry to this function */ 11722 sigset_t all_signals; /* A signal set containing all signals */ 11723 struct sigaction old_action; /* The current signal handler */ 11724 struct sigaction def_action; /* The default signal handler */ 11725 int i; 11726 /* 11727 * Create a signal mask containing the signal that was trapped. 11728 */ 11729 sigemptyset(&only_signo); 11730 sigaddset(&only_signo, signo); 11731 /* 11732 * Temporarily block all signals. 11733 */ 11734 gl_list_trappable_signals(&all_signals); 11735 sigprocmask(SIG_BLOCK, &all_signals, &oldset); 11736 /* 11737 * Restore the terminal to a usable state. 11738 */ 11739 for(i=0; i<ngl; i++) { 11740 GetLine *obj = gl + i; 11741 if(obj->raw_mode) { 11742 _gl_normal_io(obj); 11743 if(!obj->raw_mode) /* Check that gl_normal_io() succeded */ 11744 obj->raw_mode = -1; /* Flag raw mode as needing to be restored */ 11745 }; 11746 }; 11747 /* 11748 * Restore the system default disposition of the signal that we 11749 * caught. Note that this signal is currently blocked. Note that we 11750 * don't use memcpy() to copy signal sets here, because the signal safety 11751 * of memcpy() is undefined. 11752 */ 11753 def_action.sa_handler = SIG_DFL; 11754 { 11755 char *orig = (char *) &all_signals; 11756 char *dest = (char *) &def_action.sa_mask; 11757 for(i=0; i<sizeof(sigset_t); i++) 11758 *dest++ = *orig++; 11759 }; 11760 sigaction(signo, &def_action, &old_action); 11761 /* 11762 * Resend the signal, and unblock it so that it gets delivered to 11763 * the application. This will invoke the default action of this signal. 11764 */ 11765 raise(signo); 11766 sigprocmask(SIG_UNBLOCK, &only_signo, NULL); 11767 /* 11768 * If the process resumes again, it will resume here. 11769 * Block the signal again, then restore our signal handler. 11770 */ 11771 sigprocmask(SIG_BLOCK, &only_signo, NULL); 11772 sigaction(signo, &old_action, NULL); 11773 /* 11774 * Resume command-line editing. 11775 */ 11776 for(i=0; i<ngl; i++) { 11777 GetLine *obj = gl + i; 11778 if(obj->raw_mode == -1) { /* Did we flag the need to restore raw mode? */ 11779 obj->raw_mode = 0; /* gl_raw_io() does nothing unless raw_mode==0 */ 11780 _gl_raw_io(obj, 1); 11781 }; 11782 }; 11783 /* 11784 * Restore the process signal mask to the way it was when this function 11785 * was called. 11786 */ 11787 sigprocmask(SIG_SETMASK, &oldset, NULL); 11788 return; 11789 } 11790 11791 /*....................................................................... 11792 * Return the information about the default attributes of a given signal. 11793 * The attributes that are returned are as defined by the standards that 11794 * created them, including POSIX, SVR4 and 4.3+BSD, and are taken from a 11795 * table in Richard Steven's book, "Advanced programming in the UNIX 11796 * environment". 11797 * 11798 * Input: 11799 * signo int The signal to be characterized. 11800 * Output: 11801 * return int A bitwise union of GlSigAttr enumerators, or 0 11802 * if the signal isn't known. 11803 */ 11804 static int gl_classify_signal(int signo) 11805 { 11806 int i; 11807 /* 11808 * Search for the specified signal in the gl_signal_list[] table. 11809 */ 11810 for(i=0; i<sizeof(gl_signal_list)/sizeof(gl_signal_list[0]); i++) { 11811 const struct GlDefSignal *sig = gl_signal_list + i; 11812 if(sig->signo == signo) 11813 return sig->attr; 11814 }; 11815 /* 11816 * Signal not known. 11817 */ 11818 return 0; 11819 } 11820 11821 /*....................................................................... 11822 * When in non-blocking server mode, this function can be used to abandon 11823 * the current incompletely entered input line, and prepare to start 11824 * editing a new line on the next call to gl_get_line(). 11825 * 11826 * Input: 11827 * gl GetLine * The line editor resource object. 11828 */ 11829 void gl_abandon_line(GetLine *gl) 11830 { 11831 sigset_t oldset; /* The process signal mask to restore */ 11832 /* 11833 * Check the arguments. 11834 */ 11835 if(!gl) { 11836 errno = EINVAL; 11837 return; 11838 }; 11839 /* 11840 * Temporarily block all signals while we modify the contents of gl. 11841 */ 11842 gl_mask_signals(gl, &oldset); 11843 /* 11844 * Mark the input line as discarded. 11845 */ 11846 _gl_abandon_line(gl); 11847 /* 11848 * Restore the process signal mask that was superseded by the call 11849 * to gl_mask_signals(). 11850 */ 11851 gl_unmask_signals(gl, &oldset); 11852 return; 11853 } 11854 11855 /*....................................................................... 11856 * This is the private body of the gl_abandon_line() function. It 11857 * assumes that the caller has checked its arguments and blocked the 11858 * delivery of signals. 11859 */ 11860 void _gl_abandon_line(GetLine *gl) 11861 { 11862 gl->endline = 1; 11863 gl->pending_io = GLP_WRITE; 11864 } 11865 11866 /*....................................................................... 11867 * How many characters are needed to write a number as an octal string? 11868 * 11869 * Input: 11870 * num unsigned The to be measured. 11871 * Output: 11872 * return int The number of characters needed. 11873 */ 11874 static int gl_octal_width(unsigned num) 11875 { 11876 int n; /* The number of characters needed to render the number */ 11877 for(n=1; num /= 8; n++) 11878 ; 11879 return n; 11880 } 11881 11882 /*....................................................................... 11883 * Tell gl_get_line() the current terminal size. Note that this is only 11884 * necessary on systems where changes in terminal size aren't reported 11885 * via SIGWINCH. 11886 * 11887 * Input: 11888 * gl GetLine * The resource object of gl_get_line(). 11889 * ncolumn int The number of columns in the terminal. 11890 * nline int The number of lines in the terminal. 11891 * Output: 11892 * return int 0 - OK. 11893 * 1 - Error. 11894 */ 11895 int gl_set_term_size(GetLine *gl, int ncolumn, int nline) 11896 { 11897 sigset_t oldset; /* The signals that were blocked on entry */ 11898 /* to this function */ 11899 int status; /* The return status */ 11900 /* 11901 * Block all signals while accessing gl. 11902 */ 11903 gl_mask_signals(gl, &oldset); 11904 /* 11905 * Install the new terminal size. 11906 */ 11907 status = _gl_set_term_size(gl, ncolumn, nline); 11908 /* 11909 * Restore the process signal mask before returning. 11910 */ 11911 gl_unmask_signals(gl, &oldset); 11912 return status; 11913 } 11914 11915 /*....................................................................... 11916 * This is the private body of the gl_set_term_size() function. It 11917 * assumes that the caller has checked its arguments and blocked the 11918 * delivery of signals. 11919 */ 11920 static int _gl_set_term_size(GetLine *gl, int ncolumn, int nline) 11921 { 11922 /* 11923 * Check the arguments. 11924 */ 11925 if(!gl) { 11926 errno = EINVAL; 11927 return 1; 11928 }; 11929 /* 11930 * Reject non-sensical dimensions. 11931 */ 11932 if(ncolumn <= 0 || nline <= 0) { 11933 _err_record_msg(gl->err, "Invalid terminal size", END_ERR_MSG); 11934 errno = EINVAL; 11935 return 1; 11936 }; 11937 /* 11938 * Install the new dimensions in the terminal driver if possible, so 11939 * that future calls to gl_query_size() get the new value. 11940 */ 11941 #ifdef TIOCSWINSZ 11942 if(gl->is_term) { 11943 struct winsize size; 11944 size.ws_row = nline; 11945 size.ws_col = ncolumn; 11946 size.ws_xpixel = 0; 11947 size.ws_ypixel = 0; 11948 if(ioctl(gl->output_fd, TIOCSWINSZ, &size) == -1) { 11949 _err_record_msg(gl->err, "Can't change terminal size", END_ERR_MSG); 11950 return 1; 11951 }; 11952 }; 11953 #endif 11954 /* 11955 * If an input line is in the process of being edited, redisplay it to 11956 * accomodate the new dimensions, and record the new dimensions in 11957 * gl->nline and gl->ncolumn. 11958 */ 11959 return gl_handle_tty_resize(gl, ncolumn, nline); 11960 } 11961 11962 /*....................................................................... 11963 * Record a character in the input line buffer at a given position. 11964 * 11965 * Input: 11966 * gl GetLine * The resource object of gl_get_line(). 11967 * c char The character to be recorded. 11968 * bufpos int The index in the buffer at which to record the 11969 * character. 11970 * Output: 11971 * return int 0 - OK. 11972 * 1 - Insufficient room. 11973 */ 11974 static int gl_buffer_char(GetLine *gl, char c, int bufpos) 11975 { 11976 /* 11977 * Guard against buffer overruns. 11978 */ 11979 if(bufpos >= gl->linelen) 11980 return 1; 11981 /* 11982 * Record the new character. 11983 */ 11984 gl->line[bufpos] = c; 11985 /* 11986 * If the new character was placed beyond the end of the current input 11987 * line, update gl->ntotal to reflect the increased number of characters 11988 * that are in gl->line, and terminate the string. 11989 */ 11990 if(bufpos >= gl->ntotal) { 11991 gl->ntotal = bufpos+1; 11992 gl->line[gl->ntotal] = '\0'; 11993 }; 11994 return 0; 11995 } 11996 11997 /*....................................................................... 11998 * Copy a given string into the input buffer, overwriting the current 11999 * contents. 12000 * 12001 * Input: 12002 * gl GetLine * The resource object of gl_get_line(). 12003 * s const char * The string to be recorded. 12004 * n int The number of characters to be copied from the 12005 * string. 12006 * bufpos int The index in the buffer at which to place the 12007 * the first character of the string. 12008 * Output: 12009 * return int 0 - OK. 12010 * 1 - String truncated to fit. 12011 */ 12012 static int gl_buffer_string(GetLine *gl, const char *s, int n, int bufpos) 12013 { 12014 int nnew; /* The number of characters actually recorded */ 12015 int i; 12016 /* 12017 * How many of the characters will fit within the buffer? 12018 */ 12019 nnew = bufpos + n <= gl->linelen ? n : (gl->linelen - bufpos); 12020 /* 12021 * Record the first nnew characters of s[] in the buffer. 12022 */ 12023 for(i=0; i<nnew; i++) 12024 gl_buffer_char(gl, s[i], bufpos + i); 12025 /* 12026 * Was the string truncated? 12027 */ 12028 return nnew < n; 12029 } 12030 12031 /*....................................................................... 12032 * Make room in the input buffer for a string to be inserted. This 12033 * involves moving the characters that follow a specified point, towards 12034 * the end of the buffer. 12035 * 12036 * Input: 12037 * gl GetLine * The resource object of gl_get_line(). 12038 * start int The index of the first character to be moved. 12039 * n int The width of the gap. 12040 * Output: 12041 * return int 0 - OK. 12042 * 1 - Insufficient room. 12043 */ 12044 static int gl_make_gap_in_buffer(GetLine *gl, int start, int n) 12045 { 12046 /* 12047 * Ensure that the buffer has sufficient space. 12048 */ 12049 if(gl->ntotal + n > gl->linelen) 12050 return 1; 12051 /* 12052 * Move everything including and beyond the character at 'start' 12053 * towards the end of the string. 12054 */ 12055 memmove(gl->line + start + n, gl->line + start, gl->ntotal - start + 1); 12056 /* 12057 * Update the recorded size of the line. 12058 */ 12059 gl->ntotal += n; 12060 return 1; 12061 } 12062 12063 /*....................................................................... 12064 * Remove a given number of characters from the input buffer. This 12065 * involves moving the characters that follow the removed characters to 12066 * where the removed sub-string started in the input buffer. 12067 * 12068 * Input: 12069 * gl GetLine * The resource object of gl_get_line(). 12070 * start int The first character to be removed. 12071 * n int The number of characters to remove. 12072 */ 12073 static void gl_remove_from_buffer(GetLine *gl, int start, int n) 12074 { 12075 memmove(gl->line + start, gl->line + start + n, gl->ntotal - start - n + 1); 12076 /* 12077 * Update the recorded size of the line. 12078 */ 12079 gl->ntotal -= n; 12080 } 12081 12082 /*....................................................................... 12083 * Truncate the string in the input line buffer after a given number of 12084 * characters. 12085 * 12086 * Input: 12087 * gl GetLine * The resource object of gl_get_line(). 12088 * n int The new length of the line. 12089 * Output: 12090 * return int 0 - OK. 12091 * 1 - n > gl->linelen. 12092 */ 12093 static int gl_truncate_buffer(GetLine *gl, int n) 12094 { 12095 if(n > gl->linelen) 12096 return 1; 12097 gl->line[n] = '\0'; 12098 gl->ntotal = n; 12099 return 0; 12100 } 12101 12102 /*....................................................................... 12103 * When the contents of gl->line[] are changed without calling any of the 12104 * gl_ buffer manipulation functions, this function must be called to 12105 * compute the length of this string, and ancillary information. 12106 * 12107 * Input: 12108 * gl GetLine * The resource object of gl_get_line(). 12109 */ 12110 static void gl_update_buffer(GetLine *gl) 12111 { 12112 int len; /* The length of the line */ 12113 /* 12114 * Measure the length of the input line. 12115 */ 12116 for(len=0; len <= gl->linelen && gl->line[len]; len++) 12117 ; 12118 /* 12119 * Just in case the string wasn't correctly terminated, do so here. 12120 */ 12121 gl->line[len] = '\0'; 12122 /* 12123 * Record the number of characters that are now in gl->line[]. 12124 */ 12125 gl->ntotal = len; 12126 /* 12127 * Ensure that the cursor stays within the bounds of the modified 12128 * input line. 12129 */ 12130 if(gl->buff_curpos > gl->ntotal) 12131 gl->buff_curpos = gl->ntotal; 12132 /* 12133 * Arrange for the input line to be redrawn. 12134 */ 12135 gl_queue_redisplay(gl); 12136 return; 12137 } 12138 12139 /*....................................................................... 12140 * Erase the displayed input line, including its prompt, and leave the 12141 * cursor where the erased line started. Note that to allow this 12142 * function to be used when responding to a terminal resize, this 12143 * function is designed to work even if the horizontal cursor position 12144 * doesn't match the internally recorded position. 12145 * 12146 * Input: 12147 * gl GetLine * The resource object of gl_get_line(). 12148 * Output: 12149 * return int 0 - OK. 12150 * 1 - Error. 12151 */ 12152 static int gl_erase_line(GetLine *gl) 12153 { 12154 /* 12155 * Is a line currently displayed? 12156 */ 12157 if(gl->displayed) { 12158 /* 12159 * Relative the the start of the input line, which terminal line of 12160 * the current input line is the cursor currently on? 12161 */ 12162 int cursor_line = gl->term_curpos / gl->ncolumn; 12163 /* 12164 * Move the cursor to the start of the line. 12165 */ 12166 for( ; cursor_line > 0; cursor_line--) { 12167 if(gl_print_control_sequence(gl, 1, gl->up)) 12168 return 1; 12169 }; 12170 if(gl_print_control_sequence(gl, 1, gl->bol)) 12171 return 1; 12172 /* 12173 * Clear from the start of the line to the end of the terminal. 12174 */ 12175 if(gl_print_control_sequence(gl, gl->nline, gl->clear_eod)) 12176 return 1; 12177 /* 12178 * Mark the line as no longer displayed. 12179 */ 12180 gl_line_erased(gl); 12181 }; 12182 return 0; 12183 } 12184 12185 /*....................................................................... 12186 * Arrange for the input line to be redisplayed by gl_flush_output(), 12187 * as soon as the output queue becomes empty. 12188 * 12189 * Input: 12190 * gl GetLine * The resource object of gl_get_line(). 12191 */ 12192 static void gl_queue_redisplay(GetLine *gl) 12193 { 12194 gl->redisplay = 1; 12195 gl->pending_io = GLP_WRITE; 12196 } 12197 12198 /*....................................................................... 12199 * Truncate the displayed input line starting from the current 12200 * terminal cursor position, and leave the cursor at the end of the 12201 * truncated line. The input-line buffer is not affected. 12202 * 12203 * Input: 12204 * gl GetLine * The resource object of gl_get_line(). 12205 * Output: 12206 * return int 0 - OK. 12207 * 1 - Error. 12208 */ 12209 static int gl_truncate_display(GetLine *gl) 12210 { 12211 /* 12212 * Keep a record of the current terminal cursor position. 12213 */ 12214 int term_curpos = gl->term_curpos; 12215 /* 12216 * First clear from the cursor to the end of the current input line. 12217 */ 12218 if(gl_print_control_sequence(gl, 1, gl->clear_eol)) 12219 return 1; 12220 /* 12221 * If there is more than one line displayed, go to the start of the 12222 * next line and clear from there to the end of the display. Note that 12223 * we can't use clear_eod to do the whole job of clearing from the 12224 * current cursor position to the end of the terminal because 12225 * clear_eod is only defined when used at the start of a terminal line 12226 * (eg. with gnome terminals, clear_eod clears from the start of the 12227 * current terminal line, rather than from the current cursor 12228 * position). 12229 */ 12230 if(gl->term_len / gl->ncolumn > gl->term_curpos / gl->ncolumn) { 12231 if(gl_print_control_sequence(gl, 1, gl->down) || 12232 gl_print_control_sequence(gl, 1, gl->bol) || 12233 gl_print_control_sequence(gl, gl->nline, gl->clear_eod)) 12234 return 1; 12235 /* 12236 * Where is the cursor now? 12237 */ 12238 gl->term_curpos = gl->ncolumn * (term_curpos / gl->ncolumn + 1); 12239 /* 12240 * Restore the cursor position. 12241 */ 12242 gl_set_term_curpos(gl, term_curpos); 12243 }; 12244 /* 12245 * Update the recorded position of the final character. 12246 */ 12247 gl->term_len = gl->term_curpos; 12248 return 0; 12249 } 12250 12251 /*....................................................................... 12252 * Return the set of all trappable signals. 12253 * 12254 * Input: 12255 * signals sigset_t * The set of signals will be recorded in 12256 * *signals. 12257 */ 12258 static void gl_list_trappable_signals(sigset_t *signals) 12259 { 12260 /* 12261 * Start with the set of all signals. 12262 */ 12263 sigfillset(signals); 12264 /* 12265 * Remove un-trappable signals from this set. 12266 */ 12267 #ifdef SIGKILL 12268 sigdelset(signals, SIGKILL); 12269 #endif 12270 #ifdef SIGSTOP 12271 sigdelset(signals, SIGSTOP); 12272 #endif 12273 } 12274 12275 /*....................................................................... 12276 * Read an input line from a non-interactive input stream. 12277 * 12278 * Input: 12279 * gl GetLine * The resource object of gl_get_line(). 12280 * Output: 12281 * return int 0 - OK 12282 * 1 - Error. 12283 */ 12284 static int gl_read_stream_line(GetLine *gl) 12285 { 12286 char c = '\0'; /* The latest character read from fp */ 12287 /* 12288 * Record the fact that we are about to read input. 12289 */ 12290 gl->pending_io = GLP_READ; 12291 /* 12292 * If we are starting a new line, reset the line-input parameters. 12293 */ 12294 if(gl->endline) 12295 gl_reset_input_line(gl); 12296 /* 12297 * Read one character at a time. 12298 */ 12299 while(gl->ntotal < gl->linelen && c != '\n') { 12300 /* 12301 * Attempt to read one more character. 12302 */ 12303 switch(gl_read_input(gl, &c)) { 12304 case GL_READ_OK: 12305 break; 12306 case GL_READ_EOF: /* Reached end-of-file? */ 12307 /* 12308 * If any characters were read before the end-of-file condition, 12309 * interpolate a newline character, so that the caller sees a 12310 * properly terminated line. Otherwise return an end-of-file 12311 * condition. 12312 */ 12313 if(gl->ntotal > 0) { 12314 c = '\n'; 12315 } else { 12316 gl_record_status(gl, GLR_EOF, 0); 12317 return 1; 12318 }; 12319 break; 12320 case GL_READ_BLOCKED: /* Input blocked? */ 12321 gl_record_status(gl, GLR_BLOCKED, BLOCKED_ERRNO); 12322 return 1; 12323 break; 12324 case GL_READ_ERROR: /* I/O error? */ 12325 return 1; 12326 break; 12327 }; 12328 /* 12329 * Append the character to the line buffer. 12330 */ 12331 if(gl_buffer_char(gl, c, gl->ntotal)) 12332 return 1; 12333 }; 12334 /* 12335 * Was the end of the input line reached before running out of buffer space? 12336 */ 12337 gl->endline = (c == '\n'); 12338 return 0; 12339 } 12340 12341 /*....................................................................... 12342 * Read a single character from a non-interactive input stream. 12343 * 12344 * Input: 12345 * gl GetLine * The resource object of gl_get_line(). 12346 * Output: 12347 * return int The character, or EOF on error. 12348 */ 12349 static int gl_read_stream_char(GetLine *gl) 12350 { 12351 char c = '\0'; /* The latest character read from fp */ 12352 int retval = EOF; /* The return value of this function */ 12353 /* 12354 * Arrange to discard any incomplete input line. 12355 */ 12356 _gl_abandon_line(gl); 12357 /* 12358 * Record the fact that we are about to read input. 12359 */ 12360 gl->pending_io = GLP_READ; 12361 /* 12362 * Attempt to read one more character. 12363 */ 12364 switch(gl_read_input(gl, &c)) { 12365 case GL_READ_OK: /* Success */ 12366 retval = c; 12367 break; 12368 case GL_READ_BLOCKED: /* The read blocked */ 12369 gl_record_status(gl, GLR_BLOCKED, BLOCKED_ERRNO); 12370 retval = EOF; /* Failure */ 12371 break; 12372 case GL_READ_EOF: /* End of file reached */ 12373 gl_record_status(gl, GLR_EOF, 0); 12374 retval = EOF; /* Failure */ 12375 break; 12376 case GL_READ_ERROR: 12377 retval = EOF; /* Failure */ 12378 break; 12379 }; 12380 return retval; 12381 } 12382 12383 /*....................................................................... 12384 * Bind a key sequence to a given action. 12385 * 12386 * Input: 12387 * gl GetLine * The resource object of gl_get_line(). 12388 * origin GlKeyOrigin The originator of the key binding. 12389 * key const char * The key-sequence to be bound (or unbound). 12390 * action const char * The name of the action to bind the key to, 12391 * or either NULL or "" to unbind the 12392 * key-sequence. 12393 * Output: 12394 * return int 0 - OK 12395 * 1 - Error. 12396 */ 12397 int gl_bind_keyseq(GetLine *gl, GlKeyOrigin origin, const char *keyseq, 12398 const char *action) 12399 { 12400 KtBinder binder; /* The private internal equivalent of 'origin' */ 12401 /* 12402 * Check the arguments. 12403 */ 12404 if(!gl || !keyseq) { 12405 errno = EINVAL; 12406 if(gl) 12407 _err_record_msg(gl->err, "NULL argument(s)", END_ERR_MSG); 12408 return 1; 12409 }; 12410 /* 12411 * An empty action string requests that the key-sequence be unbound. 12412 * This is indicated to _kt_set_keybinding() by passing a NULL action 12413 * string, so convert an empty string to a NULL action pointer. 12414 */ 12415 if(action && *action=='\0') 12416 action = NULL; 12417 /* 12418 * Translate the public originator enumeration to the private equivalent. 12419 */ 12420 binder = origin==GL_USER_KEY ? KTB_USER : KTB_NORM; 12421 /* 12422 * Bind the action to a given key-sequence? 12423 */ 12424 if(keyseq && _kt_set_keybinding(gl->bindings, binder, keyseq, action)) { 12425 _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG); 12426 return 1; 12427 }; 12428 return 0; 12429 } 12430 12431 /*....................................................................... 12432 * This is the public wrapper around the gl_clear_termina() function. 12433 * It clears the terminal and leaves the cursor at the home position. 12434 * In server I/O mode, the next call to gl_get_line() will also 12435 * redisplay the current input line. 12436 * 12437 * Input: 12438 * gl GetLine * The resource object of gl_get_line(). 12439 * Output: 12440 * return int 0 - OK. 12441 * 1 - Error. 12442 */ 12443 int gl_erase_terminal(GetLine *gl) 12444 { 12445 sigset_t oldset; /* The signals that were blocked on entry */ 12446 /* to this function */ 12447 int status; /* The return status */ 12448 /* 12449 * Block all signals while accessing gl. 12450 */ 12451 gl_mask_signals(gl, &oldset); 12452 /* 12453 * Clear the terminal. 12454 */ 12455 status = gl_clear_screen(gl, 1, NULL); 12456 /* 12457 * Attempt to flush the clear-screen control codes to the terminal. 12458 * If this doesn't complete the job, the next call to gl_get_line() 12459 * will. 12460 */ 12461 (void) gl_flush_output(gl); 12462 /* 12463 * Restore the process signal mask before returning. 12464 */ 12465 gl_unmask_signals(gl, &oldset); 12466 return status; 12467 } 12468 12469 /*....................................................................... 12470 * This function must be called by any function that erases the input 12471 * line. 12472 * 12473 * Input: 12474 * gl GetLine * The resource object of gl_get_line(). 12475 */ 12476 static void gl_line_erased(GetLine *gl) 12477 { 12478 gl->displayed = 0; 12479 gl->term_curpos = 0; 12480 gl->term_len = 0; 12481 } 12482 12483 /*....................................................................... 12484 * Append a specified line to the history list. 12485 * 12486 * Input: 12487 * gl GetLine * The resource object of gl_get_line(). 12488 * line const char * The line to be added. 12489 * Output: 12490 * return int 0 - OK. 12491 * 1 - Error. 12492 */ 12493 int gl_append_history(GetLine *gl, const char *line) 12494 { 12495 sigset_t oldset; /* The signals that were blocked on entry */ 12496 /* to this function */ 12497 int status; /* The return status */ 12498 /* 12499 * Check the arguments. 12500 */ 12501 if(!gl || !line) { 12502 errno = EINVAL; 12503 return 1; 12504 }; 12505 /* 12506 * Block all signals. 12507 */ 12508 if(gl_mask_signals(gl, &oldset)) 12509 return 1; 12510 /* 12511 * Execute the private body of the function while signals are blocked. 12512 */ 12513 status = _gl_append_history(gl, line); 12514 /* 12515 * Restore the process signal mask. 12516 */ 12517 gl_unmask_signals(gl, &oldset); 12518 return status; 12519 } 12520 12521 /*....................................................................... 12522 * This is the private body of the public function, gl_append_history(). 12523 * It assumes that the caller has checked its arguments and blocked the 12524 * delivery of signals. 12525 */ 12526 static int _gl_append_history(GetLine *gl, const char *line) 12527 { 12528 int status =_glh_add_history(gl->glh, line, 0); 12529 if(status) 12530 _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG); 12531 return status; 12532 } 12533 12534 /*....................................................................... 12535 * Enable or disable the automatic addition of newly entered lines to the 12536 * history list. 12537 * 12538 * Input: 12539 * gl GetLine * The resource object of gl_get_line(). 12540 * enable int If true, subsequently entered lines will 12541 * automatically be added to the history list 12542 * before they are returned to the caller of 12543 * gl_get_line(). If 0, the choice of how and 12544 * when to archive lines in the history list, 12545 * is left up to the calling application, which 12546 * can do so via calls to gl_append_history(). 12547 * Output: 12548 * return int 0 - OK. 12549 * 1 - Error. 12550 */ 12551 int gl_automatic_history(GetLine *gl, int enable) 12552 { 12553 sigset_t oldset; /* The signals that were blocked on entry */ 12554 /* to this function */ 12555 /* 12556 * Check the arguments. 12557 */ 12558 if(!gl) { 12559 errno = EINVAL; 12560 return 1; 12561 }; 12562 /* 12563 * Block all signals. 12564 */ 12565 if(gl_mask_signals(gl, &oldset)) 12566 return 1; 12567 /* 12568 * Execute the private body of the function while signals are blocked. 12569 */ 12570 gl->automatic_history = enable; 12571 /* 12572 * Restore the process signal mask. 12573 */ 12574 gl_unmask_signals(gl, &oldset); 12575 return 0; 12576 } 12577 12578 /*....................................................................... 12579 * This is a public function that reads a single uninterpretted 12580 * character from the user, without displaying anything. 12581 * 12582 * Input: 12583 * gl GetLine * A resource object previously returned by 12584 * new_GetLine(). 12585 * Output: 12586 * return int The character that was read, or EOF if the read 12587 * had to be aborted (in which case you can call 12588 * gl_return_status() to find out why). 12589 */ 12590 int gl_read_char(GetLine *gl) 12591 { 12592 int retval; /* The return value of _gl_read_char() */ 12593 /* 12594 * This function can be called from application callback functions, 12595 * so check whether signals have already been masked, so that we don't 12596 * do it again, and overwrite gl->old_signal_set. 12597 */ 12598 int was_masked = gl->signals_masked; 12599 /* 12600 * Check the arguments. 12601 */ 12602 if(!gl) { 12603 errno = EINVAL; 12604 return EOF; 12605 }; 12606 /* 12607 * Temporarily block all of the signals that we have been asked to trap. 12608 */ 12609 if(!was_masked && gl_mask_signals(gl, &gl->old_signal_set)) 12610 return EOF; 12611 /* 12612 * Perform the character reading task. 12613 */ 12614 retval = _gl_read_char(gl); 12615 /* 12616 * Restore the process signal mask to how it was when this function was 12617 * first called. 12618 */ 12619 if(!was_masked) 12620 gl_unmask_signals(gl, &gl->old_signal_set); 12621 return retval; 12622 } 12623 12624 /*....................................................................... 12625 * This is the main body of the public function gl_read_char(). 12626 */ 12627 static int _gl_read_char(GetLine *gl) 12628 { 12629 int retval = EOF; /* The return value */ 12630 int waserr = 0; /* True if an error occurs */ 12631 char c; /* The character read */ 12632 /* 12633 * This function can be called from application callback functions, 12634 * so check whether signals have already been overriden, so that we don't 12635 * overwrite the preserved signal handlers with gl_get_line()s. Also 12636 * record whether we are currently in raw I/O mode or not, so that this 12637 * can be left in the same state on leaving this function. 12638 */ 12639 int was_overriden = gl->signals_overriden; 12640 int was_raw = gl->raw_mode; 12641 /* 12642 * Also keep a record of the direction of any I/O that gl_get_line() 12643 * is awaiting, so that we can restore this status on return. 12644 */ 12645 GlPendingIO old_pending_io = gl->pending_io; 12646 /* 12647 * Assume that this call will successfully complete the input operation 12648 * until proven otherwise. 12649 */ 12650 gl_clear_status(gl); 12651 /* 12652 * If this is the first call to this function or gl_get_line(), 12653 * since new_GetLine(), complete any postponed configuration. 12654 */ 12655 if(!gl->configured) { 12656 (void) _gl_configure_getline(gl, NULL, NULL, TECLA_CONFIG_FILE); 12657 gl->configured = 1; 12658 }; 12659 /* 12660 * Before installing our signal handler functions, record the fact 12661 * that there are no pending signals. 12662 */ 12663 gl_pending_signal = -1; 12664 /* 12665 * Temporarily override the signal handlers of the calling program, 12666 * so that we can intercept signals that would leave the terminal 12667 * in a bad state. 12668 */ 12669 if(!was_overriden) 12670 waserr = gl_override_signal_handlers(gl); 12671 /* 12672 * After recording the current terminal settings, switch the terminal 12673 * into raw input mode, without redisplaying any partially entered input 12674 * line. 12675 */ 12676 if(!was_raw) 12677 waserr = waserr || _gl_raw_io(gl, 0); 12678 /* 12679 * Attempt to read the line. This will require more than one attempt if 12680 * either a current temporary input file is opened by gl_get_input_line() 12681 * or the end of a temporary input file is reached by gl_read_stream_line(). 12682 */ 12683 while(!waserr) { 12684 /* 12685 * Read a line from a non-interactive stream? 12686 */ 12687 if(gl->file_fp || !gl->is_term) { 12688 retval = gl_read_stream_char(gl); 12689 if(retval != EOF) { /* Success? */ 12690 break; 12691 } else if(gl->file_fp) { /* End of temporary input file? */ 12692 gl_revert_input(gl); 12693 gl_record_status(gl, GLR_NEWLINE, 0); 12694 } else { /* An error? */ 12695 waserr = 1; 12696 break; 12697 }; 12698 }; 12699 /* 12700 * Read from the terminal? Note that the above if() block may have 12701 * changed gl->file_fp, so it is necessary to retest it here, rather 12702 * than using an else statement. 12703 */ 12704 if(!gl->file_fp && gl->is_term) { 12705 /* 12706 * Flush any pending output to the terminal before waiting 12707 * for the user to type a character. 12708 */ 12709 if(_glq_char_count(gl->cq) > 0 && gl_flush_output(gl)) { 12710 retval = EOF; 12711 /* 12712 * Read one character. Don't append it to the key buffer, since 12713 * this would subseuqnely appear as bogus input to the line editor. 12714 */ 12715 } else if(gl_read_terminal(gl, 0, &c) == 0) { 12716 /* 12717 * Record the character for return. 12718 */ 12719 retval = c; 12720 /* 12721 * In this mode, count each character as being a new key-sequence. 12722 */ 12723 gl->keyseq_count++; 12724 /* 12725 * Delete the character that was read, from the key-press buffer. 12726 */ 12727 gl_discard_chars(gl, 1); 12728 }; 12729 if(retval==EOF) 12730 waserr = 1; 12731 else 12732 break; 12733 }; 12734 }; 12735 /* 12736 * If an error occurred, but gl->rtn_status is still set to 12737 * GLR_NEWLINE, change the status to GLR_ERROR. Otherwise 12738 * leave it at whatever specific value was assigned by the function 12739 * that aborted input. This means that only functions that trap 12740 * non-generic errors have to remember to update gl->rtn_status 12741 * themselves. 12742 */ 12743 if(waserr && gl->rtn_status == GLR_NEWLINE) 12744 gl_record_status(gl, GLR_ERROR, errno); 12745 /* 12746 * Restore terminal settings, if they were changed by this function. 12747 */ 12748 if(!was_raw && gl->io_mode != GL_SERVER_MODE) 12749 _gl_normal_io(gl); 12750 /* 12751 * Restore the signal handlers, if they were overriden by this function. 12752 */ 12753 if(!was_overriden) 12754 gl_restore_signal_handlers(gl); 12755 /* 12756 * If this function gets aborted early, the errno value associated 12757 * with the event that caused this to happen is recorded in 12758 * gl->rtn_errno. Since errno may have been overwritten by cleanup 12759 * functions after this, restore its value to the value that it had 12760 * when the error condition occured, so that the caller can examine it 12761 * to find out what happened. 12762 */ 12763 errno = gl->rtn_errno; 12764 /* 12765 * Error conditions are signalled to the caller, by setting the returned 12766 * character to EOF. 12767 */ 12768 if(gl->rtn_status != GLR_NEWLINE) 12769 retval = EOF; 12770 /* 12771 * Restore the indication of what direction of I/O gl_get_line() 12772 * was awaiting before this call. 12773 */ 12774 gl->pending_io = old_pending_io; 12775 /* 12776 * Return the acquired character. 12777 */ 12778 return retval; 12779 } 12780 12781 /*....................................................................... 12782 * Reset the GetLine completion status. This function should be called 12783 * at the start of gl_get_line(), gl_read_char() and gl_query_char() 12784 * to discard the completion status and non-zero errno value of any 12785 * preceding calls to these functions. 12786 * 12787 * Input: 12788 * gl GetLine * The resource object of this module. 12789 */ 12790 static void gl_clear_status(GetLine *gl) 12791 { 12792 gl_record_status(gl, GLR_NEWLINE, 0); 12793 } 12794 12795 /*....................................................................... 12796 * When an error or other event causes gl_get_line() to return, this 12797 * function should be called to record information about what 12798 * happened, including the value of errno and the value that 12799 * gl_return_status() should return. 12800 * 12801 * Input: 12802 * gl GetLine * The resource object of this module. 12803 * rtn_status GlReturnStatus The completion status. To clear a 12804 * previous abnormal completion status, 12805 * specify GLR_NEWLINE (this is what 12806 * gl_clear_status() does). 12807 * rtn_errno int The associated value of errno. 12808 */ 12809 static void gl_record_status(GetLine *gl, GlReturnStatus rtn_status, 12810 int rtn_errno) 12811 { 12812 /* 12813 * If rtn_status==GLR_NEWLINE, then this resets the completion status, so we 12814 * should always heed this. Otherwise, only record the first abnormal 12815 * condition that occurs after such a reset. 12816 */ 12817 if(rtn_status == GLR_NEWLINE || gl->rtn_status == GLR_NEWLINE) { 12818 gl->rtn_status = rtn_status; 12819 gl->rtn_errno = rtn_errno; 12820 }; 12821 } 12822 12823