From 8e9f10023241dabd00a9555ade125f4913f041be Mon Sep 17 00:00:00 2001 From: Michael Jennings Date: Thu, 2 Mar 2000 03:31:41 +0000 Subject: [PATCH] Wed Mar 1 18:37:18 PST 2000 Michael Jennings I'm still not done with the commenting work I've been doing, but I've made some fixes, so I figured it was time to commit what I've done so far. I've added support for multi-byte selection/pastes from programs like Netscape, thanks in part to a patch from Yasuyuki Furukawa . I've also applied a bugfix for pty allocation on Irix from David Kaelbling , a display bugfix pointed out by Valdis Kletnieks , and a fix for a missing menu in the auto theme discovered by someone on IRC. I've also added quite a few comments to term.c to help people grok the parsing of escape sequences a little better. SVN revision: 2168 --- ChangeLog | 18 +++++ configure.in | 9 ++- src/command.c | 10 ++- src/command.h | 7 +- src/options.c | 5 +- src/screen.c | 52 ++++++++++-- src/term.c | 184 +++++++++++++++++++++++++----------------- src/utmp.c | 9 +-- themes/auto/menus.cfg | 21 +++++ 9 files changed, 221 insertions(+), 94 deletions(-) diff --git a/ChangeLog b/ChangeLog index aa9b6e9..c63d512 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3242,3 +3242,21 @@ Fri Feb 18 21:09:29 PST 2000 Michael Jennings functions to do it. :-) ------------------------------------------------------------------------------- +Wed Mar 1 18:37:18 PST 2000 Michael Jennings + + I'm still not done with the commenting work I've been doing, but I've + made some fixes, so I figured it was time to commit what I've done so + far. + + I've added support for multi-byte selection/pastes from programs like + Netscape, thanks in part to a patch from Yasuyuki Furukawa + . I've also applied a bugfix for pty + allocation on Irix from David Kaelbling , a display + bugfix pointed out by Valdis Kletnieks , and + a fix for a missing menu in the auto theme discovered by someone on + IRC. + + I've also added quite a few comments to term.c to help people grok + the parsing of escape sequences a little better. + +------------------------------------------------------------------------------- diff --git a/configure.in b/configure.in index 0365b72..0436d47 100644 --- a/configure.in +++ b/configure.in @@ -144,7 +144,7 @@ AC_TYPE_UID_T dnl# Checks for library functions. AC_TYPE_SIGNAL -AC_CHECK_FUNCS(atexit _exit unsetenv setutent seteuid memmove putenv strsep setresuid setresgid memmem usleep snprintf) +AC_CHECK_FUNCS(atexit _exit unsetenv setutent seteuid memmove putenv strsep setresuid setresgid memmem usleep snprintf X11/Xmu/Atoms.h) dps_snprintf_oflow() dnl# Check for the need for -lutil on BSD systems @@ -586,7 +586,12 @@ echo " the --x-libraries parameter to configure."; AC_CHECK_LIB(Xext, XShapeQueryExtension, AC_DEFINE(HAVE_X_SHAPE_EXT), , $X_LIBS $SUBLIBS) # check if we need X_LOCALE definition -AC_CHECK_LIB(X11, _Xsetlocale, , AC_DEFINE(NO_XLOCALE), , $X_LIBS $SUBLIBS) +AC_CHECK_LIB(X11, _Xsetlocale, , AC_DEFINE(NO_XLOCALE), $X_LIBS $SUBLIBS) + +# For multibyte selection handling +if test "$MULTICHAR_ENCODING" != "none"; then + AC_CHECK_LIB(Xmu, XmuInternAtom, X_LIBS="-lXmu $X_LIBS", , $X_LIBS $SUBLIBS) +fi # check X11R6 for XIM if test "$XIM" = "TRUE"; then diff --git a/src/command.c b/src/command.c index 65048d9..260b371 100644 --- a/src/command.c +++ b/src/command.c @@ -1134,10 +1134,11 @@ __inline__ int sgi_get_pty(void); __inline__ int sgi_get_pty(void) { - int fd = -1; + privileges(INVOKE); ptydev = ttydev = _getpty(&fd, O_RDWR | O_NDELAY, 0620, 0); + privileges(REVERT); return (ptydev == NULL ? -1 : fd); } @@ -2503,6 +2504,13 @@ cmd_getc(void) return (0); } +/* Put a character back in the buffer. Only use this once at a time. */ +void +cmd_ungetc(void) +{ + cmdbuf_ptr--; +} + /* tt_write(), tt_printf() - output to command */ /* * Send count characters directly to the command diff --git a/src/command.h b/src/command.h index d06adf5..ca81e74 100644 --- a/src/command.h +++ b/src/command.h @@ -266,9 +266,9 @@ if (test) PrivateModes |= (bit); else PrivateModes &= ~(bit);} while (0) # define SIG_RETURN(x) return #endif -#define CHARS_READ() (cmdbuf_ptr < cmdbuf_endp) -#define CHARS_BUFFERED() (count != CMD_BUF_SIZE) -#define RETURN_CHAR() do { refreshed = 0; return (*cmdbuf_ptr++); } while (0) +#define CHARS_READ() (cmdbuf_ptr < cmdbuf_endp) +#define CHARS_BUFFERED() (count != CMD_BUF_SIZE) +#define RETURN_CHAR() do { refreshed = 0; return (*cmdbuf_ptr++); } while (0) #ifdef REFRESH_DELAY # define REFRESH_DELAY_USEC (1000000/25) @@ -364,6 +364,7 @@ extern unsigned int cmd_write(const unsigned char *, unsigned int); extern RETSIGTYPE check_pixmap_change(int); #endif extern unsigned char cmd_getc(void); +extern void cmd_ungetc(void); extern void tt_write(const unsigned char *, unsigned int); extern void tt_printf(const unsigned char *, ...); extern void main_loop(void); diff --git a/src/options.c b/src/options.c index f500982..14dbef8 100644 --- a/src/options.c +++ b/src/options.c @@ -3568,7 +3568,6 @@ init_defaults(void) rs_name = StrDup(APL_NAME " " VERSION); Options = (Opt_scrollbar | Opt_select_trailing_spaces); Xdisplay = NULL; - display_name = NULL; rs_term_name = NULL; #ifdef CUTCHAR_OPTION rs_cutchars = NULL; @@ -3650,11 +3649,11 @@ post_parse(void) #ifdef PRINTPIPE if (!rs_print_pipe) - rs_print_pipe = PRINTPIPE; + rs_print_pipe = StrDup(PRINTPIPE); #endif #ifdef CUTCHAR_OPTION if (!rs_cutchars) - rs_cutchars = CUTCHARS; + rs_cutchars = StrDup(CUTCHARS); #endif #ifndef NO_BOLDFONT diff --git a/src/screen.c b/src/screen.c index 27b0b06..8a8d2a4 100644 --- a/src/screen.c +++ b/src/screen.c @@ -24,6 +24,9 @@ static const char cvs_ident[] = "$Id$"; #include #include #include /* CARD32 */ +#ifdef HAVE_X11_XMU_ATOMS_H +# include +#endif #include "../libmej/debug.h" #include "../libmej/mem.h" @@ -2383,15 +2386,30 @@ selection_paste(Window win, unsigned prop, int Delete) if (prop == None) return; for (nread = 0, bytes_after = 1; bytes_after > 0;) { - if ((XGetWindowProperty(Xdisplay, win, prop, (nread / 4), PROP_SIZE, - Delete, AnyPropertyType, &actual_type, &actual_fmt, - &nitems, &bytes_after, &data) != Success)) { + if ((XGetWindowProperty(Xdisplay, win, prop, (nread / 4), PROP_SIZE, Delete, AnyPropertyType, &actual_type, &actual_fmt, &nitems, &bytes_after, &data) != Success)) { XFree(data); return; } nread += nitems; - PasteIt(data, nitems); + if (actual_type == XA_STRING) { + PasteIt(data, nitems); + } else { + int size, i, ret; + XTextProperty xtextp; + char **cl; + + xtextp.value = data; + xtextp.encoding = actual_type; + xtextp.format = actual_fmt; + xtextp.nitems = nitems; + XmbTextPropertyToTextList(Xdisplay, &xtextp, &cl, &size); + + for (i = 0 ; i < size ; i ++) { + PasteIt(cl[i], strlen(cl[i])); + } + XFreeStringList(cl); + } XFree(data); } } @@ -2415,8 +2433,11 @@ selection_request(Time tm, int x, int y) selection_paste(Xroot, XA_CUT_BUFFER0, False); } else { prop = XInternAtom(Xdisplay, "VT_SELECTION", False); - XConvertSelection(Xdisplay, XA_PRIMARY, XA_STRING, prop, TermWin.vt, - tm); +#ifdef MULTI_CHARSET + XConvertSelection(Xdisplay, XA_PRIMARY, XA_COMPOUND_TEXT(Xdisplay), prop, TermWin.vt, tm); +#else + XConvertSelection(Xdisplay, XA_PRIMARY, XA_STRING, prop, TermWin.vt, tm); +#endif } } @@ -3194,10 +3215,25 @@ selection_send(XSelectionRequestEvent * rq) (unsigned char *) target_list, (sizeof(target_list) / sizeof(target_list[0]))); ev.xselection.property = rq->property; +#ifdef MULTI_CHARSET + } else if (rq->target == XA_STRING || rq->target == XA_TEXT(Xdisplay) || rq->target == XA_COMPOUND_TEXT(Xdisplay)) { + XTextProperty xtextp; + char *l[1]; + + *l = selection.text; + xtextp.value = NULL; + xtextp.nitems = 0; + if (XmbTextListToTextProperty(Xdisplay, l, 1, XCompoundTextStyle, &xtextp) == Success) { + if (xtextp.nitems > 0 && xtextp.value != NULL) { + XChangeProperty(Xdisplay, rq->requestor, rq->property, XA_COMPOUND_TEXT(Xdisplay), 8, PropModeReplace, xtextp.value, xtextp.nitems); + ev.xselection.property = rq->property; + } + } +#else } else if (rq->target == XA_STRING) { - XChangeProperty(Xdisplay, rq->requestor, rq->property, rq->target, - 8, PropModeReplace, selection.text, selection.len); + XChangeProperty(Xdisplay, rq->requestor, rq->property, rq->target, 8, PropModeReplace, selection.text, selection.len); ev.xselection.property = rq->property; +#endif } XSendEvent(Xdisplay, rq->requestor, False, 0, &ev); } diff --git a/src/term.c b/src/term.c index fd8733f..b60d9fa 100644 --- a/src/term.c +++ b/src/term.c @@ -97,6 +97,13 @@ Pixel PixColors[NRS_COLORS + NSHADOWCOLORS]; unsigned int MetaMask = 0, AltMask = 0, NumLockMask = 0; unsigned int modmasks[] = { Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask }; +/* This function queries X to see which modifier keys (specifically Alt, Meta, and NumLock, + since that's really all we care about) are bound to the 5 modifier masks. It then sets + the variables MetaMask, AltMask, and NumLockMask to the appropriate modifier mask (e.g., + Mod1Mask). That way, we can use MetaMask in lookup_key() instead of using a specific + ModMask. This function also handles fallbacks, so that if there is no Meta key, the Alt + key will be used as Meta, and vice versa. get_modifiers() is called once on startup and + after each MappingNotify event. */ void get_modifiers(void) { @@ -107,6 +114,8 @@ get_modifiers(void) modmap = XGetModifierMapping(Xdisplay); kc = modmap->modifiermap; + + /* For each of the 5 modifier masks... */ for (i = Mod5MapIndex; i >= Mod1MapIndex; i--) { unsigned short j; register unsigned short k, l; @@ -114,12 +123,14 @@ get_modifiers(void) k = i * modmap->max_keypermod; l = i - Mod1MapIndex; + /* Find each key bound to it... */ for (j = 0; j < modmap->max_keypermod; j++, k++) { unsigned char match = 0; if (kc[k] == 0) { break; } + /* Check to see if it's one that we care about. */ switch (XKeycodeToKeysym(Xdisplay, kc[k], 0)) { case XK_Meta_L: case XK_Meta_R: @@ -144,6 +155,7 @@ get_modifiers(void) } } XFreeModifiermap(modmap); + /* Fallbacks. */ if (MetaMask == 0) { if (AltMask != 0) { D_X11(("Defaulted Meta key to match Alt mask\n")); @@ -165,7 +177,14 @@ get_modifiers(void) #else # define LK_RET() return #endif -/* Convert the keypress event into a string */ + +/* This function is called for every keypress event we receive. Its job is to convert + the keypress into its corresponding action. It is responsible for calling the action + bindings routine to see if there is an action binding for that keysym; if there is, + this routine will exit. If not, it continues. It then uses the keysym to determine + the action or escape sequence which should result from the keypress. Actions are + performed and the event discarded. Escape sequences are generated and sent to the + child process. */ void lookup_key(XEvent * ev) { @@ -185,15 +204,13 @@ lookup_key(XEvent * ev) static short greek_mode = 0; #endif - /* - * use Num_Lock to toggle Keypad on/off. If Num_Lock is off, allow an - * escape sequence to toggle the Keypad. - * - * Always permit `shift' to override the current setting - */ + /* Quick boolean variables tell us which modifier keys were pressed. */ shft = (ev->xkey.state & ShiftMask); ctrl = (ev->xkey.state & ControlMask); meta = (ev->xkey.state & MetaMask); + + /* The num lock key toggles application keypad + mode. Num lock on, app. keypad mode off. */ if (numlock_state || (ev->xkey.state & NumLockMask)) { numlock_state = (ev->xkey.state & NumLockMask); PrivMode((!numlock_state), PrivMode_aplKP); @@ -203,8 +220,9 @@ lookup_key(XEvent * ev) Status status_return; kbuf[0] = '\0'; - len = XmbLookupString(xim_input_context, &ev->xkey, (char *) kbuf, - sizeof(short_buf), &keysym, &status_return); + /* Lookup the string equivalent in terms of the XIM input context. */ + len = XmbLookupString(xim_input_context, &ev->xkey, (char *) kbuf, sizeof(short_buf), &keysym, &status_return); + /* Whoops, it's too long. Allocate a new buffer and repeat the call. */ if (status_return == XBufferOverflow) { kbuf = (unsigned char *) MALLOC(len + 1); kbuf_alloced = 1; @@ -212,16 +230,15 @@ lookup_key(XEvent * ev) } valid_keysym = (status_return == XLookupKeySym) || (status_return == XLookupBoth); } else { + /* No XIM input context. Do it the normal way. */ len = XLookupString(&ev->xkey, (char *) kbuf, sizeof(short_buf), &keysym, NULL); valid_keysym = 1; } #else /* USE_XIM */ + /* Translate the key event into its corresponding string according to X. This also gets us a keysym. */ len = XLookupString(&ev->xkey, (char *) kbuf, sizeof(kbuf), &keysym, NULL); - /* - * have unmapped Latin[2-4] entries -> Latin1 - * good for installations with correct fonts, but without XLOCALE - */ + /* If there is no string and it's a Latin2-4 character, replace it with the Latin1 character instead. */ if (!len && (keysym >= 0x0100) && (keysym < 0x0400)) { len = 1; kbuf[0] = (keysym & 0xff); @@ -229,23 +246,28 @@ lookup_key(XEvent * ev) #endif /* USE_XIM */ #ifdef USE_XIM + /* Don't do anything without a valid keysym. */ if (valid_keysym) { #endif + /* Check for a corresponding action binding. If there is one, we're done with this event. */ if (action_dispatch(ev, keysym)) { LK_RET(); } + /* If we're in pause mode, exit. */ if (len && keypress_exit) { exit(0); } + /* This is a special mode that reports all extended keysyms (above 0xff00) to the application + as escape sequences. Very few applications use it, but it can be a handy thing to have. */ if ((Options & Opt_report_as_keysyms) && (keysym >= 0xff00)) { len = sprintf((char *) kbuf, "\033[k%X;%X~", (unsigned int) (ev->xkey.state & 0xff), (unsigned int) (keysym & 0xff)); tt_write(kbuf, len); LK_RET(); } #ifdef HOTKEY - /* for some backwards compatibility */ + /* Ctrl-> and Ctrl-< should change font sizes. (Meta if HOTKEY has been changed to Meta.) */ if (HOTKEY) { if (keysym == ks_bigfont) { change_font(0, BIGGER_FONT); @@ -261,7 +283,7 @@ lookup_key(XEvent * ev) /* Shift + F1 - F10 generates F11 - F20 */ if (keysym >= XK_F1 && keysym <= XK_F10) { keysym += (XK_F11 - XK_F1); - shft = 0; /* turn off Shift */ + shft = 0; } else if (!ctrl && !meta && (PrivateModes & PrivMode_ShiftKeys)) { int lnsppg; /* Lines per page to scroll */ @@ -273,32 +295,31 @@ lookup_key(XEvent * ev) #endif switch (keysym) { - /* normal XTerm key bindings */ - case XK_Prior: /* Shift+Prior = scroll back */ + case XK_Prior: /* Shift-PgUp scrolls up a page */ if (TermWin.saveLines) { scr_page(UP, lnsppg); LK_RET(); } break; - case XK_Next: /* Shift+Next = scroll forward */ + case XK_Next: /* Shift-PgDn scrolls down a page */ if (TermWin.saveLines) { scr_page(DN, lnsppg); LK_RET(); } break; - case XK_Insert: /* Shift+Insert = paste mouse selection */ + case XK_Insert: /* Shift-Ins pastes the current selection. */ selection_request(ev->xkey.time, ev->xkey.x, ev->xkey.y); LK_RET(); break; - case XK_KP_Add: /* Shift+KP_Add = bigger font */ + case XK_KP_Add: /* Shift-Plus on the keypad increases the font size */ change_font(0, BIGGER_FONT); LK_RET(); break; - case XK_KP_Subtract: /* Shift+KP_Subtract = smaller font */ + case XK_KP_Subtract: /* Shift-Minus on the keypad decreases the font size */ change_font(0, SMALLER_FONT); LK_RET(); break; @@ -306,6 +327,7 @@ lookup_key(XEvent * ev) } } #ifdef UNSHIFTED_SCROLLKEYS + /* Allow PgUp/PgDn by themselves to scroll. Not recommended. */ else if (!ctrl && !meta) { switch (keysym) { case XK_Prior: @@ -326,7 +348,7 @@ lookup_key(XEvent * ev) #endif switch (keysym) { - case XK_Print: + case XK_Print: /* Print the screen contents out to the print pipe */ #if DEBUG >= DEBUG_SELECTION if (debug_level >= DEBUG_SELECTION) { debug_selection(); @@ -356,14 +378,16 @@ lookup_key(XEvent * ev) TermWin.view_start = 0; } - if (keysym >= 0xFF00 && keysym <= 0xFFFF) { + /* Process extended keysyms. This is where the conversion to escape sequences happens. */ + if (keysym >= 0xff00 && keysym <= 0xffff) { #ifdef KEYSYM_ATTRIBUTE - if (!(shft | ctrl) && KeySym_map[keysym - 0xFF00] != NULL) { + /* The "keysym" attribute in the config file gets handled here. */ + if (!(shft | ctrl) && KeySym_map[keysym - 0xff00] != NULL) { const unsigned char *tmpbuf; unsigned int len; - tmpbuf = (KeySym_map[keysym - 0xFF00]); + tmpbuf = (KeySym_map[keysym - 0xff00]); len = *tmpbuf++; /* escape prefix */ @@ -380,6 +404,7 @@ lookup_key(XEvent * ev) LK_RET(); } else #endif + /* This is a big-ass switch statement that handles all the special keysyms */ switch (keysym) { case XK_BackSpace: len = 1; @@ -392,6 +417,7 @@ lookup_key(XEvent * ev) #endif break; + /* Tab key is normal unless it's shift-tab. */ case XK_Tab: if (shft) { len = 3; @@ -415,20 +441,19 @@ lookup_key(XEvent * ev) break; #ifdef XK_KP_Left - case XK_KP_Left: /* \033Ot or standard */ - case XK_KP_Up: /* \033Ox or standard */ - case XK_KP_Right: /* \033Ov or standard */ - case XK_KP_Down: /* \033Ow or standard */ + case XK_KP_Left: /* \033Ot or standard cursor key */ + case XK_KP_Up: /* \033Ox or standard cursor key */ + case XK_KP_Right: /* \033Ov or standard cursor key */ + case XK_KP_Down: /* \033Or or standard cursor key */ if ((PrivateModes & PrivMode_aplKP) ? !shft : shft) { len = 3; - strcpy(kbuf, "\033OZ"); + strcpy(kbuf, "\033OZ"); /* The Z is replaced by t, x, v, or r */ kbuf[2] = ("txvr"[keysym - XK_KP_Left]); break; } else { - /* translate to std. cursor key */ keysym = XK_Left + (keysym - XK_KP_Left); } - /* FALL THROUGH */ + /* Continue on with the normal cursor keys... */ #endif case XK_Left: /* "\033[D" */ case XK_Up: /* "\033[A" */ @@ -446,6 +471,8 @@ lookup_key(XEvent * ev) kbuf[2] = ("dacb"[keysym - XK_Left]); } break; + + /* Keypad and normal PgUp/PgDn */ #ifndef UNSHIFTED_SCROLLKEYS # ifdef XK_KP_Prior case XK_KP_Prior: @@ -476,6 +503,8 @@ lookup_key(XEvent * ev) strcpy(kbuf, "\033[6~"); break; #endif /* UNSHIFTED_SCROLLKEYS */ + + /* End key */ #ifdef XK_KP_End case XK_KP_End: /* allow shift to override */ @@ -495,8 +524,8 @@ lookup_key(XEvent * ev) strcpy(kbuf, "\033[4~"); break; -#ifdef DXK_Remove /* support for DEC remove like key */ - case DXK_Remove: /* drop */ +#ifdef DXK_Remove + case DXK_Remove: #endif case XK_Execute: len = 4; @@ -684,6 +713,7 @@ sprintf((char *) kbuf,"\033[%02d~", (int)((n) + (keysym - fkey))); \ } #endif + /* All processed. If there's still no string, we're done. */ if (len <= 0) { LK_RET(); } @@ -724,23 +754,29 @@ sprintf((char *) kbuf,"\033[%02d~", (int)((n) + (keysym - fkey))); \ fprintf(stderr, "'\n"); } #endif /* DEBUG_CMD */ - tt_write(kbuf, len); + tt_write(kbuf, len); /* Send the resulting string to the child process */ LK_RET(); } -/* print pipe */ #ifdef PRINTPIPE +/* Open the print pipe. */ FILE * popen_printer(void) { - FILE *stream = (FILE *) popen(rs_print_pipe, "w"); + FILE *stream; - if (stream == NULL) - print_error("can't open printer pipe \"%s\" -- %s", rs_print_pipe, strerror(errno)); + if (((my_ruid != my_euid) || (my_rgid != my_egid)) && (strcmp(rs_print_pipe, PRINTPIPE))) { + print_warning("Running setuid/setgid. Refusing to use custom printpipe."); + RESET_AND_ASSIGN(rs_print_pipe, StrDup(PRINTPIPE)); + } + if ((stream = (FILE *) popen(rs_print_pipe, "w")) == NULL) { + print_error("Can't open printer pipe \"%s\" -- %s", rs_print_pipe, strerror(errno)); + } return stream; } +/* Close the print pipe. */ int pclose_printer(FILE * stream) { @@ -748,7 +784,7 @@ pclose_printer(FILE * stream) return pclose(stream); } -/* simulate attached vt100 printer */ +/* Print everything until we hit a \e[4i sequence. */ void process_print_pipe(void) { @@ -775,14 +811,18 @@ process_print_pipe(void) } #endif /* PRINTPIPE */ -/* process escape sequences */ +/* This routine processes escape sequences; i.e., when a \033 character is encountered in the + input stream, this function is called to process it. First, we get the next character off + the input stream (the one after the ESC) and store it in ch. Then we proceed based on what + ch is. Some escape sequences are only ESC followed by a single character, so the + processing of those ends here. Others are longer and get passed on to other functions from + this one. */ void process_escape_seq(void) { unsigned char ch = cmd_getc(); switch (ch) { - /* case 1: do_tek_mode (); break; */ case '#': if (cmd_getc() == '8') scr_E(); @@ -838,11 +878,9 @@ process_escape_seq(void) case 'M': scr_index(DN); break; - /*case 'N': scr_single_shift (2); break; */ - /*case 'O': scr_single_shift (3); break; */ case 'Z': tt_printf((unsigned char *) ESCZ_ANSWER); - break; /* steal obsolete ESC [ c */ + break; case '[': process_csi_seq(); break; @@ -861,7 +899,10 @@ process_escape_seq(void) } } -/* process CSI (code sequence introducer) sequences `ESC[' */ +/* This function handles Code Sequence Introducer (CSI) escape sequences. At this point, + we've read "\e[" from the input stream. CSI sequences take an arbitrary number of + parameters and are used almost exclusively for terminal window navigation and + manipulation. */ void process_csi_seq(void) { @@ -875,12 +916,12 @@ process_csi_seq(void) arg[1] = 0; priv = 0; - ch = cmd_getc(); + ch = cmd_getc(); /* Get the next character */ if (ch >= '<' && ch <= '?') { - priv = ch; + priv = ch; /* DEC private mode sequence. Get next character. */ ch = cmd_getc(); } - /* read any numerical arguments */ + /* Read semicolon-delimited numerical arguments, if any. */ do { int n; @@ -892,64 +933,63 @@ process_csi_seq(void) if (ch == '\b') { scr_backspace(); } else if (ch == 033) { - process_escape_seq(); + cmd_ungetc(); /* New escape sequence starting in the middle of one. Punt. */ return; } else if (ch < ' ') { - scr_add_lines(&ch, 0, 1); + scr_add_lines(&ch, 0, 1); /* Insert verbatim non-printable character (NPC) */ return; } if (ch < '@') - ch = cmd_getc(); - } - while (ch >= ' ' && ch < '@'); + ch = cmd_getc(); /* Separator. Go to next digit or operation. */ + } while (ch >= ' ' && ch < '@'); if (ch == 033) { - process_escape_seq(); + cmd_ungetc(); return; } else if (ch < ' ') - return; + return; /* An NPC. Punt. */ switch (ch) { #ifdef PRINTPIPE - case 'i': /* printing */ + case 'i': switch (arg[0]) { case 0: - scr_printscreen(0); + scr_printscreen(0); /* Print screen "\e[0i" */ break; case 5: - process_print_pipe(); + process_print_pipe(); /* Start printing to print pipe "\e[5i" */ break; } break; #endif case 'A': - case 'e': /* up */ + case 'e': /* Cursor up n lines "\e[A" */ scr_gotorc((arg[0] ? -arg[0] : -1), 0, RELATIVE); break; - case 'B': /* down */ + case 'B': /* Cursor down n lines "\e[B" */ scr_gotorc((arg[0] ? +arg[0] : +1), 0, RELATIVE); break; case 'C': - case 'a': /* right */ + case 'a': /* Cursor right n columns "\e[C" */ scr_gotorc(0, (arg[0] ? +arg[0] : +1), RELATIVE); break; - case 'D': /* left */ + case 'D': /* Cursor left n columns "\e[D" */ scr_gotorc(0, (arg[0] ? -arg[0] : -1), RELATIVE); break; - case 'E': /* down & to first column */ + case 'E': /* Cursor down n lines and to first column "\e[E" */ scr_gotorc((arg[0] ? +arg[0] : +1), 0, R_RELATIVE); break; - case 'F': /* up & to first column */ + case 'F': /* Cursor up n lines and to first column "\e[F" */ scr_gotorc((arg[0] ? -arg[0] : -1), 0, R_RELATIVE); break; case 'G': - case '`': /* move to col */ + case '`': /* Cursor to column n "\e[G" */ scr_gotorc(0, (arg[0] ? arg[0] - 1 : +1), R_RELATIVE); break; - case 'd': /* move to row */ + case 'd': /* Cursor to row n "\e[d" */ scr_gotorc((arg[0] ? arg[0] - 1 : +1), 0, C_RELATIVE); break; case 'H': - case 'f': /* position cursor */ + case 'f': /* Cursor to row r, column c "\e[;H" */ switch (nargs) { case 0: scr_gotorc(0, 0, 0); @@ -962,16 +1002,16 @@ process_csi_seq(void) break; } break; - case 'I': + case 'I': /* Tab right n tab stops "\e[I" */ scr_tab(arg[0] ? +arg[0] : +1); break; - case 'Z': + case 'Z': /* Tab left n tab stops "\e[Z" */ scr_tab(arg[0] ? -arg[0] : -1); break; - case 'J': + case 'J': /* Clear part or all of screen, depending on n "\e[J" */ scr_erase_screen(arg[0]); break; - case 'K': + case 'K': /* Clear part or all of line, depending on n "\e[K" */ scr_erase_line(arg[0]); break; case '@': diff --git a/src/utmp.c b/src/utmp.c index 97dcd49..1bff994 100644 --- a/src/utmp.c +++ b/src/utmp.c @@ -230,18 +230,19 @@ remove_utmp_entry(void) if (!ut_id[0]) return; /* entry not made */ - privileges(INVOKE); utmpname(UTMP_FILENAME); setutent(); - if (getutid(&utmp) == NULL) + strncpy(utmp.ut_id, ut_id, sizeof(utmp.ut_id)); + utmp.ut_type = USER_PROCESS; + if (getutid(&utmp) == NULL) { return; + } utmp.ut_type = DEAD_PROCESS; utmp.ut_time = time(NULL); pututline(&utmp); getutmpx(&utmp, &utmpx); update_wtmp(WTMP_FILENAME, &utmpx); endutent(); - privileges(REVERT); # else /* HAVE_UTMPX_H */ struct utmp *putmp; @@ -250,7 +251,6 @@ remove_utmp_entry(void) if (!ut_id[0]) return; /* entry not made */ - privileges(INVOKE); utmpname(UTMP_FILENAME); setutent(); /* @@ -269,7 +269,6 @@ remove_utmp_entry(void) } } endutent(); - privileges(REVERT); # endif /* HAVE_UTMPX_H */ } # endif /* ifndef HAVE_UTEMPTER */ diff --git a/themes/auto/menus.cfg b/themes/auto/menus.cfg index d39cabd..88a8cf0 100644 --- a/themes/auto/menus.cfg +++ b/themes/auto/menus.cfg @@ -866,6 +866,27 @@ begin menu end end +begin menu + title "Eterm Operations" + begin menuitem + text "Version" + action string "\e[8n" + end + begin menuitem + text "Status" + action string "\e[9n" + end + separator + begin menuitem + text "Save Settings..." + action string "\e]6;71\a" + end + begin menuitem + text "Exit" + action string "\e]6;70\a" + end +end + # This is the menu that gets called by Ctrl-Button3 begin menu title Eterm