2 Generalized console input/output handler
3 A maintanable replacement for readline()
5 Updated for Bacula, Kern Sibbald, December MMIII
7 This code is in part derived from code that I wrote in
8 1981, so some of it is a bit old and could use a cleanup.
12 Copyright (C) 1981-2005 Kern Sibbald
13 Yes, that is 1981 no error.
15 This program is free software; you can redistribute it and/or
16 modify it under the terms of the GNU General Public License as
17 published by the Free Software Foundation; either version 2 of
18 the License, or (at your option) any later version.
20 This program is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 General Public License for more details.
25 You should have received a copy of the GNU General Public
26 License along with this program; if not, write to the Free
27 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
34 * If the top bit of a UTF-8 string is 0 (8 bits), then it
35 * is a normal ASCII character.
36 * If the top two bits are 11 (i.e. (c & 0xC0) == 0xC0 then
37 * it is the start of a series of chars (up to 5)
38 * Each subsequent character starts with 10 (i.e. (c & 0xC0) == 0x80)
51 /* We are in Bacula */
58 extern "C" int tgetent(void *, const char *);
59 extern "C" int tgetnum(const char *);
60 extern "C" char *tgetstr (const char*, char**);
61 extern "C" char *tgoto (const char *, int, int);
64 #elif defined (__digital__) && defined (__unix__)
65 extern "C" int tgetent(void *, const char *);
66 extern "C" int tgetnum(const char *);
67 extern "C" char *tgetstr (const char*, char**);
68 extern "C" char *tgoto (const char *, int, int);
76 /* From termios library */
85 /* Forward referenced functions */
87 static void sigintcatcher(int);
90 static void add_smap(char *str, int func);
93 /* Global variables */
95 static const char *t_up = "\n"; /* scroll up character */
96 static const char *t_honk = "\007"; /* sound beep */
97 static char *t_il; /* insert line */
98 static char *t_dl; /* delete line */
99 static char *t_cs; /* clear screen */
100 static char *t_cl; /* clear line */
101 static int t_width = 79; /* terminal width */
102 static int t_height = 24; /* terminal height */
103 static int linsdel_ok = 0; /* set if term has line insert & delete fncs */
105 static char *t_cm; /* cursor positioning */
106 static char *t_ti; /* init sequence */
107 static char *t_te; /* end sequence */
108 static char *t_do; /* down one line */
109 static char *t_sf; /* scroll screen one line up */
111 /* Keypad and Function Keys */
112 static char *kl; /* left key */
113 static char *kr; /* right */
114 static char *ku; /* up */
115 static char *kd; /* down */
116 static char *kh; /* home */
117 static char *kb; /* backspace */
118 static char *kD; /* delete key */
119 static char *kI; /* insert */
120 static char *kN; /* next page */
121 static char *kP; /* previous page */
122 static char *kH; /* home */
123 static char *kE; /* end */
126 #define EOS '\0' /* end of string terminator */
132 * Stab entry. Input chars (str), the length, and the desired
135 typedef struct s_stab {
144 static stab_t **stab = NULL; /* array of stabs by length */
145 static int num_stab; /* size of stab array */
147 static bool old_term_params_set = false;
148 static struct termios old_term_params;
150 /* Maintain lines in a doubly linked circular pool of lines. Each line is
151 preceded by a header defined by the lstr structure */
154 struct lstr { /* line pool structure */
155 struct lstr *prevl; /* link to previous line */
156 struct lstr *nextl; /* link to next line */
157 long len; /* length of line+header */
158 char used; /* set if line valid */
159 char line; /* line is actually varying length */
163 #define POOLEN 128000 /* bytes in line pool */
165 #define POOLEN 500 /* bytes in line pool */
167 char pool[POOLEN]; /* line pool */
168 #define PHDRL ((int)sizeof(struct lstr)) /* length of line header */
170 static struct lstr *lptr; /* current line pointer */
171 static struct lstr *slptr; /* store line pointer */
173 static char *getnext(), *getprev();
174 static int first = 1;
175 static int mode_insert = 0;
176 static int mode_wspace = 1; /* words separated by spaces */
179 static short char_map[600]= {
180 0, F_SOL, /* ^a Line start */
181 F_PRVWRD, /* ^b Previous word */ F_BREAK, /* ^C break */
182 F_DELCHR, /* ^D Delete character */ F_EOL, /* ^e End of line */
183 F_CSRRGT, /* ^f Right */ F_TABBAK, /* ^G Back tab */
184 F_CSRLFT, /* ^H Left */ F_TAB, /* ^I Tab */
185 F_CSRDWN, /* ^J Down */ F_DELEOL, /* ^K kill to eol */
186 F_CLRSCRN,/* ^L clear screen */ F_RETURN, /* ^M Carriage return */
187 F_RETURN, /* ^N enter line */ F_CONCAT, /* ^O Concatenate lines */
188 F_CSRUP, /* ^P cursor up */ F_TINS, /* ^Q Insert character mode */
189 F_PAGUP, /* ^R Page up */ F_CENTER, /* ^S Center text */
190 F_PAGDWN, /* ^T Page down */ F_DELSOL, /* ^U delete to start of line */
191 F_DELWRD, /* ^V Delete word */ F_PRVWRD, /* ^W Previous word */
192 F_NXTMCH, /* ^X Next match */ F_DELEOL, /* ^Y Delete to end of line */
193 F_BACKGND,/* ^Z Background */ 0x1B, /* ^[=ESC escape */
194 F_TENTRY, /* ^\ Entry mode */ F_PASTECB,/* ^]=paste clipboard */
195 F_HOME, /* ^^ Home */ F_ERSLIN, /* ^_ Erase line */
197 ' ','!','"','#','$','%','&','\047',
198 '(',')','*','+','\054','-','.','/',
199 '0','1','2','3','4','5','6','7',
200 '8','9',':',';','<','=','>','?',
201 '@','A','B','C','D','E','F','G',
202 'H','I','J','K','L','M','N','O',
203 'P','Q','R','S','T','U','V','W',
204 'X','Y','Z','[','\\',']','^','_',
205 '\140','a','b','c','d','e','f','g',
206 'h','i','j','k','l','m','n','o',
207 'p','q','r','s','t','u','v','w',
208 'x','y','z','{','|','}','\176',F_ERSCHR /* erase character */
213 /* Local variables */
215 #define CR '\r' /* carriage return */
218 /* Function Prototypes */
220 static unsigned int input_char(void);
221 static unsigned int t_gnc(void);
222 static void insert_space(char *curline, int line_len);
223 static void insert_hole(char *curline, int line_len);
224 static void forward(char *str, int str_len);
225 static void backup(char *curline);
226 static void delchr(int cnt, char *curline, int line_len);
227 static int iswordc(char c);
228 static int next_word(char *ldb_buf);
229 static int prev_word(char *ldb_buf);
230 static void prtcur(char *str);
231 static void poolinit(void);
232 static char * getnext(void);
233 static char * getprev(void);
234 static void putline(char *newl, int newlen);
235 static void t_honk_horn(void);
236 static void t_insert_line(void);
237 static void t_delete_line(void);
238 static void t_clrline(int pos, int width);
239 void t_sendl(const char *msg, int len);
240 void t_send(const char *msg);
242 static void asclrs();
243 static void ascurs(int y, int x);
245 static void rawmode(FILE *input);
246 static void normode(void);
247 static unsigned t_getch();
248 static void asclrl(int pos, int width);
249 static void asinsl();
250 static void asdell();
252 int input_line(char *string, int length);
260 void con_init(FILE *input)
270 void con_set_zed_keys(void)
272 char_map[1] = F_NXTWRD; /* ^A Next Word */
273 char_map[2] = F_SPLIT; /* ^B Split line */
274 char_map[3] = F_EOI; /* ^C Quit */
275 char_map[4] = F_DELCHR; /* ^D Delete character */
276 char_map[5] = F_EOF; /* ^E End of file */
277 char_map[6] = F_INSCHR; /* ^F Insert character */
278 char_map[7] = F_TABBAK; /* ^G Back tab */
279 char_map[8] = F_CSRLFT; /* ^H Left */
280 char_map[9] = F_TAB; /* ^I Tab */
281 char_map[10] = F_CSRDWN; /* ^J Down */
282 char_map[11] = F_CSRUP; /* ^K Up */
283 char_map[12] = F_CSRRGT; /* ^L Right */
284 char_map[13] = F_RETURN; /* ^M Carriage return */
285 char_map[14] = F_EOL; /* ^N End of line */
286 char_map[15] = F_CONCAT; /* ^O Concatenate lines */
287 char_map[16] = F_MARK; /* ^P Set marker */
288 char_map[17] = F_TINS; /* ^Q Insert character mode */
289 char_map[18] = F_PAGUP; /* ^R Page up */
290 char_map[19] = F_CENTER; /* ^S Center text */
291 char_map[20] = F_PAGDWN; /* ^T Page down */
292 char_map[21] = F_SOL; /* ^U Line start */
293 char_map[22] = F_DELWRD; /* ^V Delete word */
294 char_map[23] = F_PRVWRD; /* ^W Previous word */
295 char_map[24] = F_NXTMCH; /* ^X Next match */
296 char_map[25] = F_DELEOL; /* ^Y Delete to end of line */
297 char_map[26] = F_DELLIN; /* ^Z Delete line */
299 char_map[28] = F_TENTRY; /* ^\ Entry mode */
300 char_map[29] = F_PASTECB;/* ^]=paste clipboard */
301 char_map[30] = F_HOME; /* ^^ Home */
302 char_map[31] = F_ERSLIN; /* ^_ Erase line */
313 * Guarantee that the string is properly terminated */
314 char *bstrncpy(char *dest, const char *src, int maxlen)
316 strncpy(dest, src, maxlen-1);
324 * New style string mapping to function code
326 static unsigned do_smap(unsigned c)
346 for (i=len-1; i<MAX_STAB; i++) {
347 for (tstab=stab[i]; tstab; tstab=tstab->next) {
348 if (strncmp(str, tstab->str, len) == 0) {
349 if (len == tstab->len) {
353 break; /* found possibility continue searching */
360 /* found partial match, so get next character and retry */
361 str[len++] = t_gnc();
367 static void dump_stab()
373 for (i=0; i<MAX_STAB; i++) {
374 for (tstab=stab[i]; tstab; tstab=tstab->next) {
375 for (j=0; j<tstab->len; j++) {
377 if (c < 0x20 || c > 0x7F) {
378 sprintf(buf, " 0x%x ", c);
386 sprintf(buf, " func=%d len=%d\n\r", tstab->func, tstab->len);
394 * New routine. Add string to string->func mapping table.
396 static void add_smap(char *str, int func)
406 /* errmsg("String for func %d is zero length\n", func); */
409 tstab = (stab_t *)malloc(sizeof(stab_t));
410 memset(tstab, 0, sizeof(stab_t));
412 tstab->str = (char *)malloc(tstab->len + 1);
413 bstrncpy(tstab->str, str, tstab->len + 1);
415 if (tstab->len > num_stab) {
416 printf("stab string too long %d. Max is %d\n", tstab->len, num_stab);
419 tstab->next = stab[tstab->len-1];
420 stab[tstab->len-1] = tstab;
421 /* printf("Add_smap tstab=%x len=%d func=%d tstab->next=%x\n\r", tstab, len,
422 func, tstab->next); */
427 /* Get the next character from the terminal - performs table lookup on
428 the character to do the desired translation */
434 if ((c=t_gnc()) <= 599) { /* IBM generates codes up to 260 */
436 } else if (c > 1000) { /* stuffed function */
437 c -= 1000; /* convert back to function code */
442 /* if we got a screen size escape sequence, read height, width */
445 y = t_gnc() - 0x20; /* y */
446 x = t_gnc() - 0x20; /* x */
453 /* Get a complete input line */
456 input_line(char *string, int length)
458 char curline[2000]; /* edit buffer */
465 poolinit(); /* build line pool */
468 noline = 1; /* no line fetched yet */
469 for (cl=cp=0; cl<length && cl<(int)sizeof(curline); ) {
474 switch (c=input_char()) {
475 case F_RETURN: /* CR */
476 t_sendl("\r\n", 2); /* yes, print it and */
477 goto done; /* get out */
478 case F_CLRSCRN: /* clear screen */
480 t_sendl(curline, cl);
484 if (noline) { /* no line fetched yet */
485 getnext(); /* getnext so getprev gets current */
486 noline = 0; /* we now have line */
488 bstrncpy(curline, getprev(), sizeof(curline));
492 noline = 0; /* mark line fetched */
493 bstrncpy(curline, getnext(), sizeof(curline));
497 insert_space(curline, sizeof(curline));
500 delchr(1, curline, sizeof(curline)); /* delete one character */
502 case F_CSRLFT: /* Backspace */
506 forward(curline, sizeof(curline));
508 case F_ERSCHR: /* Rubout */
510 delchr(1, curline, sizeof(curline));
517 t_clrline(0, t_width);
522 i = next_word(curline);
524 forward(curline, sizeof(curline));
528 i = prev_word(curline);
534 delchr(next_word(curline), curline, sizeof(curline)); /* delete word */
536 case F_NXTMCH: /* Ctl-X */
538 *string = EOS; /* terminate string */
539 return(c); /* give it to him */
541 /* Note fall through */
545 backup(curline); /* backup to beginning of line */
547 t_clrline(0, t_width); /* erase line */
549 cl = 0; /* reset cursor counter */
560 forward(curline, sizeof(curline));
566 case F_TINS: /* toggle insert mode */
567 mode_insert = !mode_insert; /* flip bit */
570 if (c > 255) { /* function key hit */
571 if (cl==0) { /* if first character then */
572 *string = EOS; /* terminate string */
573 return c; /* return it */
575 t_honk_horn(); /* complain */
577 if ((c & 0xC0) == 0xC0) {
578 if ((c & 0xFC) == 0xFC) {
580 } else if ((c & 0xF8) == 0xF8) {
582 } else if ((c & 0xF0) == 0xF0) {
584 } else if ((c & 0xE0) == 0xE0) {
593 insert_space(curline, sizeof(curline));
595 curline[cp++] = c; /* store character in line being built */
596 t_char(c); /* echo character to terminal */
599 insert_hole(curline, sizeof(curline));
600 curline[cp++] = c; /* store character in line being built */
601 t_char(c); /* echo character to terminal */
604 cl = cp; /* keep current length */
611 /* If we fall through here rather than goto done, the line is too long
612 simply return what we have now. */
614 curline[cl++] = EOS; /* terminate */
615 bstrncpy(string,curline,length); /* return line to caller */
616 /* Note, put line zaps curline */
617 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-- && cp > 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) { /* split buffer */
862 nptr = (struct lstr *)((char *)lptr + newlen + PHDRL);
863 /* Appropriate byte alignment - normally 2 byte, but on
864 sparc we need 4 byte alignment, so we always do 4 */
865 if (((long unsigned)nptr & 3) != 0) { /* test four byte alignment */
867 nptr = (struct lstr *)((((long unsigned) p) & ~3) + 4);
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);
969 // signal(SIGSTOP, SIG_IGN);
970 signal(SIGINT, sigintcatcher);
971 signal(SIGWINCH, SIG_IGN);
972 signal(SIGQUIT, SIG_IGN);
973 signal(SIGCHLD, SIG_IGN);
974 // signal(SIGTSTP, SIG_IGN);
977 printf("Cannot get terminal type.\n");
981 if (tgetent(term_buffer, termtype) < 0) {
982 printf("Cannot get terminal termcap entry.\n");
986 t_width = t_height = -1;
987 t_width = tgetnum("co") - 1;
988 t_height = tgetnum("li");
991 t_cm = (char *)tgetstr("cm", &term_buffer);
992 t_cs = (char *)tgetstr("cl", &term_buffer); /* clear screen */
993 t_cl = (char *)tgetstr("ce", &term_buffer); /* clear line */
994 t_dl = (char *)tgetstr("dl", &term_buffer); /* delete line */
995 t_il = (char *)tgetstr("al", &term_buffer); /* insert line */
996 t_honk = (char *)tgetstr("bl", &term_buffer); /* beep */
997 t_ti = (char *)tgetstr("ti", &term_buffer);
998 t_te = (char *)tgetstr("te", &term_buffer);
999 t_up = (char *)tgetstr("up", &term_buffer);
1000 t_do = (char *)tgetstr("do", &term_buffer);
1001 t_sf = (char *)tgetstr("sf", &term_buffer);
1003 num_stab = MAX_STAB; /* get default stab size */
1004 stab = (stab_t **)malloc(sizeof(stab_t *) * num_stab);
1005 memset(stab, 0, sizeof(stab_t *) * num_stab);
1008 kl = (char *)tgetstr("kl", &term_buffer);
1009 kr = (char *)tgetstr("kr", &term_buffer);
1010 ku = (char *)tgetstr("ku", &term_buffer);
1011 kd = (char *)tgetstr("kd", &term_buffer);
1012 kh = (char *)tgetstr("kh", &term_buffer);
1013 kb = (char *)tgetstr("kb", &term_buffer);
1014 kD = (char *)tgetstr("kD", &term_buffer);
1015 kI = (char *)tgetstr("kI", &term_buffer);
1016 kN = (char *)tgetstr("kN", &term_buffer);
1017 kP = (char *)tgetstr("kP", &term_buffer);
1018 kH = (char *)tgetstr("kH", &term_buffer);
1019 kE = (char *)tgetstr("kE", &term_buffer);
1021 add_smap(kl, F_CSRLFT);
1022 add_smap(kr, F_CSRRGT);
1023 add_smap(ku, F_CSRUP);
1024 add_smap(kd, F_CSRDWN);
1025 add_smap(kI, F_TINS);
1026 add_smap(kN, F_PAGDWN);
1027 add_smap(kP, F_PAGUP);
1028 add_smap(kH, F_HOME);
1029 add_smap(kE, F_EOF);
1032 add_esc_smap("[A", F_CSRUP);
1033 add_esc_smap("[B", F_CSRDWN);
1034 add_esc_smap("[C", F_CSRRGT);
1035 add_esc_smap("[D", F_CSRLFT);
1036 add_esc_smap("[1~", F_HOME);
1037 add_esc_smap("[2~", F_TINS);
1038 add_esc_smap("[3~", F_DELCHR);
1039 add_esc_smap("[4~", F_EOF);
1040 add_esc_smap("f", F_NXTWRD);
1041 add_esc_smap("b", F_PRVWRD);
1045 /* Restore tty mode */
1046 static void normode()
1048 if (old_term_params_set) {
1049 tcsetattr(0, TCSANOW, &old_term_params);
1050 old_term_params_set = false;
1054 /* Get next character from terminal/script file/unget buffer */
1062 /* Get next character from OS */
1063 static unsigned t_getch(void)
1067 if (read(0, &c, 1) != 1) {
1073 /* Send message to terminal - primitive routine */
1075 t_sendl(const char *msg, int len)
1081 t_send(const char *msg)
1086 t_sendl(msg, strlen(msg)); /* faster than one char at time */
1089 /* Send single character to terminal - primitive routine - */
1097 static int brkflg = 0; /* set on user break */
1099 /* Routine to return true if user types break */
1105 /* Clear break flag */
1112 /* Interrupt caught here */
1113 static void sigintcatcher(int sig)
1120 signal(SIGINT, sigintcatcher);
1127 signal(SIGINT, sigintcatcher);
1131 /* ASCLRL() -- Clear to end of line from current position */
1132 static void asclrl(int pos, int width)
1137 t_send(t_cl); /* use clear to eol function */
1140 if (pos==1 && linsdel_ok) {
1141 t_delete_line(); /* delete line */
1142 t_insert_line(); /* reinsert it */
1145 for (i=1; i<=width-pos+1; i++)
1146 t_char(' '); /* last resort, blank it out */
1147 for (i=1; i<=width-pos+1; i++) /* backspace to original position */
1154 /* ASCURS -- Set cursor position */
1155 static void ascurs(int y, int x)
1157 t_send((char *)tgoto(t_cm, x, y));
1161 /* ASCLRS -- Clear whole screen */
1162 static void asclrs()
1170 /* ASINSL -- insert new line after cursor */
1171 static void asinsl()
1173 t_clrline(0, t_width);
1174 t_send(t_il); /* insert before */
1177 /* ASDELL -- Delete line at cursor */
1178 static void asdell()