X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Fconsole%2Fconio.c;h=7a65d2ab99d5b94924aaaca0bcac02cd8712d501;hb=f96efc7d30726fe864e38e2d7d15f8add3d22ee7;hp=fee692718ece3edeeb8c5a5f3ec41c464c34c79e;hpb=ccd957bf15c22615f7380f3c9a8c85fe457a604e;p=bacula%2Fbacula diff --git a/bacula/src/console/conio.c b/bacula/src/console/conio.c index fee692718e..7a65d2ab99 100755 --- a/bacula/src/console/conio.c +++ b/bacula/src/console/conio.c @@ -10,6 +10,7 @@ */ /* Copyright (C) 1981-2004 Kern Sibbald and John Walker + Yes, that is 1981 no error. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -28,6 +29,15 @@ */ +/* + * 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 @@ -44,7 +54,14 @@ #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); +#else #include +#endif #include "func.h" @@ -53,14 +70,17 @@ extern char *BC; extern char *UP; /* Forward referenced functions */ +extern "C" { static void sigintcatcher(int); +} + static void add_smap(char *str, int func); /* Global variables */ -static char *t_up = "\n"; /* scroll up character */ -static char *t_honk = "\007"; /* sound beep */ +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 */ @@ -177,12 +197,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 */ @@ -190,11 +204,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); @@ -208,22 +223,26 @@ 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 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) { @@ -291,22 +310,23 @@ 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; 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; @@ -393,10 +413,10 @@ static void add_smap(char *str, int func) /* Get the next character from the terminal - performs table lookup on the character to do the desired translation */ -static int +static unsigned int input_char() { - int c; + unsigned c; if ((c=t_gnc()) <= 599) { /* IBM generates codes up to 260 */ c = do_smap(c); @@ -422,185 +442,285 @@ input_char() int 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 */ 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 */ + 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)); + 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 */ + 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 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 -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 -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 -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 */ @@ -610,9 +730,9 @@ 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); } @@ -620,14 +740,14 @@ iswordc(char c) static int next_word(char *ldb_buf) { - int ncp; - - if (cp > cl) - return 0; - ncp = cp; - for ( ; ncp cl) + return 0; + ncp = cp; + for ( ; ncp 0) { + backup(str); + } t_clrline(0,t_width); cp = cl = strlen(str); - t_sendl(str,cl); + t_sendl(str, cl); } @@ -670,12 +792,12 @@ prtcur(char *str) static void 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; } @@ -683,59 +805,59 @@ poolinit() static char * 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 * 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 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 @@ -754,21 +876,21 @@ dump(struct lstr *ptr, char *msg) static void t_honk_horn() { - t_send(t_honk); + t_send(t_honk); } /* Insert line on terminal */ static void t_insert_line() { - asinsl(); + asinsl(); } /* Delete line from terminal */ static void t_delete_line() { - asdell(); + asdell(); } /* clear line from pos to width */ @@ -780,9 +902,9 @@ t_clrline(int pos, int width) /* 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]; + char buf[1000]; buf[0] = 0x1B; /* esc */ bstrncpy(buf+1, str, sizeof(buf)-1); add_smap(buf, func); @@ -834,10 +956,12 @@ static void rawmode(FILE *input) 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; @@ -896,13 +1020,6 @@ static void rawmode(FILE *input) 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 } @@ -916,7 +1033,7 @@ static void normode() } /* Get next character from terminal/script file/unget buffer */ -static int +static unsigned t_gnc() { return t_getch(); @@ -924,41 +1041,30 @@ t_gnc() /* 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 -t_sendl(char *msg,int len) +t_sendl(const char *msg, int len) { - write(1, msg, len); + write(1, msg, len); } void -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 - */ @@ -988,7 +1094,8 @@ void clrbrk() static void sigintcatcher(int sig) { brkflg++; - if (brkflg > 1) { + if (brkflg > 3) { + normode(); exit(1); } signal(SIGINT, sigintcatcher); @@ -1005,22 +1112,22 @@ void trapctlc() /* ASCLRL() -- Clear to end of line from current position */ 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; }