--- rxvt-unicode/src/command.C 2004/02/22 08:28:36 1.51 +++ rxvt-unicode/src/command.C 2004/03/28 02:07:08 1.81 @@ -54,6 +54,11 @@ /*----------------------------------------------------------------------*/ +#define IS_CONTROL(ch) !((ch) & 0xffffff60UL) + +// exception thrown when the command parser runs out of input data +class out_of_input { } out_of_input; + /*{{{ Convert the keypress event into a string */ void rxvt_term::lookup_key (XKeyEvent &ev) @@ -90,12 +95,14 @@ { Status status_return; +#if 0 #ifdef X_HAVE_UTF8_STRING if (enc_utf8 && 0) // currently disabled, doesn't seem to work, nor is useful len = Xutf8LookupString (Input_Context, &ev, (char *)kbuf, KBUFSZ, &keysym, &status_return); else #endif +#endif { wchar_t wkbuf[KBUFSZ + 1]; @@ -112,10 +119,19 @@ if (status_return == XLookupChars || status_return == XLookupBoth) { - wkbuf[len] = 0; - len = wcstombs ((char *)kbuf, wkbuf, KBUFSZ); - if (len < 0) - len = 0; + /* make sure the user can type ctrl-@, i.e. NUL */ + if (len == 1 && *wkbuf == 0) + { + kbuf[0] = 0; + len = 1; + } + else + { + wkbuf[len] = 0; + len = wcstombs ((char *)kbuf, wkbuf, KBUFSZ); + if (len < 0) + len = 0; + } } else len = 0; @@ -133,27 +149,6 @@ if (valid_keysym) { - /* for some backwards compatibility */ -#if defined(HOTKEY_CTRL) || defined(HOTKEY_META) -# ifdef HOTKEY_CTRL - if (ctrl) -# else - if (meta) -# endif - { - if (keysym == ks_bigfont) - { - change_font (FONT_UP); - return; - } - else if (keysym == ks_smallfont) - { - change_font (FONT_DN); - return; - } - } -#endif - if (TermWin.saveLines) { #ifdef UNSHIFTED_SCROLLKEYS @@ -254,17 +249,21 @@ { unsigned int l; const unsigned char *kbuf0; - const unsigned char ch = C0_ESC; kbuf0 = (Keysym_map[keysym & 0xFF]); l = (unsigned int)*kbuf0++; /* escape prefix */ - if (meta) + if (meta # ifdef META8_OPTION - if (meta_char == C0_ESC) + && meta_char == C0_ESC # endif + ) + { + const unsigned char ch = C0_ESC; tt_write (&ch, 1); + } + tt_write (kbuf0, l); return; } @@ -284,35 +283,11 @@ } else STRCPY (kbuf, key_backspace); -# ifdef MULTICHAR_SET - if ((Options & Opt_mc_hack) && screen.cur.col > 0) - { - int col, row; - - newlen = STRLEN (kbuf); - col = screen.cur.col - 1; - row = screen.cur.row + TermWin.saveLines; - if (IS_MULTI2 (screen.rend[row][col])) - MEMMOVE (kbuf + newlen, kbuf, newlen + 1); - } -# endif break; #endif #ifndef NO_DELETE_KEY case XK_Delete: STRCPY (kbuf, key_delete); -# ifdef MULTICHAR_SET - if (Options & Opt_mc_hack) - { - int col, row; - - newlen = STRLEN (kbuf); - col = screen.cur.col; - row = screen.cur.row + TermWin.saveLines; - if (IS_MULTI1 (screen.rend[row][col])) - MEMMOVE (kbuf + newlen, kbuf, newlen + 1); - } -# endif break; #endif case XK_Tab: @@ -364,41 +339,6 @@ } else if (PrivateModes & PrivMode_aplCUR) kbuf[1] = 'O'; -#ifdef MULTICHAR_SET - //TODO: ?? - if (Options & Opt_mc_hack) - { - int col, row, m; - - col = screen.cur.col; - row = screen.cur.row + TermWin.saveLines; - m = 0; - if (keysym == XK_Right - && IS_MULTI1 (screen.rend[row][col])) - m = 1; - else if (keysym == XK_Left) - { - if (col > 0) - { - if (IS_MULTI2 (screen.rend[row][col - 1])) - m = 1; - } - else if (screen.cur.row > 0) - { - col = screen.tlen[--row]; - if (col == -1) - col = TermWin.ncol - 1; - else - col--; - if (col > 0 - && IS_MULTI2 (screen.rend[row][col])) - m = 1; - } - } - if (m) - MEMMOVE (kbuf + 3, kbuf, 3 + 1); - } -#endif break; #ifndef UNSHIFTED_SCROLLKEYS @@ -597,6 +537,7 @@ if (newlen) len = STRLEN (kbuf); } + /* * Pass meta for all function keys, if 'meta' option set */ @@ -621,6 +562,7 @@ for (ch = kbuf; ch < kbuf + len; ch++) *ch |= 0x80; + meta = 0; } #endif @@ -655,25 +597,23 @@ /* escape prefix */ if (meta #ifdef META8_OPTION - && (meta_char == C0_ESC) + && meta_char == C0_ESC #endif ) { const unsigned char ch = C0_ESC; - tt_write (&ch, 1); } -#ifdef DEBUG_CMD - if (debug_key) - { /* Display keyboard buffer contents */ - char *p; - int i; - - fprintf (stderr, "key 0x%04X [%d]: `", (unsigned int)keysym, len); - for (i = 0, p = kbuf; i < len; i++, p++) - fprintf (stderr, (*p >= ' ' && *p < '\177' ? "%c" : "\\%03o"), *p); - fprintf (stderr, "'\n"); - } + +#if defined(DEBUG_CMD) + /* Display keyboard buffer contents */ + unsigned char *p; + int i; + + fprintf (stderr, "key 0x%04X [%d]: `", (unsigned int)keysym, len); + for (i = 0, p = kbuf; i < len; i++, p++) + fprintf (stderr, (*p >= ' ' && *p < '\177' ? "%c" : "\\%03o"), *p); + fprintf (stderr, "'\n"); #endif /* DEBUG_CMD */ tt_write (kbuf, (unsigned int)len); } @@ -685,10 +625,11 @@ unsigned int rxvt_term::cmd_write (const unsigned char *str, unsigned int count) { - unsigned int n, s; + unsigned int n, s; n = cmdbuf_ptr - cmdbuf_base; - s = cmdbuf_base + BUFSIZ - 1 - cmdbuf_endp; + s = cmdbuf_base + CBUFSIZ - 1 - cmdbuf_endp; + if (n > 0 && s < count) { MEMMOVE (cmdbuf_base, cmdbuf_ptr, @@ -697,13 +638,18 @@ cmdbuf_endp -= n; s += n; } + if (count > s) { - rxvt_print_error ("data loss: cmd_write too large"); + rxvt_warn ("data loss: cmd_write too large, continuing.\n"); count = s; } + for (; count--;) *cmdbuf_endp++ = *str++; + + cmd_parse (); + return 0; } #endif /* MENUBAR_MAX */ @@ -776,7 +722,7 @@ cmdbuf_ptr = cmdbuf_base; cmdbuf_endp = cmdbuf_ptr + n; - n = read (cmd_fd, cmdbuf_endp, BUFSIZ - n); + n = read (cmd_fd, cmdbuf_endp, CBUFSIZ - n); if (n > 0) { @@ -785,7 +731,7 @@ } else if (n < 0 && errno != EAGAIN) destroy (); - + return false; } @@ -799,170 +745,24 @@ tt_write (0, 0); else if (revents & EVENT_READ) { - bool flag = true; - // loop, but don't allow a single term to monopolize us // the number of loops is fully arbitrary, and thus wrong - while (flag && pty_fill ()) + while (pty_fill ()) { if (!seen_input) { seen_input = 1; /* once we know the shell is running, send the screen size. Again! */ + // I don't know why, btw. tt_winch (); } - uint32_t ch = NOCHAR; - - for (;;) - { - if (ch == NOCHAR) - ch = next_char (); - - if (ch == NOCHAR) // TODO: improve - break; - - if (ch >= ' ' || ch == '\t' || ch == '\n' || ch == '\r') - { - /* Read a text string from the input buffer */ - uint32_t buf[BUFSIZ]; - bool refreshnow = false; - int nlines = 0; - uint32_t *str = buf; - - *str++ = ch; - - for (;;) - { - ch = next_char (); - - if (ch == NOCHAR || (ch < ' ' && ch != '\t' && ch != '\n' && ch != '\r')) - break; - else - { - *str++ = ch; - - if (ch == '\n') - { - nlines++; - refresh_count++; - - if (! (Options & Opt_jumpScroll) - || (refresh_count >= (refresh_limit * (TermWin.nrow - 1)))) - { - refreshnow = true; - flag = false; - ch = NOCHAR; - break; - } - - // scr_add_lines only works for nlines < TermWin.nrow - 1. - if (nlines >= TermWin.nrow - 1) - { - scr_add_lines (buf, nlines, str - buf); - nlines = 0; - str = buf; - } - } - - if (str >= buf + BUFSIZ) - { - ch = NOCHAR; - break; - } - } - } - - scr_add_lines (buf, nlines, str - buf); - - /* - * If there have been a lot of new lines, then update the screen - * What the heck I'll cheat and only refresh less than every page-full. - * the number of pages between refreshes is refresh_limit, which - * is incremented here because we must be doing flat-out scrolling. - * - * refreshing should be correct for small scrolls, because of the - * time-out - */ - if (refreshnow) - { - if ((Options & Opt_jumpScroll) && refresh_limit < REFRESH_PERIOD) - refresh_limit++; - - scr_refresh (refresh_type); - } - - } - else - { - switch (ch) - { - default: - process_nonprinting (ch); - break; - case C0_ESC: /* escape char */ - process_escape_seq (); - break; - /*case 0x9b: */ /* CSI */ - /* process_csi_seq (); */ - } - - ch = NOCHAR; - } - } + if (cmd_parse ()) + break; } } } -// read the next character, currently handles UTF-8 -// will probably handle all sorts of other stuff in the future -uint32_t -rxvt_term::next_char () -{ - while (cmdbuf_ptr < cmdbuf_endp) - { - if (*cmdbuf_ptr < 0x80) // assume < 0x80 to be ascii ALWAYS (all shift-states etc.) uh-oh - return *cmdbuf_ptr++; - - wchar_t wc; - size_t len = mbrtowc (&wc, (char *)cmdbuf_ptr, cmdbuf_endp - cmdbuf_ptr, mbstate); - - if (len == (size_t)-2) - return NOCHAR; - - if (len == (size_t)-1) - return *cmdbuf_ptr++; // the _occasional_ latin1 character is allowed to slip through - - // assume wchar == unicode - cmdbuf_ptr += len; - return wc; - } - - return NOCHAR; -} - -/* rxvt_cmd_getc () - Return next input character */ -/* - * Return the next input character after first passing any keyboard input - * to the command. - */ -uint32_t -rxvt_term::cmd_getc () -{ - for (;;) - { - uint32_t c = next_char (); - if (c != NOCHAR) - return c; - - // incomplete sequences should occur rarely, still, a better solution - // would be preferred. either setjmp/longjmp or better design. - fcntl (cmd_fd, F_SETFL, 0); - pty_fill (); - fcntl (cmd_fd, F_SETFL, O_NONBLOCK); - } -} - #ifdef POINTER_BLANK void rxvt_term::pointer_unblank () @@ -999,10 +799,10 @@ #endif void -rxvt_term::mouse_report (const XButtonEvent &ev) +rxvt_term::mouse_report (XButtonEvent &ev) { - int button_number, key_state = 0; - int x, y; + int button_number, key_state = 0; + int x, y; x = ev.x; y = ev.y; @@ -1338,7 +1138,7 @@ break; case SelectionClear: - display->set_selection_owner (0); + selection_clear (); break; case SelectionNotify: @@ -1417,7 +1217,7 @@ #if MENUBAR if (isMenuBarWindow (ev.xany.window)) { - menubar_control (& (ev.xbutton)); + menubar_control (ev.xbutton); break; } #endif @@ -1556,7 +1356,7 @@ } void -rxvt_term::button_press (const XButtonEvent &ev) +rxvt_term::button_press (XButtonEvent &ev) { int reportmode = 0, clickintime; @@ -1794,7 +1594,7 @@ } void -rxvt_term::button_release (const XButtonEvent &ev) +rxvt_term::button_release (XButtonEvent &ev) { int reportmode = 0; @@ -1966,30 +1766,33 @@ /* * Copy display->root pixmap transparency */ - int sx, sy, nx, ny; - unsigned int nw, nh; - Window cr; - XImage *image; - GC gc; - XGCValues gcvalue; + int sx, sy, nx, ny; + unsigned int nw, nh; + Window cr; + XImage *image; + GC gc; + XGCValues gcvalue; XTranslateCoordinates (display->display, TermWin.parent[0], display->root, 0, 0, &sx, &sy, &cr); nw = (unsigned int)szHint.width; nh = (unsigned int)szHint.height; nx = ny = 0; + if (sx < 0) { nw += sx; nx = -sx; sx = 0; } + if (sy < 0) { nh += sy; ny = -sy; sy = 0; } + MIN_IT (nw, (unsigned int) (wrootattr.width - sx)); MIN_IT (nh, (unsigned int) (wrootattr.height - sy)); allowedxerror = -1; @@ -2032,6 +1835,7 @@ am_transparent = am_pixmap_trans = 1; } } + if (!am_pixmap_trans) { unsigned int n; @@ -2056,7 +1860,9 @@ if (oldp != TermWin.parent[i]) pchanged = 1; } + n = 0; + if (pchanged) { for (; n < (unsigned int)i; n++) @@ -2070,6 +1876,7 @@ } } } + if (n > (int) (sizeof (TermWin.parent) / sizeof (TermWin.parent[0]))) { @@ -2102,6 +1909,7 @@ ParentRelative); am_transparent = 1; } + for (; i < (int) (sizeof (TermWin.parent) / sizeof (Window)); i++) TermWin.parent[i] = None; } @@ -2111,16 +1919,172 @@ /*}}} */ +bool +rxvt_term::cmd_parse () +{ + bool flag = false; + unicode_t ch = NOCHAR; + unsigned char *seq_begin; // remember start of esc-sequence here + + for (;;) + { + if (ch == NOCHAR) + { + seq_begin = cmdbuf_ptr; + ch = next_char (); + } + + if (ch == NOCHAR) // TODO: improve + break; + + if (!IS_CONTROL (ch) || ch == '\t' || ch == '\n' || ch == '\r') + { + /* Read a text string from the input buffer */ + unicode_t buf[UBUFSIZ]; + bool refreshnow = false; + int nlines = 0; + unicode_t *str = buf; + + *str++ = ch; + + for (;;) + { + seq_begin = cmdbuf_ptr; + ch = next_char (); + + if (ch == NOCHAR || (IS_CONTROL (ch) && ch != '\t' && ch != '\n' && ch != '\r')) + break; + + *str++ = ch; + + if (ch == '\n') + { + nlines++; + refresh_count++; + + if (! (Options & Opt_jumpScroll) + || (refresh_count >= (refresh_limit * (TermWin.nrow - 1)))) + { + refreshnow = true; + flag = true; + ch = NOCHAR; + break; + } + + // scr_add_lines only works for nlines < TermWin.nrow - 1. + if (nlines >= TermWin.nrow - 1) + { + scr_add_lines (buf, nlines, str - buf); + nlines = 0; + str = buf; + } + } + + if (str >= buf + UBUFSIZ) + { + ch = NOCHAR; + break; + } + } + + scr_add_lines (buf, nlines, str - buf); + + /* + * If there have been a lot of new lines, then update the screen + * What the heck I'll cheat and only refresh less than every page-full. + * the number of pages between refreshes is refresh_limit, which + * is incremented here because we must be doing flat-out scrolling. + * + * refreshing should be correct for small scrolls, because of the + * time-out + */ + if (refreshnow) + { + if ((Options & Opt_jumpScroll) && refresh_limit < REFRESH_PERIOD) + refresh_limit++; + + scr_refresh (refresh_type); + } + + } + else + { + try + { + process_nonprinting (ch); + } + catch (const class out_of_input &o) + { + // we ran out of input, retry later + cmdbuf_ptr = seq_begin; + break; + } + + ch = NOCHAR; + } + } + + return flag; +} + +// read the next character +unicode_t +rxvt_term::next_char () +{ + while (cmdbuf_ptr < cmdbuf_endp) + { + // assume 7-bit to be ascii ALWAYS + if (*cmdbuf_ptr <= 0x7f && *cmdbuf_ptr != 0x1b) + return *cmdbuf_ptr++; + + wchar_t wc; + size_t len = mbrtowc (&wc, (char *)cmdbuf_ptr, cmdbuf_endp - cmdbuf_ptr, mbstate); + + if (len == (size_t)-2) + { + // the mbstate stores incomplete sequences. didn't know this :/ + cmdbuf_ptr = cmdbuf_endp; + break; + } + + if (len == (size_t)-1) + return *cmdbuf_ptr++; // the _occasional_ latin1 character is allowed to slip through + + // assume wchar == unicode + cmdbuf_ptr += len; + return wc; + } + + return NOCHAR; +} + +/* rxvt_cmd_getc () - Return next input character */ +/* + * Return the next input character after first passing any keyboard input + * to the command. + */ +unicode_t +rxvt_term::cmd_getc () +{ + unicode_t c = next_char (); + + if (c == NOCHAR) + throw out_of_input; + + return c; +} + /*{{{ print pipe */ /*----------------------------------------------------------------------*/ #ifdef PRINTPIPE FILE * rxvt_term::popen_printer () { - FILE *stream = popen (rs[Rs_print_pipe], "w"); + FILE *stream = popen (rs[Rs_print_pipe], "w"); if (stream == NULL) - rxvt_print_error ("can't open printer pipe"); + rxvt_warn ("can't open printer pipe, not printing.\n"); + return stream; } @@ -2128,13 +2092,7 @@ rxvt_term::pclose_printer (FILE *stream) { fflush (stream); - /* pclose () reported not to work on SunOS 4.1.3 */ -# if defined (__sun__) /* TODO: RESOLVE THIS */ - /* pclose works provided SIGCHLD handler uses waitpid */ - return pclose (stream); /* return fclose (stream); */ -# else return pclose (stream); -# endif } /* @@ -2143,8 +2101,8 @@ void rxvt_term::process_print_pipe () { - int done; - FILE *fd; + int done; + FILE *fd; if ((fd = popen_printer ()) == NULL) return; @@ -2155,9 +2113,9 @@ */ for (done = 0; !done;) { - unsigned char buf[8]; - unsigned char ch; - unsigned int i, len; + unsigned char buf[8]; + unicode_t ch; + unsigned int i, len; if ((ch = cmd_getc ()) != C0_ESC) { @@ -2182,6 +2140,7 @@ break; /* done = 1 */ } } + for (i = 0; i < len; i++) if (putc (buf[i], fd) == EOF) { @@ -2190,6 +2149,7 @@ } } } + pclose_printer (fd); } #endif /* PRINTPIPE */ @@ -2207,10 +2167,13 @@ /*{{{ process non-printing single characters */ void -rxvt_term::process_nonprinting (unsigned char ch) +rxvt_term::process_nonprinting (unicode_t ch) { switch (ch) { + case C0_ESC: + process_escape_seq (); + break; case C0_ENQ: /* terminal Status */ if (rs[Rs_answerbackstring]) tt_write ( @@ -2243,6 +2206,17 @@ case C0_SI: /* shift in - acs */ scr_charset_choose (0); break; + + // 8-bit controls + case 0x90: /* DCS */ + process_dcs_seq (); + break; + case 0x9b: /* CSI */ + process_csi_seq (); + break; + case 0x9d: /* CSI */ + process_osc_seq (); + break; } } /*}}} */ @@ -2250,7 +2224,7 @@ /*{{{ process VT52 escape sequences */ void -rxvt_term::process_escape_vt52 (unsigned char ch) +rxvt_term::process_escape_vt52 (unicode_t ch) { int row, col; @@ -2312,7 +2286,7 @@ void rxvt_term::process_escape_seq () { - unsigned char ch = cmd_getc (); + unicode_t ch = cmd_getc (); if (PrivateModes & PrivMode_vt52) { @@ -2339,11 +2313,6 @@ case '+': scr_charset_set (3, (unsigned int)cmd_getc ()); break; -#ifdef MULTICHAR_SET - case '$': - scr_charset_set (-2, (unsigned int)cmd_getc ()); - break; -#endif #ifndef NO_FRILLS case '6': scr_backindex (); @@ -2375,7 +2344,7 @@ /* 8.3.87: NEXT LINE */ case C1_NEL: /* ESC E */ { - uint32_t nlcr[] = { '\n', '\r' }; + unicode_t nlcr[] = { L'\n', L'\r' }; scr_add_lines (nlcr, 1, 2); } break; @@ -2477,10 +2446,10 @@ void rxvt_term::process_csi_seq () { - unsigned char ch, priv, i; - unsigned int nargs, p; - int n, ndef; - int arg[ESC_ARGS]; + unicode_t ch, priv, i; + unsigned int nargs, p; + int n, ndef; + int arg[ESC_ARGS]; for (nargs = ESC_ARGS; nargs > 0;) arg[--nargs] = 0; @@ -2492,6 +2461,7 @@ priv = ch; ch = cmd_getc (); } + /* read any numerical arguments */ for (n = -1; ch < CSI_ICH; ) { @@ -2508,19 +2478,9 @@ arg[nargs++] = n; n = -1; } - else if (ch == '\b') - { - scr_backspace (); - } - else if (ch == C0_ESC) - { - process_escape_seq (); - return; - } - else if (ch < ' ') - { - process_nonprinting (ch); - } + else if (IS_CONTROL (ch)) + process_nonprinting (ch); + ch = cmd_getc (); } @@ -2694,7 +2654,7 @@ break; #endif case 8: /* unofficial extension */ - xterm_seq (XTerm_title, APL_NAME "-" VERSION, CHAR_ST); + xterm_seq (XTerm_title, RESNAME "-" VERSION, CHAR_ST); break; } break; @@ -2772,7 +2732,7 @@ case CSI_78: /* DECREQTPARM */ if (arg[0] == 0 || arg[0] == 1) tt_printf ("\033[%d;1;1;128;128;1;0x", arg[0] + 2); - /* FALLTHROUGH */ + break; default: break; @@ -2785,20 +2745,18 @@ void rxvt_term::process_window_ops (const int *args, unsigned int nargs) { - int x, y; -#if 0 - char *s; -#endif + int x, y; XWindowAttributes wattr; - Window wdummy; + Window wdummy; if (nargs == 0) return; + switch (args[0]) { - /* - * commands - */ + /* + * commands + */ case 1: /* deiconify window */ XMapWindow (display->display, TermWin.parent[0]); break; @@ -2825,14 +2783,18 @@ set_widthheight ((unsigned int) (args[2] * TermWin.fwidth), (unsigned int) (args[1] * TermWin.fheight)); break; + + //case 9: NYI, TODO, restore maximized window or maximize window default: if (args[0] >= 24) /* set height (chars) */ set_widthheight ((unsigned int)TermWin.width, (unsigned int) (args[1] * TermWin.fheight)); break; - /* - * reports - some output format copied from XTerm - */ + + + /* + * reports - some output format copied from XTerm + */ case 11: /* report window state */ XGetWindowAttributes (display->display, TermWin.parent[0], &wattr); tt_printf ("\033[%dt", wattr.map_state == IsViewable ? 1 : 2); @@ -2848,9 +2810,12 @@ XGetWindowAttributes (display->display, TermWin.parent[0], &wattr); tt_printf ("\033[4;%d;%dt", wattr.height, wattr.width); break; - case 18: /* report window size (chars) */ + case 18: /* report text area size (chars) */ tt_printf ("\033[8;%d;%dt", TermWin.nrow, TermWin.ncol); break; + case 19: /* report window size (chars) */ + tt_printf ("\033[9;%d;%dt", TermWin.nrow, TermWin.ncol); + break; #if 0 /* XXX: currently disabled due to security concerns */ case 20: /* report icon label */ XGetIconName (display->display, TermWin.parent[0], &s); @@ -2861,7 +2826,6 @@ tt_printf ("\033]l%-.200s\234", s ? s : ""); /* 8bit ST */ break; #endif - } } #endif @@ -2869,22 +2833,24 @@ /*----------------------------------------------------------------------*/ /* * get input up until STRING TERMINATOR (or BEL) - * ends_how is terminator used. returned input must be free ()d + * ends_how is terminator used. returned input must be free ()d */ -unsigned char * -rxvt_term::get_to_st (unsigned char *ends_how) +unsigned char * +rxvt_term::get_to_st (unicode_t &ends_how) { - int seen_esc = 0; /* seen escape? */ - unsigned int n = 0; - unsigned char *s; - unsigned char ch, string[STRING_MAX]; + int seen_esc = 0; /* seen escape? */ + unsigned int n = 0; + unsigned char *s; + unicode_t ch; + unsigned char string[STRING_MAX]; - for (; (ch = cmd_getc ());) + while ((ch = cmd_getc ())) { if (ch == C0_BEL || ch == CHAR_ST || (ch == 0x5c && seen_esc)) /* 7bit ST */ break; + if (ch == C0_ESC) { seen_esc = 1; @@ -2894,14 +2860,19 @@ ch = ' '; /* translate '\t' to space */ else if (ch < 0x08 || (ch > 0x0d && ch < 0x20)) return NULL; /* other control character - exit */ + if (n < sizeof (string) - 1) string[n++] = ch; + seen_esc = 0; } + string[n++] = '\0'; + if ((s = (unsigned char *)rxvt_malloc (n)) == NULL) return NULL; - *ends_how = (ch == 0x5c ? C0_ESC : ch); + + ends_how = (ch == 0x5c ? C0_ESC : ch); STRNCPY (s, string, n); return s; } @@ -2913,13 +2884,16 @@ void rxvt_term::process_dcs_seq () { - unsigned char eh, *s; + unsigned char *s; + unicode_t eh; + /* * Not handled yet */ - s = get_to_st (&eh); + s = get_to_st (eh); if (s) free (s); + return; } @@ -2930,8 +2904,8 @@ void rxvt_term::process_osc_seq () { - unsigned char ch, eh, *s; - int arg; + unicode_t ch, eh; + int arg; ch = cmd_getc (); for (arg = 0; isdigit (ch); ch = cmd_getc ()) @@ -2939,7 +2913,8 @@ if (ch == ';') { - s = get_to_st (&eh); + unsigned char *s = get_to_st (eh); + if (s) { /* @@ -2954,6 +2929,7 @@ #endif else xterm_seq (arg, (char *)s, eh); + free (s); } } @@ -2973,19 +2949,20 @@ * 50 = change font * * rxvt extensions: - * 9 = change locale (NYI) * 10 = menu (may change in future) * 20 = bg pixmap * 39 = change default fg color * 49 = change default bg color * 55 = dump scrollback buffer and all of screen + * 701 = change locale + * 702 = find font */ void rxvt_term::xterm_seq (int op, const char *str, unsigned char resp __attribute__ ((unused))) { - int changed = 0; - int color; - char *buf, *name; + int changed = 0; + int color; + char *buf, *name; assert (str != NULL); switch (op) @@ -2994,7 +2971,7 @@ set_title (str); /* FALLTHROUGH */ case XTerm_iconName: - set_iconName (str); + set_icon_name (str); break; case XTerm_title: set_title (str); @@ -3004,12 +2981,16 @@ { if ((name = STRCHR (buf, ';')) == NULL) break; + *name++ = '\0'; color = atoi (buf); + if (color < 0 || color >= TOTAL_COLORS) break; + if ((buf = STRCHR (name, ';')) != NULL) *buf++ = '\0'; + set_window_color (color + minCOLOR, name); } break; @@ -3072,13 +3053,30 @@ set_window_color (Color_bg, str); break; case XTerm_logfile: + // TODO, when secure mode? break; case XTerm_font: change_font (str); break; +#ifndef NO_FRILLS case XTerm_locale: - /* TODO */ + if (str[0] == '?' && !str[1]) + tt_printf ("%-.250s\n", locale); + else + { + set_locale (str); +# ifdef USE_XIM + im_cb (); +# endif + } break; + case XTerm_findfont: + { + int fid = TermWin.fontset->find_font (atoi (str)); + tt_printf ("%d %-.250s\n", fid, (*TermWin.fontset)[fid]->name); + } + break; +#endif #if 0 case XTerm_dumpscreen: /* no error notices */ { @@ -3091,7 +3089,6 @@ } break; #endif - } } /*----------------------------------------------------------------------*/ @@ -3109,7 +3106,7 @@ int rxvt_term::privcases (int mode, unsigned long bit) { - int state; + int state; if (mode == 's') { @@ -3124,6 +3121,7 @@ state = (mode == 't') ? ! (PrivateModes & bit) : mode; PrivMode (state, bit); } + return state; } @@ -3131,13 +3129,15 @@ void rxvt_term::process_terminal_mode (int mode, int priv __attribute__ ((unused)), unsigned int nargs, const int *arg) { - unsigned int i, j; - int state; + unsigned int i, j; + int state; + static const struct { const int argval; const unsigned long bit; } + argtopriv[] = { { 1, PrivMode_aplCUR }, { 2, PrivMode_vt52 }, @@ -3153,19 +3153,32 @@ #ifdef scrollBar_esc { scrollBar_esc, PrivMode_scrollBar }, #endif + // 18, 19 printing-related { 25, PrivMode_VisibleCursor }, - { 35, PrivMode_ShiftKeys }, + // 30 show scrollbar rxvt. extension + { 35, PrivMode_ShiftKeys }, // rxvt extension { 40, PrivMode_132OK }, + // 41 xterm more fixes NYI + // 45 margin bell NYI + // 46 start logging { 47, PrivMode_Screen }, { 66, PrivMode_aplKP }, #ifndef NO_BACKSPACE_KEY { 67, PrivMode_BackSpace }, #endif { 1000, PrivMode_MouseX11 }, - { 1010, PrivMode_TtyOutputInh }, - { 1011, PrivMode_Keypress }, + // 1001 Use Hilite Mouse Tracking. NYI, TODO + // 1002 Use Cell Motion Mouse Tracking. NYI, TODO + // 1003 Use All Motion Mouse Tracking. NYI, TODO + { 1010, PrivMode_TtyOutputInh }, // rxvt extension + { 1011, PrivMode_Keypress }, // rxvt extension + // 1035 enable modifiers for alt, numlock NYI + // 1036 send ESC for meta keys NYI + // 1037 send DEL for keypad delete NYI { 1047, PrivMode_Screen }, + // 1048 save and restore cursor { 1049, PrivMode_Screen }, /* xterm extension, not fully implemented */ + // 1051, 1052, 1060, 1061 keyboard emulation NYI }; if (nargs == 0) @@ -3190,110 +3203,109 @@ } /* extra handling for values with state unkept */ - if (state == -1) - switch (arg[i]) - { - case 1048: /* alternative cursor save */ - if (mode == 0) - scr_cursor (RESTORE); - else if (mode == 1) - scr_cursor (SAVE); - /* FALLTHROUGH */ - default: - continue; /* for (;i;) */ - } - - /* extra handling for values with valid 0 or 1 state */ switch (arg[i]) { - /* case 1: - application cursor keys */ - case 2: /* VT52 mode */ - /* oddball mode. should be set regardless of set/reset - * parameter. Return from VT52 mode with an ESC < from - * within VT52 mode - */ - PrivMode (1, PrivMode_vt52); - break; - case 3: /* 80/132 */ - if (PrivateModes & PrivMode_132OK) - set_widthheight ( (unsigned int) ((state ? 132 : 80) * TermWin.fwidth), - (unsigned int)TermWin.height); - break; - case 4: /* smooth scrolling */ - if (state) - Options &= ~Opt_jumpScroll; - else - Options |= Opt_jumpScroll; - break; - case 5: /* reverse video */ - scr_rvideo_mode (state); - break; - case 6: /* relative/absolute origins */ - scr_relative_origin (state); - break; - case 7: /* autowrap */ - scr_autowrap (state); - break; - /* case 8: - auto repeat, can't do on a per window basis */ - case 9: /* X10 mouse reporting */ - if (state) /* orthogonal */ - PrivateModes &= ~ (PrivMode_MouseX11); - break; + case 1048: /* alternative cursor save */ + case 1049: + if (mode == 0) + scr_cursor (RESTORE); + else if (mode == 1) + scr_cursor (SAVE); + /* FALLTHROUGH */ + } + + if (state >= 0) + /* extra handling for values with valid 0 or 1 state */ + switch (arg[i]) + { + /* case 1: - application cursor keys */ + case 2: /* VT52 mode */ + /* oddball mode. should be set regardless of set/reset + * parameter. Return from VT52 mode with an ESC < from + * within VT52 mode + */ + PrivMode (1, PrivMode_vt52); + break; + case 3: /* 80/132 */ + if (PrivateModes & PrivMode_132OK) + set_widthheight (((state ? 132 : 80) * TermWin.fwidth), TermWin.height); + break; + case 4: /* smooth scrolling */ + if (state) + Options &= ~Opt_jumpScroll; + else + Options |= Opt_jumpScroll; + break; + case 5: /* reverse video */ + scr_rvideo_mode (state); + break; + case 6: /* relative/absolute origins */ + scr_relative_origin (state); + break; + case 7: /* autowrap */ + scr_autowrap (state); + break; + /* case 8: - auto repeat, can't do on a per window basis */ + case 9: /* X10 mouse reporting */ + if (state) /* orthogonal */ + PrivateModes &= ~PrivMode_MouseX11; + break; #ifdef menuBar_esc - case menuBar_esc: + case menuBar_esc: #ifdef MENUBAR - map_menuBar (state); + map_menuBar (state); #endif - break; + break; #endif #ifdef scrollBar_esc - case scrollBar_esc: - if (scrollbar_mapping (state)) - { - resize_all_windows (0, 0, 0); - scr_touch (true); - } - break; + case scrollBar_esc: + if (scrollbar_mapping (state)) + { + resize_all_windows (0, 0, 0); + scr_touch (true); + } + break; #endif - case 25: /* visible/invisible cursor */ - scr_cursor_visible (state); - break; - /* case 35: - shift keys */ - /* case 40: - 80 <--> 132 mode */ - case 47: /* secondary screen */ - scr_change_screen (state); - break; - /* case 66: - application key pad */ - /* case 67: - backspace key */ - case 1000: /* X11 mouse reporting */ - if (state) /* orthogonal */ - PrivateModes &= ~ (PrivMode_MouseX10); - break; + case 25: /* visible/invisible cursor */ + scr_cursor_visible (state); + break; + /* case 35: - shift keys */ + /* case 40: - 80 <--> 132 mode */ + case 47: /* secondary screen */ + scr_change_screen (state); + break; + /* case 66: - application key pad */ + /* case 67: - backspace key */ + case 1000: /* X11 mouse reporting */ + if (state) /* orthogonal */ + PrivateModes &= ~PrivMode_MouseX10; + break; #if 0 - case 1001: - break; /* X11 mouse highlighting */ + case 1001: + break; /* X11 mouse highlighting */ #endif - case 1010: /* scroll to bottom on TTY output inhibit */ - if (state) - Options &= ~Opt_scrollTtyOutput; - else - Options |= Opt_scrollTtyOutput; - break; - case 1011: /* scroll to bottom on key press */ - if (state) - Options |= Opt_scrollTtyKeypress; - else - Options &= ~Opt_scrollTtyKeypress; - break; - case 1047: /* secondary screen w/ clearing */ - case 1049: /* better secondary screen w/ clearing, but not fully implemented */ - if (current_screen != PRIMARY) - scr_erase_screen (2); - scr_change_screen (state); - /* FALLTHROUGH */ - default: - break; - } + case 1010: /* scroll to bottom on TTY output inhibit */ + if (state) + Options &= ~Opt_scrollTtyOutput; + else + Options |= Opt_scrollTtyOutput; + break; + case 1011: /* scroll to bottom on key press */ + if (state) + Options |= Opt_scrollTtyKeypress; + else + Options &= ~Opt_scrollTtyKeypress; + break; + case 1047: /* secondary screen w/ clearing */ + case 1049: /* better secondary screen w/ clearing, but not fully implemented */ + if (current_screen != PRIMARY) + scr_erase_screen (2); + + scr_change_screen (state); + /* FALLTHROUGH */ + default: + break; + } } } /*}}} */ @@ -3302,15 +3314,16 @@ void rxvt_term::process_sgr_mode (unsigned int nargs, const int *arg) { - unsigned int i; - short rendset; - int rendstyle; + unsigned int i; + short rendset; + int rendstyle; if (nargs == 0) { scr_rendition (0, ~RS_None); return; } + for (i = 0; i < nargs; i++) { rendset = -1; @@ -3331,6 +3344,9 @@ case 7: rendset = 1, rendstyle = RS_RVid; break; + case 8: + // invisible. NYI + break; case 22: rendset = 0, rendstyle = RS_Bold; break; @@ -3343,7 +3359,11 @@ case 27: rendset = 0, rendstyle = RS_RVid; break; + case 28: + // visible. NYI + break; } + if (rendset != -1) { scr_rendition (rendset, rendstyle); @@ -3360,15 +3380,13 @@ case 35: case 36: case 37: - scr_color ((unsigned int) (minCOLOR + (arg[i] - 30)), - Color_fg); + scr_color ((unsigned int) (minCOLOR + (arg[i] - 30)), Color_fg); break; #ifdef TTY_256COLOR case 38: if (nargs > i + 2 && arg[i + 1] == 5) { - scr_color ((unsigned int) (minCOLOR + arg[i + 2]), - Color_fg); + scr_color ((unsigned int) (minCOLOR + arg[i + 2]), Color_fg); i += 2; } break; @@ -3385,15 +3403,13 @@ case 45: case 46: case 47: - scr_color ((unsigned int) (minCOLOR + (arg[i] - 40)), - Color_bg); + scr_color ((unsigned int) (minCOLOR + (arg[i] - 40)), Color_bg); break; #ifdef TTY_256COLOR case 48: if (nargs > i + 2 && arg[i + 1] == 5) { - scr_color ((unsigned int) (minCOLOR + arg[i + 2]), - Color_bg); + scr_color ((unsigned int) (minCOLOR + arg[i + 2]), Color_bg); i += 2; } break; @@ -3436,7 +3452,7 @@ void rxvt_term::process_graphics () { - unsigned char ch, cmd = cmd_getc (); + unicode_t ch, cmd = cmd_getc (); if (cmd == 'Q') { /* query graphics */