X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Fconsole%2Fconio.c;h=24f4f9807f10080a965151a598287c58cc597a6f;hb=37190d54ceff7f2b45a58a1c6241688cc5cba1c2;hp=7c9ed72d9624dabac8574d8c4bfbd525e65d18f0;hpb=d2c744a5b5048924554409449dc42ffe24f2f7e1;p=bacula%2Fbacula diff --git a/bacula/src/console/conio.c b/bacula/src/console/conio.c index 7c9ed72d96..24f4f9807f 100755 --- a/bacula/src/console/conio.c +++ b/bacula/src/console/conio.c @@ -1,67 +1,134 @@ -/* +/* Generalized console input/output handler - Kern Sibbald, December MMIII + A maintanable replacement for readline() + + Updated for Bacula, Kern Sibbald, December MMIII + + This code is in part derived from code that I wrote in + 1981, so some of it is a bit old and could use a cleanup. + +*/ +/* + Bacula® - The Network Backup Solution + + Copyright (C) 1981-2006 Free Software Foundation Europe e.V. + Yes, that is 1981 no error. + + The main author of Bacula is Kern Sibbald, with contributions from + many others, a complete list can be found in the file AUTHORS. + This program is Free Software; you can redistribute it and/or + modify it under the terms of version two of the GNU General Public + License as published by the Free Software Foundation plus additions + that are listed in the file LICENSE. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. + + Bacula® is a registered trademark of John Walker. + The licensor of Bacula is the Free Software Foundation Europe + (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, + Switzerland, email:ftf@fsfeurope.org. */ -#define BACULA -#ifdef BACULA -#include "bacula.h" -#else +/* + * UTF-8 + * If the top bit of a UTF-8 string is 0 (8 bits), then it + * is a normal ASCII character. + * If the top two bits are 11 (i.e. (c & 0xC0) == 0xC0 then + * it is the start of a series of chars (up to 5) + * Each subsequent character starts with 10 (i.e. (c & 0xC0) == 0x80) + */ + + +#ifdef TEST_PROGRAM #include #include +#include #include #include -#include -#endif +#include +#else -#ifdef HAVE_CONIO +/* We are in Bacula */ +#include "bacula.h" + +#endif #include +#ifdef HAVE_SUN_OS +extern "C" int tgetent(void *, const char *); +extern "C" int tgetnum(const char *); +extern "C" char *tgetstr (const char*, char**); +extern "C" char *tgoto (const char *, int, int); +#elif HAVE_HPUX_OS +#include +#elif defined (__digital__) && defined (__unix__) +extern "C" int tgetent(void *, const char *); +extern "C" int tgetnum(const char *); +extern "C" char *tgetstr (const char*, char**); +extern "C" char *tgoto (const char *, int, int); + +#else #include +#endif #include "func.h" -/* Global functions imported */ +/* From termios library */ +#ifdef HAVE_HPUX_OS +static char *BC; +static char *UP; +#else +extern char *BC; +extern char *UP; +#endif -extern char *getenv(char *); +/* Forward referenced functions */ +extern "C" { +static void sigintcatcher(int); +} static void add_smap(char *str, int func); -/* From termios library */ -extern char *BC; -extern char *UP; /* Global variables */ -static char *t_up = "\n"; /* scroll up character */ -static char *t_honk = "\007"; /* sound beep */ -static char *t_il; /* insert line */ -static char *t_dl; /* delete line */ -static char *t_cs; /* clear screen */ -static char *t_cl; /* clear line */ -static int t_width = 79; /* terminal width */ -static int t_height = 24; /* terminal height */ -static int linsdel_ok = 0; /* set if term has line insert & delete fncs */ - -static char *t_cm; /* cursor positioning */ -static char *t_ti; /* init sequence */ -static char *t_te; /* end sequence */ -static char *t_do; /* down one line */ -static char *t_sf; /* scroll screen one line up */ +static const char *t_up = "\n"; /* scroll up character */ +static const char *t_honk = "\007"; /* sound beep */ +static char *t_il; /* insert line */ +static char *t_dl; /* delete line */ +static char *t_cs; /* clear screen */ +static char *t_cl; /* clear line */ +static int t_width = 79; /* terminal width */ +static int t_height = 24; /* terminal height */ +static int linsdel_ok = 0; /* set if term has line insert & delete fncs */ + +static char *t_cm; /* cursor positioning */ +static char *t_ti; /* init sequence */ +static char *t_te; /* end sequence */ +static char *t_do; /* down one line */ +static char *t_sf; /* scroll screen one line up */ /* Keypad and Function Keys */ -static char *kl; /* left key */ -static char *kr; /* right */ -static char *ku; /* up */ -static char *kd; /* down */ -static char *kh; /* home */ -static char *kb; /* backspace */ -static char *kD; /* delete key */ -static char *kI; /* insert */ -static char *kN; /* next page */ -static char *kP; /* previous page */ -static char *kH; /* home */ -static char *kE; /* end */ +static char *kl; /* left key */ +static char *kr; /* right */ +static char *ku; /* up */ +static char *kd; /* down */ +static char *kh; /* home */ +static char *kb; /* backspace */ +static char *kD; /* delete key */ +static char *kI; /* insert */ +static char *kN; /* next page */ +static char *kP; /* previous page */ +static char *kH; /* home */ +static char *kE; /* end */ #ifndef EOS #define EOS '\0' /* end of string terminator */ @@ -82,10 +149,8 @@ typedef struct s_stab { #define MAX_STAB 30 -static stab_t **stab = NULL; /* array of stabs by length */ -static int num_stab; /* size of stab array */ - -/* Local variables */ +static stab_t **stab = NULL; /* array of stabs by length */ +static int num_stab; /* size of stab array */ static bool old_term_params_set = false; static struct termios old_term_params; @@ -94,52 +159,48 @@ static struct termios old_term_params; preceded by a header defined by the lstr structure */ -struct lstr { /* line pool structure */ - struct lstr *prevl; /* link to previous line */ - struct lstr *nextl; /* link to next line */ - long len; /* length of line+header */ - char used; /* set if line valid */ - char line; /* line is actually varying length */ +struct lstr { /* line pool structure */ + struct lstr *prevl; /* link to previous line */ + struct lstr *nextl; /* link to next line */ + long len; /* length of line+header */ + char used; /* set if line valid */ + char line; /* line is actually varying length */ }; #ifdef unix -#define POOLEN 128000 /* bytes in line pool */ +#define POOLEN 128000 /* bytes in line pool */ #else -#define POOLEN 500 /* bytes in line pool */ +#define POOLEN 500 /* bytes in line pool */ #endif -char pool[POOLEN]; /* line pool */ +char pool[POOLEN]; /* line pool */ #define PHDRL ((int)sizeof(struct lstr)) /* length of line header */ -static struct lstr *lptr; /* current line pointer */ -static struct lstr *slptr; /* store line pointer */ +static struct lstr *lptr; /* current line pointer */ +static struct lstr *slptr; /* store line pointer */ static int cl, cp; static char *getnext(), *getprev(); static int first = 1; static int mode_insert = 0; -static int mode_wspace = 1; /* words separated by spaces */ - -/* Forward referenced functions */ -static void sigintcatcher(int); +static int mode_wspace = 1; /* words separated by spaces */ -/* Global variables Exported */ static short char_map[600]= { - 0, F_SOL, /* ^a Line start */ + 0, F_SOL, /* ^a Line start */ F_PRVWRD, /* ^b Previous word */ F_BREAK, /* ^C break */ - F_DELCHR, /* ^D Delete character */ F_EOL, /* ^e End of line */ - F_CSRRGT, /* ^f Right */ F_TABBAK, /* ^G Back tab */ - F_CSRLFT, /* ^H Left */ F_TAB, /* ^I Tab */ - F_CSRDWN, /* ^J Down */ F_DELEOL, /* ^K kill to eol */ + F_DELCHR, /* ^D Delete character */ F_EOL, /* ^e End of line */ + F_CSRRGT, /* ^f Right */ F_TABBAK, /* ^G Back tab */ + F_CSRLFT, /* ^H Left */ F_TAB, /* ^I Tab */ + F_CSRDWN, /* ^J Down */ F_DELEOL, /* ^K kill to eol */ F_CLRSCRN,/* ^L clear screen */ F_RETURN, /* ^M Carriage return */ F_RETURN, /* ^N enter line */ F_CONCAT, /* ^O Concatenate lines */ - F_CSRUP, /* ^P cursor up */ F_TINS, /* ^Q Insert character mode */ - F_PAGUP, /* ^R Page up */ F_CENTER, /* ^S Center text */ + F_CSRUP, /* ^P cursor up */ F_TINS, /* ^Q Insert character mode */ + F_PAGUP, /* ^R Page up */ F_CENTER, /* ^S Center text */ F_PAGDWN, /* ^T Page down */ F_DELSOL, /* ^U delete to start of line */ F_DELWRD, /* ^V Delete word */ F_PRVWRD, /* ^W Previous word */ F_NXTMCH, /* ^X Next match */ F_DELEOL, /* ^Y Delete to end of line */ - F_BACKGND,/* ^Z Background */ 0x1B, /* ^[=ESC escape */ + F_BACKGND,/* ^Z Background */ 0x1B, /* ^[=ESC escape */ F_TENTRY, /* ^\ Entry mode */ F_PASTECB,/* ^]=paste clipboard */ - F_HOME, /* ^^ Home */ F_ERSLIN, /* ^_ Erase line */ + F_HOME, /* ^^ Home */ F_ERSLIN, /* ^_ Erase line */ ' ','!','"','#','$','%','&','\047', '(',')','*','+','\054','-','.','/', @@ -157,12 +218,6 @@ static short char_map[600]= { }; -#define NVID 0x1E /* normal video -- blue */ -#define RVID 0x4F /* reverse video -- red */ -#define MNVID 0x07 /* normal video (monochrome tube) */ -#define MRVID 0x70 /* reverse video (monochrome tube) */ - - /* Local variables */ #define CR '\r' /* carriage return */ @@ -170,11 +225,12 @@ static short char_map[600]= { /* Function Prototypes */ -static int input_char(void); -static int t_gnc(void); +static unsigned int input_char(void); +static unsigned int t_gnc(void); static void insert_space(char *curline, int line_len); -static void forward(int i, char *str, int str_len); -static void backup(int i); +static void insert_hole(char *curline, int line_len); +static void forward(char *str, int str_len); +static void backup(char *curline); static void delchr(int cnt, char *curline, int line_len); static int iswordc(char c); static int next_word(char *ldb_buf); @@ -188,24 +244,30 @@ static void t_honk_horn(void); static void t_insert_line(void); static void t_delete_line(void); static void t_clrline(int pos, int width); -void t_sendl(char *msg, int len); -void t_send(char *msg); +void t_sendl(const char *msg, int len); +void t_send(const char *msg); void t_char(char c); static void asclrs(); static void ascurs(int y, int x); static void rawmode(FILE *input); static void normode(void); -static int t_getch(); -static void trapctlc(); +static unsigned t_getch(); static void asclrl(int pos, int width); static void asinsl(); static void asdell(); int input_line(char *string, int length); +extern "C" { +void con_term(); +} +void trapctlc(); +int usrbrk(); +void clrbrk(); void con_init(FILE *input) { + atexit(con_term); rawmode(input); trapctlc(); } @@ -215,15 +277,15 @@ void con_init(FILE *input) */ void con_set_zed_keys(void) { - char_map[1] = F_NXTWRD; /* ^A Next Word */ - char_map[2] = F_SPLIT; /* ^B Split line */ - char_map[3] = F_EOI; /* ^C Quit */ - char_map[4] = F_DELCHR; /* ^D Delete character */ - char_map[5] = F_EOF; /* ^E End of file */ - char_map[6] = F_INSCHR; /* ^F Insert character */ - char_map[7] = F_TABBAK; /* ^G Back tab */ - char_map[8] = F_CSRLFT; /* ^H Left */ - char_map[9] = F_TAB; /* ^I Tab */ + char_map[1] = F_NXTWRD; /* ^A Next Word */ + char_map[2] = F_SPLIT; /* ^B Split line */ + char_map[3] = F_EOI; /* ^C Quit */ + char_map[4] = F_DELCHR; /* ^D Delete character */ + char_map[5] = F_EOF; /* ^E End of file */ + char_map[6] = F_INSCHR; /* ^F Insert character */ + char_map[7] = F_TABBAK; /* ^G Back tab */ + char_map[8] = F_CSRLFT; /* ^H Left */ + char_map[9] = F_TAB; /* ^I Tab */ char_map[10] = F_CSRDWN; /* ^J Down */ char_map[11] = F_CSRUP; /* ^K Up */ char_map[12] = F_CSRRGT; /* ^L Right */ @@ -254,10 +316,10 @@ void con_term() normode(); } -#ifndef BACULA +#ifdef TEST_PROGRAM /* * Guarantee that the string is properly terminated */ -static char *bstrncpy(char *dest, const char *src, int maxlen) +char *bstrncpy(char *dest, const char *src, int maxlen) { strncpy(dest, src, maxlen-1); dest[maxlen-1] = 0; @@ -269,38 +331,39 @@ static char *bstrncpy(char *dest, const char *src, int maxlen) /* * New style string mapping to function code */ -static int do_smap(int c) +static unsigned do_smap(unsigned c) { char str[MAX_STAB]; - int len = 0; + int len = 0; stab_t *tstab; int i, found; + unsigned cm; len = 1; str[0] = c; str[1] = 0; - if (c != 27) { - c = char_map[c]; - } - if (c <= 0) { + cm = char_map[c]; + if (cm == 0) { return c; + } else { + c = cm; } for ( ;; ) { found = 0; for (i=len-1; inext) { - if (strncmp(str, tstab->str, len) == 0) { - if (len == tstab->len) { - return tstab->func; - } - found = 1; - break; /* found possibility continue searching */ - } - } + for (tstab=stab[i]; tstab; tstab=tstab->next) { + if (strncmp(str, tstab->str, len) == 0) { + if (len == tstab->len) { + return tstab->func; + } + found = 1; + break; /* found possibility continue searching */ + } + } } if (!found) { - return len==1?c:0; + return len==1?c:0; } /* found partial match, so get next character and retry */ str[len++] = t_gnc(); @@ -317,19 +380,19 @@ static void dump_stab() for (i=0; inext) { - for (j=0; jlen; j++) { - c = tstab->str[j]; - if (c < 0x20 || c > 0x7F) { + for (j=0; jlen; j++) { + c = tstab->str[j]; + if (c < 0x20 || c > 0x7F) { sprintf(buf, " 0x%x ", c); - t_send(buf); - } else { - buf[0] = c; - buf[1] = 0; - t_sendl(buf, 1); - } - } + t_send(buf); + } else { + buf[0] = c; + buf[1] = 0; + t_sendl(buf, 1); + } + } sprintf(buf, " func=%d len=%d\n\r", tstab->func, tstab->len); - t_send(buf); + t_send(buf); } } } @@ -342,7 +405,7 @@ static void add_smap(char *str, int func) { stab_t *tstab; int len; - + if (!str) { return; } @@ -363,32 +426,32 @@ static void add_smap(char *str, int func) } tstab->next = stab[tstab->len-1]; stab[tstab->len-1] = tstab; -/* printf("Add_smap tstab=%x len=%d func=%d tstab->next=%x\n\r", tstab, len, - func, tstab->next); */ +/* printf("Add_smap tstab=%x len=%d func=%d tstab->next=%x\n\r", tstab, len, + func, tstab->next); */ } /* Get the next character from the terminal - performs table lookup on the character to do the desired translation */ -static int -/*FCN*/input_char() +static unsigned int +input_char() { - int c; + unsigned c; - if ((c=t_gnc()) <= 599) { /* IBM generates codes up to 260 */ - c = do_smap(c); - } else if (c > 1000) { /* stuffed function */ - c -= 1000; /* convert back to function code */ + if ((c=t_gnc()) <= 599) { /* IBM generates codes up to 260 */ + c = do_smap(c); + } else if (c > 1000) { /* stuffed function */ + c -= 1000; /* convert back to function code */ } if (c <= 0) { - t_honk_horn(); + t_honk_horn(); } /* if we got a screen size escape sequence, read height, width */ if (c == F_SCRSIZ) { int y, x; - y = t_gnc() - 0x20; /* y */ - x = t_gnc() - 0x20; /* x */ + y = t_gnc() - 0x20; /* y */ + x = t_gnc() - 0x20; /* x */ c = input_char(); } return c; @@ -398,370 +461,478 @@ static int /* Get a complete input line */ int -/*FCN*/input_line(char *string, int length) +input_line(char *string, int length) { - char curline[200]; /* edit buffer */ + char curline[2000]; /* edit buffer */ int noline; - int c; + unsigned c; + int more; + int i; if (first) { - poolinit(); /* build line pool */ - first = 0; + poolinit(); /* build line pool */ + first = 0; } - noline = 1; /* no line fetched yet */ + noline = 1; /* no line fetched yet */ for (cl=cp=0; cl cp) - cl = cp; - break; - case F_NXTWRD: - forward(next_word(curline),curline, sizeof(curline)); - break; - case F_PRVWRD: - backup(prev_word(curline)); - break; - case F_DELWRD: - delchr(next_word(curline), curline, sizeof(curline)); /* delete word */ - break; - case F_NXTMCH: /* Ctl-X */ - if (cl==0) { - *string = EOS; /* terminate string */ - return(c); /* give it to him */ - } - /* Note fall through */ - case F_DELLIN: - case F_ERSLIN: - backup(cp); /* backup to beginning of line */ - t_clrline(0,t_width); /* erase line */ - cp = 0; - cl = 0; /* reset cursor counter */ - break; - case F_SOL: - backup(cp); - break; - case F_EOL: - while (cp < cl) { - forward(1,curline, sizeof(curline)); - } - while (cp > cl) { - backup(1); - } - break; - case F_TINS: /* toggle insert mode */ - mode_insert = !mode_insert; /* flip bit */ - break; - default: - if (c > 255) { /* function key hit */ - if (cl==0) { /* if first character then */ - *string = EOS; /* terminate string */ - return c; /* return it */ - } - t_honk_horn(); /* complain */ - } else { - if (mode_insert) { - insert_space(curline, sizeof(curline)); - } - curline[cp++] = c; /* store character in line being built */ - t_char((char)c); /* echo character to terminal */ - if (cp > cl) { - cl = cp; /* keep current length */ - } - } - break; - } /* end switch */ + if (usrbrk()) { + clrbrk(); + break; + } + switch (c=input_char()) { + case F_RETURN: /* CR */ + t_sendl("\r\n", 2); /* yes, print it and */ + goto done; /* get out */ + case F_CLRSCRN: /* clear screen */ + asclrs(); + t_sendl(curline, cl); + ascurs(0, cp); + break; + case F_CSRUP: + if (noline) { /* no line fetched yet */ + getnext(); /* getnext so getprev gets current */ + noline = 0; /* we now have line */ + } + bstrncpy(curline, getprev(), sizeof(curline)); + prtcur(curline); + break; + case F_CSRDWN: + noline = 0; /* mark line fetched */ + bstrncpy(curline, getnext(), sizeof(curline)); + prtcur(curline); + break; + case F_INSCHR: + insert_space(curline, sizeof(curline)); + break; + case F_DELCHR: + delchr(1, curline, sizeof(curline)); /* delete one character */ + break; + case F_CSRLFT: /* Backspace */ + backup(curline); + break; + case F_CSRRGT: + forward(curline, sizeof(curline)); + break; + case F_ERSCHR: /* Rubout */ + backup(curline); + delchr(1, curline, sizeof(curline)); + if (cp == 0) { + t_char(' '); + t_char(0x8); + } + break; + case F_DELEOL: + t_clrline(0, t_width); + if (cl > cp) + cl = cp; + break; + case F_NXTWRD: + i = next_word(curline); + while (i--) { + forward(curline, sizeof(curline)); + } + break; + case F_PRVWRD: + i = prev_word(curline); + while (i--) { + backup(curline); + } + break; + case F_DELWRD: + delchr(next_word(curline), curline, sizeof(curline)); /* delete word */ + break; + case F_NXTMCH: /* Ctl-X */ + if (cl==0) { + *string = EOS; /* terminate string */ + return(c); /* give it to him */ + } + /* Note fall through */ + case F_DELLIN: + case F_ERSLIN: + while (cp > 0) { + backup(curline); /* backup to beginning of line */ + } + t_clrline(0, t_width); /* erase line */ + cp = 0; + cl = 0; /* reset cursor counter */ + t_char(' '); + t_char(0x8); + break; + case F_SOL: + while (cp > 0) { + backup(curline); + } + break; + case F_EOL: + while (cp < cl) { + forward(curline, sizeof(curline)); + } + while (cp > cl) { + backup(curline); + } + break; + case F_TINS: /* toggle insert mode */ + mode_insert = !mode_insert; /* flip bit */ + break; + default: + if (c > 255) { /* function key hit */ + if (cl==0) { /* if first character then */ + *string = EOS; /* terminate string */ + return c; /* return it */ + } + t_honk_horn(); /* complain */ + } else { + if ((c & 0xC0) == 0xC0) { + if ((c & 0xFC) == 0xFC) { + more = 5; + } else if ((c & 0xF8) == 0xF8) { + more = 4; + } else if ((c & 0xF0) == 0xF0) { + more = 3; + } else if ((c & 0xE0) == 0xE0) { + more = 2; + } else { + more = 1; + } + } else { + more = 0; + } + if (mode_insert) { + insert_space(curline, sizeof(curline)); + } + curline[cp++] = c; /* store character in line being built */ + t_char(c); /* echo character to terminal */ + while (more--) { + c= input_char(); + insert_hole(curline, sizeof(curline)); + curline[cp++] = c; /* store character in line being built */ + t_char(c); /* echo character to terminal */ + } + if (cp > cl) { + cl = cp; /* keep current length */ + curline[cp] = 0; + } + } + break; + } /* end switch */ } /* If we fall through here rather than goto done, the line is too long simply return what we have now. */ done: - curline[cl++] = EOS; /* terminate */ - bstrncpy(string,curline,length); /* return line to caller */ - /* Note, put line zaps curline */ - putline(curline,cl); /* save line for posterity */ - return 0; /* give it to him/her */ + curline[cl++] = EOS; /* terminate */ + bstrncpy(string,curline,length); /* return line to caller */ + /* Note, put line zaps curline */ + putline(curline,cl); /* save line for posterity */ + return 0; /* give it to him/her */ } /* Insert a space at the current cursor position */ static void -/*FCN*/insert_space(char *curline, int curline_len) +insert_space(char *curline, int curline_len) { - int i; - - if (cp > cl || cl+1 > curline_len) return; - /* Note! source and destination overlap */ - memmove(&curline[cp+1],&curline[cp],i=cl-cp); - cl++; - i++; - curline[cp] = ' '; - forward(i,curline, curline_len); - backup(i); + int i; + + if (cp > cl || cl+1 > curline_len) { + return; + } + /* Note! source and destination overlap */ + memmove(&curline[cp+1],&curline[cp],i=cl-cp); + cl++; + curline[cp] = ' '; + i = 0; + while (cl > cp) { + forward(curline, curline_len); + i++; + } + while (i--) { + backup(curline); + } +} + + +static void +insert_hole(char *curline, int curline_len) +{ + int i; + + if (cp > cl || cl+1 > curline_len) { + return; + } + /* Note! source and destination overlap */ + memmove(&curline[cp+1], &curline[cp], i=cl-cp); + cl++; + curline[cl] = 0; } /* Move cursor forward keeping characters under it */ static void -/*FCN*/forward(int i,char *str, int str_len) +forward(char *str, int str_len) { - while (i--) { - if (cp > str_len) { - return; - } - if (cp>=cl) { - t_char(' '); - str[cp+1] = ' '; - } else { - t_char(str[cp]); - } - cp++; - } + if (cp > str_len) { + return; + } + if (cp >= cl) { + t_char(' '); + str[cp+1] = ' '; + str[cp+2] = 0; + } else { + t_char(str[cp]); + if ((str[cp] & 0xC0) == 0xC0) { + cp++; + while ((str[cp] & 0xC0) == 0x80) { + t_char(str[cp]); + cp++; + } + cp--; + } + } + cp++; +} + +/* How many characters under the cursor */ +static int +char_count(int cptr, char *str) +{ + int cnt = 1; + if (cptr > cl) { + return 0; + } + if ((str[cptr] & 0xC0) == 0xC0) { + cptr++; + while ((str[cptr] & 0xC0) == 0x80) { + cnt++; + cptr++; + } + } + return cnt; } /* Backup cursor keeping characters under it */ static void -/*FCN*/backup(int i) +backup(char *str) { - for ( ;i && cp; i--,cp--) - t_char('\010'); + if (cp == 0) { + return; + } + while ((str[cp] & 0xC0) == 0x80) { + cp--; + } + t_char('\010'); + cp--; } /* Delete the character under the cursor */ static void -/*FCN*/delchr(int cnt, char *curline, int line_len) +delchr(int del, char *curline, int line_len) { - register int i; + int i, cnt; - if (cp > cl) - return; - if ((i=cl-cp-cnt+1) > 0) { - memcpy(&curline[cp],&curline[cp+cnt],i); - } - curline[cl -= cnt] = EOS; - t_clrline(0,t_width); - if (cl > cp) { - forward(i=cl-cp,curline, line_len); - backup(i); - } + if (cp > cl || del == 0) { + return; + } + while (del-- && cp > 0) { + cnt = char_count(cp, curline); + if ((i=cl-cp-cnt) > 0) { + memcpy(&curline[cp], &curline[cp+cnt], i); + } + cl -= cnt; + curline[cl] = EOS; + t_clrline(0, t_width); + i = 0; + while (cl > cp) { + forward(curline, line_len); + i++; + } + while (i--) { + backup(curline); + } + } } /* Determine if character is part of a word */ static int -/*FCN*/iswordc(char c) +iswordc(char c) { if (mode_wspace) return !isspace(c); if (c >= '0' && c <= '9') - return TRUE; + return true; if (c == '$' || c == '%') - return TRUE; + return true; return isalpha(c); } /* Return number of characters to get to next word */ static int -/*FCN*/next_word(char *ldb_buf) +next_word(char *ldb_buf) { - int ncp; - - if (cp > cl) - return 0; - ncp = cp; - for ( ; ncp cl) + return 0; + ncp = cp; + for ( ; ncp cl) /* if past eol start at eol */ - ncp=cl+1; + if (cp == 0) /* if at begin of line stop now */ + return 0; + if (cp > cl) /* if past eol start at eol */ + ncp=cl+1; else - ncp = cp; + ncp = cp; /* backup to end of previous word - i.e. skip special chars */ for (i=ncp-1; i && !iswordc(*(ldb_buf+i)); i--) ; - if (i == 0) { /* at beginning of line? */ - return cp; /* backup to beginning */ + if (i == 0) { /* at beginning of line? */ + return cp; /* backup to beginning */ } /* now move back through word to beginning of word */ for ( ; i && iswordc(*(ldb_buf+i)); i--) ; - ncp = i+1; /* position to first char of word */ + ncp = i+1; /* position to first char of word */ if (i==0 && iswordc(*ldb_buf)) /* check for beginning of line */ - ncp = 0; - return cp-ncp; /* return count */ + ncp = 0; + return cp-ncp; /* return count */ } /* Display new current line */ static void -/*FCN*/prtcur(char *str) +prtcur(char *str) { - backup(cp); + while (cp > 0) { + backup(str); + } t_clrline(0,t_width); cp = cl = strlen(str); - t_sendl(str,cl); + t_sendl(str, cl); } /* Initialize line pool. Split pool into two pieces. */ static void -/*FCN*/poolinit() +poolinit() { - slptr = lptr = (struct lstr *)pool; - lptr->nextl = lptr; - lptr->prevl = lptr; - lptr->used = 1; - lptr->line = 0; - lptr->len = POOLEN; + slptr = lptr = (struct lstr *)pool; + lptr->nextl = lptr; + lptr->prevl = lptr; + lptr->used = 1; + lptr->line = 0; + lptr->len = POOLEN; } /* Return pointer to next line in the pool and advance current line pointer */ static char * -/*FCN*/getnext() +getnext() { - do { /* find next used line */ - lptr = lptr->nextl; - } while (!lptr->used); - return (char *)&lptr->line; + do { /* find next used line */ + lptr = lptr->nextl; + } while (!lptr->used); + return (char *)&lptr->line; } /* Return pointer to previous line in the pool */ static char * -/*FCN*/getprev() +getprev() { - do { /* find previous used line */ - lptr = lptr->prevl; - } while (!lptr->used); - return (char *)&lptr->line; + do { /* find previous used line */ + lptr = lptr->prevl; + } while (!lptr->used); + return (char *)&lptr->line; } static void -/*FCN*/putline(char *newl, int newlen) +putline(char *newl, int newlen) { - struct lstr *nptr; /* points to next line */ - char *p; - - lptr = slptr; /* get ptr to last line stored */ - lptr = lptr->nextl; /* advance pointer */ - if ((char *)lptr-pool+newlen+PHDRL > POOLEN) { /* not enough room */ - lptr->used = 0; /* delete line */ - lptr = (struct lstr *)pool; /* start at beginning of buffer */ - } - while (lptr->len < newlen+PHDRL) { /* concatenate buffers */ - nptr = lptr->nextl; /* point to next line */ - lptr->nextl = nptr->nextl; /* unlink it from list */ - nptr->nextl->prevl = lptr; - lptr->len += nptr->len; - } - if (lptr->len > newlen + 2 * PHDRL) { /* split buffer */ - nptr = (struct lstr *)((char *)lptr + newlen + PHDRL); - /* Appropriate byte alignment - normally 2 byte, but on - sparc we need 4 byte alignment, so we always do 4 */ - if (((unsigned)nptr & 3) != 0) { /* test four byte alignment */ - p = (char *)nptr; - nptr = (struct lstr *)((((unsigned) p) & ~3) + 4); - } - nptr->len = lptr->len - ((char *)nptr - (char *)lptr); - lptr->len -= nptr->len; - nptr->nextl = lptr->nextl; /* link in new buffer */ - lptr->nextl->prevl = nptr; - lptr->nextl = nptr; - nptr->prevl = lptr; - nptr->used = 0; - } - memcpy(&lptr->line,newl,newlen); - lptr->used = 1; /* mark line used */ - slptr = lptr; /* save as stored line */ + struct lstr *nptr; /* points to next line */ + char *p; + + lptr = slptr; /* get ptr to last line stored */ + lptr = lptr->nextl; /* advance pointer */ + if ((char *)lptr-pool+newlen+PHDRL > POOLEN) { /* not enough room */ + lptr->used = 0; /* delete line */ + lptr = (struct lstr *)pool; /* start at beginning of buffer */ + } + while (lptr->len < newlen+PHDRL) { /* concatenate buffers */ + nptr = lptr->nextl; /* point to next line */ + lptr->nextl = nptr->nextl; /* unlink it from list */ + nptr->nextl->prevl = lptr; + lptr->len += nptr->len; + } + if (lptr->len > newlen + 2 * PHDRL) { /* split buffer */ + nptr = (struct lstr *)((char *)lptr + newlen + PHDRL); + /* Appropriate byte alignment - normally 2 byte, but on + sparc we need 4 byte alignment, so we always do 4 */ + if (((long unsigned)nptr & 3) != 0) { /* test four byte alignment */ + p = (char *)nptr; + nptr = (struct lstr *)((((long unsigned) p) & ~3) + 4); + } + nptr->len = lptr->len - ((char *)nptr - (char *)lptr); + lptr->len -= nptr->len; + nptr->nextl = lptr->nextl; /* link in new buffer */ + lptr->nextl->prevl = nptr; + lptr->nextl = nptr; + nptr->prevl = lptr; + nptr->used = 0; + } + memcpy(&lptr->line,newl,newlen); + lptr->used = 1; /* mark line used */ + slptr = lptr; /* save as stored line */ } -#ifdef DEBUGOUT +#ifdef DEBUGOUT static void -/*FCN*/dump(struct lstr *ptr, char *msg) +dump(struct lstr *ptr, char *msg) { printf("%s buf=%x nextl=%x prevl=%x len=%d used=%d\n", - msg,ptr,ptr->nextl,ptr->prevl,ptr->len,ptr->used); + msg,ptr,ptr->nextl,ptr->prevl,ptr->len,ptr->used); if (ptr->used) printf("line=%s\n",&ptr->line); } -#endif /* DEBUGOUT */ +#endif /* DEBUGOUT */ /* Honk horn on terminal */ static void -/*FCN*/t_honk_horn() +t_honk_horn() { - t_send(t_honk); + t_send(t_honk); } /* Insert line on terminal */ static void -/*FCN*/t_insert_line() +t_insert_line() { - asinsl(); + asinsl(); } /* Delete line from terminal */ static void -/*FCN*/t_delete_line() +t_delete_line() { - asdell(); + asdell(); } /* clear line from pos to width */ static void -/*FCN*/t_clrline(int pos, int width) +t_clrline(int pos, int width) { - asclrl(pos, width); /* clear to end of line */ + asclrl(pos, width); /* clear to end of line */ } -/* Helper function to add string preceded by +/* Helper function to add string preceded by * ESC to smap table */ -static void add_esc_smap(char *str, int func) +static void add_esc_smap(const char *str, int func) { - char buf[100]; - buf[0] = 0x1B; /* esc */ + char buf[1000]; + buf[0] = 0x1B; /* esc */ bstrncpy(buf+1, str, sizeof(buf)-1); add_smap(buf, func); } @@ -770,7 +941,7 @@ static void add_esc_smap(char *str, int func) mode in which all characters can be read as they are entered. CBREAK mode is not sufficient. */ -/*FCN*/static void rawmode(FILE *input) +static void rawmode(FILE *input) { struct termios t; static char term_buf[2048]; @@ -782,40 +953,38 @@ static void add_esc_smap(char *str, int func) return; } if (tcgetattr(0, &old_term_params) != 0) { - printf(_("conio: Cannot tcgetattr()\n")); + printf("conio: Cannot tcgetattr()\n"); exit(1); } old_term_params_set = true; - t = old_term_params; + t = old_term_params; t.c_cc[VMIN] = 1; /* satisfy read after 1 char */ t.c_cc[VTIME] = 0; - t.c_iflag &= ~(BRKINT | IGNPAR | PARMRK | INPCK | - ISTRIP | ICRNL | IXON | IXOFF | INLCR | IGNCR); - t.c_iflag |= IGNBRK | ISIG; -// t.c_oflag &= ~(OPOST); /* no output processing */ + t.c_iflag &= ~(BRKINT | IGNPAR | PARMRK | INPCK | + ISTRIP | ICRNL | IXON | IXOFF | INLCR | IGNCR); + t.c_iflag |= IGNBRK; t.c_oflag |= ONLCR; t.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL | ICANON | - NOFLSH | TOSTOP); + NOFLSH | TOSTOP); tcflush(0, TCIFLUSH); if (tcsetattr(0, TCSANOW, &t) == -1) { printf("Cannot tcsetattr()\n"); } -// signal(SIGQUIT, SIG_IGN); -// signal(SIGHUP, SIG_IGN); -// signal(SIGSTOP, SIG_IGN); + /* Defaults, the main program can override these */ + signal(SIGQUIT, SIG_IGN); + signal(SIGHUP, SIG_IGN); signal(SIGINT, sigintcatcher); -// signal(SIGWINCH, SIG_IGN); -// signal(SIGQUIT, SIG_IGN); -// signal(SIGCHLD, SIG_IGN); -// signal(SIGTSTP, SIG_IGN); + signal(SIGWINCH, SIG_IGN); if (!termtype) { printf("Cannot get terminal type.\n"); + normode(); exit(1); } if (tgetent(term_buffer, termtype) < 0) { printf("Cannot get terminal termcap entry.\n"); + normode(); exit(1); } t_width = t_height = -1; @@ -835,7 +1004,7 @@ static void add_esc_smap(char *str, int func) t_do = (char *)tgetstr("do", &term_buffer); t_sf = (char *)tgetstr("sf", &term_buffer); - num_stab = MAX_STAB; /* get default stab size */ + num_stab = MAX_STAB; /* get default stab size */ stab = (stab_t **)malloc(sizeof(stab_t *) * num_stab); memset(stab, 0, sizeof(stab_t *) * num_stab); @@ -874,85 +1043,65 @@ static void add_esc_smap(char *str, int func) add_esc_smap("[4~", F_EOF); add_esc_smap("f", F_NXTWRD); add_esc_smap("b", F_PRVWRD); - - -#ifdef needed - for (i=301; i<600; i++) { - char_map[i] = i; /* setup IBM function codes */ - } -#endif } /* Restore tty mode */ -/*FCN*/static void normode() +static void normode() { if (old_term_params_set) { tcsetattr(0, TCSANOW, &old_term_params); + old_term_params_set = false; } } /* Get next character from terminal/script file/unget buffer */ -static int -/*FCN*/t_gnc() +static unsigned +t_gnc() { - int ch; - - while ((ch=t_getch()) == 0) ; /* get next input character */ - return(ch); + return t_getch(); } /* Get next character from OS */ -static int t_getch(void) +static unsigned t_getch(void) { - char c; + unsigned char c; if (read(0, &c, 1) != 1) { c = 0; } - return (int)c; + return (unsigned)c; } - -#ifdef xxx - -/* window_size -- Return window height and width to caller. */ -static int window_size(int *height, int *width) /* /window_size/ */ -{ - *width = tgetnum("co") - 1; - *height = tgetnum("li"); - return 1; -} -#endif /* Send message to terminal - primitive routine */ void -/*FCN*/t_sendl(char *msg,int len) +t_sendl(const char *msg, int len) { - write(1, msg, len); + write(1, msg, len); } void -/*FCN*/t_send(char *msg) +t_send(const char *msg) { - if (msg == NULL) { - return; - } - t_sendl(msg, strlen(msg)); /* faster than one char at time */ + if (msg == NULL) { + return; + } + t_sendl(msg, strlen(msg)); /* faster than one char at time */ } /* Send single character to terminal - primitive routine - */ void -/*FCN*/t_char(char c) +t_char(char c) { - write(1, &c, 1); + (void)write(1, &c, 1); } -static int brkflg = 0; /* set on user break */ +static int brkflg = 0; /* set on user break */ /* Routine to return true if user types break */ -/*FCN*/int usrbrk() +int usrbrk() { return brkflg; } @@ -967,38 +1116,42 @@ void clrbrk() /* Interrupt caught here */ static void sigintcatcher(int sig) { - brkflg = 1; + brkflg++; + if (brkflg > 3) { + normode(); + exit(1); + } signal(SIGINT, sigintcatcher); } /* Trap Ctl-C */ -/*FCN*/void trapctlc() +void trapctlc() { signal(SIGINT, sigintcatcher); } /* ASCLRL() -- Clear to end of line from current position */ -static void asclrl(int pos, int width) +static void asclrl(int pos, int width) { - int i; + int i; + + if (t_cl) { + t_send(t_cl); /* use clear to eol function */ + return; + } + if (pos==1 && linsdel_ok) { + t_delete_line(); /* delete line */ + t_insert_line(); /* reinsert it */ + return; + } + for (i=1; i<=width-pos+1; i++) + t_char(' '); /* last resort, blank it out */ + for (i=1; i<=width-pos+1; i++) /* backspace to original position */ + t_char(0x8); + return; - if (t_cl) { - t_send(t_cl); /* use clear to eol function */ - return; - } - if (pos==1 && linsdel_ok) { - t_delete_line(); /* delete line */ - t_insert_line(); /* reinsert it */ - return; - } - for (i=1; i<=width-pos+1; i++) - t_char(' '); /* last resort, blank it out */ - for (i=1; i<=width-pos+1; i++) /* backspace to original position */ - t_char(0x8); - return; - } @@ -1007,10 +1160,10 @@ static void ascurs(int y, int x) { t_send((char *)tgoto(t_cm, x, y)); } - + /* ASCLRS -- Clear whole screen */ -static void asclrs() +static void asclrs() { ascurs(0,0); t_send(t_cs); @@ -1022,7 +1175,7 @@ static void asclrs() static void asinsl() { t_clrline(0, t_width); - t_send(t_il); /* insert before */ + t_send(t_il); /* insert before */ } /* ASDELL -- Delete line at cursor */ @@ -1030,5 +1183,3 @@ static void asdell() { t_send(t_dl); } - -#endif