diff options
author | Matthieu Herrb <matthieu@cvs.openbsd.org> | 2008-08-25 18:05:58 +0000 |
---|---|---|
committer | Matthieu Herrb <matthieu@cvs.openbsd.org> | 2008-08-25 18:05:58 +0000 |
commit | 8178291553b032de1eb17eddaf1b776d58a08f8a (patch) | |
tree | 9d62774ffa340b2d23952c8ac62b5625f514d060 /app/xterm/misc.c | |
parent | 7f8f6db35e2fbeae9a6f2ce8c5ed7f4dd7498a3f (diff) |
xterm-236. Tested by form@ and simon@.
Diffstat (limited to 'app/xterm/misc.c')
-rw-r--r-- | app/xterm/misc.c | 1692 |
1 files changed, 1102 insertions, 590 deletions
diff --git a/app/xterm/misc.c b/app/xterm/misc.c index 8589fadfa..63408aadc 100644 --- a/app/xterm/misc.c +++ b/app/xterm/misc.c @@ -1,10 +1,8 @@ -/* $XTermId: misc.c,v 1.314 2006/08/03 23:54:32 tom Exp $ */ - -/* $XFree86: xc/programs/xterm/misc.c,v 3.107 2006/06/19 00:36:51 dickey Exp $ */ +/* $XTermId: misc.c,v 1.384 2008/07/27 15:38:05 tom Exp $ */ /* * - * Copyright 1999-2005,2006 by Thomas E. Dickey + * Copyright 1999-2007,2008 by Thomas E. Dickey * * All Rights Reserved * @@ -65,8 +63,10 @@ #include <pwd.h> #include <sys/wait.h> +#include <X11/keysym.h> #include <X11/Xatom.h> #include <X11/cursorfont.h> +#include <X11/Xlocale.h> #include <X11/Xmu/Error.h> #include <X11/Xmu/SysUtil.h> @@ -88,6 +88,7 @@ #include <fontutils.h> #include <xcharmouse.h> #include <xstrings.h> +#include <xtermcap.h> #include <VTparse.h> #include <assert.h> @@ -108,27 +109,169 @@ #if OPT_TEK4014 #define OUR_EVENT(event,Type) \ (event.type == Type && \ - (event.xcrossing.window == XtWindow(XtParent(term)) || \ + (event.xcrossing.window == XtWindow(XtParent(xw)) || \ (tekWidget && \ event.xcrossing.window == XtWindow(XtParent(tekWidget))))) #else #define OUR_EVENT(event,Type) \ (event.type == Type && \ - (event.xcrossing.window == XtWindow(XtParent(term)))) + (event.xcrossing.window == XtWindow(XtParent(xw)))) +#endif + +static Cursor make_hidden_cursor(XtermWidget); + +#if OPT_EXEC_XTERM +/* Like readlink(2), but returns a malloc()ed buffer, or NULL on + error; adapted from libc docs */ +static char * +Readlink(const char *filename) +{ + char *buf = NULL; + unsigned size = 100; + int n; + + for (;;) { + buf = TypeRealloc(char, size, buf); + memset(buf, 0, size); + + n = readlink(filename, buf, size); + if (n < 0) { + free(buf); + return NULL; + } + + if ((unsigned) n < size) { + return buf; + } + + size *= 2; + } +} +#endif /* OPT_EXEC_XTERM */ + +static void +Sleep(int msec) +{ + static struct timeval select_timeout; + + select_timeout.tv_sec = 0; + select_timeout.tv_usec = msec * 1000; + select(0, 0, 0, 0, &select_timeout); +} + +static void +selectwindow(TScreen * screen, int flag) +{ + TRACE(("selectwindow(%d) flag=%d\n", screen->select, flag)); + +#if OPT_TEK4014 + if (TEK4014_ACTIVE(term)) { + if (!Ttoggled) + TCursorToggle(tekWidget, TOGGLE); + screen->select |= flag; + if (!Ttoggled) + TCursorToggle(tekWidget, TOGGLE); + } else +#endif + { + if (screen->xic) + XSetICFocus(screen->xic); + + if (screen->cursor_state && CursorMoved(screen)) + HideCursor(); + screen->select |= flag; + if (screen->cursor_state) + ShowCursor(); + } +} + +static void +unselectwindow(TScreen * screen, int flag) +{ + TRACE(("unselectwindow(%d) flag=%d\n", screen->select, flag)); + + if (screen->hide_pointer) { + screen->hide_pointer = False; + xtermDisplayCursor(term); + } + + if (!screen->always_highlight) { +#if OPT_TEK4014 + if (TEK4014_ACTIVE(term)) { + if (!Ttoggled) + TCursorToggle(tekWidget, TOGGLE); + screen->select &= ~flag; + if (!Ttoggled) + TCursorToggle(tekWidget, TOGGLE); + } else #endif + { + if (screen->xic) + XUnsetICFocus(screen->xic); + + screen->select &= ~flag; + if (screen->cursor_state && CursorMoved(screen)) + HideCursor(); + if (screen->cursor_state) + ShowCursor(); + } + } +} -static Bool ChangeColorsRequest(XtermWidget xw, int start, char - *names, int final); -static void DoSpecialEnterNotify(XEnterWindowEvent * ev); -static void DoSpecialLeaveNotify(XEnterWindowEvent * ev); -static void selectwindow(TScreen * screen, int flag); -static void unselectwindow(TScreen * screen, int flag); -static void Sleep(int msec); +static void +DoSpecialEnterNotify(XtermWidget xw, XEnterWindowEvent * ev) +{ + TScreen *screen = TScreenOf(xw); + + TRACE(("DoSpecialEnterNotify(%d)\n", screen->select)); +#ifdef ACTIVEWINDOWINPUTONLY + if (ev->window == XtWindow(XtParent(CURRENT_EMU()))) +#endif + if (((ev->detail) != NotifyInferior) && + ev->focus && + !(screen->select & FOCUS)) + selectwindow(screen, INWINDOW); +} + +static void +DoSpecialLeaveNotify(XtermWidget xw, XEnterWindowEvent * ev) +{ + TScreen *screen = TScreenOf(xw); + + TRACE(("DoSpecialLeaveNotify(%d)\n", screen->select)); +#ifdef ACTIVEWINDOWINPUTONLY + if (ev->window == XtWindow(XtParent(CURRENT_EMU()))) +#endif + if (((ev->detail) != NotifyInferior) && + ev->focus && + !(screen->select & FOCUS)) + unselectwindow(screen, INWINDOW); +} + +#ifndef XUrgencyHint +#define XUrgencyHint (1L << 8) /* X11R5 does not define */ +#endif + +static void +setXUrgency(TScreen * screen, Bool enable) +{ + if (screen->bellIsUrgent) { + XWMHints *h = XGetWMHints(screen->display, VShellWindow); + if (h != 0) { + if (enable) { + h->flags |= XUrgencyHint; + } else { + h->flags &= ~XUrgencyHint; + } + XSetWMHints(screen->display, VShellWindow, h); + } + } +} void do_xevents(void) { - TScreen *screen = &term->screen; + TScreen *screen = TScreenOf(term); if (XtAppPending(app_con) || @@ -142,17 +285,94 @@ do_xevents(void) } void +xtermDisplayCursor(XtermWidget xw) +{ + TScreen *screen = TScreenOf(xw); + + if (screen->Vshow) { + if (screen->hide_pointer) { + TRACE(("Display hidden_cursor\n")); + XDefineCursor(screen->display, VWindow(screen), screen->hidden_cursor); + } else { + TRACE(("Display pointer_cursor\n")); + recolor_cursor(screen, + screen->pointer_cursor, + T_COLOR(screen, MOUSE_FG), + T_COLOR(screen, MOUSE_BG)); + XDefineCursor(screen->display, VWindow(screen), screen->pointer_cursor); + } + } +} + +void +xtermShowPointer(XtermWidget xw, Bool enable) +{ + static int tried = -1; + TScreen *screen = TScreenOf(xw); + +#if OPT_TEK4014 + if (TEK4014_SHOWN(xw)) + enable = True; +#endif + + /* + * Whether we actually hide the pointer depends on the pointer-mode and + * the mouse-mode: + */ + if (!enable) { + switch (screen->pointer_mode) { + case pNever: + enable = True; + break; + case pNoMouse: + if (screen->send_mouse_pos != MOUSE_OFF) + enable = True; + break; + case pAlways: + break; + } + } + + if (enable) { + if (screen->hide_pointer) { + screen->hide_pointer = False; + xtermDisplayCursor(xw); + switch (screen->send_mouse_pos) { + case ANY_EVENT_MOUSE: + break; + default: + MotionOff(screen, xw); + break; + } + } + } else if (!(screen->hide_pointer) && (tried <= 0)) { + if (screen->hidden_cursor == 0) { + screen->hidden_cursor = make_hidden_cursor(xw); + } + if (screen->hidden_cursor == 0) { + tried = 1; + } else { + tried = 0; + screen->hide_pointer = True; + xtermDisplayCursor(xw); + MotionOn(screen, xw); + } + } +} + +void xevents(void) { + XtermWidget xw = term; + TScreen *screen = TScreenOf(xw); XEvent event; XtInputMask input_mask; - TScreen *screen = &term->screen; if (need_cleanup) Cleanup(0); if (screen->scroll_amt) - FlushScroll(term); + FlushScroll(xw); /* * process timeouts, relying on the fact that XtAppProcessEvent * will process the timeout and return without blockng on the @@ -181,7 +401,7 @@ xevents(void) * We simply ignore all events except for those not passed down to * this function, e.g., those handled in in_put(). */ - if (waitingForTrackInfo) { + if (screen->waitingForTrackInfo) { Sleep(10); return; } @@ -192,18 +412,18 @@ xevents(void) * looking at the event ourselves we make sure that we can * do the right thing. */ - if (OUR_EVENT(event, EnterNotify)) - DoSpecialEnterNotify(&event.xcrossing); - else if (OUR_EVENT(event, LeaveNotify)) - DoSpecialLeaveNotify(&event.xcrossing); - else if ((screen->send_mouse_pos == ANY_EVENT_MOUSE + if (OUR_EVENT(event, EnterNotify)) { + DoSpecialEnterNotify(xw, &event.xcrossing); + } else if (OUR_EVENT(event, LeaveNotify)) { + DoSpecialLeaveNotify(xw, &event.xcrossing); + } else if ((screen->send_mouse_pos == ANY_EVENT_MOUSE #if OPT_DEC_LOCATOR - || screen->send_mouse_pos == DEC_LOCATOR + || screen->send_mouse_pos == DEC_LOCATOR #endif /* OPT_DEC_LOCATOR */ - ) - && event.xany.type == MotionNotify - && event.xcrossing.window == XtWindow(term)) { - SendMousePosition(term, &event); + ) + && event.xany.type == MotionNotify + && event.xcrossing.window == XtWindow(xw)) { + SendMousePosition(xw, &event); continue; } @@ -212,25 +432,79 @@ xevents(void) ((event.xany.type != KeyPress) && (event.xany.type != KeyRelease) && (event.xany.type != ButtonPress) && - (event.xany.type != ButtonRelease))) + (event.xany.type != ButtonRelease))) { + + /* + * If the event is interesting (and not a keyboard event), turn the + * mouse pointer back on. + */ + if (screen->hide_pointer) { + switch (event.xany.type) { + case KeyPress: + case KeyRelease: + case ButtonPress: + case ButtonRelease: + /* also these... */ + case Expose: + case NoExpose: + case PropertyNotify: + break; + default: + xtermShowPointer(xw, True); + break; + } + } + XtDispatchEvent(&event); + } } while ((input_mask = XtAppPending(app_con)) & XtIMXEvent); } +static Cursor +make_hidden_cursor(XtermWidget xw) +{ + TScreen *screen = TScreenOf(xw); + Cursor c; + Display *dpy = screen->display; + XFontStruct *fn; + + static XColor dummy; + + /* + * Prefer nil2 (which is normally available) to "fixed" (which is supposed + * to be "always" available), since it's a smaller glyph in case the + * server insists on drawing _somethng_. + */ + TRACE(("Ask for nil2 font\n")); + if ((fn = XLoadQueryFont(dpy, "nil2")) == 0) { + TRACE(("...Ask for fixed font\n")); + fn = XLoadQueryFont(dpy, "fixed"); + } + + if (fn != 0) { + /* a space character seems to work as a cursor (dots are not needed) */ + c = XCreateGlyphCursor(dpy, fn->fid, fn->fid, 'X', ' ', &dummy, &dummy); + XFreeFont(dpy, fn); + } else { + c = 0; + } + TRACE(("XCreateGlyphCursor ->%#lx\n", c)); + return (c); +} + Cursor make_colored_cursor(unsigned cursorindex, /* index into font */ unsigned long fg, /* pixel value */ unsigned long bg) /* pixel value */ { - TScreen *screen = &term->screen; + TScreen *screen = TScreenOf(term); Cursor c; Display *dpy = screen->display; c = XCreateFontCursor(dpy, cursorindex); - if (c == (Cursor) 0) - return (c); - - recolor_cursor(screen, c, fg, bg); + if (c != None) { + recolor_cursor(screen, c, fg, bg); + } return (c); } @@ -243,7 +517,7 @@ HandleKeyPressed(Widget w GCC_UNUSED, { TRACE(("Handle 7bit-key\n")); #ifdef ACTIVEWINDOWINPUTONLY - if (w == CURRENT_EMU(&(term->screen))) + if (w == CURRENT_EMU()) #endif Input(term, &event->xkey, False); } @@ -257,7 +531,7 @@ HandleEightBitKeyPressed(Widget w GCC_UNUSED, { TRACE(("Handle 8bit-key\n")); #ifdef ACTIVEWINDOWINPUTONLY - if (w == CURRENT_EMU(&(term->screen))) + if (w == CURRENT_EMU()) #endif Input(term, &event->xkey, True); } @@ -270,7 +544,7 @@ HandleStringEvent(Widget w GCC_UNUSED, Cardinal *nparams) { #ifdef ACTIVEWINDOWINPUTONLY - if (w != CURRENT_EMU(&(term->screen))) + if (w != CURRENT_EMU()) return; #endif @@ -299,6 +573,95 @@ HandleStringEvent(Widget w GCC_UNUSED, } } +#if OPT_EXEC_XTERM + +#ifndef PROCFS_ROOT +#define PROCFS_ROOT "/proc" +#endif + +/* ARGSUSED */ +void +HandleSpawnTerminal(Widget w GCC_UNUSED, + XEvent * event GCC_UNUSED, + String * params, + Cardinal *nparams) +{ + TScreen *screen = &term->screen; + char *child_cwd = NULL; + char *child_exe; + pid_t pid; + + /* + * Try to find the actual program which is running in the child process. + * This works for Linux. If we cannot find the program, fall back to the + * xterm program (which is usually adequate). Give up if we are given only + * a relative path to xterm, since that would not always match $PATH. + */ + child_exe = Readlink(PROCFS_ROOT "/self/exe"); + if (!child_exe) { + if (strncmp(ProgramName, "./", 2) + && strncmp(ProgramName, "../", 3)) { + child_exe = xtermFindShell(ProgramName, True); + } else { + fprintf(stderr, "Cannot exec-xterm given %s\n", ProgramName); + } + if (child_exe == 0) + return; + } + + /* + * Determine the current working directory of the child so that we can + * spawn a new terminal in the same directory. + * + * If we cannot get the CWD of the child, just use our own. + */ + if (screen->pid) { + char child_cwd_link[sizeof(PROCFS_ROOT) + 80]; + sprintf(child_cwd_link, PROCFS_ROOT "/%lu/cwd", (unsigned long) screen->pid); + child_cwd = Readlink(child_cwd_link); + } + + /* The reaper will take care of cleaning up the child */ + pid = fork(); + if (pid == -1) { + fprintf(stderr, "Could not fork: %s\n", SysErrorMsg(errno)); + } else if (!pid) { + /* We are the child */ + if (child_cwd) { + chdir(child_cwd); /* We don't care if this fails */ + } + + if (setuid(screen->uid) == -1 + || setgid(screen->gid) == -1) { + fprintf(stderr, "Cannot reset uid/gid\n"); + } else { + int myargc = *nparams + 1; + char **myargv = TypeMallocN(char *, myargc + 1); + int n = 0; + + myargv[n++] = child_exe; + + while (n < myargc) { + myargv[n++] = *params++; + } + + myargv[n] = 0; + execv(child_exe, myargv); + + /* If we get here, we've failed */ + fprintf(stderr, "exec of '%s': %s\n", child_exe, SysErrorMsg(errno)); + } + _exit(0); + } else { + /* We are the parent; clean up */ + if (child_cwd) + free(child_cwd); + if (child_exe) + free(child_exe); + } +} +#endif /* OPT_EXEC_XTERM */ + /* * Rather than sending characters to the host, put them directly into our * input queue. That lets a user have access to any of the control sequences @@ -326,7 +689,7 @@ HandleInterpret(Widget w GCC_UNUSED, if (have - used + need < BUF_SIZE) { - fillPtyData(&term->screen, VTbuffer, value, (int) strlen(value)); + fillPtyData(TScreenOf(term), VTbuffer, value, (int) strlen(value)); TRACE(("Interpret %s\n", value)); VTbuffer->update++; @@ -334,21 +697,6 @@ HandleInterpret(Widget w GCC_UNUSED, } } -static void -DoSpecialEnterNotify(XEnterWindowEvent * ev) -{ - TScreen *screen = &term->screen; - - TRACE(("DoSpecialEnterNotify(%d)\n", screen->select)); -#ifdef ACTIVEWINDOWINPUTONLY - if (ev->window == XtWindow(XtParent(CURRENT_EMU(screen)))) -#endif - if (((ev->detail) != NotifyInferior) && - ev->focus && - !(screen->select & FOCUS)) - selectwindow(screen, INWINDOW); -} - /*ARGSUSED*/ void HandleEnterWindow(Widget w GCC_UNUSED, @@ -360,21 +708,6 @@ HandleEnterWindow(Widget w GCC_UNUSED, TRACE(("HandleEnterWindow ignored\n")); } -static void -DoSpecialLeaveNotify(XEnterWindowEvent * ev) -{ - TScreen *screen = &term->screen; - - TRACE(("DoSpecialLeaveNotify(%d)\n", screen->select)); -#ifdef ACTIVEWINDOWINPUTONLY - if (ev->window == XtWindow(XtParent(CURRENT_EMU(screen)))) -#endif - if (((ev->detail) != NotifyInferior) && - ev->focus && - !(screen->select & FOCUS)) - unselectwindow(screen, INWINDOW); -} - /*ARGSUSED*/ void HandleLeaveWindow(Widget w GCC_UNUSED, @@ -394,14 +727,20 @@ HandleFocusChange(Widget w GCC_UNUSED, Boolean * cont GCC_UNUSED) { XFocusChangeEvent *event = (XFocusChangeEvent *) ev; - TScreen *screen = &term->screen; + XtermWidget xw = term; + TScreen *screen = TScreenOf(xw); - TRACE(("HandleFocusChange type=%d, mode=%d, detail=%d\n", - event->type, + TRACE(("HandleFocusChange type=%s, mode=%d, detail=%d\n", + visibleEventType(event->type), event->mode, event->detail)); - if (event->type == FocusIn) { + if (screen->quiet_grab + && (event->mode == NotifyGrab || event->mode == NotifyUngrab)) { + ; + } else if (event->type == FocusIn) { + setXUrgency(screen, False); + /* * NotifyNonlinear only happens (on FocusIn) if the pointer was not in * one of our windows. Use this to reset a case where one xterm is @@ -418,10 +757,16 @@ HandleFocusChange(Widget w GCC_UNUSED, ((event->detail == NotifyPointer) ? INWINDOW : FOCUS)); + SendFocusButton(xw, event); } else { +#if OPT_FOCUS_EVENT + if (event->type == FocusOut) { + SendFocusButton(xw, event); + } +#endif /* - * XGrabKeyboard() will generate FocusOut/NotifyGrab event that we want - * to ignore. + * XGrabKeyboard() will generate NotifyGrab event that we want to + * ignore. */ if (event->mode != NotifyGrab) { unselectwindow(screen, @@ -431,75 +776,19 @@ HandleFocusChange(Widget w GCC_UNUSED, } if (screen->grabbedKbd && (event->mode == NotifyUngrab)) { Bell(XkbBI_Info, 100); - ReverseVideo(term); + ReverseVideo(xw); screen->grabbedKbd = False; update_securekbd(); } } } -static void -selectwindow(TScreen * screen, int flag) -{ - TRACE(("selectwindow(%d) flag=%d\n", screen->select, flag)); - -#if OPT_TEK4014 - if (screen->TekEmu) { - if (!Ttoggled) - TCursorToggle(TOGGLE); - screen->select |= flag; - if (!Ttoggled) - TCursorToggle(TOGGLE); - return; - } else -#endif - { - if (screen->xic) - XSetICFocus(screen->xic); - - if (screen->cursor_state && CursorMoved(screen)) - HideCursor(); - screen->select |= flag; - if (screen->cursor_state) - ShowCursor(); - return; - } -} - -static void -unselectwindow(TScreen * screen, int flag) -{ - TRACE(("unselectwindow(%d) flag=%d\n", screen->select, flag)); - - if (screen->always_highlight) - return; - -#if OPT_TEK4014 - if (screen->TekEmu) { - if (!Ttoggled) - TCursorToggle(TOGGLE); - screen->select &= ~flag; - if (!Ttoggled) - TCursorToggle(TOGGLE); - } else -#endif - { - if (screen->xic) - XUnsetICFocus(screen->xic); - screen->select &= ~flag; - if (screen->cursor_state && CursorMoved(screen)) - HideCursor(); - if (screen->cursor_state) - ShowCursor(); - } -} - static long lastBellTime; /* in milliseconds */ void Bell(Atom which GCC_UNUSED, int percent) { - TScreen *screen = &term->screen; + TScreen *screen = TScreenOf(term); struct timeval curtime; long now_msecs; @@ -508,6 +797,8 @@ Bell(Atom which GCC_UNUSED, int percent) return; } + setXUrgency(screen, True); + /* has enough time gone by that we are allowed to ring the bell again? */ if (screen->bellSuppressTime) { @@ -544,7 +835,7 @@ Bell(Atom which GCC_UNUSED, int percent) back. If the server is suspending operations while the bell is being emitted (problematic for audio bell), this lets us know when the previous bell has finished */ - Widget w = CURRENT_EMU(screen); + Widget w = CURRENT_EMU(); XChangeProperty(XtDisplay(w), XtWindow(w), XA_NOTICE, XA_NOTICE, 8, PropModeAppend, NULL, 0); screen->bellInProgress = True; @@ -565,7 +856,7 @@ flashWindow(TScreen * screen, Window window, GC visualGC, unsigned width, unsign void VisualBell(void) { - TScreen *screen = &term->screen; + TScreen *screen = TScreenOf(term); if (VB_DELAY > 0) { Pixel xorPixel = (T_COLOR(screen, TEXT_FG) ^ @@ -577,10 +868,11 @@ VisualBell(void) gcval.foreground = xorPixel; visualGC = XtGetGC((Widget) term, GCFunction + GCForeground, &gcval); #if OPT_TEK4014 - if (screen->TekEmu) { - flashWindow(screen, TWindow(screen), visualGC, - TFullWidth(screen), - TFullHeight(screen)); + if (TEK4014_ACTIVE(term)) { + TekScreen *tekscr = &(tekWidget->screen); + flashWindow(screen, TWindow(tekscr), visualGC, + TFullWidth(tekscr), + TFullHeight(tekscr)); } else #endif { @@ -599,7 +891,7 @@ HandleBellPropertyChange(Widget w GCC_UNUSED, XEvent * ev, Boolean * more GCC_UNUSED) { - TScreen *screen = &term->screen; + TScreen *screen = TScreenOf(term); if (ev->xproperty.atom == XA_NOTICE) { screen->bellInProgress = False; @@ -695,15 +987,16 @@ dabbrev_expand(TScreen * screen) static int x, y; static char *dabbrev_hint = 0, *lastexpansion = 0; + static unsigned int expansions; char *expansion; Char *copybuffer; size_t hint_len; - unsigned i; unsigned del_cnt; unsigned buf_cnt; if (!screen->dabbrev_working) { /* initialize */ + expansions = 0; x = screen->cur_col; y = screen->cur_row + screen->savelines; @@ -722,7 +1015,16 @@ dabbrev_expand(TScreen * screen) } hint_len = strlen(dabbrev_hint); - while ((expansion = dabbrev_prev_word(&x, &y, screen))) { + for (;;) { + if (!(expansion = dabbrev_prev_word(&x, &y, screen))) { + if (expansions >= 2) { + expansions = 0; + x = screen->cur_col; + y = screen->cur_row + screen->savelines; + continue; + } + break; + } if (!strncmp(dabbrev_hint, expansion, hint_len) && /* empty hint matches everything */ strlen(expansion) > hint_len && /* trivial expansion disallowed */ strcmp(expansion, lastexpansion)) /* different from previous */ @@ -735,9 +1037,7 @@ dabbrev_expand(TScreen * screen) buf_cnt = del_cnt + strlen(expansion) - hint_len; if (!(copybuffer = TypeMallocN(Char, buf_cnt))) return 0; - for (i = 0; i < del_cnt; i++) { /* delete previous expansion */ - copybuffer[i] = screen->dabbrev_erase_char; - } + memset(copybuffer, screen->dabbrev_erase_char, del_cnt); /* delete previous expansion */ memmove(copybuffer + del_cnt, expansion + hint_len, strlen(expansion) - hint_len); @@ -749,6 +1049,7 @@ dabbrev_expand(TScreen * screen) lastexpansion = strdup(expansion); if (!lastexpansion) return 0; + expansions++; return 1; } @@ -759,10 +1060,12 @@ HandleDabbrevExpand(Widget gw, String * params GCC_UNUSED, Cardinal *nparams GCC_UNUSED) { - XtermWidget w = (XtermWidget) gw; - TScreen *screen = &w->screen; - if (!dabbrev_expand(screen)) - Bell(XkbBI_TerminalBell, 0); + if (IsXtermWidget(gw)) { + XtermWidget w = (XtermWidget) gw; + TScreen *screen = &w->screen; + if (!dabbrev_expand(screen)) + Bell(XkbBI_TerminalBell, 0); + } } #endif /* OPT_DABBREV */ @@ -775,7 +1078,7 @@ HandleDeIconify(Widget gw, Cardinal *nparams GCC_UNUSED) { if (IsXtermWidget(gw)) { - TScreen *screen = &((XtermWidget) gw)->screen; + TScreen *screen = TScreenOf((XtermWidget) gw); XMapWindow(screen->display, VShellWindow); } } @@ -788,7 +1091,7 @@ HandleIconify(Widget gw, Cardinal *nparams GCC_UNUSED) { if (IsXtermWidget(gw)) { - TScreen *screen = &((XtermWidget) gw)->screen; + TScreen *screen = TScreenOf((XtermWidget) gw); XIconifyWindow(screen->display, VShellWindow, DefaultScreen(screen->display)); @@ -942,9 +1245,11 @@ HandleRestoreSize(Widget gw, void Redraw(void) { - TScreen *screen = &term->screen; + TScreen *screen = TScreenOf(term); XExposeEvent event; + TRACE(("Redraw\n")); + event.type = Expose; event.display = screen->display; event.x = 0; @@ -964,8 +1269,9 @@ Redraw(void) } } #if OPT_TEK4014 - if (TWindow(screen) && screen->Tshow) { - event.window = TWindow(screen); + if (TEK4014_SHOWN(term)) { + TekScreen *tekscr = &(tekWidget->screen); + event.window = TWindow(tekscr); event.width = tekWidget->core.width; event.height = tekWidget->core.height; TekExpose((Widget) tekWidget, (XEvent *) & event, NULL); @@ -1074,8 +1380,8 @@ creat_as(uid_t uid, gid_t gid, Bool append, char *pathname, int mode) #endif /* HAVE_WAITPID */ TRACE(("creat_as(uid=%d/%d, gid=%d/%d, append=%d, pathname=%s, mode=%#o)\n", - uid, geteuid(), - gid, getegid(), + (int) uid, (int) geteuid(), + (int) gid, (int) getegid(), append, pathname, mode)); @@ -1173,7 +1479,7 @@ xtermResetIds(TScreen * screen) static SIGNAL_T logpipe(int sig GCC_UNUSED) { - TScreen *screen = &term->screen; + TScreen *screen = TScreenOf(term); #ifdef SYSV (void) signal(SIGPIPE, SIG_IGN); @@ -1223,7 +1529,7 @@ StartLog(TScreen * screen) sizeof(yyyy_mm_dd_hh_mm_ss), "%Y.%m.%d.%H.%M.%S", ltm) > 0)) { (void) sprintf(log_def_name, "Xterm.log.%.255s.%.20s.%d", - hostname, yyyy_mm_dd_hh_mm_ss, getpid()); + hostname, yyyy_mm_dd_hh_mm_ss, (int) getpid()); } if ((log_default = x_strdup(log_def_name)) == NULL) return; @@ -1268,7 +1574,7 @@ StartLog(TScreen * screen) close(ConnectionNumber(screen->display)); close(screen->respond); - if ((((cp = getenv("SHELL")) == NULL || *cp == 0) + if ((((cp = x_getenv("SHELL")) == NULL) && ((pw = getpwuid(screen->uid)) == NULL || *(cp = pw->pw_shell) == 0)) || (shell = CastMallocN(char, strlen(cp))) == 0) { @@ -1364,107 +1670,141 @@ ReportAnsiColorRequest(XtermWidget xw, int colornum, int final) color.red, color.green, color.blue); - unparseputc1(xw, OSC); + unparseputc1(xw, ANSI_OSC); unparseputs(xw, buffer); unparseputc1(xw, final); unparse_end(xw); } -/* -* Find closest color for "def" in "cmap". -* Set "def" to the resulting color. -* Based on Monish Shah's "find_closest_color()" for Vim 6.0, -* modified with ideas from David Tong's "noflash" library. -* Return False if not able to find or allocate a color. -*/ static int -find_closest_color(Display * display, Colormap cmap, XColor * def) +getColormapSize(Display * display) { - double tmp, distance, closestDistance; - int closest, numFound; - XColor *colortable; + int result; + int numFound; XVisualInfo myTemplate, *visInfoPtr; - char *found; - unsigned i; - unsigned cmap_size; - unsigned attempts; myTemplate.visualid = XVisualIDFromVisual(DefaultVisual(display, XDefaultScreen(display))); visInfoPtr = XGetVisualInfo(display, (long) VisualIDMask, &myTemplate, &numFound); - if (numFound < 1) { - /* FindClosestColor couldn't lookup visual */ - return False; - } + result = (numFound >= 1) ? visInfoPtr->colormap_size : 0; - cmap_size = visInfoPtr->colormap_size; XFree((char *) visInfoPtr); - colortable = TypeMallocN(XColor, cmap_size); - if (!colortable) { - return False; /* out of memory */ - } - found = TypeCallocN(char, cmap_size); - if (!found) { - free(colortable); - return False; /* out of memory */ - } + return result; +} - for (i = 0; i < cmap_size; i++) { - colortable[i].pixel = (unsigned long) i; - } - XQueryColors(display, cmap, colortable, (int) cmap_size); +/* + * Find closest color for "def" in "cmap". + * Set "def" to the resulting color. + * + * Based on Monish Shah's "find_closest_color()" for Vim 6.0, + * modified with ideas from David Tong's "noflash" library. + * The code from Vim in turn was derived from FindClosestColor() in Tcl/Tk. + * + * These provide some introduction: + * http://en.wikipedia.org/wiki/YIQ + * for an introduction to YIQ weights. + * http://en.wikipedia.org/wiki/Luminance_(video) + * for a discussion of luma. + * http://en.wikipedia.org/wiki/YUV + * + * Return False if not able to find or allocate a color. + */ +static Boolean +find_closest_color(Display * dpy, Colormap cmap, XColor * def) +{ + Boolean result = False; + XColor *colortable; + char *tried; + double diff, thisRGB, bestRGB; + unsigned attempts; + unsigned bestInx; + unsigned cmap_size; + unsigned i; + + cmap_size = getColormapSize(dpy); + if (cmap_size != 0) { + + colortable = TypeMallocN(XColor, cmap_size); + if (colortable != 0) { + + tried = TypeCallocN(char, cmap_size); + if (tried != 0) { + + for (i = 0; i < cmap_size; i++) { + colortable[i].pixel = (unsigned long) i; + } + XQueryColors(dpy, cmap, colortable, (int) cmap_size); - /* - * Find the color that best approximates the desired one, then - * try to allocate that color. If that fails, it must mean that - * the color was read-write (so we can't use it, since its owner - * might change it) or else it was already freed. Try again, - * over and over again, until something succeeds. - */ - for (attempts = 0; attempts < cmap_size; attempts++) { - closestDistance = 1e30; - closest = 0; - for (i = 0; i < cmap_size; i++) { - if (!found[closest]) { /* - * Use Euclidean distance in RGB space, weighted by Y (of YIQ) - * as the objective function; this accounts for differences - * in the color sensitivity of the eye. + * Try (possibly each entry in the color map) to find the best + * approximation to the requested color. */ - tmp = .30 * (((int) def->red) - (int) colortable[i].red); - distance = tmp * tmp; - tmp = .61 * (((int) def->green) - (int) colortable[i].green); - distance += tmp * tmp; - tmp = .11 * (((int) def->blue) - (int) colortable[i].blue); - distance += tmp * tmp; - if (distance < closestDistance) { - closest = i; - closestDistance = distance; + for (attempts = 0; attempts < cmap_size; attempts++) { + Boolean first = True; + + bestRGB = 0.0; + bestInx = 0; + for (i = 0; i < cmap_size; i++) { + if (!tried[bestInx]) { + /* + * Look for the best match based on luminance. + * Measure this by the least-squares difference of + * the weighted R/G/B components from the color map + * versus the requested color. Use the Y (luma) + * component of the YIQ color space model for + * weights that correspond to the luminance. + */ +#define AddColorWeight(weight, color) \ + diff = weight * (int) ((def->color) - colortable[i].color); \ + thisRGB = diff * diff + + AddColorWeight(0.30, red); + AddColorWeight(0.61, green); + AddColorWeight(0.11, blue); + + if (first || (thisRGB < bestRGB)) { + first = False; + bestInx = i; + bestRGB = thisRGB; + } + } + } + if (XAllocColor(dpy, cmap, &colortable[bestInx]) != 0) { + *def = colortable[bestInx]; + result = True; + break; + } + /* + * It failed - either the color map entry was readonly, or + * another client has allocated the entry. Mark the entry + * so we will ignore it + */ + tried[bestInx] = True; } + free(tried); } + free(colortable); } - if (XAllocColor(display, cmap, &colortable[closest]) != 0) { - *def = colortable[closest]; - break; - } - found[closest] = True; /* Don't look at this entry again */ - } - - free(colortable); - free(found); - if (attempts < cmap_size) { - return True; /* Got a closest matching color */ - } else { - return False; /* Couldn't allocate a near match */ } + return result; } -static Bool +/* + * Allocate a color for the "ANSI" colors. That actually includes colors up + * to 256. + * + * Returns + * -1 on error + * 0 on no change + * 1 if a new color was allocated. + */ +static int AllocateAnsiColor(XtermWidget xw, ColorRes * res, char *spec) { + int result; XColor def; TScreen *screen = &xw->screen; Colormap cmap = xw->core.colormap; @@ -1472,16 +1812,28 @@ AllocateAnsiColor(XtermWidget xw, if (XParseColor(screen->display, cmap, spec, &def) && (XAllocColor(screen->display, cmap, &def) || find_closest_color(screen->display, cmap, &def))) { - SET_COLOR_RES(res, def.pixel); - TRACE(("AllocateAnsiColor[%d] %s (pixel %#lx)\n", - (res - screen->Acolors), spec, def.pixel)); + if ( #if OPT_COLOR_RES - res->mode = True; + res->mode == True && #endif - return (True); + EQL_COLOR_RES(res, def.pixel)) { + result = 0; + } else { + result = 1; + SET_COLOR_RES(res, def.pixel); + TRACE(("AllocateAnsiColor[%d] %s (pixel %#lx)\n", + (res - screen->Acolors), spec, def.pixel)); +#if OPT_COLOR_RES + if (!res->mode) + result = 0; + res->mode = True; +#endif + } + } else { + TRACE(("AllocateAnsiColor %s (failed)\n", spec)); + result = -1; } - TRACE(("AllocateAnsiColor %s (failed)\n", spec)); - return (False); + return (result); } #if OPT_COLOR_RES @@ -1499,7 +1851,7 @@ xtermGetColorRes(ColorRes * res) if (res >= term->screen.Acolors) { assert(res - term->screen.Acolors < MAXCOLORS); - if (!AllocateAnsiColor(term, res, res->resource)) { + if (AllocateAnsiColor(term, res, res->resource) < 0) { res->value = term->screen.Tcolors[TEXT_FG].value; res->mode = -True; fprintf(stderr, @@ -1523,7 +1875,8 @@ ChangeAnsiColorRequest(XtermWidget xw, { char *name; int color; - int r = False; + int repaint = False; + int code; TRACE(("ChangeAnsiColorRequest string='%s'\n", buf)); @@ -1545,17 +1898,22 @@ ChangeAnsiColorRequest(XtermWidget xw, ReportAnsiColorRequest(xw, color, final); else { TRACE(("ChangeAnsiColor for Acolors[%d]\n", color)); - if (!AllocateAnsiColor(xw, &(xw->screen.Acolors[color]), name)) + code = AllocateAnsiColor(xw, &(xw->screen.Acolors[color]), name); + if (code < 0) { + /* stop on any error */ break; + } else if (code > 0) { + repaint = True; + } /* FIXME: free old color somehow? We aren't for the other color * change style (dynamic colors). */ - r = True; } } - if (r) - ChangeAnsiColors(xw); - return (r); + if (repaint) + xtermRepaint(xw); + + return (repaint); } #else #define find_closest_color(display, cmap, def) 0 @@ -1616,7 +1974,7 @@ ManipulateSelectionData(XtermWidget xw, TScreen * screen, char *buf, int final) if (!strcmp(buf, "?")) { TRACE(("Getting selection\n")); - unparseputc1(xw, OSC); + unparseputc1(xw, ANSI_OSC); unparseputs(xw, "52"); unparseputc(xw, ';'); @@ -1642,6 +2000,278 @@ ManipulateSelectionData(XtermWidget xw, TScreen * screen, char *buf, int final) /***====================================================================***/ +static Bool +xtermIsPrintable(TScreen * screen, Char ** bufp, Char * last) +{ + Bool result = False; + Char *cp = *bufp; + Char *next = cp; + + (void) screen; + (void) last; + +#if OPT_WIDE_CHARS + if (xtermEnvUTF8() && screen->utf8_title) { + PtyData data; + + if (decodeUtf8(fakePtyData(&data, cp, last))) { + if (data.utf_data != UCS_REPL + && (data.utf_data >= 128 || + ansi_table[data.utf_data] == CASE_PRINT)) { + next += (data.utf_size - 1); + result = True; + } else { + result = False; + } + } else { + result = False; + } + } else +#endif +#if OPT_C1_PRINT + if (screen->c1_printable + && (*cp >= 128 && *cp < 160)) { + result = True; + } else +#endif + if (ansi_table[*cp] == CASE_PRINT) { + result = True; + } + *bufp = next; + return result; +} + +/***====================================================================***/ + +/* + * Enum corresponding to the actual OSC codes rather than the internal + * array indices. + */ +typedef enum { + OSC_TEXT_FG = 10 + ,OSC_TEXT_BG + ,OSC_TEXT_CURSOR + ,OSC_MOUSE_FG + ,OSC_MOUSE_BG +#if OPT_TEK4014 + ,OSC_TEK_FG = 15 + ,OSC_TEK_BG +#endif +#if OPT_HIGHLIGHT_COLOR + ,OSC_HIGHLIGHT_BG = 17 +#endif +#if OPT_TEK4014 + ,OSC_TEK_CURSOR = 18 +#endif +#if OPT_HIGHLIGHT_COLOR + ,OSC_HIGHLIGHT_FG = 19 +#endif + ,OSC_NCOLORS +} OscTextColors; + +static ScrnColors *pOldColors = NULL; + +static Bool +GetOldColors(XtermWidget xw) +{ + int i; + if (pOldColors == NULL) { + pOldColors = (ScrnColors *) XtMalloc(sizeof(ScrnColors)); + if (pOldColors == NULL) { + fprintf(stderr, "allocation failure in GetOldColors\n"); + return (False); + } + pOldColors->which = 0; + for (i = 0; i < NCOLORS; i++) { + pOldColors->colors[i] = 0; + pOldColors->names[i] = NULL; + } + GetColors(xw, pOldColors); + } + return (True); +} + +static int +oppositeColor(int n) +{ + switch (n) { + case TEXT_FG: + n = TEXT_BG; + break; + case TEXT_BG: + n = TEXT_FG; + break; + case MOUSE_FG: + n = MOUSE_BG; + break; + case MOUSE_BG: + n = MOUSE_FG; + break; +#if OPT_TEK4014 + case TEK_FG: + n = TEK_BG; + break; + case TEK_BG: + n = TEK_FG; + break; +#endif +#if OPT_HIGHLIGHT_COLOR + case HIGHLIGHT_FG: + n = HIGHLIGHT_BG; + break; + case HIGHLIGHT_BG: + n = HIGHLIGHT_FG; + break; +#endif + default: + break; + } + return n; +} + +static void +ReportColorRequest(XtermWidget xw, int ndx, int final) +{ + XColor color; + Colormap cmap = xw->core.colormap; + char buffer[80]; + + /* + * ChangeColorsRequest() has "always" chosen the opposite color when + * reverse-video is set. Report this as the original color index, but + * reporting the opposite color which would be used. + */ + int i = (xw->misc.re_verse) ? oppositeColor(ndx) : ndx; + + GetOldColors(xw); + color.pixel = pOldColors->colors[ndx]; + XQueryColor(xw->screen.display, cmap, &color); + sprintf(buffer, "%d;rgb:%04x/%04x/%04x", i + 10, + color.red, + color.green, + color.blue); + TRACE(("ReportColors %d: %#lx as %s\n", ndx, pOldColors->colors[ndx], buffer)); + unparseputc1(xw, ANSI_OSC); + unparseputs(xw, buffer); + unparseputc1(xw, final); + unparse_end(xw); +} + +static Bool +UpdateOldColors(XtermWidget xw GCC_UNUSED, ScrnColors * pNew) +{ + int i; + + /* if we were going to free old colors, this would be the place to + * do it. I've decided not to (for now), because it seems likely + * that we'd have a small set of colors we use over and over, and that + * we could save some overhead this way. The only case in which this + * (clearly) fails is if someone is trying a boatload of colors, in + * which case they can restart xterm + */ + for (i = 0; i < NCOLORS; i++) { + if (COLOR_DEFINED(pNew, i)) { + if (pOldColors->names[i] != NULL) { + XtFree(pOldColors->names[i]); + pOldColors->names[i] = NULL; + } + if (pNew->names[i]) { + pOldColors->names[i] = pNew->names[i]; + } + pOldColors->colors[i] = pNew->colors[i]; + } + } + return (True); +} + +/* + * OSC codes are constant, but the indices for the color arrays depend on how + * xterm is compiled. + */ +static int +OscToColorIndex(OscTextColors mode) +{ + int result = 0; + +#define CASE(name) case OSC_##name: result = name; break + switch (mode) { + CASE(TEXT_FG); + CASE(TEXT_BG); + CASE(TEXT_CURSOR); + CASE(MOUSE_FG); + CASE(MOUSE_BG); +#if OPT_TEK4014 + CASE(TEK_FG); + CASE(TEK_BG); +#endif +#if OPT_HIGHLIGHT_COLOR + CASE(HIGHLIGHT_BG); + CASE(HIGHLIGHT_FG); +#endif +#if OPT_TEK4014 + CASE(TEK_CURSOR); +#endif + case OSC_NCOLORS: + break; + } + return result; +} + +static Bool +ChangeColorsRequest(XtermWidget xw, + int start, + char *names, + int final) +{ + Bool result = False; + char *thisName; + ScrnColors newColors; + int i, ndx; + + TRACE(("ChangeColorsRequest start=%d, names='%s'\n", start, names)); + + if (GetOldColors(xw)) { + newColors.which = 0; + for (i = 0; i < NCOLORS; i++) { + newColors.names[i] = NULL; + } + for (i = start; i < OSC_NCOLORS; i++) { + ndx = OscToColorIndex((OscTextColors) i); + if (xw->misc.re_verse) + ndx = oppositeColor(ndx); + + if ((names == NULL) || (names[0] == '\0')) { + newColors.names[ndx] = NULL; + } else { + if (names[0] == ';') + thisName = NULL; + else + thisName = names; + names = strchr(names, ';'); + if (names != NULL) { + *names++ = '\0'; + } + if (thisName != 0 && !strcmp(thisName, "?")) { + ReportColorRequest(xw, ndx, final); + } else if (!pOldColors->names[ndx] + || (thisName + && strcmp(thisName, pOldColors->names[ndx]))) { + AllocateTermColor(xw, &newColors, ndx, thisName); + } + } + } + + if (newColors.which != 0) { + ChangeColors(xw, &newColors); + UpdateOldColors(xw, &newColors); + } + result = True; + } + return result; +} + +/***====================================================================***/ + void do_osc(XtermWidget xw, Char * oscbuf, unsigned len GCC_UNUSED, int final) { @@ -1685,19 +2315,12 @@ do_osc(XtermWidget xw, Char * oscbuf, unsigned len GCC_UNUSED, int final) state = 3; /* FALLTHRU */ default: - if (ansi_table[CharOf(*cp)] != CASE_PRINT) { + if (!xtermIsPrintable(screen, &cp, oscbuf + len)) { switch (mode) { case 0: case 1: case 2: -#if OPT_WIDE_CHARS - /* - * If we're running with UTF-8, it is possible for title - * strings to contain "nonprinting" text. - */ - if (xtermEnvUTF8()) -#endif - break; + break; default: TRACE(("do_osc found nonprinting char %02X offset %d\n", CharOf(*cp), @@ -1712,16 +2335,16 @@ do_osc(XtermWidget xw, Char * oscbuf, unsigned len GCC_UNUSED, int final) switch (mode) { case 0: /* new icon name and title */ - Changename(buf); - Changetitle(buf); + ChangeIconName(buf); + ChangeTitle(buf); break; case 1: /* new icon name only */ - Changename(buf); + ChangeIconName(buf); break; case 2: /* new title only */ - Changetitle(buf); + ChangeTitle(buf); break; case 3: /* change X property */ @@ -1732,21 +2355,21 @@ do_osc(XtermWidget xw, Char * oscbuf, unsigned len GCC_UNUSED, int final) ChangeAnsiColorRequest(xw, buf, final); break; #endif - case 10 + TEXT_FG: - case 10 + TEXT_BG: - case 10 + TEXT_CURSOR: - case 10 + MOUSE_FG: - case 10 + MOUSE_BG: + case OSC_TEXT_FG: + case OSC_TEXT_BG: + case OSC_TEXT_CURSOR: + case OSC_MOUSE_FG: + case OSC_MOUSE_BG: #if OPT_HIGHLIGHT_COLOR - case 10 + HIGHLIGHT_BG: + case OSC_HIGHLIGHT_BG: #endif #if OPT_TEK4014 - case 10 + TEK_FG: - case 10 + TEK_BG: - case 10 + TEK_CURSOR: + case OSC_TEK_FG: + case OSC_TEK_BG: + case OSC_TEK_CURSOR: #endif if (xw->misc.dynamicColors) - ChangeColorsRequest(xw, mode - 10, buf, final); + ChangeColorsRequest(xw, mode, buf, final); break; case 30: @@ -1777,10 +2400,11 @@ do_osc(XtermWidget xw, Char * oscbuf, unsigned len GCC_UNUSED, int final) #endif /* ALLOWLOGGING */ case 50: +#if OPT_SHIFT_FONTS if (buf != 0 && !strcmp(buf, "?")) { int num = screen->menu_font_number; - unparseputc1(xw, OSC); + unparseputc1(xw, ANSI_OSC); unparseputs(xw, "50"); if ((buf = screen->MenuFontName(num)) != 0) { @@ -1790,6 +2414,7 @@ do_osc(XtermWidget xw, Char * oscbuf, unsigned len GCC_UNUSED, int final) unparseputc1(xw, final); unparse_end(xw); } else if (buf != 0) { + int num = screen->menu_font_number; VTFontNames fonts; memset(&fonts, 0, sizeof(fonts)); @@ -1800,7 +2425,6 @@ do_osc(XtermWidget xw, Char * oscbuf, unsigned len GCC_UNUSED, int final) * corresponding menu font entry. */ if (*buf == '#') { - int num = screen->menu_font_number; int rel = 0; if (*++buf == '+') { @@ -1823,20 +2447,24 @@ do_osc(XtermWidget xw, Char * oscbuf, unsigned len GCC_UNUSED, int final) num = 0; } - if (rel != 0) - num = lookupRelativeFontSize(screen, + if (rel != 0) { + num = lookupRelativeFontSize(xw, screen->menu_font_number, rel); + } if (num < 0 || num > fontMenu_lastBuiltin || (buf = screen->MenuFontName(num)) == 0) { Bell(XkbBI_MinorError, 0); break; } + } else { + num = fontMenu_fontescape; } fonts.f_n = buf; - SetVTFont(xw, fontMenu_fontescape, True, &fonts); + SetVTFont(xw, num, True, &fonts); } +#endif /* OPT_SHIFT_FONTS */ break; case 51: /* reserved for Emacs shell (Rob Mayoff <mayoff@dqd.com>) */ @@ -2003,7 +2631,7 @@ parse_decdld(ANSI * params, char *string) len = 0; while (*string != '\0') { ch = CharOf(*string++); - if (ch >= 0x20 && ch <= 0x2f) { + if (ch >= ANSI_SPA && ch <= 0x2f) { if (len < 2) DscsName[len++] = ch; } else if (ch >= 0x30 && ch <= 0x7e) { @@ -2185,16 +2813,16 @@ do_dcs(XtermWidget xw, Char * dcsbuf, size_t dcslen) } else okay = False; - unparseputc1(xw, DCS); + unparseputc1(xw, ANSI_DCS); unparseputc(xw, okay ? '1' : '0'); unparseputc(xw, '$'); unparseputc(xw, 'r'); if (okay) cp = reply; unparseputs(xw, cp); - unparseputc1(xw, ST); + unparseputc1(xw, ANSI_ST); } else { - unparseputc(xw, CAN); + unparseputc(xw, ANSI_CAN); } break; #if OPT_TCAP_QUERY @@ -2207,7 +2835,7 @@ do_dcs(XtermWidget xw, Char * dcsbuf, size_t dcslen) char *tmp; char *parsed = ++cp; - unparseputc1(xw, DCS); + unparseputc1(xw, ANSI_DCS); code = xtermcapKeycode(xw, &parsed, &state, &fkey); @@ -2227,11 +2855,22 @@ do_dcs(XtermWidget xw, Char * dcsbuf, size_t dcslen) unparseputc(xw, '='); screen->tc_query_code = code; screen->tc_query_fkey = fkey; +#if OPT_ISO_COLORS /* XK_COLORS is a fake code for the "Co" entry (maximum * number of colors) */ if (code == XK_COLORS) { unparseputn(xw, NUM_ANSI_COLORS); - } else { + } else +#endif +#if OPT_TCAP_FKEYS + /* + * First ensure that we handle the extended cursor- and + * editing-keypad keys. + */ + if ((code <= XK_Fn(MAX_FKEY)) + || xtermcapString(xw, CodeToXkey(code), 0) == 0) +#endif + { XKeyEvent event; event.state = state; Input(xw, &event, False); @@ -2248,7 +2887,7 @@ do_dcs(XtermWidget xw, Char * dcsbuf, size_t dcslen) code = xtermcapKeycode(xw, &parsed, &state, &fkey); } } - unparseputc1(xw, ST); + unparseputc1(xw, ANSI_ST); } break; #endif @@ -2285,17 +2924,22 @@ ChangeGroup(String attribute, char *value) #if OPT_WIDE_CHARS static Char *converted; /* NO_LEAKS */ #endif + static char empty[1]; + Arg args[1]; - char *original = (value != 0) ? value : ""; + char *original = (value != 0) ? value : empty; char *name = original; - TScreen *screen = &term->screen; - Widget w = CURRENT_EMU(screen); + TScreen *screen = TScreenOf(term); + Widget w = CURRENT_EMU(); Widget top = SHELL_OF(w); unsigned limit = strlen(name); + Char *c1 = (Char *) original; + Char *cp; TRACE(("ChangeGroup(attribute=%s, value=%s)\n", attribute, name)); - (void) screen; + if (!screen->allowTitleOps) + return; /* * Ignore titles that are too long to be plausible requests. @@ -2303,6 +2947,13 @@ ChangeGroup(String attribute, char *value) if (limit >= 1024) return; + for (cp = c1; *cp != 0; ++cp) { + Char *c2 = cp; + if (!xtermIsPrintable(screen, &cp, c1 + limit)) { + memset(c2, '?', (unsigned) (cp + 1 - c2)); + } + } + #if OPT_WIDE_CHARS /* * Title strings are limited to ISO-8859-1, which is consistent with the @@ -2337,7 +2988,7 @@ ChangeGroup(String attribute, char *value) #if OPT_SAME_NAME /* If the attribute isn't going to change, then don't bother... */ - if (sameName) { + if (resource.sameName) { char *buf; XtSetArg(args[0], attribute, &buf); XtGetValues(top, args, 1); @@ -2348,6 +2999,7 @@ ChangeGroup(String attribute, char *value) #endif /* OPT_SAME_NAME */ TRACE(("...updating %s\n", attribute)); + TRACE(("...value is %s\n", name)); XtSetArg(args[0], attribute, name); XtSetValues(top, args, 1); @@ -2355,12 +3007,14 @@ ChangeGroup(String attribute, char *value) if (xtermEnvUTF8()) { Display *dpy = XtDisplay(term); Atom my_atom; - char *propname = (!strcmp(attribute, XtNtitle) - ? "_NET_WM_NAME" - : "_NET_WM_ICON_NAME"); + + const char *propname = (!strcmp(attribute, XtNtitle) + ? "_NET_WM_NAME" + : "_NET_WM_ICON_NAME"); if ((my_atom = XInternAtom(dpy, propname, False)) != None) { - if (screen->utf8_title) { + if (screen->utf8_title) { /* FIXME - redundant? */ TRACE(("...updating %s\n", propname)); + TRACE(("...value is %s\n", original)); XChangeProperty(dpy, VShellWindow, my_atom, XA_UTF8_STRING(dpy), 8, PropModeReplace, @@ -2375,15 +3029,15 @@ ChangeGroup(String attribute, char *value) } void -Changename(char *name) +ChangeIconName(char *name) { if (name == 0) name = ""; #if OPT_ZICONBEEP /* If warning should be given then give it */ - if (zIconBeep && zIconBeep_flagged) { + if (resource.zIconBeep && term->screen.zIconBeep_flagged) { char *newname = CastMallocN(char, strlen(name) + 4); if (!newname) { - fprintf(stderr, "malloc failed in Changename\n"); + fprintf(stderr, "malloc failed in ChangeIconName\n"); return; } strcpy(newname, "*** "); @@ -2396,7 +3050,7 @@ Changename(char *name) } void -Changetitle(char *name) +ChangeTitle(char *name) { ChangeGroup(XtNtitle, name); } @@ -2429,113 +3083,6 @@ ChangeXprop(char *buf) /***====================================================================***/ -static ScrnColors *pOldColors = NULL; - -static Bool -GetOldColors(XtermWidget xw) -{ - int i; - if (pOldColors == NULL) { - pOldColors = (ScrnColors *) XtMalloc(sizeof(ScrnColors)); - if (pOldColors == NULL) { - fprintf(stderr, "allocation failure in GetOldColors\n"); - return (False); - } - pOldColors->which = 0; - for (i = 0; i < NCOLORS; i++) { - pOldColors->colors[i] = 0; - pOldColors->names[i] = NULL; - } - GetColors(xw, pOldColors); - } - return (True); -} - -static int -oppositeColor(int n) -{ - switch (n) { - case TEXT_FG: - n = TEXT_BG; - break; - case TEXT_BG: - n = TEXT_FG; - break; - case MOUSE_FG: - n = MOUSE_BG; - break; - case MOUSE_BG: - n = MOUSE_FG; - break; -#if OPT_TEK4014 - case TEK_FG: - n = TEK_BG; - break; - case TEK_BG: - n = TEK_FG; - break; -#endif - default: - break; - } - return n; -} - -static void -ReportColorRequest(XtermWidget xw, int ndx, int final) -{ - XColor color; - Colormap cmap = xw->core.colormap; - char buffer[80]; - - /* - * ChangeColorsRequest() has "always" chosen the opposite color when - * reverse-video is set. Report this as the original color index, but - * reporting the opposite color which would be used. - */ - int i = (xw->misc.re_verse) ? oppositeColor(ndx) : ndx; - - GetOldColors(xw); - color.pixel = pOldColors->colors[ndx]; - XQueryColor(xw->screen.display, cmap, &color); - sprintf(buffer, "%d;rgb:%04x/%04x/%04x", i + 10, - color.red, - color.green, - color.blue); - TRACE(("ReportColors %d: %#lx as %s\n", ndx, pOldColors->colors[ndx], buffer)); - unparseputc1(xw, OSC); - unparseputs(xw, buffer); - unparseputc1(xw, final); - unparse_end(xw); -} - -static Bool -UpdateOldColors(XtermWidget xw GCC_UNUSED, ScrnColors * pNew) -{ - int i; - - /* if we were going to free old colors, this would be the place to - * do it. I've decided not to (for now), because it seems likely - * that we'd have a small set of colors we use over and over, and that - * we could save some overhead this way. The only case in which this - * (clearly) fails is if someone is trying a boatload of colors, in - * which case they can restart xterm - */ - for (i = 0; i < NCOLORS; i++) { - if (COLOR_DEFINED(pNew, i)) { - if (pOldColors->names[i] != NULL) { - XtFree(pOldColors->names[i]); - pOldColors->names[i] = NULL; - } - if (pNew->names[i]) { - pOldColors->names[i] = pNew->names[i]; - } - pOldColors->colors[i] = pNew->colors[i]; - } - } - return (True); -} - /* * This is part of ReverseVideo(). It reverses the data stored for the old * "dynamic" colors that might have been retrieved using OSC 10-18. @@ -2601,67 +3148,9 @@ AllocateTermColor(XtermWidget xw, TRACE(("AllocateTermColor #%d: %s (failed)\n", ndx, name)); return (False); } - -static Bool -ChangeColorsRequest(XtermWidget xw, - int start, - char *names, - int final) -{ - char *thisName; - ScrnColors newColors; - int i, ndx; - - TRACE(("ChangeColorsRequest start=%d, names='%s'\n", start, names)); - - if ((pOldColors == NULL) - && (!GetOldColors(xw))) { - return (False); - } - newColors.which = 0; - for (i = 0; i < NCOLORS; i++) { - newColors.names[i] = NULL; - } - for (i = start; i < NCOLORS; i++) { - if (xw->misc.re_verse) - ndx = oppositeColor(i); - else - ndx = i; - if ((names == NULL) || (names[0] == '\0')) { - newColors.names[ndx] = NULL; - } else { - if (names[0] == ';') - thisName = NULL; - else - thisName = names; - names = strchr(names, ';'); - if (names != NULL) { - *names = '\0'; - names++; - } - if (thisName != 0 && !strcmp(thisName, "?")) - ReportColorRequest(xw, ndx, final); - else if (!pOldColors->names[ndx] - || (thisName - && strcmp(thisName, pOldColors->names[ndx]))) { - AllocateTermColor(xw, &newColors, ndx, thisName); - } - } - } - - if (newColors.which == 0) - return (True); - - ChangeColors(xw, &newColors); - UpdateOldColors(xw, &newColors); - return (True); -} - /***====================================================================***/ -#ifndef DEBUG /* ARGSUSED */ -#endif void Panic(char *s GCC_UNUSED, int a GCC_UNUSED) { @@ -2675,100 +3164,91 @@ Panic(char *s GCC_UNUSED, int a GCC_UNUSED) #endif /* DEBUG */ } -char * -SysErrorMsg(int n) +const char * +SysErrorMsg(int code) { static char unknown[] = "unknown error"; - char *s = strerror(n); + char *s = strerror(code); return s ? s : unknown; } -void -SysError(int i) +const char * +SysReasonMsg(int code) { - static const char *table[] = - { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - ,"main: ioctl() failed on FIONBIO" /* 11 */ - ,"main: ioctl() failed on F_GETFL" /* 12 */ - ,"main: ioctl() failed on F_SETFL" /* 13 */ - ,"spawn: open() failed on /dev/tty" /* 14 */ - ,"spawn: ioctl() failed on TIOCGETP" /* 15 */ - ,0 - ,"spawn: ptsname() failed" /* 17 */ - ,"spawn: open() failed on ptsname" /* 18 */ - ,"spawn: ioctl() failed on I_PUSH/\"ptem\"" /* 19 */ - ,"spawn: ioctl() failed on I_PUSH/\"consem\"" /* 20 */ - ,"spawn: ioctl() failed on I_PUSH/\"ldterm\"" /* 21 */ - ,"spawn: ioctl() failed on I_PUSH/\"ttcompat\"" /* 22 */ - ,"spawn: ioctl() failed on TIOCSETP" /* 23 */ - ,"spawn: ioctl() failed on TIOCSETC" /* 24 */ - ,"spawn: ioctl() failed on TIOCSETD" /* 25 */ - ,"spawn: ioctl() failed on TIOCSLTC" /* 26 */ - ,"spawn: ioctl() failed on TIOCLSET" /* 27 */ - ,"spawn: initgroups() failed" /* 28 */ - ,"spawn: fork() failed" /* 29 */ - ,"spawn: exec() failed" /* 30 */ - ,0 - ,"get_pty: not enough ptys" /* 32 */ - ,0 - ,"waiting for initial map" /* 34 */ - ,"spawn: setuid() failed" /* 35 */ - ,"spawn: can't initialize window" /* 36 */ - ,0, 0, 0, 0, 0, 0, 0, 0, 0 - ,"spawn: ioctl() failed on TIOCKSET" /* 46 */ - ,"spawn: ioctl() failed on TIOCKSETC" /* 47 */ - ,"spawn: realloc of ttydev failed" /* 48 */ - ,"luit: command-line malloc failed" /* 49 */ - ,"in_put: select() failed" /* 50 */ - ,0, 0, 0 - ,"VTInit: can't initialize window" /* 54 */ - ,0, 0 - ,"HandleKeymapChange: malloc failed" /* 57 */ - ,0, 0 - ,"Tinput: select() failed" /* 60 */ - ,0, 0, 0 - ,"TekInit: can't initialize window" /* 64 */ - ,0, 0, 0, 0, 0, 0 - ,"SaltTextAway: malloc() failed" /* 71 */ - ,0, 0, 0, 0, 0, 0, 0, 0 - ,"StartLog: exec() failed" /* 80 */ - ,0, 0 - ,"xerror: XError event" /* 83 */ - ,"xioerror: X I/O error" /* 84 */ - ,0, 0, 0, 0, 0 - ,"Alloc: calloc() failed on base" /* 90 */ - ,"Alloc: calloc() failed on rows" /* 91 */ - ,"ScreenResize: realloc() failed on alt base" /* 92 */ - ,0, 0, 0 - ,"ScreenResize: malloc() or realloc() failed" /* 96 */ - ,0, 0, 0, 0, 0 - ,"ScrnPointers: malloc/realloc() failed" /* 102 */ - ,0, 0, 0, 0, 0, 0, 0 - ,"ScrollBarOn: realloc() failed on base" /* 110 */ - ,"ScrollBarOn: realloc() failed on rows" /* 111 */ - ,0, 0, 0, 0, 0, 0, 0, 0, 0 - ,"my_memmove: malloc/realloc failed" /* 121 */ + /* *INDENT-OFF* */ + static const struct { + int code; + const char *name; + } table[] = { + { ERROR_FIONBIO, "main: ioctl() failed on FIONBIO" }, + { ERROR_F_GETFL, "main: ioctl() failed on F_GETFL" }, + { ERROR_F_SETFL, "main: ioctl() failed on F_SETFL", }, + { ERROR_OPDEVTTY, "spawn: open() failed on /dev/tty", }, + { ERROR_TIOCGETP, "spawn: ioctl() failed on TIOCGETP", }, + { ERROR_PTSNAME, "spawn: ptsname() failed", }, + { ERROR_OPPTSNAME, "spawn: open() failed on ptsname", }, + { ERROR_PTEM, "spawn: ioctl() failed on I_PUSH/\"ptem\"" }, + { ERROR_CONSEM, "spawn: ioctl() failed on I_PUSH/\"consem\"" }, + { ERROR_LDTERM, "spawn: ioctl() failed on I_PUSH/\"ldterm\"" }, + { ERROR_TTCOMPAT, "spawn: ioctl() failed on I_PUSH/\"ttcompat\"" }, + { ERROR_TIOCSETP, "spawn: ioctl() failed on TIOCSETP" }, + { ERROR_TIOCSETC, "spawn: ioctl() failed on TIOCSETC" }, + { ERROR_TIOCSETD, "spawn: ioctl() failed on TIOCSETD" }, + { ERROR_TIOCSLTC, "spawn: ioctl() failed on TIOCSLTC" }, + { ERROR_TIOCLSET, "spawn: ioctl() failed on TIOCLSET" }, + { ERROR_INIGROUPS, "spawn: initgroups() failed" }, + { ERROR_FORK, "spawn: fork() failed" }, + { ERROR_EXEC, "spawn: exec() failed" }, + { ERROR_PTYS, "get_pty: not enough ptys" }, + { ERROR_PTY_EXEC, "waiting for initial map" }, + { ERROR_SETUID, "spawn: setuid() failed" }, + { ERROR_INIT, "spawn: can't initialize window" }, + { ERROR_TIOCKSET, "spawn: ioctl() failed on TIOCKSET" }, + { ERROR_TIOCKSETC, "spawn: ioctl() failed on TIOCKSETC" }, + { ERROR_SPREALLOC, "spawn: realloc of ttydev failed" }, + { ERROR_LUMALLOC, "luit: command-line malloc failed" }, + { ERROR_SELECT, "in_put: select() failed" }, + { ERROR_VINIT, "VTInit: can't initialize window" }, + { ERROR_KMMALLOC1, "HandleKeymapChange: malloc failed" }, + { ERROR_TSELECT, "Tinput: select() failed" }, + { ERROR_TINIT, "TekInit: can't initialize window" }, + { ERROR_BMALLOC2, "SaltTextAway: malloc() failed" }, + { ERROR_LOGEXEC, "StartLog: exec() failed" }, + { ERROR_XERROR, "xerror: XError event" }, + { ERROR_XIOERROR, "xioerror: X I/O error" }, + { ERROR_SCALLOC, "Alloc: calloc() failed on base" }, + { ERROR_SCALLOC2, "Alloc: calloc() failed on rows" }, + { ERROR_SREALLOC, "ScreenResize: realloc() failed on alt base" }, + { ERROR_RESIZE, "ScreenResize: malloc() or realloc() failed" }, + { ERROR_SAVE_PTR, "ScrnPointers: malloc/realloc() failed" }, + { ERROR_SBRALLOC, "ScrollBarOn: realloc() failed on base" }, + { ERROR_SBRALLOC2, "ScrollBarOn: realloc() failed on rows" }, + { ERROR_MMALLOC, "my_memmove: malloc/realloc failed" }, }; - int oerrno; + /* *INDENT-ON* */ - oerrno = errno; - fprintf(stderr, "%s: Error %d, errno %d: ", xterm_name, i, oerrno); - fprintf(stderr, "%s\n", SysErrorMsg(oerrno)); - if ((Cardinal) i < XtNumber(table) && table[i] != 0) { - fprintf(stderr, "Reason: %s\n", table[i]); + Cardinal n; + const char *result = "?"; + + for (n = 0; n < XtNumber(table); ++n) { + if (code == table[n].code) { + result = table[n].name; + break; + } } - Cleanup(i); + return result; } -static void -Sleep(int msec) +void +SysError(int code) { - static struct timeval select_timeout; + int oerrno = errno; - select_timeout.tv_sec = 0; - select_timeout.tv_usec = msec * 1000; - select(0, 0, 0, 0, &select_timeout); + fprintf(stderr, "%s: Error %d, errno %d: ", xterm_name, code, oerrno); + fprintf(stderr, "%s\n", SysErrorMsg(oerrno)); + fprintf(stderr, "Reason: %s\n", SysReasonMsg(code)); + + Cleanup(code); } /* @@ -2778,7 +3258,7 @@ void Cleanup(int code) { static Bool cleaning; - TScreen *screen = &term->screen; + TScreen *screen = TScreenOf(term); /* * Process "-hold" and session cleanup only for a normal exit. @@ -2790,7 +3270,7 @@ Cleanup(int code) } cleaning = True; - need_cleanup = FALSE; + need_cleanup = False; TRACE(("Cleanup %d\n", code)); @@ -2828,8 +3308,8 @@ xtermFindShell(char *leaf, Bool warning) TRACE(("xtermFindShell(%s)\n", leaf)); if (*result != '\0' && strchr("+/-", *result) == 0) { /* find it in $PATH */ - if ((s = getenv("PATH")) != 0) { - if ((tmp = TypeMallocN(char, strlen(leaf) + strlen(s) + 1)) != 0) { + if ((s = x_getenv("PATH")) != 0) { + if ((tmp = TypeMallocN(char, strlen(leaf) + strlen(s) + 2)) != 0) { Bool found = False; while (*s != '\0') { strcpy(tmp, s); @@ -2871,6 +3351,26 @@ xtermFindShell(char *leaf, Bool warning) } #endif /* VMS */ +#define ENV_HUNK(n) ((((n) + 1) | 31) + 1) + +/* + * copy the environment before Setenv'ing. + */ +void +xtermCopyEnv(char **oldenv) +{ + unsigned size; + char **newenv; + + for (size = 0; oldenv[size] != NULL; size++) { + ; + } + + newenv = TypeCallocN(char *, ENV_HUNK(size)); + memmove(newenv, oldenv, size * sizeof(char *)); + environ = newenv; +} + /* * sets the value of var to be arg in the Unix 4.2 BSD environment env. * Var should end with '=' (bindings are of the form "var=value"). @@ -2882,28 +3382,48 @@ void xtermSetenv(char *var, char *value) { if (value != 0) { + char *test; int envindex = 0; size_t len = strlen(var); + int found = -1; - TRACE(("xtermSetenv(var=%s, value=%s)\n", var, value)); + TRACE(("xtermSetenv(%s=%s)\n", var, value)); - while (environ[envindex] != NULL) { - if (strncmp(environ[envindex], var, len) == 0) { - /* found it */ - environ[envindex] = CastMallocN(char, len + strlen(value)); - strcpy(environ[envindex], var); - strcat(environ[envindex], value); - return; + while ((test = environ[envindex]) != NULL) { + if (strncmp(test, var, len) == 0 && test[len] == '=') { + found = envindex; + break; } envindex++; } - TRACE(("...expanding env to %d\n", envindex + 1)); + if (found < 0) { + unsigned need = ENV_HUNK(envindex + 1); + unsigned have = ENV_HUNK(envindex); + + if (need > have) { + char **newenv; + newenv = TypeMallocN(char *, need); + if (newenv == 0) { + fprintf(stderr, "Cannot increase environment\n"); + return; + } + memmove(newenv, environ, have * sizeof(*newenv)); + free(environ); + environ = newenv; + } + + found = envindex; + environ[found + 1] = NULL; + environ = environ; + } - environ[envindex] = CastMallocN(char, len + strlen(value)); - (void) strcpy(environ[envindex], var); - strcat(environ[envindex], value); - environ[++envindex] = NULL; + environ[found] = CastMallocN(char, 1 + len + strlen(value)); + if (environ[found] == 0) { + fprintf(stderr, "Cannot allocate environment %s\n", var); + return; + } + sprintf(environ[found], "%s=%s", var, value); } } @@ -2935,14 +3455,12 @@ xioerror(Display * dpy) void xt_error(String message) { - char *ptr; - (void) fprintf(stderr, "%s Xt error: %s\n", ProgramName, message); /* * Check for the obvious - Xt does a poor job of reporting this. */ - if ((ptr = getenv("DISPLAY")) == 0 || *x_strtrim(ptr) == '\0') { + if (x_getenv("DISPLAY") == 0) { fprintf(stderr, "%s: DISPLAY is not set\n", ProgramName); } exit(1); @@ -2974,7 +3492,7 @@ withdraw_window(Display * dpy, Window w, int scr) void set_vt_visibility(Bool on) { - TScreen *screen = &term->screen; + TScreen *screen = TScreenOf(term); TRACE(("set_vt_visibility(%d)\n", on)); if (on) { @@ -3011,11 +3529,10 @@ set_vt_visibility(Bool on) void set_tek_visibility(Bool on) { - TScreen *screen = &term->screen; - TRACE(("set_tek_visibility(%d)\n", on)); + if (on) { - if (!screen->Tshow && (tekWidget || TekInit())) { + if (!TEK4014_SHOWN(term) && (tekWidget || TekInit())) { Widget tekParent = SHELL_OF(tekWidget); XtRealizeWidget(tekParent); XtMapWidget(XtParent(tekWidget)); @@ -3030,14 +3547,14 @@ set_tek_visibility(Bool on) (void) XSetWMProtocols(XtDisplay(tekParent), XtWindow(tekParent), &wm_delete_window, 1); - screen->Tshow = True; + TEK4014_SHOWN(term) = True; } } else { - if (screen->Tshow && tekWidget) { + if (TEK4014_SHOWN(term) && tekWidget) { withdraw_window(XtDisplay(tekWidget), TShellWindow, XScreenNumberOfScreen(XtScreen(tekWidget))); - screen->Tshow = False; + TEK4014_SHOWN(term) = False; } } set_tekhide_sensitivity(); @@ -3051,10 +3568,8 @@ set_tek_visibility(Bool on) void end_tek_mode(void) { - TScreen *screen = &term->screen; - - if (screen->TekEmu) { - FlushLog(screen); + if (TEK4014_ACTIVE(term)) { + FlushLog(&(term->screen)); longjmp(Tekend, 1); } return; @@ -3063,11 +3578,9 @@ end_tek_mode(void) void end_vt_mode(void) { - TScreen *screen = &term->screen; - - if (!screen->TekEmu) { - FlushLog(screen); - screen->TekEmu = True; + if (!TEK4014_ACTIVE(term)) { + FlushLog(&(term->screen)); + TEK4014_ACTIVE(term) = True; longjmp(VTend, 1); } return; @@ -3077,8 +3590,8 @@ void switch_modes(Bool tovt) /* if true, then become vt mode */ { if (tovt) { - if (TekRefresh) - dorefresh(); + if (tekRefreshList) + TekRefresh(tekWidget); end_tek_mode(); /* WARNING: this does a longjmp... */ } else { end_vt_mode(); /* WARNING: this does a longjmp... */ @@ -3088,21 +3601,17 @@ switch_modes(Bool tovt) /* if true, then become vt mode */ void hide_vt_window(void) { - TScreen *screen = &term->screen; - set_vt_visibility(False); - if (!screen->TekEmu) + if (!TEK4014_ACTIVE(term)) switch_modes(False); /* switch to tek mode */ } void hide_tek_window(void) { - TScreen *screen = &term->screen; - set_tek_visibility(False); - TekRefresh = (TekLink *) 0; - if (screen->TekEmu) + tekRefreshList = (TekLink *) 0; + if (TEK4014_ACTIVE(term)) switch_modes(True); /* does longjmp to vt mode */ } #endif /* OPT_TEK4014 */ @@ -3170,8 +3679,12 @@ sortedOpts(OptionHelp * options, XrmOptionDescRec * descs, Cardinal numDescs) sortedOptDescs(descs, numDescs); free(opt_array); opt_array = 0; - } else if (options != 0 && descs != 0) + return 0; + } else if (options == 0 || descs == 0) { + return 0; + } #endif + if (opt_array == 0) { Cardinal opt_count, j; #if OPT_TRACE @@ -3250,7 +3763,7 @@ sortedOpts(OptionHelp * options, XrmOptionDescRec * descs, Cardinal numDescs) } /* - * Report the locale that xterm was started in. + * Report the character-type locale that xterm was started in. */ char * xtermEnvLocale(void) @@ -3258,10 +3771,9 @@ xtermEnvLocale(void) static char *result; if (result == 0) { - if ((result = getenv("LC_ALL")) == 0 || *result == '\0') - if ((result = getenv("LC_CTYPE")) == 0 || *result == '\0') - if ((result = getenv("LANG")) == 0 || *result == '\0') - result = ""; + if ((result = x_nonempty(setlocale(LC_CTYPE, 0))) == 0) { + result = "C"; + } TRACE(("xtermEnvLocale ->%s\n", result)); } return result; @@ -3277,7 +3789,7 @@ xtermEnvEncoding(void) result = nl_langinfo(CODESET); #else char *locale = xtermEnvLocale(); - if (*locale == 0 || !strcmp(locale, "C") || !strcmp(locale, "POSIX")) { + if (!strcmp(locale, "C") || !strcmp(locale, "POSIX")) { result = "ASCII"; } else { result = "ISO-8859-1"; |