2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2016 Kern Sibbald
6 The original author of Bacula is Kern Sibbald, with contributions
7 from many others, a complete list can be found in the file AUTHORS.
9 You may use this file and others of this release according to the
10 license defined in the LICENSE file, which includes the Affero General
11 Public License, v3.0 ("AGPLv3") and some additional permissions and
12 terms pursuant to its AGPLv3 Section 7.
14 This notice must be preserved when any source code is
15 conveyed and/or propagated.
17 Bacula(R) is a registered trademark of Kern Sibbald.
20 Generalized console input/output handler
21 A maintanable replacement for readline()
23 Updated for Bacula, Kern Sibbald, December MMIII
25 This code is in part derived from code that I wrote in
26 1981, so some of it is a bit old and could use a cleanup.
32 * If the top bit of a UTF-8 string is 0 (8 bits), then it
33 * is a normal ASCII character.
34 * If the top two bits are 11 (i.e. (c & 0xC0) == 0xC0 then
35 * it is the start of a series of chars (up to 5)
36 * Each subsequent character starts with 10 (i.e. (c & 0xC0) == 0x80)
50 /* We are in Bacula */
62 extern "C" int tgetent(void *, const char *);
63 extern "C" int tgetnum(const char *);
64 extern "C" char *tgetstr (const char*, char**);
65 # Note: the following on older (Solaris 10) systems
66 # may need to be moved to after the #endif
67 extern "C" char *tgoto (const char *, int, int);
70 extern "C" int tgetent(char *, char *);
71 extern "C" int tgetnum(char id[2]);
72 extern "C" char *tgetstr(char id[2], char **);
73 extern "C" char *tgoto(char *, int, int);
74 #elif defined (__digital__) && defined (__unix__)
75 extern "C" int tgetent(void *, const char *);
76 extern "C" int tgetnum(const char *);
77 extern "C" char *tgetstr (const char*, char**);
78 extern "C" char *tgoto (const char *, int, int);
83 /* From termios library */
84 #if defined(HAVE_HPUX_OS) || defined(HAVE_AIX_OS)
92 /* Forward referenced functions */
94 static void sigintcatcher(int);
97 static void add_smap(char *str, int func);
100 /* Global variables */
102 static const char *t_up = "\n"; /* scroll up character */
103 static const char *t_honk = "\007"; /* sound beep */
104 static char *t_il; /* insert line */
105 static char *t_dl; /* delete line */
106 static char *t_cs; /* clear screen */
107 static char *t_cl; /* clear line */
108 static int t_width = 79; /* terminal width */
109 static int t_height = 24; /* terminal height */
110 static int linsdel_ok = 0; /* set if term has line insert & delete fncs */
112 static char *t_cm; /* cursor positioning */
113 static char *t_ti; /* init sequence */
114 static char *t_te; /* end sequence */
115 static char *t_do; /* down one line */
116 static char *t_sf; /* scroll screen one line up */
118 /* Keypad and Function Keys */
119 static char *kl; /* left key */
120 static char *kr; /* right */
121 static char *ku; /* up */
122 static char *kd; /* down */
123 static char *kh; /* home */
124 static char *kb; /* backspace */
125 static char *kD; /* delete key */
126 static char *kI; /* insert */
127 static char *kN; /* next page */
128 static char *kP; /* previous page */
129 static char *kH; /* home */
130 static char *kE; /* end */
133 #define EOS '\0' /* end of string terminator */
139 * Stab entry. Input chars (str), the length, and the desired
142 typedef struct s_stab {
151 static stab_t **stab = NULL; /* array of stabs by length */
152 static int num_stab; /* size of stab array */
154 static bool old_term_params_set = false;
155 static struct termios old_term_params;
157 /* Maintain lines in a doubly linked circular pool of lines. Each line is
158 preceded by a header defined by the lstr structure */
161 struct lstr { /* line pool structure */
162 struct lstr *prevl; /* link to previous line */
163 struct lstr *nextl; /* link to next line */
164 long len; /* length of line+header */
165 char used; /* set if line valid */
166 char line; /* line is actually varying length */
170 #define POOLEN 128000 /* bytes in line pool */
172 #define POOLEN 500 /* bytes in line pool */
174 char pool[POOLEN]; /* line pool */
175 #define PHDRL ((int)sizeof(struct lstr)) /* length of line header */
177 static struct lstr *lptr; /* current line pointer */
178 static struct lstr *slptr; /* store line pointer */
180 static char *getnext(), *getprev();
181 static int first = 1;
182 static int mode_insert = 1;
183 static int mode_wspace = 1; /* words separated by spaces */
186 static short char_map[600]= {
187 0, F_SOL, /* ^a Line start */
188 F_PRVWRD, /* ^b Previous word */ F_BREAK, /* ^C break */
189 F_DELCHR, /* ^D Delete character */ F_EOL, /* ^e End of line */
190 F_CSRRGT, /* ^f Right */ F_TABBAK, /* ^G Back tab */
191 F_CSRLFT, /* ^H Left */ F_TAB, /* ^I Tab */
192 F_CSRDWN, /* ^J Down */ F_DELEOL, /* ^K kill to eol */
193 F_CLRSCRN,/* ^L clear screen */ F_RETURN, /* ^M Carriage return */
194 F_RETURN, /* ^N enter line */ F_CONCAT, /* ^O Concatenate lines */
195 F_CSRUP, /* ^P cursor up */ F_TINS, /* ^Q Insert character mode */
196 F_PAGUP, /* ^R Page up */ F_CENTER, /* ^S Center text */
197 F_PAGDWN, /* ^T Page down */ F_DELSOL, /* ^U delete to start of line */
198 F_DELWRD, /* ^V Delete word */ F_PRVWRD, /* ^W Previous word */
199 F_NXTMCH, /* ^X Next match */ F_DELEOL, /* ^Y Delete to end of line */
200 F_BACKGND,/* ^Z Background */ 0x1B, /* ^[=ESC escape */
201 F_TENTRY, /* ^\ Entry mode */ F_PASTECB,/* ^]=paste clipboard */
202 F_HOME, /* ^^ Home */ F_ERSLIN, /* ^_ Erase line */
204 ' ','!','"','#','$','%','&','\047',
205 '(',')','*','+','\054','-','.','/',
206 '0','1','2','3','4','5','6','7',
207 '8','9',':',';','<','=','>','?',
208 '@','A','B','C','D','E','F','G',
209 'H','I','J','K','L','M','N','O',
210 'P','Q','R','S','T','U','V','W',
211 'X','Y','Z','[','\\',']','^','_',
212 '\140','a','b','c','d','e','f','g',
213 'h','i','j','k','l','m','n','o',
214 'p','q','r','s','t','u','v','w',
215 'x','y','z','{','|','}','\176',F_ERSCHR /* erase character */
220 /* Local variables */
222 #define CR '\r' /* carriage return */
225 /* Function Prototypes */
227 static unsigned int input_char(void);
228 static unsigned int t_gnc(void);
229 static void insert_space(char *curline, int line_len);
230 static void insert_hole(char *curline, int line_len);
231 static void forward(char *str, int str_len);
232 static void backup(char *curline);
233 static void delchr(int cnt, char *curline, int line_len);
234 static int iswordc(char c);
235 static int next_word(char *ldb_buf);
236 static int prev_word(char *ldb_buf);
237 static void prtcur(char *str);
238 static void poolinit(void);
239 static char * getnext(void);
240 static char * getprev(void);
241 static void putline(char *newl, int newlen);
242 static void t_honk_horn(void);
243 static void t_insert_line(void);
244 static void t_delete_line(void);
245 static void t_clrline(int pos, int width);
246 void t_sendl(const char *msg, int len);
247 void t_send(const char *msg);
249 static void asclrs();
250 static void ascurs(int y, int x);
252 static void rawmode(FILE *input);
253 static void normode(void);
254 static unsigned t_getch();
255 static void asclrl(int pos, int width);
256 static void asinsl();
257 static void asdell();
259 int input_line(char *string, int length);
267 void con_init(FILE *input)
277 void con_set_zed_keys(void)
279 char_map[1] = F_NXTWRD; /* ^A Next Word */
280 char_map[2] = F_SPLIT; /* ^B Split line */
281 char_map[3] = F_EOI; /* ^C Quit */
282 char_map[4] = F_DELCHR; /* ^D Delete character */
283 char_map[5] = F_EOF; /* ^E End of file */
284 char_map[6] = F_INSCHR; /* ^F Insert character */
285 char_map[7] = F_TABBAK; /* ^G Back tab */
286 char_map[8] = F_CSRLFT; /* ^H Left */
287 char_map[9] = F_TAB; /* ^I Tab */
288 char_map[10] = F_CSRDWN; /* ^J Down */
289 char_map[11] = F_CSRUP; /* ^K Up */
290 char_map[12] = F_CSRRGT; /* ^L Right */
291 char_map[13] = F_RETURN; /* ^M Carriage return */
292 char_map[14] = F_EOL; /* ^N End of line */
293 char_map[15] = F_CONCAT; /* ^O Concatenate lines */
294 char_map[16] = F_MARK; /* ^P Set marker */
295 char_map[17] = F_TINS; /* ^Q Insert character mode */
296 char_map[18] = F_PAGUP; /* ^R Page up */
297 char_map[19] = F_CENTER; /* ^S Center text */
298 char_map[20] = F_PAGDWN; /* ^T Page down */
299 char_map[21] = F_SOL; /* ^U Line start */
300 char_map[22] = F_DELWRD; /* ^V Delete word */
301 char_map[23] = F_PRVWRD; /* ^W Previous word */
302 char_map[24] = F_NXTMCH; /* ^X Next match */
303 char_map[25] = F_DELEOL; /* ^Y Delete to end of line */
304 char_map[26] = F_DELLIN; /* ^Z Delete line */
306 char_map[28] = F_TENTRY; /* ^\ Entry mode */
307 char_map[29] = F_PASTECB;/* ^]=paste clipboard */
308 char_map[30] = F_HOME; /* ^^ Home */
309 char_map[31] = F_ERSLIN; /* ^_ Erase line */
320 * Guarantee that the string is properly terminated */
321 char *bstrncpy(char *dest, const char *src, int maxlen)
323 strncpy(dest, src, maxlen-1);
331 * New style string mapping to function code
333 static unsigned do_smap(unsigned c)
353 for (i=len-1; i<MAX_STAB; i++) {
354 for (tstab=stab[i]; tstab; tstab=tstab->next) {
355 if (strncmp(str, tstab->str, len) == 0) {
356 if (len == tstab->len) {
360 break; /* found possibility continue searching */
367 /* found partial match, so get next character and retry */
368 str[len++] = t_gnc();
374 static void dump_stab()
380 for (i=0; i<MAX_STAB; i++) {
381 for (tstab=stab[i]; tstab; tstab=tstab->next) {
382 for (j=0; j<tstab->len; j++) {
384 if (c < 0x20 || c > 0x7F) {
385 sprintf(buf, " 0x%x ", c);
393 sprintf(buf, " func=%d len=%d\n\r", tstab->func, tstab->len);
401 * New routine. Add string to string->func mapping table.
403 static void add_smap(char *str, int func)
413 /* errmsg("String for func %d is zero length\n", func); */
416 tstab = (stab_t *)malloc(sizeof(stab_t));
417 memset(tstab, 0, sizeof(stab_t));
419 tstab->str = (char *)malloc(tstab->len + 1);
420 bstrncpy(tstab->str, str, tstab->len + 1);
422 if (tstab->len > num_stab) {
423 printf("stab string too long %d. Max is %d\n", tstab->len, num_stab);
426 tstab->next = stab[tstab->len-1];
427 stab[tstab->len-1] = tstab;
428 /* printf("Add_smap tstab=%x len=%d func=%d tstab->next=%x\n\r", tstab, len,
429 func, tstab->next); */
434 /* Get the next character from the terminal - performs table lookup on
435 the character to do the desired translation */
441 if ((c=t_gnc()) <= 599) { /* IBM generates codes up to 260 */
443 } else if (c > 1000) { /* stuffed function */
444 c -= 1000; /* convert back to function code */
449 /* if we got a screen size escape sequence, read height, width */
451 t_gnc(); /* - 0x20 = y */
452 t_gnc(); /* - 0x20 = x */
459 /* Get a complete input line */
462 input_line(char *string, int length)
464 char curline[2000]; /* edit buffer */
471 poolinit(); /* build line pool */
474 noline = 1; /* no line fetched yet */
475 for (cl=cp=0; cl<length && cl<(int)sizeof(curline); ) {
480 switch (c=input_char()) {
481 case F_RETURN: /* CR */
482 t_sendl("\r\n", 2); /* yes, print it and */
483 goto done; /* get out */
484 case F_CLRSCRN: /* clear screen */
486 t_sendl(curline, cl);
490 if (noline) { /* no line fetched yet */
491 getnext(); /* getnext so getprev gets current */
492 noline = 0; /* we now have line */
494 bstrncpy(curline, getprev(), sizeof(curline));
498 noline = 0; /* mark line fetched */
499 bstrncpy(curline, getnext(), sizeof(curline));
503 insert_space(curline, sizeof(curline));
506 delchr(1, curline, sizeof(curline)); /* delete one character */
508 case F_CSRLFT: /* Backspace */
512 forward(curline, sizeof(curline));
514 case F_ERSCHR: /* Rubout */
516 delchr(1, curline, sizeof(curline));
523 t_clrline(0, t_width);
528 i = next_word(curline);
530 forward(curline, sizeof(curline));
534 i = prev_word(curline);
540 delchr(next_word(curline), curline, sizeof(curline)); /* delete word */
542 case F_NXTMCH: /* Ctl-X */
544 *string = EOS; /* terminate string */
545 return(c); /* give it to him */
547 /* Note fall through */
551 backup(curline); /* backup to beginning of line */
553 t_clrline(0, t_width); /* erase line */
555 cl = 0; /* reset cursor counter */
566 forward(curline, sizeof(curline));
572 case F_TINS: /* toggle insert mode */
573 mode_insert = !mode_insert; /* flip bit */
576 if (c > 255) { /* function key hit */
577 if (cl==0) { /* if first character then */
578 *string = EOS; /* terminate string */
579 return c; /* return it */
581 t_honk_horn(); /* complain */
583 if ((c & 0xC0) == 0xC0) {
584 if ((c & 0xFC) == 0xFC) {
586 } else if ((c & 0xF8) == 0xF8) {
588 } else if ((c & 0xF0) == 0xF0) {
590 } else if ((c & 0xE0) == 0xE0) {
599 insert_space(curline, sizeof(curline));
601 curline[cp++] = c; /* store character in line being built */
602 t_char(c); /* echo character to terminal */
605 insert_hole(curline, sizeof(curline));
606 curline[cp++] = c; /* store character in line being built */
607 t_char(c); /* echo character to terminal */
610 cl = cp; /* keep current length */
617 /* If we fall through here rather than goto done, the line is too long
618 simply return what we have now. */
620 curline[cl++] = EOS; /* terminate */
621 bstrncpy(string,curline,length); /* return line to caller */
622 /* Save non-blank lines. Note, put line zaps curline */
623 if (curline[0] != EOS) {
624 putline(curline,cl); /* save line for posterity */
626 return 0; /* give it to him/her */
629 /* Insert a space at the current cursor position */
631 insert_space(char *curline, int curline_len)
635 if (cp >= cl || cl+1 > curline_len) {
638 /* Note! source and destination overlap */
639 memmove(&curline[cp+1],&curline[cp],i=cl-cp);
644 forward(curline, curline_len);
654 insert_hole(char *curline, int curline_len)
658 if (cp > cl || cl+1 > curline_len) {
661 /* Note! source and destination overlap */
662 memmove(&curline[cp+1], &curline[cp], i=cl-cp);
668 /* Move cursor forward keeping characters under it */
670 forward(char *str, int str_len)
681 if ((str[cp] & 0xC0) == 0xC0) {
683 while ((str[cp] & 0xC0) == 0x80) {
693 /* How many characters under the cursor */
695 char_count(int cptr, char *str)
701 if ((str[cptr] & 0xC0) == 0xC0) {
703 while ((str[cptr] & 0xC0) == 0x80) {
711 /* Backup cursor keeping characters under it */
718 while ((str[cp] & 0xC0) == 0x80) {
725 /* Delete the character under the cursor */
727 delchr(int del, char *curline, int line_len)
731 if (cp > cl || del == 0) {
734 while (del-- && cl > 0) {
735 cnt = char_count(cp, curline);
736 if ((i=cl-cp-cnt) > 0) {
737 memcpy(&curline[cp], &curline[cp+cnt], i);
741 t_clrline(0, t_width);
744 forward(curline, line_len);
753 /* Determine if character is part of a word */
759 if (c >= '0' && c <= '9')
761 if (c == '$' || c == '%')
766 /* Return number of characters to get to next word */
768 next_word(char *ldb_buf)
775 for ( ; ncp<cl && iswordc(*(ldb_buf+ncp)); ncp++) ;
776 for ( ; ncp<cl && !iswordc(*(ldb_buf+ncp)); ncp++) ;
780 /* Return number of characters to get to previous word */
782 prev_word(char *ldb_buf)
786 if (cp == 0) /* if at begin of line stop now */
788 if (cp > cl) /* if past eol start at eol */
792 /* backup to end of previous word - i.e. skip special chars */
793 for (i=ncp-1; i && !iswordc(*(ldb_buf+i)); i--) ;
794 if (i == 0) { /* at beginning of line? */
795 return cp; /* backup to beginning */
797 /* now move back through word to beginning of word */
798 for ( ; i && iswordc(*(ldb_buf+i)); i--) ;
799 ncp = i+1; /* position to first char of word */
800 if (i==0 && iswordc(*ldb_buf)) /* check for beginning of line */
802 return cp-ncp; /* return count */
805 /* Display new current line */
812 t_clrline(0,t_width);
813 cp = cl = strlen(str);
818 /* Initialize line pool. Split pool into two pieces. */
822 slptr = lptr = (struct lstr *)pool;
831 /* Return pointer to next line in the pool and advance current line pointer */
835 do { /* find next used line */
837 } while (!lptr->used);
838 return (char *)&lptr->line;
841 /* Return pointer to previous line in the pool */
845 do { /* find previous used line */
847 } while (!lptr->used);
848 return (char *)&lptr->line;
852 putline(char *newl, int newlen)
854 struct lstr *nptr; /* points to next line */
857 lptr = slptr; /* get ptr to last line stored */
858 lptr = lptr->nextl; /* advance pointer */
859 if ((char *)lptr-pool+newlen+PHDRL > POOLEN) { /* not enough room */
860 lptr->used = 0; /* delete line */
861 lptr = (struct lstr *)pool; /* start at beginning of buffer */
863 while (lptr->len < newlen+PHDRL) { /* concatenate buffers */
864 nptr = lptr->nextl; /* point to next line */
865 lptr->nextl = nptr->nextl; /* unlink it from list */
866 nptr->nextl->prevl = lptr;
867 lptr->len += nptr->len;
869 if (lptr->len > newlen + 2 * PHDRL + 7) { /* split buffer */
870 nptr = (struct lstr *)((char *)lptr + newlen + PHDRL);
871 /* Appropriate byte alignment - for Intel 2 byte, but on
872 Sparc we need 8 byte alignment, so we always do 8 */
873 if (((long unsigned)nptr & 7) != 0) { /* test eight byte alignment */
875 nptr = (struct lstr *)((((long unsigned) p) & ~7) + 8);
877 nptr->len = lptr->len - ((char *)nptr - (char *)lptr);
878 lptr->len -= nptr->len;
879 nptr->nextl = lptr->nextl; /* link in new buffer */
880 lptr->nextl->prevl = nptr;
885 memcpy(&lptr->line,newl,newlen);
886 lptr->used = 1; /* mark line used */
887 slptr = lptr; /* save as stored line */
892 dump(struct lstr *ptr, char *msg)
894 printf("%s buf=%x nextl=%x prevl=%x len=%d used=%d\n",
895 msg,ptr,ptr->nextl,ptr->prevl,ptr->len,ptr->used);
897 printf("line=%s\n",&ptr->line);
899 #endif /* DEBUGOUT */
902 /* Honk horn on terminal */
909 /* Insert line on terminal */
916 /* Delete line from terminal */
923 /* clear line from pos to width */
925 t_clrline(int pos, int width)
927 asclrl(pos, width); /* clear to end of line */
930 /* Helper function to add string preceded by
931 * ESC to smap table */
932 static void add_esc_smap(const char *str, int func)
935 buf[0] = 0x1B; /* esc */
936 bstrncpy(buf+1, str, sizeof(buf)-1);
940 /* Set raw mode on terminal file. Basically, get the terminal into a
941 mode in which all characters can be read as they are entered. CBREAK
942 mode is not sufficient.
944 static void rawmode(FILE *input)
947 static char term_buf[2048];
948 static char *term_buffer = term_buf;
949 char *termtype = (char *)getenv("TERM");
951 /* Make sure we are dealing with a terminal */
952 if (!isatty(fileno(input))) {
955 if (tcgetattr(0, &old_term_params) != 0) {
956 printf("conio: Cannot tcgetattr()\n");
959 old_term_params_set = true;
961 t.c_cc[VMIN] = 1; /* satisfy read after 1 char */
963 t.c_iflag &= ~(BRKINT | IGNPAR | PARMRK | INPCK |
964 ISTRIP | ICRNL | IXON | IXOFF | INLCR | IGNCR);
967 t.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL | ICANON |
969 tcflush(0, TCIFLUSH);
970 if (tcsetattr(0, TCSANOW, &t) == -1) {
971 printf("Cannot tcsetattr()\n");
974 /* Defaults, the main program can override these */
975 signal(SIGQUIT, SIG_IGN);
976 signal(SIGHUP, SIG_IGN);
977 signal(SIGINT, sigintcatcher);
978 signal(SIGWINCH, SIG_IGN);
981 printf("Cannot get terminal type.\n");
985 if (tgetent(term_buffer, termtype) < 0) {
986 printf("Cannot get terminal termcap entry.\n");
990 t_width = t_height = -1;
991 /* Note (char *)casting is due to really stupid compiler warnings */
992 t_width = tgetnum((char *)"co") - 1;
993 t_height = tgetnum((char *)"li");
996 t_cm = (char *)tgetstr((char *)"cm", &term_buffer);
997 t_cs = (char *)tgetstr((char *)"cl", &term_buffer); /* clear screen */
998 t_cl = (char *)tgetstr((char *)"ce", &term_buffer); /* clear line */
999 t_dl = (char *)tgetstr((char *)"dl", &term_buffer); /* delete line */
1000 t_il = (char *)tgetstr((char *)"al", &term_buffer); /* insert line */
1001 t_honk = (char *)tgetstr((char *)"bl", &term_buffer); /* beep */
1002 t_ti = (char *)tgetstr((char *)"ti", &term_buffer);
1003 t_te = (char *)tgetstr((char *)"te", &term_buffer);
1004 t_up = (char *)tgetstr((char *)"up", &term_buffer);
1005 t_do = (char *)tgetstr((char *)"do", &term_buffer);
1006 t_sf = (char *)tgetstr((char *)"sf", &term_buffer);
1008 num_stab = MAX_STAB; /* get default stab size */
1009 stab = (stab_t **)malloc(sizeof(stab_t *) * num_stab);
1010 memset(stab, 0, sizeof(stab_t *) * num_stab);
1013 kl = (char *)tgetstr((char *)"kl", &term_buffer);
1014 kr = (char *)tgetstr((char *)"kr", &term_buffer);
1015 ku = (char *)tgetstr((char *)"ku", &term_buffer);
1016 kd = (char *)tgetstr((char *)"kd", &term_buffer);
1017 kh = (char *)tgetstr((char *)"kh", &term_buffer);
1018 kb = (char *)tgetstr((char *)"kb", &term_buffer);
1019 kD = (char *)tgetstr((char *)"kD", &term_buffer);
1020 kI = (char *)tgetstr((char *)"kI", &term_buffer);
1021 kN = (char *)tgetstr((char *)"kN", &term_buffer);
1022 kP = (char *)tgetstr((char *)"kP", &term_buffer);
1023 kH = (char *)tgetstr((char *)"kH", &term_buffer);
1024 kE = (char *)tgetstr((char *)"kE", &term_buffer);
1026 add_smap(kl, F_CSRLFT);
1027 add_smap(kr, F_CSRRGT);
1028 add_smap(ku, F_CSRUP);
1029 add_smap(kd, F_CSRDWN);
1030 add_smap(kI, F_TINS);
1031 add_smap(kN, F_PAGDWN);
1032 add_smap(kP, F_PAGUP);
1033 add_smap(kH, F_HOME);
1034 add_smap(kE, F_EOF);
1037 add_esc_smap("[A", F_CSRUP);
1038 add_esc_smap("[B", F_CSRDWN);
1039 add_esc_smap("[C", F_CSRRGT);
1040 add_esc_smap("[D", F_CSRLFT);
1041 add_esc_smap("[1~", F_HOME);
1042 add_esc_smap("[2~", F_TINS);
1043 add_esc_smap("[3~", F_DELCHR);
1044 add_esc_smap("[4~", F_EOF);
1045 add_esc_smap("f", F_NXTWRD);
1046 add_esc_smap("b", F_PRVWRD);
1050 /* Restore tty mode */
1051 static void normode()
1053 if (old_term_params_set) {
1054 tcsetattr(0, TCSANOW, &old_term_params);
1055 old_term_params_set = false;
1059 /* Get next character from terminal/script file/unget buffer */
1067 /* Get next character from OS */
1068 static unsigned t_getch(void)
1072 if (read(0, &c, 1) != 1) {
1078 /* Send message to terminal - primitive routine */
1080 t_sendl(const char *msg, int len)
1086 t_send(const char *msg)
1091 t_sendl(msg, strlen(msg)); /* faster than one char at time */
1094 /* Send single character to terminal - primitive routine - */
1098 (void)write(1, &c, 1);
1102 static int brkflg = 0; /* set on user break */
1104 /* Routine to return true if user types break */
1110 /* Clear break flag */
1117 /* Interrupt caught here */
1118 static void sigintcatcher(int sig)
1125 signal(SIGINT, sigintcatcher);
1132 signal(SIGINT, sigintcatcher);
1136 /* ASCLRL() -- Clear to end of line from current position */
1137 static void asclrl(int pos, int width)
1142 t_send(t_cl); /* use clear to eol function */
1145 if (pos==1 && linsdel_ok) {
1146 t_delete_line(); /* delete line */
1147 t_insert_line(); /* reinsert it */
1150 for (i=1; i<=width-pos+1; i++)
1151 t_char(' '); /* last resort, blank it out */
1152 for (i=1; i<=width-pos+1; i++) /* backspace to original position */
1159 /* ASCURS -- Set cursor position */
1160 static void ascurs(int y, int x)
1162 t_send((char *)tgoto(t_cm, x, y));
1166 /* ASCLRS -- Clear whole screen */
1167 static void asclrs()
1175 /* ASINSL -- insert new line after cursor */
1176 static void asinsl()
1178 t_clrline(0, t_width);
1179 t_send(t_il); /* insert before */
1182 /* ASDELL -- Delete line at cursor */
1183 static void asdell()