]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/console/conio.c
Add this for symmetry
[bacula/bacula] / bacula / src / console / conio.c
1 /*        
2       Generalized consol input/output handler
3       Kern Sibbald, December MMIII
4 */
5
6 #define BACULA
7 #ifdef BACULA
8 #include "bacula.h"
9 #else
10 #include <stdio.h>
11 #include <unistd.h>
12 #include <signal.h>
13 #include <string.h>
14 #include <ctype.h> 
15 #endif
16
17 #include <curses.h>
18 #include <term.h>
19 #include "func.h"
20
21 /* Global functions imported */
22
23
24 extern char *getenv(char *);
25
26 static void add_smap(char *str, int func);
27
28 /* From termios library */
29 extern char *BC;
30 extern char *UP;
31
32 /* Global variables */
33
34 static char *t_up = "\n";                    /* scroll up character */
35 static char *t_honk = "\007";                /* sound beep */
36 static char *t_flag = "+";                   /* mark flag sequence */
37 static char *t_norm = " ";                   /* clear mark sequence */
38 static char *t_il;                           /* insert line */
39 static char *t_dl;                           /* delete line */
40 static char *t_cs;                           /* clear screen */
41 static char *t_cl;                           /* clear line */
42 static int t_width = 79;                     /* terminal width */
43 static int t_height = 24;                    /* terminal height */
44 static int t_flagl = 1;                      /* # chars for flag */
45 static int linsdel_ok = 0;              /* set if term has line insert & delete fncs */
46 static short dioflag = 1;                    /* set if ok to use ibm bios calls */
47
48 static char *t_cm;                           /* cursor positioning */
49 static char *t_ti;                           /* init sequence */
50 static char *t_te;                           /* end sequence */
51 static char *t_do;                           /* down one line */
52 static char *t_sf;                           /* scroll screen one line up */
53
54 /* Keypad and Function Keys */
55 static char *kl;                             /* left key */
56 static char *kr;                             /* right */
57 static char *ku;
58 static char *kd;
59 static char *kh;                             /* home */
60 static char *kb;                             /* backspace */
61 static char *k0;                             /* function key 10 */
62 static char *k1;                             /* function key 1 */
63 static char *k2;                             /* function key 2 */
64 static char *k3;                             /* function key 3 */
65 static char *k4;                             /* function key 4 */
66 static char *k5;                             /* function key 5 */
67 static char *k6;                             /* function key 6 */
68 static char *k7;                             /* function key 7 */
69 static char *k8;                             /* function key 8 */
70 static char *k9;                             /* function key 9 */
71 static char *kD;                             /* delete key */
72 static char *kI;                             /* insert */
73 static char *kN;                             /* next page */
74 static char *kP;                             /* previous page */
75 static char *kH;                             /* home */
76 static char *kE;                             /* end */
77
78 static int use_termcap;
79 #ifndef EOS
80 #define EOS  '\0'                     /* end of string terminator */
81 #endif
82
83 #define TRUE  1
84 #define FALSE 0
85 /*
86  * Stab entry. Input chars (str), the length, and the desired
87  *  func code.
88  */
89 typedef struct s_stab {
90    struct s_stab *next;
91    int len;
92    int func;
93    char *str;
94 } stab_t;
95
96 #define MAX_STAB 30
97
98 static stab_t **stab = NULL;                 /* array of stabs by length */
99 static int num_stab;                         /* size of stab array */
100
101 /* Local variables */
102
103 static struct termios old_term_params;
104
105 /* Maintain lines in a doubly linked circular pool of lines. Each line is
106    preceded by a header defined by the lstr structure */
107
108
109 struct lstr {                         /* line pool structure */
110    struct lstr *prevl;                /* link to previous line */
111    struct lstr *nextl;                /* link to next line */
112    long len;                          /* length of line+header */
113    char used;                         /* set if line valid */
114    char line;                         /* line is actually varying length */
115 };
116
117 #ifdef unix
118 #define POOLEN 128000                 /* bytes in line pool */
119 #else
120 #define POOLEN 500                    /* bytes in line pool */
121 #endif
122 char pool[POOLEN];                    /* line pool */
123 #define PHDRL ((int)sizeof(struct lstr))  /* length of line header */
124
125 static struct lstr *lptr;             /* current line pointer */
126 static struct lstr *slptr;            /* store line pointer */
127 static int cl, cp;
128 static char *getnext(), *getprev();
129 static int first = 1;
130 static int mode_insert = 0;
131 static int mode_wspace = 1;           /* words separated by spaces */
132
133 /* Forward referenced functions */
134 static void sigintcatcher(int);
135
136 /* Global variables Exported */
137
138 static short char_map[600]= {
139    0,                                  F_NXTWRD, /* ^A Next Word */
140    F_SPLIT,  /* ^B Split line */       F_EOI,    /* ^C Quit */
141    F_DELCHR, /* ^D Delete character */ F_EOF,    /* ^E End of file */
142    F_INSCHR, /* ^F Insert character */ F_TABBAK, /* ^G Back tab */
143    F_CSRLFT, /* ^H Left */             F_TAB,    /* ^I Tab */
144    F_CSRDWN, /* ^J Down */             F_CSRUP,  /* ^K Up */
145    F_CSRRGT, /* ^L Right */            F_RETURN, /* ^M Carriage return */
146    F_EOL,    /* ^N End of line */      F_CONCAT, /* ^O Concatenate lines */
147    F_MARK,   /* ^P Set marker */       F_TINS,   /* ^Q Insert character mode */
148    F_PAGUP,  /* ^R Page up */          F_CENTER, /* ^S Center text */
149    F_PAGDWN, /* ^T Page down */        F_SOL,    /* ^U Line start */
150    F_DELWRD, /* ^V Delete word */      F_PRVWRD, /* ^W Previous word */
151    F_NXTMCH, /* ^X Next match */       F_DELEOL, /* ^Y Delete to end of line */
152    F_DELLIN, /* ^Z Delete line */      0x1B,     /* ^[=ESC escape */
153    F_TENTRY, /* ^\ Entry mode */       F_PASTECB,/* ^]=paste clipboard */
154    F_HOME,   /* ^^ Home */             F_ERSLIN, /* ^_ Erase line */
155    ' ','!','"','#','$','%','&','\047',
156    '(',')','*','+','\054','-','.','/',
157    '0','1','2','3','4','5','6','7',
158    '8','9',':',';','<','=','>','?',
159    '@','A','B','C','D','E','F','G',
160    'H','I','J','K','L','M','N','O',
161    'P','Q','R','S','T','U','V','W',
162    'X','Y','Z','[','\\',']','^','_',
163    '\140','a','b','c','d','e','f','g',
164    'h','i','j','k','l','m','n','o',
165    'p','q','r','s','t','u','v','w',
166    'x','y','z','{','|','}','\176',F_ERSCHR  /* erase character */
167
168   };
169
170
171 #define NVID  0x1E                    /* normal video -- blue */
172 #define RVID  0x4F                    /* reverse video -- red */
173 #define MNVID 0x07                    /* normal video (monochrome tube) */
174 #define MRVID 0x70                    /* reverse video (monochrome tube) */
175
176
177 /* Local variables */
178
179 #define CR '\r'                       /* carriage return */
180
181
182 /* Function Prototypes */
183
184 static int input_char(void);
185 static int t_gnc(void);
186 static void insert_space(char *curline, int line_len);
187 static void forward(int i, char *str, int str_len);
188 static void backup(int i);
189 static void delchr(int cnt, char *curline, int line_len);
190 static int iswordc(char c);
191 static int  next_word(char *ldb_buf);
192 static int  prev_word(char *ldb_buf);
193 static void prtcur(char *str);
194 static void poolinit(void);
195 static char * getnext(void);
196 static char * getprev(void);
197 static void putline(char *newl, int newlen);
198 static void t_honk_horn(void);
199 static void t_insert_line(void);
200 static void t_delete_line(void);
201 static void t_clrline(int pos, int width);
202 static void t_sendl(char *msg, int len);
203 static void t_send(char *msg);
204 static void t_char(char c);
205
206 static void rawmode(void);
207 static void normode(void);
208 static int t_getch();
209 static void trapctlc();
210 static void asclrl(int pos, int width);
211 static void asinsl();
212 static void asdell();
213
214 int input_line(char *string, int length);
215
216 void con_init() 
217 {
218    rawmode();
219    trapctlc();
220 }
221
222 void con_term()
223 {
224    normode();
225 }
226
227 #ifndef BACULA
228 /*
229  * Guarantee that the string is properly terminated */
230 static char *bstrncpy(char *dest, const char *src, int maxlen)
231 {
232    strncpy(dest, src, maxlen-1);
233    dest[maxlen-1] = 0;
234    return dest;
235 }
236 #endif
237
238
239 /*
240  * New style string mapping to function code
241  */
242 static int do_smap(int c)
243 {
244     char str[MAX_STAB];
245     int len = 0; 
246     stab_t *tstab;
247     int i, found;
248
249     len = 1;
250     str[0] = c;
251     str[1] = 0;
252
253     if (c != 27) {
254        c = char_map[c];
255     }
256     if (c <= 0) {
257        return c;
258     }
259     for ( ;; ) {
260        found = 0;
261        for (i=len-1; i<MAX_STAB; i++) {
262           for (tstab=stab[i]; tstab; tstab=tstab->next) {
263              if (strncmp(str, tstab->str, len) == 0) {
264                 if (len == tstab->len) {
265                    return tstab->func;
266                 }
267                 found = 1;
268                 break;                /* found possibility continue searching */
269              }
270           }
271        }
272        if (!found) {
273           return len==1?c:0;
274        }
275        /* found partial match, so get next character and retry */
276        str[len++] = t_gnc();
277        str[len] = 0;
278     }
279 }
280
281 #ifdef DEBUG_x
282 static void dump_stab()
283 {
284     int i, j, c;
285     stab_t *tstab;
286     char buf[100];
287
288     for (i=0; i<MAX_STAB; i++) {
289        for (tstab=stab[i]; tstab; tstab=tstab->next) {
290           for (j=0; j<tstab->len; j++) {
291              c = tstab->str[j];
292              if (c < 0x20 || c > 0x7F) {
293                 sprintf(buf, " 0x%x ", c);
294                 t_send(buf);
295              } else {
296                 buf[0] = c;
297                 buf[1] = 0;
298                 t_sendl(buf, 1);
299              }
300           }
301           sprintf(buf, " func=%d len=%d\n\r", tstab->func, tstab->len);
302           t_send(buf);
303        }
304     }
305 }
306 #endif
307
308 /*
309  * New routine. Add string to string->func mapping table.
310  */
311 static void add_smap(char *str, int func)
312 {
313    stab_t *tstab;
314    int len;
315   
316    if (!str) {
317       return;
318    }
319    len = strlen(str);
320    if (len == 0) {
321 /*    errmsg("String for func %d is zero length\n", func); */
322       return;
323    }
324    tstab = (stab_t *)malloc(sizeof(stab_t));
325    memset(tstab, 0, sizeof(stab_t));
326    tstab->len = len;
327    tstab->str = (char *)malloc(tstab->len + 1);
328    bstrncpy(tstab->str, str, tstab->len + 1);
329    tstab->func = func;
330    if (tstab->len > num_stab) {
331       printf("stab string too long %d. Max is %d\n", tstab->len, num_stab);
332       exit(1);
333    }
334    tstab->next = stab[tstab->len-1];
335    stab[tstab->len-1] = tstab;
336 /* printf("Add_smap tstab=%x len=%d func=%d tstab->next=%x\n\r", tstab, len, 
337           func, tstab->next); */
338
339 }
340
341
342 /* Get the next character from the terminal - performs table lookup on
343    the character to do the desired translation */
344 static int
345 /*FCN*/input_char()
346 {
347     int c;
348
349     if ((c=t_gnc()) <= 599) {         /* IBM generates codes up to 260 */
350           c = do_smap(c);
351     } else if (c > 1000) {            /* stuffed function */
352        c -= 1000;                     /* convert back to function code */
353     }
354     if (c <= 0) {
355         t_honk_horn();
356     }
357     /* if we got a screen size escape sequence, read height, width */
358     if (c == F_SCRSIZ) {
359        int y, x;
360        y = t_gnc() - 0x20;        /* y */
361        x = t_gnc() - 0x20;      /* x */
362        c = input_char();
363     }
364     return c;
365 }
366
367
368 /* Get a complete input line */
369
370 int
371 /*FCN*/input_line(char *string, int length)
372 {
373    char curline[200];                 /* edit buffer */
374    int noline;
375    int c;
376
377     if (first) {
378         poolinit();                   /* build line pool */
379         first = 0;
380     }
381     noline = 1;                       /* no line fetched yet */
382     for (cl=cp=0; cl<length && cl<(int)sizeof(curline); ) {
383         switch (c=(int)input_char()) {
384         case F_RETURN:                /* CR */
385             t_sendl("\r\n", 2);       /* yes, print it and */
386             goto done;                /* get out */
387         case F_CSRUP:
388 #ifdef xxx
389             if (noline) {             /* no line fetched yet */
390                 getnext();            /* getnext so getprev gets current */
391                 noline = 0;           /* we now have line */
392             }
393 #endif
394             bstrncpy(curline, getprev(), sizeof(curline));
395             prtcur(curline);
396             break;
397         case F_CSRDWN:
398             noline = 0;               /* mark line fetched */
399             bstrncpy(curline, getnext(), sizeof(curline));
400             prtcur(curline);
401             break;
402         case F_INSCHR:
403             insert_space(curline, sizeof(curline));
404             break;
405         case F_DELCHR:
406             delchr(1, curline, sizeof(curline));       /* delete one character */
407             break;
408         case F_CSRLFT:                /* Backspace */
409             backup(1);
410             break;
411         case F_CSRRGT:
412             forward(1,curline, sizeof(curline));
413             break;
414         case F_ERSCHR:                /* Rubout */
415             backup(1);
416             delchr(1, curline, sizeof(curline));
417             break;
418         case F_DELEOL:
419             t_clrline(0, t_width);
420             if (cl > cp)
421                 cl = cp;
422             break;
423         case F_NXTWRD:
424             forward(next_word(curline),curline, sizeof(curline));
425             break;
426         case F_PRVWRD:
427             backup(prev_word(curline));
428             break;
429         case F_DELWRD:
430             delchr(next_word(curline), curline, sizeof(curline)); /* delete word */
431             break;
432         case F_NXTMCH:                /* Ctl-X */
433             if (cl==0) {
434                 *string = EOS;        /* terminate string */
435                 return(c);            /* give it to him */
436             }
437             /* Note fall through */
438         case F_DELLIN:
439         case F_ERSLIN:
440             backup(cp);               /* backup to beginning of line */
441             t_clrline(0,t_width);     /* erase line */
442             cp = 0;
443             cl = 0;                   /* reset cursor counter */
444             break;
445         case F_SOL:
446             backup(cp);
447             break;
448         case F_EOL:
449             while (cp < cl) {
450                 forward(1,curline, sizeof(curline));
451             }
452             while (cp > cl) {
453                 backup(1);
454             }
455             break;
456         case F_TINS:                  /* toggle insert mode */
457             mode_insert = !mode_insert;  /* flip bit */
458             break;
459         default:
460             if (c > 255) {            /* function key hit */
461                 if (cl==0) {          /* if first character then */
462                     *string = EOS;         /* terminate string */
463                     return c;              /* return it */
464                 }
465                 t_honk_horn();        /* complain */
466             } else {
467                 if (mode_insert) {
468                     insert_space(curline, sizeof(curline));
469                 }
470                 curline[cp++] = c;    /* store character in line being built */
471                 t_char((char)c);      /* echo character to terminal */
472                 if (cp > cl) {
473                     cl = cp;          /* keep current length */
474                 }
475             }
476             break;
477         }                             /* end switch */
478     }
479 /* If we fall through here rather than goto done, the line is too long
480    simply return what we have now. */
481 done:
482     curline[cl++] = EOS;              /* terminate */
483     bstrncpy(string,curline,length);           /* return line to caller */
484     /* Note, put line zaps curline */
485     putline(curline,cl);              /* save line for posterity */
486     return 0;                         /* give it to him/her */
487 }
488
489 /* Insert a space at the current cursor position */
490 static void
491 /*FCN*/insert_space(char *curline, int curline_len)
492 {
493     int i;
494
495     if (cp > cl || cl+1 > curline_len) return;
496     /* Note! source and destination overlap */
497     memmove(&curline[cp+1],&curline[cp],i=cl-cp);
498     cl++;
499     i++;
500     curline[cp] = ' ';
501     forward(i,curline, curline_len);
502     backup(i);
503 }
504
505
506 /* Move cursor forward keeping characters under it */
507 static void
508 /*FCN*/forward(int i,char *str, int str_len)
509 {
510     while (i--) {
511         if (cp > str_len) {
512            return;
513         }
514         if (cp>=cl) {
515             t_char(' ');
516             str[cp+1] = ' ';
517         } else {
518             t_char(str[cp]);
519         }
520         cp++;
521     }
522 }
523
524 /* Backup cursor keeping characters under it */
525 static void
526 /*FCN*/backup(int i)
527 {
528     for ( ;i && cp; i--,cp--)
529         t_char('\010');
530 }
531
532 /* Delete the character under the cursor */
533 static void
534 /*FCN*/delchr(int cnt, char *curline, int line_len) 
535 {
536     register int i;
537
538     if (cp > cl)
539         return;
540     if ((i=cl-cp-cnt+1) > 0) {
541         memcpy(&curline[cp],&curline[cp+cnt],i);
542     }
543     curline[cl -= cnt] = EOS;
544     t_clrline(0,t_width);
545     if (cl > cp) {
546         forward(i=cl-cp,curline, line_len);
547         backup(i);
548     }
549 }
550
551 /* Determine if character is part of a word */
552 static int
553 /*FCN*/iswordc(char c)
554 {
555    if (mode_wspace)
556       return !isspace(c);
557    if (c >= '0' && c <= '9')
558       return TRUE;
559    if (c == '$' || c == '%')
560       return TRUE;
561    return isalpha(c);
562 }
563
564 /* Return number of characters to get to next word */
565 static int
566 /*FCN*/next_word(char *ldb_buf)
567 {
568     int ncp;
569
570     if (cp > cl)
571         return 0;
572     ncp = cp;
573     for ( ; ncp<cl && iswordc(*(ldb_buf+ncp)); ncp++) ;
574     for ( ; ncp<cl && !iswordc(*(ldb_buf+ncp)); ncp++) ;
575     return ncp-cp;
576 }
577
578 /* Return number of characters to get to previous word */
579 static int
580 /*FCN*/prev_word(char *ldb_buf)
581 {
582     int ncp, i;
583
584     if (cp == 0)                      /* if at begin of line stop now */
585         return 0;
586     if (cp > cl)                      /* if past eol start at eol */
587         ncp=cl+1;
588     else
589         ncp = cp;
590     /* backup to end of previous word - i.e. skip special chars */
591     for (i=ncp-1; i && !iswordc(*(ldb_buf+i)); i--) ;
592     if (i == 0) {                     /* at beginning of line? */
593         return cp;                    /* backup to beginning */
594     }
595     /* now move back through word to beginning of word */
596     for ( ; i && iswordc(*(ldb_buf+i)); i--) ;
597     ncp = i+1;                        /* position to first char of word */
598     if (i==0 && iswordc(*ldb_buf))    /* check for beginning of line */
599         ncp = 0;
600     return cp-ncp;                    /* return count */
601 }
602
603 /* Display new current line */
604 static void
605 /*FCN*/prtcur(char *str)
606 {
607     backup(cp);
608     t_clrline(0,t_width);
609     cp = cl = strlen(str);
610     t_sendl(str,cl);
611 }
612
613
614 /* Initialize line pool. Split pool into two pieces. */
615 static void
616 /*FCN*/poolinit()
617 {
618     slptr = lptr = (struct lstr *)pool;
619     lptr->nextl = lptr;
620     lptr->prevl = lptr;
621     lptr->used = 1;
622     lptr->line = 0;
623     lptr->len = POOLEN;
624 }
625
626
627 /* Return pointer to next line in the pool and advance current line pointer */
628 static char *
629 /*FCN*/getnext()
630 {
631     do {                              /* find next used line */
632         lptr = lptr->nextl;
633     } while (!lptr->used);
634     return (char *)&lptr->line;
635 }
636
637 /* Return pointer to previous line in the pool */
638 static char *
639 /*FCN*/getprev()
640 {
641     do {                              /* find previous used line */
642         lptr = lptr->prevl;
643     } while (!lptr->used);
644     return (char *)&lptr->line;
645 }
646
647 static void
648 /*FCN*/putline(char *newl, int newlen)
649 {
650     struct lstr *nptr;                /* points to next line */
651     char *p;
652
653     lptr = slptr;                     /* get ptr to last line stored */
654     lptr = lptr->nextl;               /* advance pointer */
655     if ((char *)lptr-pool+newlen+PHDRL > POOLEN) { /* not enough room */
656         lptr->used = 0;               /* delete line */
657         lptr = (struct lstr *)pool;   /* start at beginning of buffer */
658     }
659     while (lptr->len < newlen+PHDRL) { /* concatenate buffers */
660         nptr = lptr->nextl;           /* point to next line */
661         lptr->nextl = nptr->nextl;    /* unlink it from list */
662         nptr->nextl->prevl = lptr;
663         lptr->len += nptr->len;
664     }
665     if (lptr->len > newlen + 2 * PHDRL) { /* split buffer */
666         nptr = (struct lstr *)((char *)lptr + newlen + PHDRL);
667         /* Appropriate byte alignment - normally 2 byte, but on
668            sparc we need 4 byte alignment, so we always do 4 */
669         if (((unsigned)nptr & 3) != 0) { /* test four byte alignment */
670             p = (char *)nptr;
671             nptr = (struct lstr *)((((unsigned) p) & ~3) + 4);
672         }
673         nptr->len = lptr->len - ((char *)nptr - (char *)lptr);
674         lptr->len -= nptr->len;
675         nptr->nextl = lptr->nextl;    /* link in new buffer */
676         lptr->nextl->prevl = nptr;
677         lptr->nextl = nptr;
678         nptr->prevl = lptr;
679         nptr->used = 0;
680     }
681     memcpy(&lptr->line,newl,newlen);
682     lptr->used = 1;                   /* mark line used */
683     slptr = lptr;                     /* save as stored line */
684 }
685
686 #ifdef  DEBUGOUT
687 static void
688 /*FCN*/dump(struct lstr *ptr, char *msg)
689 {
690     printf("%s buf=%x nextl=%x prevl=%x len=%d used=%d\n",
691         msg,ptr,ptr->nextl,ptr->prevl,ptr->len,ptr->used);
692     if (ptr->used)
693         printf("line=%s\n",&ptr->line);
694 }
695 #endif  /* DEBUGOUT */
696
697
698 /* Honk horn on terminal */
699 static void
700 /*FCN*/t_honk_horn()
701 {
702     t_send(t_honk);
703 }
704
705 /* Insert line on terminal */
706 static void
707 /*FCN*/t_insert_line()
708 {
709     asinsl();
710 }
711
712 /* Delete line from terminal */
713 static void
714 /*FCN*/t_delete_line()
715 {
716     asdell();
717 }
718
719 /* clear line from pos to width */
720 static void
721 /*FCN*/t_clrline(int pos, int width)
722 {
723     asclrl(pos, width);           /* clear to end of line */
724 }
725
726 /* Helper function to add string preceded by 
727  *  ESC to smap table */
728 static void add_esc_smap(char *str, int func)
729 {
730    char buf[100];
731    buf[0] = 0x1B;                     /* esc */
732    bstrncpy(buf+1, str, sizeof(buf)-1);
733    add_smap(buf, func);
734 }
735
736 /* Set raw mode on terminal file.  Basically, get the terminal into a
737    mode in which all characters can be read as they are entered.  CBREAK
738    mode is not sufficient.
739  */
740 /*FCN*/static void rawmode(void)
741 {
742    struct termios t;
743    static char term_buf[2048];
744    static char *term_buffer = term_buf;
745    char *termtype = (char *)getenv("TERM");
746
747    if (tcgetattr(0, &old_term_params) != 0) {
748       printf("Cannot tcgetattr()\n");
749       exit(1);
750    }
751    t = old_term_params;                         
752    t.c_cc[VMIN] = 1; /* satisfy read after 1 char */
753    t.c_cc[VTIME] = 0;
754    t.c_iflag &= ~(BRKINT | IGNPAR | PARMRK | INPCK | 
755                   ISTRIP | ICRNL | IXON | IXOFF | INLCR | IGNCR);     
756    t.c_iflag |= IGNBRK;
757    t.c_oflag &= ~(OPOST);    /* no output processing */       
758    t.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL | ICANON |
759                   ISIG | NOFLSH | TOSTOP);
760    tcflush(0, TCIFLUSH);
761    if (tcsetattr(0, TCSANOW, &t) == -1) {
762       printf("Cannot tcsetattr()\n");
763    }
764
765    signal(SIGQUIT, SIG_IGN);
766    signal(SIGHUP, SIG_IGN);
767    signal(SIGSTOP, SIG_IGN);
768    signal(SIGINT, sigintcatcher);
769    signal(SIGWINCH, SIG_IGN);   
770    signal(SIGQUIT, SIG_IGN);
771    signal(SIGCHLD, SIG_IGN);
772    signal(SIGTSTP, SIG_IGN);
773
774    if (!termtype) {
775       printf("Cannot get terminal type.\n");
776       exit(1);
777    }
778    if (tgetent(term_buffer, termtype) < 0) {
779       printf("Cannot get terminal termcap entry.\n");
780       exit(1);
781    }
782    t_width = t_height = -1;
783    t_width = tgetnum("co") - 1;
784    t_height = tgetnum("li");
785    BC = NULL;
786    UP = NULL;
787    t_cm = (char *)tgetstr("cm", &term_buffer);
788    t_cs = (char *)tgetstr("cl", &term_buffer); /* clear screen */
789    t_cl = (char *)tgetstr("ce", &term_buffer); /* clear line */
790    t_dl = (char *)tgetstr("dl", &term_buffer); /* delete line */
791    t_il = (char *)tgetstr("al", &term_buffer); /* insert line */
792    t_honk = (char *)tgetstr("bl", &term_buffer); /* beep */
793    t_ti = (char *)tgetstr("ti", &term_buffer);
794    t_te = (char *)tgetstr("te", &term_buffer);
795    t_up = (char *)tgetstr("up", &term_buffer);
796    t_do = (char *)tgetstr("do", &term_buffer);
797    t_sf = (char *)tgetstr("sf", &term_buffer);
798    t_flag = (char *)tgetstr("so", &term_buffer);
799    t_norm = (char *)tgetstr("se", &term_buffer);
800
801    
802
803    dioflag = 1;
804    use_termcap = 1;
805    t_flagl = tgetnum("sg");
806    if (t_flagl < 0) {
807       t_flagl = 0;
808    }
809
810    num_stab = MAX_STAB;                  /* get default stab size */
811    stab = (stab_t **)malloc(sizeof(stab_t *) * num_stab);
812    memset(stab, 0, sizeof(stab_t *) * num_stab);
813
814    /* Key bindings */
815    kl = (char *)tgetstr("kl", &term_buffer);
816    kr = (char *)tgetstr("kr", &term_buffer);
817    ku = (char *)tgetstr("ku", &term_buffer);
818    kd = (char *)tgetstr("kd", &term_buffer);
819    kh = (char *)tgetstr("kh", &term_buffer);
820    kb = (char *)tgetstr("kb", &term_buffer);
821    k0 = (char *)tgetstr("k0", &term_buffer);
822    k1 = (char *)tgetstr("k1", &term_buffer);
823    k2 = (char *)tgetstr("k2", &term_buffer);
824    k3 = (char *)tgetstr("k3", &term_buffer);
825    k4 = (char *)tgetstr("k4", &term_buffer);
826    k5 = (char *)tgetstr("k5", &term_buffer);
827    k6 = (char *)tgetstr("k6", &term_buffer);
828    k7 = (char *)tgetstr("k7", &term_buffer);
829    k8 = (char *)tgetstr("k8", &term_buffer);
830    k9 = (char *)tgetstr("k9", &term_buffer);
831    kD = (char *)tgetstr("kD", &term_buffer);
832    kI = (char *)tgetstr("kI", &term_buffer);
833    kN = (char *)tgetstr("kN", &term_buffer);
834    kP = (char *)tgetstr("kP", &term_buffer);
835    kH = (char *)tgetstr("kH", &term_buffer);
836    kE = (char *)tgetstr("kE", &term_buffer);
837
838    add_smap(kl, F_CSRLFT);
839    add_smap(kr, F_CSRRGT);
840    add_smap(ku, F_CSRUP);
841    add_smap(kd, F_CSRDWN);
842    add_smap(kI, F_TINS);
843    add_smap(kN, F_PAGDWN);
844    add_smap(kP, F_PAGUP);
845    add_smap(kH, F_HOME);
846    add_smap(kE, F_EOF);
847
848
849    add_esc_smap("[A",   F_CSRUP);
850    add_esc_smap("[B",   F_CSRDWN);
851    add_esc_smap("[C",   F_CSRRGT);
852    add_esc_smap("[D",   F_CSRLFT);
853    add_esc_smap("[1~",  F_HOME);
854    add_esc_smap("[2~",  F_TINS);
855    add_esc_smap("[3~",  F_DELCHR);
856    add_esc_smap("[4~",  F_EOF);
857
858 #ifdef needed
859    for (i=301; i<600; i++) {
860       char_map[i] = i;                /* setup IBM function codes */
861    }
862 #endif
863 }
864
865
866 /* Restore tty mode */
867 /*FCN*/static void normode()
868 {
869    tcsetattr(0, TCSANOW, &old_term_params);
870 }
871
872 /* Get next character from terminal/script file/unget buffer */
873 static int
874 /*FCN*/t_gnc()
875 {
876     int ch;
877
878     while ((ch=t_getch()) == 0) ;     /* get next input character */
879     return(ch);
880 }
881
882
883 /* Get next character from OS */
884 static int t_getch(void)
885 {
886    char c;
887
888    if (read(0, &c, 1) != 1) {
889       c = 0;
890    }
891    return (int)c;   
892 }
893     
894 #ifdef xxx
895
896 /* window_size -- Return window height and width to caller. */
897 static int window_size(int *height, int *width)         /* /window_size/ */
898 {
899    *width = tgetnum("co") - 1;
900    *height = tgetnum("li");
901    return 1;
902 }
903 #endif
904
905 /* Send message to terminal - primitive routine */
906 static void
907 /*FCN*/t_sendl(char *msg,int len)
908 {
909     write(1, msg, len);
910 }
911
912 static void
913 /*FCN*/t_send(char *msg)
914 {
915     if (msg == NULL) {
916        return;
917     }
918     t_sendl(msg, strlen(msg));    /* faster than one char at time */
919 }
920
921 /* Send single character to terminal - primitive routine -
922    NOTE! don't convert this routine to use the dioflag routines unless
923    those routines are made to simulate a backspace. */
924 static void
925 /*FCN*/t_char(char c)
926 {
927    write(1, &c, 1);
928 }
929
930
931 static int brkflg = 0;              /* set on user break */
932
933 /* Routine to return true if user types break */
934 /*FCN*/int usrbrk()
935 {
936    return brkflg;
937 }
938
939 /* Clear break flag */
940 void clrbrk()
941 {
942    brkflg = 0;
943
944 }
945
946 /* Interrupt caught here */
947 static void sigintcatcher(int sig)
948 {
949    brkflg = 1;
950    signal(SIGINT, sigintcatcher);
951 }
952
953
954 /* Trap Ctl-C */
955 /*FCN*/void trapctlc()
956 {
957    signal(SIGINT, sigintcatcher);
958 }
959
960
961 /* ASCLRL() -- Clear to end of line from current position */
962 static void asclrl(int pos, int width) 
963 {
964     int i;
965
966     if (t_cl) {
967         t_send(t_cl);                 /* use clear to eol function */
968         return;
969     }
970     if (pos==1 && linsdel_ok) {
971         t_delete_line();              /* delete line */
972         t_insert_line();              /* reinsert it */
973         return;
974     }
975     for (i=1; i<=width-pos+1; i++)
976         t_char(' ');                  /* last resort, blank it out */
977     for (i=1; i<=width-pos+1; i++)    /* backspace to original position */
978         t_char(0x8);
979     return;
980   
981 }
982
983 #ifdef xxx
984
985 /* ASCURS -- Set cursor position */
986 static void ascurs(int y, int x)
987 {
988    t_send((char *)tgoto(t_cm, x, y));
989 }
990                                                                                         
991
992 /* ASCLRS -- Clear whole screen */
993 static void asclrs() 
994 {
995    ascurs(0,0);
996    t_send(t_cs);
997 }
998
999 #endif
1000
1001
1002 /* ASINSL -- insert new line after cursor */
1003 static void asinsl()
1004 {
1005    t_clrline(0, t_width);
1006    t_send(t_il);                      /* insert before */
1007 }
1008
1009 /* ASDELL -- Delete line at cursor */
1010 static void asdell()
1011 {
1012    t_send(t_dl);
1013 }