2 Bacula(R) - The Network Backup Solution
5 The original author of Bacula is Kern Sibbald, with contributions
6 from many others, a complete list can be found in the file AUTHORS.
8 You may use this file and others of this release according to the
9 license defined in the LICENSE file, which includes the Affero General
10 Public License, v3.0 ("AGPLv3") and some additional permissions and
11 terms pursuant to its AGPLv3 Section 7.
13 This notice must be preserved when any source code is
14 conveyed and/or propagated.
16 Bacula(R) is a registered trademark of Kern Sibbald.
19 Generalized console input/output handler
20 A maintanable replacement for readline()
22 Updated for Bacula, Kern Sibbald, December MMIII
24 This code is in part derived from code that I wrote in
25 1981, so some of it is a bit old and could use a cleanup.
31 * If the top bit of a UTF-8 string is 0 (8 bits), then it
32 * is a normal ASCII character.
33 * If the top two bits are 11 (i.e. (c & 0xC0) == 0xC0 then
34 * it is the start of a series of chars (up to 5)
35 * Each subsequent character starts with 10 (i.e. (c & 0xC0) == 0x80)
49 /* We are in Bacula */
61 extern "C" int tgetent(void *, const char *);
62 extern "C" int tgetnum(const char *);
63 extern "C" char *tgetstr (const char*, char**);
64 # Note: the following on older (Solaris 10) systems
65 # may need to be moved to after the #endif
66 extern "C" char *tgoto (const char *, int, int);
69 extern "C" int tgetent(char *, char *);
70 extern "C" int tgetnum(char id[2]);
71 extern "C" char *tgetstr(char id[2], char **);
72 extern "C" char *tgoto(char *, int, int);
73 #elif defined (__digital__) && defined (__unix__)
74 extern "C" int tgetent(void *, const char *);
75 extern "C" int tgetnum(const char *);
76 extern "C" char *tgetstr (const char*, char**);
77 extern "C" char *tgoto (const char *, int, int);
82 /* From termios library */
83 #if defined(HAVE_HPUX_OS) || defined(HAVE_AIX_OS)
91 static void add_smap(char *str, int func);
94 /* Global variables */
96 static const char *t_up = "\n"; /* scroll up character */
97 static const char *t_honk = "\007"; /* sound beep */
98 static char *t_il; /* insert line */
99 static char *t_dl; /* delete line */
100 static char *t_cs; /* clear screen */
101 static char *t_cl; /* clear line */
102 static int t_width = 79; /* terminal width */
103 static int t_height = 24; /* terminal height */
104 static int linsdel_ok = 0; /* set if term has line insert & delete fncs */
106 static char *t_cm; /* cursor positioning */
107 static char *t_ti; /* init sequence */
108 static char *t_te; /* end sequence */
109 static char *t_do; /* down one line */
110 static char *t_sf; /* scroll screen one line up */
112 /* Keypad and Function Keys */
113 static char *kl; /* left key */
114 static char *kr; /* right */
115 static char *ku; /* up */
116 static char *kd; /* down */
117 static char *kh; /* home */
118 static char *kb; /* backspace */
119 static char *kD; /* delete key */
120 static char *kI; /* insert */
121 static char *kN; /* next page */
122 static char *kP; /* previous page */
123 static char *kH; /* home */
124 static char *kE; /* end */
127 #define EOS '\0' /* end of string terminator */
133 * Stab entry. Input chars (str), the length, and the desired
136 typedef struct s_stab {
145 static stab_t **stab = NULL; /* array of stabs by length */
146 static int num_stab; /* size of stab array */
148 static bool old_term_params_set = false;
149 static struct termios old_term_params;
151 /* Maintain lines in a doubly linked circular pool of lines. Each line is
152 preceded by a header defined by the lstr structure */
155 struct lstr { /* line pool structure */
156 struct lstr *prevl; /* link to previous line */
157 struct lstr *nextl; /* link to next line */
158 long len; /* length of line+header */
159 char used; /* set if line valid */
160 char line; /* line is actually varying length */
164 #define POOLEN 128000 /* bytes in line pool */
166 #define POOLEN 500 /* bytes in line pool */
168 char pool[POOLEN]; /* line pool */
169 #define PHDRL ((int)sizeof(struct lstr)) /* length of line header */
171 static struct lstr *lptr; /* current line pointer */
172 static struct lstr *slptr; /* store line pointer */
174 static char *getnext(), *getprev();
175 static int first = 1;
176 static int mode_insert = 1;
177 static int mode_wspace = 1; /* words separated by spaces */
180 static short char_map[600]= {
181 0, F_SOL, /* ^a Line start */
182 F_PRVWRD, /* ^b Previous word */ F_BREAK, /* ^C break */
183 F_DELCHR, /* ^D Delete character */ F_EOL, /* ^e End of line */
184 F_CSRRGT, /* ^f Right */ F_TABBAK, /* ^G Back tab */
185 F_CSRLFT, /* ^H Left */ F_TAB, /* ^I Tab */
186 F_CSRDWN, /* ^J Down */ F_DELEOL, /* ^K kill to eol */
187 F_CLRSCRN,/* ^L clear screen */ F_RETURN, /* ^M Carriage return */
188 F_RETURN, /* ^N enter line */ F_CONCAT, /* ^O Concatenate lines */
189 F_CSRUP, /* ^P cursor up */ F_TINS, /* ^Q Insert character mode */
190 F_PAGUP, /* ^R Page up */ F_CENTER, /* ^S Center text */
191 F_PAGDWN, /* ^T Page down */ F_DELSOL, /* ^U delete to start of line */
192 F_DELWRD, /* ^V Delete word */ F_PRVWRD, /* ^W Previous word */
193 F_NXTMCH, /* ^X Next match */ F_DELEOL, /* ^Y Delete to end of line */
194 F_BACKGND,/* ^Z Background */ 0x1B, /* ^[=ESC escape */
195 F_TENTRY, /* ^\ Entry mode */ F_PASTECB,/* ^]=paste clipboard */
196 F_HOME, /* ^^ Home */ F_ERSLIN, /* ^_ Erase line */
198 ' ','!','"','#','$','%','&','\047',
199 '(',')','*','+','\054','-','.','/',
200 '0','1','2','3','4','5','6','7',
201 '8','9',':',';','<','=','>','?',
202 '@','A','B','C','D','E','F','G',
203 'H','I','J','K','L','M','N','O',
204 'P','Q','R','S','T','U','V','W',
205 'X','Y','Z','[','\\',']','^','_',
206 '\140','a','b','c','d','e','f','g',
207 'h','i','j','k','l','m','n','o',
208 'p','q','r','s','t','u','v','w',
209 'x','y','z','{','|','}','\176',F_ERSCHR /* erase character */
214 /* Local variables */
216 #define CR '\r' /* carriage return */
219 /* Function Prototypes */
221 static unsigned int input_char(void);
222 static unsigned int t_gnc(void);
223 static void insert_space(char *curline, int line_len);
224 static void insert_hole(char *curline, int line_len);
225 static void forward(char *str, int str_len);
226 static void backup(char *curline);
227 static void delchr(int cnt, char *curline, int line_len);
228 static int iswordc(char c);
229 static int next_word(char *ldb_buf);
230 static int prev_word(char *ldb_buf);
231 static void prtcur(char *str);
232 static void poolinit(void);
233 static char * getnext(void);
234 static char * getprev(void);
235 static void putline(char *newl, int newlen);
236 static void t_honk_horn(void);
237 static void t_insert_line(void);
238 static void t_delete_line(void);
239 static void t_clrline(int pos, int width);
240 void t_sendl(const char *msg, int len);
241 void t_send(const char *msg);
243 static void asclrs();
244 static void ascurs(int y, int x);
246 static void rawmode(FILE *input);
247 static void normode(void);
248 static unsigned t_getch();
249 static void asclrl(int pos, int width);
250 static void asinsl();
251 static void asdell();
253 int input_line(char *string, int length);
259 void con_init(FILE *input)
269 void con_set_zed_keys(void)
271 char_map[1] = F_NXTWRD; /* ^A Next Word */
272 char_map[2] = F_SPLIT; /* ^B Split line */
273 char_map[3] = F_EOI; /* ^C Quit */
274 char_map[4] = F_DELCHR; /* ^D Delete character */
275 char_map[5] = F_EOF; /* ^E End of file */
276 char_map[6] = F_INSCHR; /* ^F Insert character */
277 char_map[7] = F_TABBAK; /* ^G Back tab */
278 char_map[8] = F_CSRLFT; /* ^H Left */
279 char_map[9] = F_TAB; /* ^I Tab */
280 char_map[10] = F_CSRDWN; /* ^J Down */
281 char_map[11] = F_CSRUP; /* ^K Up */
282 char_map[12] = F_CSRRGT; /* ^L Right */
283 char_map[13] = F_RETURN; /* ^M Carriage return */
284 char_map[14] = F_EOL; /* ^N End of line */
285 char_map[15] = F_CONCAT; /* ^O Concatenate lines */
286 char_map[16] = F_MARK; /* ^P Set marker */
287 char_map[17] = F_TINS; /* ^Q Insert character mode */
288 char_map[18] = F_PAGUP; /* ^R Page up */
289 char_map[19] = F_CENTER; /* ^S Center text */
290 char_map[20] = F_PAGDWN; /* ^T Page down */
291 char_map[21] = F_SOL; /* ^U Line start */
292 char_map[22] = F_DELWRD; /* ^V Delete word */
293 char_map[23] = F_PRVWRD; /* ^W Previous word */
294 char_map[24] = F_NXTMCH; /* ^X Next match */
295 char_map[25] = F_DELEOL; /* ^Y Delete to end of line */
296 char_map[26] = F_DELLIN; /* ^Z Delete line */
298 char_map[28] = F_TENTRY; /* ^\ Entry mode */
299 char_map[29] = F_PASTECB;/* ^]=paste clipboard */
300 char_map[30] = F_HOME; /* ^^ Home */
301 char_map[31] = F_ERSLIN; /* ^_ Erase line */
312 * Guarantee that the string is properly terminated */
313 char *bstrncpy(char *dest, const char *src, int maxlen)
315 strncpy(dest, src, maxlen-1);
323 * New style string mapping to function code
325 static unsigned do_smap(unsigned c)
345 for (i=len-1; i<MAX_STAB; i++) {
346 for (tstab=stab[i]; tstab; tstab=tstab->next) {
347 if (strncmp(str, tstab->str, len) == 0) {
348 if (len == tstab->len) {
352 break; /* found possibility continue searching */
359 /* found partial match, so get next character and retry */
360 str[len++] = t_gnc();
366 static void dump_stab()
372 for (i=0; i<MAX_STAB; i++) {
373 for (tstab=stab[i]; tstab; tstab=tstab->next) {
374 for (j=0; j<tstab->len; j++) {
376 if (c < 0x20 || c > 0x7F) {
377 sprintf(buf, " 0x%x ", c);
385 sprintf(buf, " func=%d len=%d\n\r", tstab->func, tstab->len);
393 * New routine. Add string to string->func mapping table.
395 static void add_smap(char *str, int func)
405 /* errmsg("String for func %d is zero length\n", func); */
408 tstab = (stab_t *)malloc(sizeof(stab_t));
409 memset(tstab, 0, sizeof(stab_t));
411 tstab->str = (char *)malloc(tstab->len + 1);
412 bstrncpy(tstab->str, str, tstab->len + 1);
414 if (tstab->len > num_stab) {
415 printf("stab string too long %d. Max is %d\n", tstab->len, num_stab);
418 tstab->next = stab[tstab->len-1];
419 stab[tstab->len-1] = tstab;
420 /* printf("Add_smap tstab=%x len=%d func=%d tstab->next=%x\n\r", tstab, len,
421 func, tstab->next); */
426 /* Get the next character from the terminal - performs table lookup on
427 the character to do the desired translation */
433 if ((c=t_gnc()) <= 599) { /* IBM generates codes up to 260 */
435 } else if (c > 1000) { /* stuffed function */
436 c -= 1000; /* convert back to function code */
441 /* if we got a screen size escape sequence, read height, width */
443 t_gnc(); /* - 0x20 = y */
444 t_gnc(); /* - 0x20 = x */
451 /* Get a complete input line */
454 input_line(char *string, int length)
456 char curline[2000]; /* edit buffer */
463 poolinit(); /* build line pool */
466 noline = 1; /* no line fetched yet */
467 for (cl=cp=0; cl<length && cl<(int)sizeof(curline); ) {
472 switch (c=input_char()) {
473 case F_RETURN: /* CR */
474 t_sendl("\r\n", 2); /* yes, print it and */
475 goto done; /* get out */
476 case F_CLRSCRN: /* clear screen */
478 t_sendl(curline, cl);
482 if (noline) { /* no line fetched yet */
483 getnext(); /* getnext so getprev gets current */
484 noline = 0; /* we now have line */
486 bstrncpy(curline, getprev(), sizeof(curline));
490 noline = 0; /* mark line fetched */
491 bstrncpy(curline, getnext(), sizeof(curline));
495 insert_space(curline, sizeof(curline));
498 delchr(1, curline, sizeof(curline)); /* delete one character */
500 case F_CSRLFT: /* Backspace */
504 forward(curline, sizeof(curline));
506 case F_ERSCHR: /* Rubout */
508 delchr(1, curline, sizeof(curline));
515 t_clrline(0, t_width);
520 i = next_word(curline);
522 forward(curline, sizeof(curline));
526 i = prev_word(curline);
532 delchr(next_word(curline), curline, sizeof(curline)); /* delete word */
534 case F_NXTMCH: /* Ctl-X */
536 *string = EOS; /* terminate string */
537 return(c); /* give it to him */
539 /* Note fall through */
543 backup(curline); /* backup to beginning of line */
545 t_clrline(0, t_width); /* erase line */
547 cl = 0; /* reset cursor counter */
558 forward(curline, sizeof(curline));
564 case F_TINS: /* toggle insert mode */
565 mode_insert = !mode_insert; /* flip bit */
568 if (c > 255) { /* function key hit */
569 if (cl==0) { /* if first character then */
570 *string = EOS; /* terminate string */
571 return c; /* return it */
573 t_honk_horn(); /* complain */
575 if ((c & 0xC0) == 0xC0) {
576 if ((c & 0xFC) == 0xFC) {
578 } else if ((c & 0xF8) == 0xF8) {
580 } else if ((c & 0xF0) == 0xF0) {
582 } else if ((c & 0xE0) == 0xE0) {
591 insert_space(curline, sizeof(curline));
593 curline[cp++] = c; /* store character in line being built */
594 t_char(c); /* echo character to terminal */
597 insert_hole(curline, sizeof(curline));
598 curline[cp++] = c; /* store character in line being built */
599 t_char(c); /* echo character to terminal */
602 cl = cp; /* keep current length */
609 /* If we fall through here rather than goto done, the line is too long
610 simply return what we have now. */
612 curline[cl++] = EOS; /* terminate */
613 bstrncpy(string,curline,length); /* return line to caller */
614 /* Save non-blank lines. Note, put line zaps curline */
615 if (curline[0] != EOS) {
616 putline(curline,cl); /* save line for posterity */
618 return 0; /* give it to him/her */
621 /* Insert a space at the current cursor position */
623 insert_space(char *curline, int curline_len)
627 if (cp >= cl || cl+1 > curline_len) {
630 /* Note! source and destination overlap */
631 memmove(&curline[cp+1],&curline[cp],i=cl-cp);
636 forward(curline, curline_len);
646 insert_hole(char *curline, int curline_len)
650 if (cp > cl || cl+1 > curline_len) {
653 /* Note! source and destination overlap */
654 memmove(&curline[cp+1], &curline[cp], i=cl-cp);
660 /* Move cursor forward keeping characters under it */
662 forward(char *str, int str_len)
673 if ((str[cp] & 0xC0) == 0xC0) {
675 while ((str[cp] & 0xC0) == 0x80) {
685 /* How many characters under the cursor */
687 char_count(int cptr, char *str)
693 if ((str[cptr] & 0xC0) == 0xC0) {
695 while ((str[cptr] & 0xC0) == 0x80) {
703 /* Backup cursor keeping characters under it */
710 while ((str[cp] & 0xC0) == 0x80) {
717 /* Delete the character under the cursor */
719 delchr(int del, char *curline, int line_len)
723 if (cp > cl || del == 0) {
726 while (del-- && cl > 0) {
727 cnt = char_count(cp, curline);
728 if ((i=cl-cp-cnt) > 0) {
729 memcpy(&curline[cp], &curline[cp+cnt], i);
733 t_clrline(0, t_width);
736 forward(curline, line_len);
745 /* Determine if character is part of a word */
751 if (c >= '0' && c <= '9')
753 if (c == '$' || c == '%')
758 /* Return number of characters to get to next word */
760 next_word(char *ldb_buf)
767 for ( ; ncp<cl && iswordc(*(ldb_buf+ncp)); ncp++) ;
768 for ( ; ncp<cl && !iswordc(*(ldb_buf+ncp)); ncp++) ;
772 /* Return number of characters to get to previous word */
774 prev_word(char *ldb_buf)
778 if (cp == 0) /* if at begin of line stop now */
780 if (cp > cl) /* if past eol start at eol */
784 /* backup to end of previous word - i.e. skip special chars */
785 for (i=ncp-1; i && !iswordc(*(ldb_buf+i)); i--) ;
786 if (i == 0) { /* at beginning of line? */
787 return cp; /* backup to beginning */
789 /* now move back through word to beginning of word */
790 for ( ; i && iswordc(*(ldb_buf+i)); i--) ;
791 ncp = i+1; /* position to first char of word */
792 if (i==0 && iswordc(*ldb_buf)) /* check for beginning of line */
794 return cp-ncp; /* return count */
797 /* Display new current line */
804 t_clrline(0,t_width);
805 cp = cl = strlen(str);
810 /* Initialize line pool. Split pool into two pieces. */
814 slptr = lptr = (struct lstr *)pool;
823 /* Return pointer to next line in the pool and advance current line pointer */
827 do { /* find next used line */
829 } while (!lptr->used);
830 return (char *)&lptr->line;
833 /* Return pointer to previous line in the pool */
837 do { /* find previous used line */
839 } while (!lptr->used);
840 return (char *)&lptr->line;
844 putline(char *newl, int newlen)
846 struct lstr *nptr; /* points to next line */
849 lptr = slptr; /* get ptr to last line stored */
850 lptr = lptr->nextl; /* advance pointer */
851 if ((char *)lptr-pool+newlen+PHDRL > POOLEN) { /* not enough room */
852 lptr->used = 0; /* delete line */
853 lptr = (struct lstr *)pool; /* start at beginning of buffer */
855 while (lptr->len < newlen+PHDRL) { /* concatenate buffers */
856 nptr = lptr->nextl; /* point to next line */
857 lptr->nextl = nptr->nextl; /* unlink it from list */
858 nptr->nextl->prevl = lptr;
859 lptr->len += nptr->len;
861 if (lptr->len > newlen + 2 * PHDRL + 7) { /* split buffer */
862 nptr = (struct lstr *)((char *)lptr + newlen + PHDRL);
863 /* Appropriate byte alignment - for Intel 2 byte, but on
864 Sparc we need 8 byte alignment, so we always do 8 */
865 if (((long unsigned)nptr & 7) != 0) { /* test eight byte alignment */
867 nptr = (struct lstr *)((((long unsigned) p) & ~7) + 8);
869 nptr->len = lptr->len - ((char *)nptr - (char *)lptr);
870 lptr->len -= nptr->len;
871 nptr->nextl = lptr->nextl; /* link in new buffer */
872 lptr->nextl->prevl = nptr;
877 memcpy(&lptr->line,newl,newlen);
878 lptr->used = 1; /* mark line used */
879 slptr = lptr; /* save as stored line */
884 dump(struct lstr *ptr, char *msg)
886 printf("%s buf=%x nextl=%x prevl=%x len=%d used=%d\n",
887 msg,ptr,ptr->nextl,ptr->prevl,ptr->len,ptr->used);
889 printf("line=%s\n",&ptr->line);
891 #endif /* DEBUGOUT */
894 /* Honk horn on terminal */
901 /* Insert line on terminal */
908 /* Delete line from terminal */
915 /* clear line from pos to width */
917 t_clrline(int pos, int width)
919 asclrl(pos, width); /* clear to end of line */
922 /* Helper function to add string preceded by
923 * ESC to smap table */
924 static void add_esc_smap(const char *str, int func)
927 buf[0] = 0x1B; /* esc */
928 bstrncpy(buf+1, str, sizeof(buf)-1);
932 /* Set raw mode on terminal file. Basically, get the terminal into a
933 mode in which all characters can be read as they are entered. CBREAK
934 mode is not sufficient.
936 static void rawmode(FILE *input)
939 static char term_buf[2048];
940 static char *term_buffer = term_buf;
941 char *termtype = (char *)getenv("TERM");
943 /* Make sure we are dealing with a terminal */
944 if (!isatty(fileno(input))) {
947 if (tcgetattr(0, &old_term_params) != 0) {
948 printf("conio: Cannot tcgetattr()\n");
951 old_term_params_set = true;
953 t.c_cc[VMIN] = 1; /* satisfy read after 1 char */
955 t.c_iflag &= ~(BRKINT | IGNPAR | PARMRK | INPCK |
956 ISTRIP | ICRNL | IXON | IXOFF | INLCR | IGNCR);
959 t.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL | ICANON |
961 tcflush(0, TCIFLUSH);
962 if (tcsetattr(0, TCSANOW, &t) == -1) {
963 printf("Cannot tcsetattr()\n");
966 /* Defaults, the main program can override these */
967 signal(SIGQUIT, SIG_IGN);
968 signal(SIGHUP, SIG_IGN);
970 signal(SIGWINCH, SIG_IGN);
973 printf("Cannot get terminal type.\n");
977 if (tgetent(term_buffer, termtype) < 0) {
978 printf("Cannot get terminal termcap entry.\n");
982 t_width = t_height = -1;
983 /* Note (char *)casting is due to really stupid compiler warnings */
984 t_width = tgetnum((char *)"co") - 1;
985 t_height = tgetnum((char *)"li");
988 t_cm = (char *)tgetstr((char *)"cm", &term_buffer);
989 t_cs = (char *)tgetstr((char *)"cl", &term_buffer); /* clear screen */
990 t_cl = (char *)tgetstr((char *)"ce", &term_buffer); /* clear line */
991 t_dl = (char *)tgetstr((char *)"dl", &term_buffer); /* delete line */
992 t_il = (char *)tgetstr((char *)"al", &term_buffer); /* insert line */
993 t_honk = (char *)tgetstr((char *)"bl", &term_buffer); /* beep */
994 t_ti = (char *)tgetstr((char *)"ti", &term_buffer);
995 t_te = (char *)tgetstr((char *)"te", &term_buffer);
996 t_up = (char *)tgetstr((char *)"up", &term_buffer);
997 t_do = (char *)tgetstr((char *)"do", &term_buffer);
998 t_sf = (char *)tgetstr((char *)"sf", &term_buffer);
1000 num_stab = MAX_STAB; /* get default stab size */
1001 stab = (stab_t **)malloc(sizeof(stab_t *) * num_stab);
1002 memset(stab, 0, sizeof(stab_t *) * num_stab);
1005 kl = (char *)tgetstr((char *)"kl", &term_buffer);
1006 kr = (char *)tgetstr((char *)"kr", &term_buffer);
1007 ku = (char *)tgetstr((char *)"ku", &term_buffer);
1008 kd = (char *)tgetstr((char *)"kd", &term_buffer);
1009 kh = (char *)tgetstr((char *)"kh", &term_buffer);
1010 kb = (char *)tgetstr((char *)"kb", &term_buffer);
1011 kD = (char *)tgetstr((char *)"kD", &term_buffer);
1012 kI = (char *)tgetstr((char *)"kI", &term_buffer);
1013 kN = (char *)tgetstr((char *)"kN", &term_buffer);
1014 kP = (char *)tgetstr((char *)"kP", &term_buffer);
1015 kH = (char *)tgetstr((char *)"kH", &term_buffer);
1016 kE = (char *)tgetstr((char *)"kE", &term_buffer);
1018 add_smap(kl, F_CSRLFT);
1019 add_smap(kr, F_CSRRGT);
1020 add_smap(ku, F_CSRUP);
1021 add_smap(kd, F_CSRDWN);
1022 add_smap(kI, F_TINS);
1023 add_smap(kN, F_PAGDWN);
1024 add_smap(kP, F_PAGUP);
1025 add_smap(kH, F_HOME);
1026 add_smap(kE, F_EOF);
1029 add_esc_smap("[A", F_CSRUP);
1030 add_esc_smap("[B", F_CSRDWN);
1031 add_esc_smap("[C", F_CSRRGT);
1032 add_esc_smap("[D", F_CSRLFT);
1033 add_esc_smap("[1~", F_HOME);
1034 add_esc_smap("[2~", F_TINS);
1035 add_esc_smap("[3~", F_DELCHR);
1036 add_esc_smap("[4~", F_EOF);
1037 add_esc_smap("f", F_NXTWRD);
1038 add_esc_smap("b", F_PRVWRD);
1042 /* Restore tty mode */
1043 static void normode()
1045 if (old_term_params_set) {
1046 tcsetattr(0, TCSANOW, &old_term_params);
1047 old_term_params_set = false;
1051 /* Get next character from terminal/script file/unget buffer */
1059 /* Get next character from OS */
1060 static unsigned t_getch(void)
1064 if (read(0, &c, 1) != 1) {
1070 /* Send message to terminal - primitive routine */
1072 t_sendl(const char *msg, int len)
1078 t_send(const char *msg)
1083 t_sendl(msg, strlen(msg)); /* faster than one char at time */
1086 /* Send single character to terminal - primitive routine - */
1090 (void)write(1, &c, 1);
1093 /* ASCLRL() -- Clear to end of line from current position */
1094 static void asclrl(int pos, int width)
1099 t_send(t_cl); /* use clear to eol function */
1102 if (pos==1 && linsdel_ok) {
1103 t_delete_line(); /* delete line */
1104 t_insert_line(); /* reinsert it */
1107 for (i=1; i<=width-pos+1; i++)
1108 t_char(' '); /* last resort, blank it out */
1109 for (i=1; i<=width-pos+1; i++) /* backspace to original position */
1116 /* ASCURS -- Set cursor position */
1117 static void ascurs(int y, int x)
1119 t_send((char *)tgoto(t_cm, x, y));
1123 /* ASCLRS -- Clear whole screen */
1124 static void asclrs()
1132 /* ASINSL -- insert new line after cursor */
1133 static void asinsl()
1135 t_clrline(0, t_width);
1136 t_send(t_il); /* insert before */
1139 /* ASDELL -- Delete line at cursor */
1140 static void asdell()