2 Bacula® - The Network Backup Solution
4 Copyright (C) 1981-2010 Free Software Foundation Europe e.V.
5 Yes, that is 1981 no error.
7 The main author of Bacula is Kern Sibbald, with contributions from
8 many others, a complete list can be found in the file AUTHORS.
9 This program is Free Software; you can redistribute it and/or
10 modify it under the terms of version two of the GNU General Public
11 License as published by the Free Software Foundation and included
14 This program is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
24 Bacula® is a registered trademark of Kern Sibbald.
25 The licensor of Bacula is the Free Software Foundation Europe
26 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
27 Switzerland, email:ftf@fsfeurope.org.
30 Generalized console input/output handler
31 A maintanable replacement for readline()
33 Updated for Bacula, Kern Sibbald, December MMIII
35 This code is in part derived from code that I wrote in
36 1981, so some of it is a bit old and could use a cleanup.
42 * If the top bit of a UTF-8 string is 0 (8 bits), then it
43 * is a normal ASCII character.
44 * If the top two bits are 11 (i.e. (c & 0xC0) == 0xC0 then
45 * it is the start of a series of chars (up to 5)
46 * Each subsequent character starts with 10 (i.e. (c & 0xC0) == 0x80)
59 /* We are in Bacula */
68 extern "C" int tgetent(void *, const char *);
69 extern "C" int tgetnum(const char *);
70 extern "C" char *tgetstr (const char*, char**);
71 extern "C" char *tgoto (const char *, int, int);
73 extern "C" int tgetent(char *, char *);
74 extern "C" int tgetnum(char id[2]);
75 extern "C" char *tgetstr(char id[2], char **);
76 extern "C" char *tgoto(char *, int, int);
77 #elif defined (__digital__) && defined (__unix__)
78 extern "C" int tgetent(void *, const char *);
79 extern "C" int tgetnum(const char *);
80 extern "C" char *tgetstr (const char*, char**);
81 extern "C" char *tgoto (const char *, int, int);
86 /* From termios library */
87 #if defined(HAVE_HPUX_OS) || defined(HAVE_AIX_OS)
95 /* Forward referenced functions */
97 static void sigintcatcher(int);
100 static void add_smap(char *str, int func);
103 /* Global variables */
105 static const char *t_up = "\n"; /* scroll up character */
106 static const char *t_honk = "\007"; /* sound beep */
107 static char *t_il; /* insert line */
108 static char *t_dl; /* delete line */
109 static char *t_cs; /* clear screen */
110 static char *t_cl; /* clear line */
111 static int t_width = 79; /* terminal width */
112 static int t_height = 24; /* terminal height */
113 static int linsdel_ok = 0; /* set if term has line insert & delete fncs */
115 static char *t_cm; /* cursor positioning */
116 static char *t_ti; /* init sequence */
117 static char *t_te; /* end sequence */
118 static char *t_do; /* down one line */
119 static char *t_sf; /* scroll screen one line up */
121 /* Keypad and Function Keys */
122 static char *kl; /* left key */
123 static char *kr; /* right */
124 static char *ku; /* up */
125 static char *kd; /* down */
126 static char *kh; /* home */
127 static char *kb; /* backspace */
128 static char *kD; /* delete key */
129 static char *kI; /* insert */
130 static char *kN; /* next page */
131 static char *kP; /* previous page */
132 static char *kH; /* home */
133 static char *kE; /* end */
136 #define EOS '\0' /* end of string terminator */
142 * Stab entry. Input chars (str), the length, and the desired
145 typedef struct s_stab {
154 static stab_t **stab = NULL; /* array of stabs by length */
155 static int num_stab; /* size of stab array */
157 static bool old_term_params_set = false;
158 static struct termios old_term_params;
160 /* Maintain lines in a doubly linked circular pool of lines. Each line is
161 preceded by a header defined by the lstr structure */
164 struct lstr { /* line pool structure */
165 struct lstr *prevl; /* link to previous line */
166 struct lstr *nextl; /* link to next line */
167 long len; /* length of line+header */
168 char used; /* set if line valid */
169 char line; /* line is actually varying length */
173 #define POOLEN 128000 /* bytes in line pool */
175 #define POOLEN 500 /* bytes in line pool */
177 char pool[POOLEN]; /* line pool */
178 #define PHDRL ((int)sizeof(struct lstr)) /* length of line header */
180 static struct lstr *lptr; /* current line pointer */
181 static struct lstr *slptr; /* store line pointer */
183 static char *getnext(), *getprev();
184 static int first = 1;
185 static int mode_insert = 1;
186 static int mode_wspace = 1; /* words separated by spaces */
189 static short char_map[600]= {
190 0, F_SOL, /* ^a Line start */
191 F_PRVWRD, /* ^b Previous word */ F_BREAK, /* ^C break */
192 F_DELCHR, /* ^D Delete character */ F_EOL, /* ^e End of line */
193 F_CSRRGT, /* ^f Right */ F_TABBAK, /* ^G Back tab */
194 F_CSRLFT, /* ^H Left */ F_TAB, /* ^I Tab */
195 F_CSRDWN, /* ^J Down */ F_DELEOL, /* ^K kill to eol */
196 F_CLRSCRN,/* ^L clear screen */ F_RETURN, /* ^M Carriage return */
197 F_RETURN, /* ^N enter line */ F_CONCAT, /* ^O Concatenate lines */
198 F_CSRUP, /* ^P cursor up */ F_TINS, /* ^Q Insert character mode */
199 F_PAGUP, /* ^R Page up */ F_CENTER, /* ^S Center text */
200 F_PAGDWN, /* ^T Page down */ F_DELSOL, /* ^U delete to start of line */
201 F_DELWRD, /* ^V Delete word */ F_PRVWRD, /* ^W Previous word */
202 F_NXTMCH, /* ^X Next match */ F_DELEOL, /* ^Y Delete to end of line */
203 F_BACKGND,/* ^Z Background */ 0x1B, /* ^[=ESC escape */
204 F_TENTRY, /* ^\ Entry mode */ F_PASTECB,/* ^]=paste clipboard */
205 F_HOME, /* ^^ Home */ F_ERSLIN, /* ^_ Erase line */
207 ' ','!','"','#','$','%','&','\047',
208 '(',')','*','+','\054','-','.','/',
209 '0','1','2','3','4','5','6','7',
210 '8','9',':',';','<','=','>','?',
211 '@','A','B','C','D','E','F','G',
212 'H','I','J','K','L','M','N','O',
213 'P','Q','R','S','T','U','V','W',
214 'X','Y','Z','[','\\',']','^','_',
215 '\140','a','b','c','d','e','f','g',
216 'h','i','j','k','l','m','n','o',
217 'p','q','r','s','t','u','v','w',
218 'x','y','z','{','|','}','\176',F_ERSCHR /* erase character */
223 /* Local variables */
225 #define CR '\r' /* carriage return */
228 /* Function Prototypes */
230 static unsigned int input_char(void);
231 static unsigned int t_gnc(void);
232 static void insert_space(char *curline, int line_len);
233 static void insert_hole(char *curline, int line_len);
234 static void forward(char *str, int str_len);
235 static void backup(char *curline);
236 static void delchr(int cnt, char *curline, int line_len);
237 static int iswordc(char c);
238 static int next_word(char *ldb_buf);
239 static int prev_word(char *ldb_buf);
240 static void prtcur(char *str);
241 static void poolinit(void);
242 static char * getnext(void);
243 static char * getprev(void);
244 static void putline(char *newl, int newlen);
245 static void t_honk_horn(void);
246 static void t_insert_line(void);
247 static void t_delete_line(void);
248 static void t_clrline(int pos, int width);
249 void t_sendl(const char *msg, int len);
250 void t_send(const char *msg);
252 static void asclrs();
253 static void ascurs(int y, int x);
255 static void rawmode(FILE *input);
256 static void normode(void);
257 static unsigned t_getch();
258 static void asclrl(int pos, int width);
259 static void asinsl();
260 static void asdell();
262 int input_line(char *string, int length);
270 void con_init(FILE *input)
280 void con_set_zed_keys(void)
282 char_map[1] = F_NXTWRD; /* ^A Next Word */
283 char_map[2] = F_SPLIT; /* ^B Split line */
284 char_map[3] = F_EOI; /* ^C Quit */
285 char_map[4] = F_DELCHR; /* ^D Delete character */
286 char_map[5] = F_EOF; /* ^E End of file */
287 char_map[6] = F_INSCHR; /* ^F Insert character */
288 char_map[7] = F_TABBAK; /* ^G Back tab */
289 char_map[8] = F_CSRLFT; /* ^H Left */
290 char_map[9] = F_TAB; /* ^I Tab */
291 char_map[10] = F_CSRDWN; /* ^J Down */
292 char_map[11] = F_CSRUP; /* ^K Up */
293 char_map[12] = F_CSRRGT; /* ^L Right */
294 char_map[13] = F_RETURN; /* ^M Carriage return */
295 char_map[14] = F_EOL; /* ^N End of line */
296 char_map[15] = F_CONCAT; /* ^O Concatenate lines */
297 char_map[16] = F_MARK; /* ^P Set marker */
298 char_map[17] = F_TINS; /* ^Q Insert character mode */
299 char_map[18] = F_PAGUP; /* ^R Page up */
300 char_map[19] = F_CENTER; /* ^S Center text */
301 char_map[20] = F_PAGDWN; /* ^T Page down */
302 char_map[21] = F_SOL; /* ^U Line start */
303 char_map[22] = F_DELWRD; /* ^V Delete word */
304 char_map[23] = F_PRVWRD; /* ^W Previous word */
305 char_map[24] = F_NXTMCH; /* ^X Next match */
306 char_map[25] = F_DELEOL; /* ^Y Delete to end of line */
307 char_map[26] = F_DELLIN; /* ^Z Delete line */
309 char_map[28] = F_TENTRY; /* ^\ Entry mode */
310 char_map[29] = F_PASTECB;/* ^]=paste clipboard */
311 char_map[30] = F_HOME; /* ^^ Home */
312 char_map[31] = F_ERSLIN; /* ^_ Erase line */
323 * Guarantee that the string is properly terminated */
324 char *bstrncpy(char *dest, const char *src, int maxlen)
326 strncpy(dest, src, maxlen-1);
334 * New style string mapping to function code
336 static unsigned do_smap(unsigned c)
356 for (i=len-1; i<MAX_STAB; i++) {
357 for (tstab=stab[i]; tstab; tstab=tstab->next) {
358 if (strncmp(str, tstab->str, len) == 0) {
359 if (len == tstab->len) {
363 break; /* found possibility continue searching */
370 /* found partial match, so get next character and retry */
371 str[len++] = t_gnc();
377 static void dump_stab()
383 for (i=0; i<MAX_STAB; i++) {
384 for (tstab=stab[i]; tstab; tstab=tstab->next) {
385 for (j=0; j<tstab->len; j++) {
387 if (c < 0x20 || c > 0x7F) {
388 sprintf(buf, " 0x%x ", c);
396 sprintf(buf, " func=%d len=%d\n\r", tstab->func, tstab->len);
404 * New routine. Add string to string->func mapping table.
406 static void add_smap(char *str, int func)
416 /* errmsg("String for func %d is zero length\n", func); */
419 tstab = (stab_t *)malloc(sizeof(stab_t));
420 memset(tstab, 0, sizeof(stab_t));
422 tstab->str = (char *)malloc(tstab->len + 1);
423 bstrncpy(tstab->str, str, tstab->len + 1);
425 if (tstab->len > num_stab) {
426 printf("stab string too long %d. Max is %d\n", tstab->len, num_stab);
429 tstab->next = stab[tstab->len-1];
430 stab[tstab->len-1] = tstab;
431 /* printf("Add_smap tstab=%x len=%d func=%d tstab->next=%x\n\r", tstab, len,
432 func, tstab->next); */
437 /* Get the next character from the terminal - performs table lookup on
438 the character to do the desired translation */
444 if ((c=t_gnc()) <= 599) { /* IBM generates codes up to 260 */
446 } else if (c > 1000) { /* stuffed function */
447 c -= 1000; /* convert back to function code */
452 /* if we got a screen size escape sequence, read height, width */
455 y = t_gnc() - 0x20; /* y */
456 x = t_gnc() - 0x20; /* x */
463 /* Get a complete input line */
466 input_line(char *string, int length)
468 char curline[2000]; /* edit buffer */
475 poolinit(); /* build line pool */
478 noline = 1; /* no line fetched yet */
479 for (cl=cp=0; cl<length && cl<(int)sizeof(curline); ) {
484 switch (c=input_char()) {
485 case F_RETURN: /* CR */
486 t_sendl("\r\n", 2); /* yes, print it and */
487 goto done; /* get out */
488 case F_CLRSCRN: /* clear screen */
490 t_sendl(curline, cl);
494 if (noline) { /* no line fetched yet */
495 getnext(); /* getnext so getprev gets current */
496 noline = 0; /* we now have line */
498 bstrncpy(curline, getprev(), sizeof(curline));
502 noline = 0; /* mark line fetched */
503 bstrncpy(curline, getnext(), sizeof(curline));
507 insert_space(curline, sizeof(curline));
510 delchr(1, curline, sizeof(curline)); /* delete one character */
512 case F_CSRLFT: /* Backspace */
516 forward(curline, sizeof(curline));
518 case F_ERSCHR: /* Rubout */
520 delchr(1, curline, sizeof(curline));
527 t_clrline(0, t_width);
532 i = next_word(curline);
534 forward(curline, sizeof(curline));
538 i = prev_word(curline);
544 delchr(next_word(curline), curline, sizeof(curline)); /* delete word */
546 case F_NXTMCH: /* Ctl-X */
548 *string = EOS; /* terminate string */
549 return(c); /* give it to him */
551 /* Note fall through */
555 backup(curline); /* backup to beginning of line */
557 t_clrline(0, t_width); /* erase line */
559 cl = 0; /* reset cursor counter */
570 forward(curline, sizeof(curline));
576 case F_TINS: /* toggle insert mode */
577 mode_insert = !mode_insert; /* flip bit */
580 if (c > 255) { /* function key hit */
581 if (cl==0) { /* if first character then */
582 *string = EOS; /* terminate string */
583 return c; /* return it */
585 t_honk_horn(); /* complain */
587 if ((c & 0xC0) == 0xC0) {
588 if ((c & 0xFC) == 0xFC) {
590 } else if ((c & 0xF8) == 0xF8) {
592 } else if ((c & 0xF0) == 0xF0) {
594 } else if ((c & 0xE0) == 0xE0) {
603 insert_space(curline, sizeof(curline));
605 curline[cp++] = c; /* store character in line being built */
606 t_char(c); /* echo character to terminal */
609 insert_hole(curline, sizeof(curline));
610 curline[cp++] = c; /* store character in line being built */
611 t_char(c); /* echo character to terminal */
614 cl = cp; /* keep current length */
621 /* If we fall through here rather than goto done, the line is too long
622 simply return what we have now. */
624 curline[cl++] = EOS; /* terminate */
625 bstrncpy(string,curline,length); /* return line to caller */
626 /* Save non-blank lines. Note, put line zaps curline */
627 if (curline[0] != EOS) {
628 putline(curline,cl); /* save line for posterity */
630 return 0; /* give it to him/her */
633 /* Insert a space at the current cursor position */
635 insert_space(char *curline, int curline_len)
639 if (cp >= cl || cl+1 > curline_len) {
642 /* Note! source and destination overlap */
643 memmove(&curline[cp+1],&curline[cp],i=cl-cp);
648 forward(curline, curline_len);
658 insert_hole(char *curline, int curline_len)
662 if (cp > cl || cl+1 > curline_len) {
665 /* Note! source and destination overlap */
666 memmove(&curline[cp+1], &curline[cp], i=cl-cp);
672 /* Move cursor forward keeping characters under it */
674 forward(char *str, int str_len)
685 if ((str[cp] & 0xC0) == 0xC0) {
687 while ((str[cp] & 0xC0) == 0x80) {
697 /* How many characters under the cursor */
699 char_count(int cptr, char *str)
705 if ((str[cptr] & 0xC0) == 0xC0) {
707 while ((str[cptr] & 0xC0) == 0x80) {
715 /* Backup cursor keeping characters under it */
722 while ((str[cp] & 0xC0) == 0x80) {
729 /* Delete the character under the cursor */
731 delchr(int del, char *curline, int line_len)
735 if (cp > cl || del == 0) {
738 while (del-- && cl > 0) {
739 cnt = char_count(cp, curline);
740 if ((i=cl-cp-cnt) > 0) {
741 memcpy(&curline[cp], &curline[cp+cnt], i);
745 t_clrline(0, t_width);
748 forward(curline, line_len);
757 /* Determine if character is part of a word */
763 if (c >= '0' && c <= '9')
765 if (c == '$' || c == '%')
770 /* Return number of characters to get to next word */
772 next_word(char *ldb_buf)
779 for ( ; ncp<cl && iswordc(*(ldb_buf+ncp)); ncp++) ;
780 for ( ; ncp<cl && !iswordc(*(ldb_buf+ncp)); ncp++) ;
784 /* Return number of characters to get to previous word */
786 prev_word(char *ldb_buf)
790 if (cp == 0) /* if at begin of line stop now */
792 if (cp > cl) /* if past eol start at eol */
796 /* backup to end of previous word - i.e. skip special chars */
797 for (i=ncp-1; i && !iswordc(*(ldb_buf+i)); i--) ;
798 if (i == 0) { /* at beginning of line? */
799 return cp; /* backup to beginning */
801 /* now move back through word to beginning of word */
802 for ( ; i && iswordc(*(ldb_buf+i)); i--) ;
803 ncp = i+1; /* position to first char of word */
804 if (i==0 && iswordc(*ldb_buf)) /* check for beginning of line */
806 return cp-ncp; /* return count */
809 /* Display new current line */
816 t_clrline(0,t_width);
817 cp = cl = strlen(str);
822 /* Initialize line pool. Split pool into two pieces. */
826 slptr = lptr = (struct lstr *)pool;
835 /* Return pointer to next line in the pool and advance current line pointer */
839 do { /* find next used line */
841 } while (!lptr->used);
842 return (char *)&lptr->line;
845 /* Return pointer to previous line in the pool */
849 do { /* find previous used line */
851 } while (!lptr->used);
852 return (char *)&lptr->line;
856 putline(char *newl, int newlen)
858 struct lstr *nptr; /* points to next line */
861 lptr = slptr; /* get ptr to last line stored */
862 lptr = lptr->nextl; /* advance pointer */
863 if ((char *)lptr-pool+newlen+PHDRL > POOLEN) { /* not enough room */
864 lptr->used = 0; /* delete line */
865 lptr = (struct lstr *)pool; /* start at beginning of buffer */
867 while (lptr->len < newlen+PHDRL) { /* concatenate buffers */
868 nptr = lptr->nextl; /* point to next line */
869 lptr->nextl = nptr->nextl; /* unlink it from list */
870 nptr->nextl->prevl = lptr;
871 lptr->len += nptr->len;
873 if (lptr->len > newlen + 2 * PHDRL) { /* split buffer */
874 nptr = (struct lstr *)((char *)lptr + newlen + PHDRL);
875 /* Appropriate byte alignment - normally 2 byte, but on
876 sparc we need 4 byte alignment, so we always do 4 */
877 if (((long unsigned)nptr & 3) != 0) { /* test four byte alignment */
879 nptr = (struct lstr *)((((long unsigned) p) & ~3) + 4);
881 nptr->len = lptr->len - ((char *)nptr - (char *)lptr);
882 lptr->len -= nptr->len;
883 nptr->nextl = lptr->nextl; /* link in new buffer */
884 lptr->nextl->prevl = nptr;
889 memcpy(&lptr->line,newl,newlen);
890 lptr->used = 1; /* mark line used */
891 slptr = lptr; /* save as stored line */
896 dump(struct lstr *ptr, char *msg)
898 printf("%s buf=%x nextl=%x prevl=%x len=%d used=%d\n",
899 msg,ptr,ptr->nextl,ptr->prevl,ptr->len,ptr->used);
901 printf("line=%s\n",&ptr->line);
903 #endif /* DEBUGOUT */
906 /* Honk horn on terminal */
913 /* Insert line on terminal */
920 /* Delete line from terminal */
927 /* clear line from pos to width */
929 t_clrline(int pos, int width)
931 asclrl(pos, width); /* clear to end of line */
934 /* Helper function to add string preceded by
935 * ESC to smap table */
936 static void add_esc_smap(const char *str, int func)
939 buf[0] = 0x1B; /* esc */
940 bstrncpy(buf+1, str, sizeof(buf)-1);
944 /* Set raw mode on terminal file. Basically, get the terminal into a
945 mode in which all characters can be read as they are entered. CBREAK
946 mode is not sufficient.
948 static void rawmode(FILE *input)
951 static char term_buf[2048];
952 static char *term_buffer = term_buf;
953 char *termtype = (char *)getenv("TERM");
955 /* Make sure we are dealing with a terminal */
956 if (!isatty(fileno(input))) {
959 if (tcgetattr(0, &old_term_params) != 0) {
960 printf("conio: Cannot tcgetattr()\n");
963 old_term_params_set = true;
965 t.c_cc[VMIN] = 1; /* satisfy read after 1 char */
967 t.c_iflag &= ~(BRKINT | IGNPAR | PARMRK | INPCK |
968 ISTRIP | ICRNL | IXON | IXOFF | INLCR | IGNCR);
971 t.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL | ICANON |
973 tcflush(0, TCIFLUSH);
974 if (tcsetattr(0, TCSANOW, &t) == -1) {
975 printf("Cannot tcsetattr()\n");
978 /* Defaults, the main program can override these */
979 signal(SIGQUIT, SIG_IGN);
980 signal(SIGHUP, SIG_IGN);
981 signal(SIGINT, sigintcatcher);
982 signal(SIGWINCH, SIG_IGN);
985 printf("Cannot get terminal type.\n");
989 if (tgetent(term_buffer, termtype) < 0) {
990 printf("Cannot get terminal termcap entry.\n");
994 t_width = t_height = -1;
995 /* Note (char *)casting is due to really stupid compiler warnings */
996 t_width = tgetnum((char *)"co") - 1;
997 t_height = tgetnum((char *)"li");
1000 t_cm = (char *)tgetstr((char *)"cm", &term_buffer);
1001 t_cs = (char *)tgetstr((char *)"cl", &term_buffer); /* clear screen */
1002 t_cl = (char *)tgetstr((char *)"ce", &term_buffer); /* clear line */
1003 t_dl = (char *)tgetstr((char *)"dl", &term_buffer); /* delete line */
1004 t_il = (char *)tgetstr((char *)"al", &term_buffer); /* insert line */
1005 t_honk = (char *)tgetstr((char *)"bl", &term_buffer); /* beep */
1006 t_ti = (char *)tgetstr((char *)"ti", &term_buffer);
1007 t_te = (char *)tgetstr((char *)"te", &term_buffer);
1008 t_up = (char *)tgetstr((char *)"up", &term_buffer);
1009 t_do = (char *)tgetstr((char *)"do", &term_buffer);
1010 t_sf = (char *)tgetstr((char *)"sf", &term_buffer);
1012 num_stab = MAX_STAB; /* get default stab size */
1013 stab = (stab_t **)malloc(sizeof(stab_t *) * num_stab);
1014 memset(stab, 0, sizeof(stab_t *) * num_stab);
1017 kl = (char *)tgetstr((char *)"kl", &term_buffer);
1018 kr = (char *)tgetstr((char *)"kr", &term_buffer);
1019 ku = (char *)tgetstr((char *)"ku", &term_buffer);
1020 kd = (char *)tgetstr((char *)"kd", &term_buffer);
1021 kh = (char *)tgetstr((char *)"kh", &term_buffer);
1022 kb = (char *)tgetstr((char *)"kb", &term_buffer);
1023 kD = (char *)tgetstr((char *)"kD", &term_buffer);
1024 kI = (char *)tgetstr((char *)"kI", &term_buffer);
1025 kN = (char *)tgetstr((char *)"kN", &term_buffer);
1026 kP = (char *)tgetstr((char *)"kP", &term_buffer);
1027 kH = (char *)tgetstr((char *)"kH", &term_buffer);
1028 kE = (char *)tgetstr((char *)"kE", &term_buffer);
1030 add_smap(kl, F_CSRLFT);
1031 add_smap(kr, F_CSRRGT);
1032 add_smap(ku, F_CSRUP);
1033 add_smap(kd, F_CSRDWN);
1034 add_smap(kI, F_TINS);
1035 add_smap(kN, F_PAGDWN);
1036 add_smap(kP, F_PAGUP);
1037 add_smap(kH, F_HOME);
1038 add_smap(kE, F_EOF);
1041 add_esc_smap("[A", F_CSRUP);
1042 add_esc_smap("[B", F_CSRDWN);
1043 add_esc_smap("[C", F_CSRRGT);
1044 add_esc_smap("[D", F_CSRLFT);
1045 add_esc_smap("[1~", F_HOME);
1046 add_esc_smap("[2~", F_TINS);
1047 add_esc_smap("[3~", F_DELCHR);
1048 add_esc_smap("[4~", F_EOF);
1049 add_esc_smap("f", F_NXTWRD);
1050 add_esc_smap("b", F_PRVWRD);
1054 /* Restore tty mode */
1055 static void normode()
1057 if (old_term_params_set) {
1058 tcsetattr(0, TCSANOW, &old_term_params);
1059 old_term_params_set = false;
1063 /* Get next character from terminal/script file/unget buffer */
1071 /* Get next character from OS */
1072 static unsigned t_getch(void)
1076 if (read(0, &c, 1) != 1) {
1082 /* Send message to terminal - primitive routine */
1084 t_sendl(const char *msg, int len)
1090 t_send(const char *msg)
1095 t_sendl(msg, strlen(msg)); /* faster than one char at time */
1098 /* Send single character to terminal - primitive routine - */
1102 (void)write(1, &c, 1);
1106 static int brkflg = 0; /* set on user break */
1108 /* Routine to return true if user types break */
1114 /* Clear break flag */
1121 /* Interrupt caught here */
1122 static void sigintcatcher(int sig)
1129 signal(SIGINT, sigintcatcher);
1136 signal(SIGINT, sigintcatcher);
1140 /* ASCLRL() -- Clear to end of line from current position */
1141 static void asclrl(int pos, int width)
1146 t_send(t_cl); /* use clear to eol function */
1149 if (pos==1 && linsdel_ok) {
1150 t_delete_line(); /* delete line */
1151 t_insert_line(); /* reinsert it */
1154 for (i=1; i<=width-pos+1; i++)
1155 t_char(' '); /* last resort, blank it out */
1156 for (i=1; i<=width-pos+1; i++) /* backspace to original position */
1163 /* ASCURS -- Set cursor position */
1164 static void ascurs(int y, int x)
1166 t_send((char *)tgoto(t_cm, x, y));
1170 /* ASCLRS -- Clear whole screen */
1171 static void asclrs()
1179 /* ASINSL -- insert new line after cursor */
1180 static void asinsl()
1182 t_clrline(0, t_width);
1183 t_send(t_il); /* insert before */
1186 /* ASDELL -- Delete line at cursor */
1187 static void asdell()