2 Bacula® - The Network Backup Solution
4 Copyright (C) 1981-2012 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 three of the GNU Affero 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 Affero 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)
60 /* We are in Bacula */
70 #if defined(HAVE_SUN_OS)
72 extern "C" int tgetent(void *, const char *);
73 extern "C" int tgetnum(const char *);
74 extern "C" char *tgetstr (const char*, char**);
75 # Note: the following on older (Solaris 10) systems
76 # may need to be moved to after the #endif
77 extern "C" char *tgoto (const char *, int, int);
80 extern "C" int tgetent(char *, char *);
81 extern "C" int tgetnum(char id[2]);
82 extern "C" char *tgetstr(char id[2], char **);
83 extern "C" char *tgoto(char *, int, int);
84 #elif defined (__digital__) && defined (__unix__)
85 extern "C" int tgetent(void *, const char *);
86 extern "C" int tgetnum(const char *);
87 extern "C" char *tgetstr (const char*, char**);
88 extern "C" char *tgoto (const char *, int, int);
93 /* From termios library */
94 #if defined(HAVE_HPUX_OS) || defined(HAVE_AIX_OS)
102 /* Forward referenced functions */
104 static void sigintcatcher(int);
107 static void add_smap(char *str, int func);
110 /* Global variables */
112 static const char *t_up = "\n"; /* scroll up character */
113 static const char *t_honk = "\007"; /* sound beep */
114 static char *t_il; /* insert line */
115 static char *t_dl; /* delete line */
116 static char *t_cs; /* clear screen */
117 static char *t_cl; /* clear line */
118 static int t_width = 79; /* terminal width */
119 static int t_height = 24; /* terminal height */
120 static int linsdel_ok = 0; /* set if term has line insert & delete fncs */
122 static char *t_cm; /* cursor positioning */
123 static char *t_ti; /* init sequence */
124 static char *t_te; /* end sequence */
125 static char *t_do; /* down one line */
126 static char *t_sf; /* scroll screen one line up */
128 /* Keypad and Function Keys */
129 static char *kl; /* left key */
130 static char *kr; /* right */
131 static char *ku; /* up */
132 static char *kd; /* down */
133 static char *kh; /* home */
134 static char *kb; /* backspace */
135 static char *kD; /* delete key */
136 static char *kI; /* insert */
137 static char *kN; /* next page */
138 static char *kP; /* previous page */
139 static char *kH; /* home */
140 static char *kE; /* end */
143 #define EOS '\0' /* end of string terminator */
149 * Stab entry. Input chars (str), the length, and the desired
152 typedef struct s_stab {
161 static stab_t **stab = NULL; /* array of stabs by length */
162 static int num_stab; /* size of stab array */
164 static bool old_term_params_set = false;
165 static struct termios old_term_params;
167 /* Maintain lines in a doubly linked circular pool of lines. Each line is
168 preceded by a header defined by the lstr structure */
171 struct lstr { /* line pool structure */
172 struct lstr *prevl; /* link to previous line */
173 struct lstr *nextl; /* link to next line */
174 long len; /* length of line+header */
175 char used; /* set if line valid */
176 char line; /* line is actually varying length */
180 #define POOLEN 128000 /* bytes in line pool */
182 #define POOLEN 500 /* bytes in line pool */
184 char pool[POOLEN]; /* line pool */
185 #define PHDRL ((int)sizeof(struct lstr)) /* length of line header */
187 static struct lstr *lptr; /* current line pointer */
188 static struct lstr *slptr; /* store line pointer */
190 static char *getnext(), *getprev();
191 static int first = 1;
192 static int mode_insert = 1;
193 static int mode_wspace = 1; /* words separated by spaces */
196 static short char_map[600]= {
197 0, F_SOL, /* ^a Line start */
198 F_PRVWRD, /* ^b Previous word */ F_BREAK, /* ^C break */
199 F_DELCHR, /* ^D Delete character */ F_EOL, /* ^e End of line */
200 F_CSRRGT, /* ^f Right */ F_TABBAK, /* ^G Back tab */
201 F_CSRLFT, /* ^H Left */ F_TAB, /* ^I Tab */
202 F_CSRDWN, /* ^J Down */ F_DELEOL, /* ^K kill to eol */
203 F_CLRSCRN,/* ^L clear screen */ F_RETURN, /* ^M Carriage return */
204 F_RETURN, /* ^N enter line */ F_CONCAT, /* ^O Concatenate lines */
205 F_CSRUP, /* ^P cursor up */ F_TINS, /* ^Q Insert character mode */
206 F_PAGUP, /* ^R Page up */ F_CENTER, /* ^S Center text */
207 F_PAGDWN, /* ^T Page down */ F_DELSOL, /* ^U delete to start of line */
208 F_DELWRD, /* ^V Delete word */ F_PRVWRD, /* ^W Previous word */
209 F_NXTMCH, /* ^X Next match */ F_DELEOL, /* ^Y Delete to end of line */
210 F_BACKGND,/* ^Z Background */ 0x1B, /* ^[=ESC escape */
211 F_TENTRY, /* ^\ Entry mode */ F_PASTECB,/* ^]=paste clipboard */
212 F_HOME, /* ^^ Home */ F_ERSLIN, /* ^_ Erase line */
214 ' ','!','"','#','$','%','&','\047',
215 '(',')','*','+','\054','-','.','/',
216 '0','1','2','3','4','5','6','7',
217 '8','9',':',';','<','=','>','?',
218 '@','A','B','C','D','E','F','G',
219 'H','I','J','K','L','M','N','O',
220 'P','Q','R','S','T','U','V','W',
221 'X','Y','Z','[','\\',']','^','_',
222 '\140','a','b','c','d','e','f','g',
223 'h','i','j','k','l','m','n','o',
224 'p','q','r','s','t','u','v','w',
225 'x','y','z','{','|','}','\176',F_ERSCHR /* erase character */
230 /* Local variables */
232 #define CR '\r' /* carriage return */
235 /* Function Prototypes */
237 static unsigned int input_char(void);
238 static unsigned int t_gnc(void);
239 static void insert_space(char *curline, int line_len);
240 static void insert_hole(char *curline, int line_len);
241 static void forward(char *str, int str_len);
242 static void backup(char *curline);
243 static void delchr(int cnt, char *curline, int line_len);
244 static int iswordc(char c);
245 static int next_word(char *ldb_buf);
246 static int prev_word(char *ldb_buf);
247 static void prtcur(char *str);
248 static void poolinit(void);
249 static char * getnext(void);
250 static char * getprev(void);
251 static void putline(char *newl, int newlen);
252 static void t_honk_horn(void);
253 static void t_insert_line(void);
254 static void t_delete_line(void);
255 static void t_clrline(int pos, int width);
256 void t_sendl(const char *msg, int len);
257 void t_send(const char *msg);
259 static void asclrs();
260 static void ascurs(int y, int x);
262 static void rawmode(FILE *input);
263 static void normode(void);
264 static unsigned t_getch();
265 static void asclrl(int pos, int width);
266 static void asinsl();
267 static void asdell();
269 int input_line(char *string, int length);
277 void con_init(FILE *input)
287 void con_set_zed_keys(void)
289 char_map[1] = F_NXTWRD; /* ^A Next Word */
290 char_map[2] = F_SPLIT; /* ^B Split line */
291 char_map[3] = F_EOI; /* ^C Quit */
292 char_map[4] = F_DELCHR; /* ^D Delete character */
293 char_map[5] = F_EOF; /* ^E End of file */
294 char_map[6] = F_INSCHR; /* ^F Insert character */
295 char_map[7] = F_TABBAK; /* ^G Back tab */
296 char_map[8] = F_CSRLFT; /* ^H Left */
297 char_map[9] = F_TAB; /* ^I Tab */
298 char_map[10] = F_CSRDWN; /* ^J Down */
299 char_map[11] = F_CSRUP; /* ^K Up */
300 char_map[12] = F_CSRRGT; /* ^L Right */
301 char_map[13] = F_RETURN; /* ^M Carriage return */
302 char_map[14] = F_EOL; /* ^N End of line */
303 char_map[15] = F_CONCAT; /* ^O Concatenate lines */
304 char_map[16] = F_MARK; /* ^P Set marker */
305 char_map[17] = F_TINS; /* ^Q Insert character mode */
306 char_map[18] = F_PAGUP; /* ^R Page up */
307 char_map[19] = F_CENTER; /* ^S Center text */
308 char_map[20] = F_PAGDWN; /* ^T Page down */
309 char_map[21] = F_SOL; /* ^U Line start */
310 char_map[22] = F_DELWRD; /* ^V Delete word */
311 char_map[23] = F_PRVWRD; /* ^W Previous word */
312 char_map[24] = F_NXTMCH; /* ^X Next match */
313 char_map[25] = F_DELEOL; /* ^Y Delete to end of line */
314 char_map[26] = F_DELLIN; /* ^Z Delete line */
316 char_map[28] = F_TENTRY; /* ^\ Entry mode */
317 char_map[29] = F_PASTECB;/* ^]=paste clipboard */
318 char_map[30] = F_HOME; /* ^^ Home */
319 char_map[31] = F_ERSLIN; /* ^_ Erase line */
330 * Guarantee that the string is properly terminated */
331 char *bstrncpy(char *dest, const char *src, int maxlen)
333 strncpy(dest, src, maxlen-1);
341 * New style string mapping to function code
343 static unsigned do_smap(unsigned c)
363 for (i=len-1; i<MAX_STAB; i++) {
364 for (tstab=stab[i]; tstab; tstab=tstab->next) {
365 if (strncmp(str, tstab->str, len) == 0) {
366 if (len == tstab->len) {
370 break; /* found possibility continue searching */
377 /* found partial match, so get next character and retry */
378 str[len++] = t_gnc();
384 static void dump_stab()
390 for (i=0; i<MAX_STAB; i++) {
391 for (tstab=stab[i]; tstab; tstab=tstab->next) {
392 for (j=0; j<tstab->len; j++) {
394 if (c < 0x20 || c > 0x7F) {
395 sprintf(buf, " 0x%x ", c);
403 sprintf(buf, " func=%d len=%d\n\r", tstab->func, tstab->len);
411 * New routine. Add string to string->func mapping table.
413 static void add_smap(char *str, int func)
423 /* errmsg("String for func %d is zero length\n", func); */
426 tstab = (stab_t *)malloc(sizeof(stab_t));
427 memset(tstab, 0, sizeof(stab_t));
429 tstab->str = (char *)malloc(tstab->len + 1);
430 bstrncpy(tstab->str, str, tstab->len + 1);
432 if (tstab->len > num_stab) {
433 printf("stab string too long %d. Max is %d\n", tstab->len, num_stab);
436 tstab->next = stab[tstab->len-1];
437 stab[tstab->len-1] = tstab;
438 /* printf("Add_smap tstab=%x len=%d func=%d tstab->next=%x\n\r", tstab, len,
439 func, tstab->next); */
444 /* Get the next character from the terminal - performs table lookup on
445 the character to do the desired translation */
451 if ((c=t_gnc()) <= 599) { /* IBM generates codes up to 260 */
453 } else if (c > 1000) { /* stuffed function */
454 c -= 1000; /* convert back to function code */
459 /* if we got a screen size escape sequence, read height, width */
461 t_gnc(); /* - 0x20 = y */
462 t_gnc(); /* - 0x20 = x */
469 /* Get a complete input line */
472 input_line(char *string, int length)
474 char curline[2000]; /* edit buffer */
481 poolinit(); /* build line pool */
484 noline = 1; /* no line fetched yet */
485 for (cl=cp=0; cl<length && cl<(int)sizeof(curline); ) {
490 switch (c=input_char()) {
491 case F_RETURN: /* CR */
492 t_sendl("\r\n", 2); /* yes, print it and */
493 goto done; /* get out */
494 case F_CLRSCRN: /* clear screen */
496 t_sendl(curline, cl);
500 if (noline) { /* no line fetched yet */
501 getnext(); /* getnext so getprev gets current */
502 noline = 0; /* we now have line */
504 bstrncpy(curline, getprev(), sizeof(curline));
508 noline = 0; /* mark line fetched */
509 bstrncpy(curline, getnext(), sizeof(curline));
513 insert_space(curline, sizeof(curline));
516 delchr(1, curline, sizeof(curline)); /* delete one character */
518 case F_CSRLFT: /* Backspace */
522 forward(curline, sizeof(curline));
524 case F_ERSCHR: /* Rubout */
526 delchr(1, curline, sizeof(curline));
533 t_clrline(0, t_width);
538 i = next_word(curline);
540 forward(curline, sizeof(curline));
544 i = prev_word(curline);
550 delchr(next_word(curline), curline, sizeof(curline)); /* delete word */
552 case F_NXTMCH: /* Ctl-X */
554 *string = EOS; /* terminate string */
555 return(c); /* give it to him */
557 /* Note fall through */
561 backup(curline); /* backup to beginning of line */
563 t_clrline(0, t_width); /* erase line */
565 cl = 0; /* reset cursor counter */
576 forward(curline, sizeof(curline));
582 case F_TINS: /* toggle insert mode */
583 mode_insert = !mode_insert; /* flip bit */
586 if (c > 255) { /* function key hit */
587 if (cl==0) { /* if first character then */
588 *string = EOS; /* terminate string */
589 return c; /* return it */
591 t_honk_horn(); /* complain */
593 if ((c & 0xC0) == 0xC0) {
594 if ((c & 0xFC) == 0xFC) {
596 } else if ((c & 0xF8) == 0xF8) {
598 } else if ((c & 0xF0) == 0xF0) {
600 } else if ((c & 0xE0) == 0xE0) {
609 insert_space(curline, sizeof(curline));
611 curline[cp++] = c; /* store character in line being built */
612 t_char(c); /* echo character to terminal */
615 insert_hole(curline, sizeof(curline));
616 curline[cp++] = c; /* store character in line being built */
617 t_char(c); /* echo character to terminal */
620 cl = cp; /* keep current length */
627 /* If we fall through here rather than goto done, the line is too long
628 simply return what we have now. */
630 curline[cl++] = EOS; /* terminate */
631 bstrncpy(string,curline,length); /* return line to caller */
632 /* Save non-blank lines. Note, put line zaps curline */
633 if (curline[0] != EOS) {
634 putline(curline,cl); /* save line for posterity */
636 return 0; /* give it to him/her */
639 /* Insert a space at the current cursor position */
641 insert_space(char *curline, int curline_len)
645 if (cp >= cl || cl+1 > curline_len) {
648 /* Note! source and destination overlap */
649 memmove(&curline[cp+1],&curline[cp],i=cl-cp);
654 forward(curline, curline_len);
664 insert_hole(char *curline, int curline_len)
668 if (cp > cl || cl+1 > curline_len) {
671 /* Note! source and destination overlap */
672 memmove(&curline[cp+1], &curline[cp], i=cl-cp);
678 /* Move cursor forward keeping characters under it */
680 forward(char *str, int str_len)
691 if ((str[cp] & 0xC0) == 0xC0) {
693 while ((str[cp] & 0xC0) == 0x80) {
703 /* How many characters under the cursor */
705 char_count(int cptr, char *str)
711 if ((str[cptr] & 0xC0) == 0xC0) {
713 while ((str[cptr] & 0xC0) == 0x80) {
721 /* Backup cursor keeping characters under it */
728 while ((str[cp] & 0xC0) == 0x80) {
735 /* Delete the character under the cursor */
737 delchr(int del, char *curline, int line_len)
741 if (cp > cl || del == 0) {
744 while (del-- && cl > 0) {
745 cnt = char_count(cp, curline);
746 if ((i=cl-cp-cnt) > 0) {
747 memcpy(&curline[cp], &curline[cp+cnt], i);
751 t_clrline(0, t_width);
754 forward(curline, line_len);
763 /* Determine if character is part of a word */
769 if (c >= '0' && c <= '9')
771 if (c == '$' || c == '%')
776 /* Return number of characters to get to next word */
778 next_word(char *ldb_buf)
785 for ( ; ncp<cl && iswordc(*(ldb_buf+ncp)); ncp++) ;
786 for ( ; ncp<cl && !iswordc(*(ldb_buf+ncp)); ncp++) ;
790 /* Return number of characters to get to previous word */
792 prev_word(char *ldb_buf)
796 if (cp == 0) /* if at begin of line stop now */
798 if (cp > cl) /* if past eol start at eol */
802 /* backup to end of previous word - i.e. skip special chars */
803 for (i=ncp-1; i && !iswordc(*(ldb_buf+i)); i--) ;
804 if (i == 0) { /* at beginning of line? */
805 return cp; /* backup to beginning */
807 /* now move back through word to beginning of word */
808 for ( ; i && iswordc(*(ldb_buf+i)); i--) ;
809 ncp = i+1; /* position to first char of word */
810 if (i==0 && iswordc(*ldb_buf)) /* check for beginning of line */
812 return cp-ncp; /* return count */
815 /* Display new current line */
822 t_clrline(0,t_width);
823 cp = cl = strlen(str);
828 /* Initialize line pool. Split pool into two pieces. */
832 slptr = lptr = (struct lstr *)pool;
841 /* Return pointer to next line in the pool and advance current line pointer */
845 do { /* find next used line */
847 } while (!lptr->used);
848 return (char *)&lptr->line;
851 /* Return pointer to previous line in the pool */
855 do { /* find previous used line */
857 } while (!lptr->used);
858 return (char *)&lptr->line;
862 putline(char *newl, int newlen)
864 struct lstr *nptr; /* points to next line */
867 lptr = slptr; /* get ptr to last line stored */
868 lptr = lptr->nextl; /* advance pointer */
869 if ((char *)lptr-pool+newlen+PHDRL > POOLEN) { /* not enough room */
870 lptr->used = 0; /* delete line */
871 lptr = (struct lstr *)pool; /* start at beginning of buffer */
873 while (lptr->len < newlen+PHDRL) { /* concatenate buffers */
874 nptr = lptr->nextl; /* point to next line */
875 lptr->nextl = nptr->nextl; /* unlink it from list */
876 nptr->nextl->prevl = lptr;
877 lptr->len += nptr->len;
879 if (lptr->len > newlen + 2 * PHDRL + 7) { /* split buffer */
880 nptr = (struct lstr *)((char *)lptr + newlen + PHDRL);
881 /* Appropriate byte alignment - for Intel 2 byte, but on
882 Sparc we need 8 byte alignment, so we always do 8 */
883 if (((long unsigned)nptr & 7) != 0) { /* test eight byte alignment */
885 nptr = (struct lstr *)((((long unsigned) p) & ~7) + 8);
887 nptr->len = lptr->len - ((char *)nptr - (char *)lptr);
888 lptr->len -= nptr->len;
889 nptr->nextl = lptr->nextl; /* link in new buffer */
890 lptr->nextl->prevl = nptr;
895 memcpy(&lptr->line,newl,newlen);
896 lptr->used = 1; /* mark line used */
897 slptr = lptr; /* save as stored line */
902 dump(struct lstr *ptr, char *msg)
904 printf("%s buf=%x nextl=%x prevl=%x len=%d used=%d\n",
905 msg,ptr,ptr->nextl,ptr->prevl,ptr->len,ptr->used);
907 printf("line=%s\n",&ptr->line);
909 #endif /* DEBUGOUT */
912 /* Honk horn on terminal */
919 /* Insert line on terminal */
926 /* Delete line from terminal */
933 /* clear line from pos to width */
935 t_clrline(int pos, int width)
937 asclrl(pos, width); /* clear to end of line */
940 /* Helper function to add string preceded by
941 * ESC to smap table */
942 static void add_esc_smap(const char *str, int func)
945 buf[0] = 0x1B; /* esc */
946 bstrncpy(buf+1, str, sizeof(buf)-1);
950 /* Set raw mode on terminal file. Basically, get the terminal into a
951 mode in which all characters can be read as they are entered. CBREAK
952 mode is not sufficient.
954 static void rawmode(FILE *input)
957 static char term_buf[2048];
958 static char *term_buffer = term_buf;
959 char *termtype = (char *)getenv("TERM");
961 /* Make sure we are dealing with a terminal */
962 if (!isatty(fileno(input))) {
965 if (tcgetattr(0, &old_term_params) != 0) {
966 printf("conio: Cannot tcgetattr()\n");
969 old_term_params_set = true;
971 t.c_cc[VMIN] = 1; /* satisfy read after 1 char */
973 t.c_iflag &= ~(BRKINT | IGNPAR | PARMRK | INPCK |
974 ISTRIP | ICRNL | IXON | IXOFF | INLCR | IGNCR);
977 t.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL | ICANON |
979 tcflush(0, TCIFLUSH);
980 if (tcsetattr(0, TCSANOW, &t) == -1) {
981 printf("Cannot tcsetattr()\n");
984 /* Defaults, the main program can override these */
985 signal(SIGQUIT, SIG_IGN);
986 signal(SIGHUP, SIG_IGN);
987 signal(SIGINT, sigintcatcher);
988 signal(SIGWINCH, SIG_IGN);
991 printf("Cannot get terminal type.\n");
995 if (tgetent(term_buffer, termtype) < 0) {
996 printf("Cannot get terminal termcap entry.\n");
1000 t_width = t_height = -1;
1001 /* Note (char *)casting is due to really stupid compiler warnings */
1002 t_width = tgetnum((char *)"co") - 1;
1003 t_height = tgetnum((char *)"li");
1006 t_cm = (char *)tgetstr((char *)"cm", &term_buffer);
1007 t_cs = (char *)tgetstr((char *)"cl", &term_buffer); /* clear screen */
1008 t_cl = (char *)tgetstr((char *)"ce", &term_buffer); /* clear line */
1009 t_dl = (char *)tgetstr((char *)"dl", &term_buffer); /* delete line */
1010 t_il = (char *)tgetstr((char *)"al", &term_buffer); /* insert line */
1011 t_honk = (char *)tgetstr((char *)"bl", &term_buffer); /* beep */
1012 t_ti = (char *)tgetstr((char *)"ti", &term_buffer);
1013 t_te = (char *)tgetstr((char *)"te", &term_buffer);
1014 t_up = (char *)tgetstr((char *)"up", &term_buffer);
1015 t_do = (char *)tgetstr((char *)"do", &term_buffer);
1016 t_sf = (char *)tgetstr((char *)"sf", &term_buffer);
1018 num_stab = MAX_STAB; /* get default stab size */
1019 stab = (stab_t **)malloc(sizeof(stab_t *) * num_stab);
1020 memset(stab, 0, sizeof(stab_t *) * num_stab);
1023 kl = (char *)tgetstr((char *)"kl", &term_buffer);
1024 kr = (char *)tgetstr((char *)"kr", &term_buffer);
1025 ku = (char *)tgetstr((char *)"ku", &term_buffer);
1026 kd = (char *)tgetstr((char *)"kd", &term_buffer);
1027 kh = (char *)tgetstr((char *)"kh", &term_buffer);
1028 kb = (char *)tgetstr((char *)"kb", &term_buffer);
1029 kD = (char *)tgetstr((char *)"kD", &term_buffer);
1030 kI = (char *)tgetstr((char *)"kI", &term_buffer);
1031 kN = (char *)tgetstr((char *)"kN", &term_buffer);
1032 kP = (char *)tgetstr((char *)"kP", &term_buffer);
1033 kH = (char *)tgetstr((char *)"kH", &term_buffer);
1034 kE = (char *)tgetstr((char *)"kE", &term_buffer);
1036 add_smap(kl, F_CSRLFT);
1037 add_smap(kr, F_CSRRGT);
1038 add_smap(ku, F_CSRUP);
1039 add_smap(kd, F_CSRDWN);
1040 add_smap(kI, F_TINS);
1041 add_smap(kN, F_PAGDWN);
1042 add_smap(kP, F_PAGUP);
1043 add_smap(kH, F_HOME);
1044 add_smap(kE, F_EOF);
1047 add_esc_smap("[A", F_CSRUP);
1048 add_esc_smap("[B", F_CSRDWN);
1049 add_esc_smap("[C", F_CSRRGT);
1050 add_esc_smap("[D", F_CSRLFT);
1051 add_esc_smap("[1~", F_HOME);
1052 add_esc_smap("[2~", F_TINS);
1053 add_esc_smap("[3~", F_DELCHR);
1054 add_esc_smap("[4~", F_EOF);
1055 add_esc_smap("f", F_NXTWRD);
1056 add_esc_smap("b", F_PRVWRD);
1060 /* Restore tty mode */
1061 static void normode()
1063 if (old_term_params_set) {
1064 tcsetattr(0, TCSANOW, &old_term_params);
1065 old_term_params_set = false;
1069 /* Get next character from terminal/script file/unget buffer */
1077 /* Get next character from OS */
1078 static unsigned t_getch(void)
1082 if (read(0, &c, 1) != 1) {
1088 /* Send message to terminal - primitive routine */
1090 t_sendl(const char *msg, int len)
1096 t_send(const char *msg)
1101 t_sendl(msg, strlen(msg)); /* faster than one char at time */
1104 /* Send single character to terminal - primitive routine - */
1108 (void)write(1, &c, 1);
1112 static int brkflg = 0; /* set on user break */
1114 /* Routine to return true if user types break */
1120 /* Clear break flag */
1127 /* Interrupt caught here */
1128 static void sigintcatcher(int sig)
1135 signal(SIGINT, sigintcatcher);
1142 signal(SIGINT, sigintcatcher);
1146 /* ASCLRL() -- Clear to end of line from current position */
1147 static void asclrl(int pos, int width)
1152 t_send(t_cl); /* use clear to eol function */
1155 if (pos==1 && linsdel_ok) {
1156 t_delete_line(); /* delete line */
1157 t_insert_line(); /* reinsert it */
1160 for (i=1; i<=width-pos+1; i++)
1161 t_char(' '); /* last resort, blank it out */
1162 for (i=1; i<=width-pos+1; i++) /* backspace to original position */
1169 /* ASCURS -- Set cursor position */
1170 static void ascurs(int y, int x)
1172 t_send((char *)tgoto(t_cm, x, y));
1176 /* ASCLRS -- Clear whole screen */
1177 static void asclrs()
1185 /* ASINSL -- insert new line after cursor */
1186 static void asinsl()
1188 t_clrline(0, t_width);
1189 t_send(t_il); /* insert before */
1192 /* ASDELL -- Delete line at cursor */
1193 static void asdell()