*** empty log message ***
[dana/urxvt.git] / src / main.C
index 1e7b167..e08736b 100644 (file)
@@ -13,7 +13,7 @@
  * Copyright (c) 1997,1998 Oezguer Kesim <kesim@math.fu-berlin.de>
  * Copyright (c) 1998-2001 Geoff Wing <gcw@pobox.com>
  *                              - extensive modifications
- * Copyright (c) 2003-2004 Marc Lehmann <pcg@goof.com>
+ * Copyright (c) 2003-2006 Marc Lehmann <pcg@goof.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 
 #include "../config.h"          /* NECESSARY */
 #include "rxvt.h"               /* NECESSARY */
+#include "keyboard.h"
+#include "rxvtperl.h"
+
+#include <limits>
 
 #include <csignal>
 #include <cstring>
 # include <termios.h>
 #endif
 
-#ifdef KEYSYM_RESOURCE
-# include "keyboard.h"
-#endif
-
 vector<rxvt_term *> rxvt_term::termlist;
 
-static char curlocale[128];
+static char curlocale[128], savelocale[128];
 
 bool
 rxvt_set_locale (const char *locale)
@@ -63,6 +63,19 @@ rxvt_set_locale (const char *locale)
   return true;
 }
 
+void
+rxvt_push_locale (const char *locale)
+{
+  strcpy (savelocale, curlocale);
+  rxvt_set_locale (locale);
+}
+
+void
+rxvt_pop_locale ()
+{
+  rxvt_set_locale (savelocale);
+}
+
 #if ENABLE_COMBINING
 class rxvt_composite_vec rxvt_composite;
 
@@ -135,9 +148,6 @@ rxvt_term::rxvt_term ()
 #ifdef HAVE_SCROLLBARS
     scrollbar_ev (this, &rxvt_term::x_cb),
 #endif
-#ifdef MENUBAR
-    menubar_ev (this, &rxvt_term::x_cb),
-#endif
 #ifdef CURSOR_BLINK
     cursor_blink_ev (this, &rxvt_term::cursor_blink_cb),
 #endif
@@ -159,9 +169,6 @@ rxvt_term::rxvt_term ()
 #ifdef USE_XIM
     im_ev (this, &rxvt_term::im_cb),
 #endif
-    sw_term (this, &rxvt_term::sig_term),
-    sw_int (this, &rxvt_term::sig_term),
-    sw_chld (this, &rxvt_term::sig_chld),
     termwin_ev (this, &rxvt_term::x_cb),
     vt_ev (this, &rxvt_term::x_cb),
     check_ev (this, &rxvt_term::check_cb),
@@ -189,25 +196,23 @@ void rxvt_term::emergency_cleanup ()
   if (cmd_pid)
     kill (-cmd_pid, SIGHUP);
 
-#ifdef UTMP_SUPPORT
-  privileged_utmp (RESTORE);
-#endif
-
-  pty.put ();
+  delete pty; pty = 0;
 }
 
 rxvt_term::~rxvt_term ()
 {
+  HOOK_INVOKE ((this, HOOK_DESTROY, DT_END));
+
   termlist.erase (find (termlist.begin (), termlist.end(), this));
 
   emergency_cleanup ();
 
 #if ENABLE_STYLES
   for (int i = RS_styleCount; --i; )
-    if (TermWin.fontset[i] != TermWin.fontset[0])
-      delete TermWin.fontset[i];
+    if (fontset[i] != fontset[0])
+      delete fontset[i];
 #endif
-  delete TermWin.fontset[0];
+  delete fontset[0];
 
   if (display)
     {
@@ -218,9 +223,6 @@ rxvt_term::~rxvt_term ()
 #ifdef USE_XIM
       im_destroy ();
 #endif
-#ifdef MENUBAR
-      if (menubarGC)    XFreeGC (disp, menubarGC);
-#endif
 #ifdef XTERM_SCROLLBAR
       if (xscrollbarGC) XFreeGC (disp, xscrollbarGC);
       if (ShadowGC)     XFreeGC (disp, ShadowGC);
@@ -240,26 +242,20 @@ rxvt_term::~rxvt_term ()
       if (upArrowHi)    XFreePixmap (disp, upArrowHi);
       if (downArrowHi)  XFreePixmap (disp, downArrowHi);
 #endif
-#if defined(MENUBAR) || defined(RXVT_SCROLLBAR)
+#ifdef RXVT_SCROLLBAR
       if (topShadowGC)  XFreeGC (disp, topShadowGC);
       if (botShadowGC)  XFreeGC (disp, botShadowGC);
       if (scrollbarGC)  XFreeGC (disp, scrollbarGC);
 #endif
-      if (TermWin.gc)   XFreeGC (disp, TermWin.gc);
+      if (gc)   XFreeGC (disp, gc);
 
-#if defined(MENUBAR) && (MENUBAR_MAX > 1)
-      delete menuBar.drawable;
-      //if (menuBar.win)
-      //  XDestroyWindow (disp, menuBar.win);
-#endif
-      delete TermWin.drawable;
+      delete drawable;
       // destroy all windows
-      if (TermWin.parent[0])
-        XDestroyWindow (disp, TermWin.parent[0]);
+      if (parent[0])
+        XDestroyWindow (disp, parent[0]);
     }
 
   // TODO: free pixcolours, colours should become part of rxvt_display
-
   delete pix_colors_focused;
 #if OFF_FOCUS_FADING
   delete pix_colors_unfocused;
@@ -292,6 +288,15 @@ rxvt_term::~rxvt_term ()
 }
 
 void
+rxvt_term::child_exit ()
+{
+  cmd_pid = 0;
+
+  if (!OPTION (Opt_hold))
+    destroy ();
+}
+
+void
 rxvt_term::destroy ()
 {
   if (destroy_ev.active)
@@ -309,9 +314,6 @@ rxvt_term::destroy ()
 #if HAVE_SCROLLBARS
       scrollbar_ev.stop (display);
 #endif
-#if MENUBAR
-      menubar_ev.stop (display);
-#endif
 #if TRANSPARENT
       rootwin_ev.stop (display);
 #endif
@@ -344,7 +346,7 @@ rxvt_term::destroy ()
 void
 rxvt_term::destroy_cb (time_watcher &w)
 {
-  SET_R (this);
+  make_current ();
 
   delete this;
 }
@@ -419,8 +421,8 @@ rxvt_xerror_handler (Display *display, XErrorEvent *event)
     GET_R->allowedxerror = event->error_code;
   else
     {
-      //TODO: GET_R is most likely not the terminal which caused the error
-      //TODO: maybe just output the error and continue?
+      // GET_R is most likely not the terminal which caused the error,
+      // so just output the error and continue
 #if ENABLE_FRILLS
       print_x_error (display, event);
 #else
@@ -440,28 +442,13 @@ rxvt_xioerror_handler (Display *display)
   _exit (EXIT_FAILURE);
 }
 
-/*
- * Catch a fatal signal and tidy up before quitting
- */
-void
-rxvt_term::sig_term (sig_watcher &w)
-{
-#ifdef DEBUG_CMD
-  rxvt_warn ("caught signal %d, exiting.\n", w.signum);
-#endif
-  rxvt_emergency_cleanup ();
-  signal (w.signum, SIG_DFL);
-  kill (getpid (), w.signum);
-}
-
 /*----------------------------------------------------------------------*/
-/* rxvt_init () */
 bool
 rxvt_term::init (int argc, const char *const *argv)
 {
   SET_R (this);
-
   set_locale ("");
+  set_environ (envv); // few things in X do not call setlocale :(
 
   if (!init_vars ())
     return false;
@@ -474,36 +461,44 @@ rxvt_term::init (int argc, const char *const *argv)
   keyboard->register_done ();
 #endif
 
-#if MENUBAR_MAX
-  menubar_read (rs[Rs_menu]);
-#endif
 #ifdef HAVE_SCROLLBARS
-  if (options & Opt_scrollBar)
+  if (OPTION (Opt_scrollBar))
     scrollBar.setIdle ();    /* set existence for size calculations */
 #endif
 
+#if ENABLE_PERL
+  if (!rs[Rs_perl_ext_1])
+    rs[Rs_perl_ext_1] = "default";
+
+  if ((rs[Rs_perl_ext_1] && *rs[Rs_perl_ext_1])
+      || (rs[Rs_perl_ext_2] && *rs[Rs_perl_ext_2])
+      || (rs[Rs_perl_eval] && *rs[Rs_perl_eval]))
+    {
+      rxvt_perl.init (this);
+      HOOK_INVOKE ((this, HOOK_INIT, DT_END));
+    }
+#endif
+
+  pty = rxvt_new_ptytty ();
+
   create_windows (argc, argv);
 
   dDisp;
 
   init_xlocale ();
 
-  scr_reset ();         /* initialize screen */
+  scr_reset (); // initialize screen
 
 #if 0
   XSynchronize (disp, True);
 #endif
 
 #ifdef HAVE_SCROLLBARS
-  if (options & Opt_scrollBar)
+  if (OPTION (Opt_scrollBar))
     resize_scrollbar ();      /* create and map scrollbar */
 #endif
-#if (MENUBAR_MAX)
-  if (menubar_visible ())
-    XMapWindow (disp, menuBar.win);
-#endif
 #ifdef TRANSPARENT
-  if (options & Opt_transparent)
+  if (OPTION (Opt_transparent))
     {
       XSelectInput (disp, display->root, PropertyChangeMask);
       check_our_parents ();
@@ -511,8 +506,8 @@ rxvt_term::init (int argc, const char *const *argv)
     }
 #endif
 
-  XMapWindow (disp, TermWin.vt);
-  XMapWindow (disp, TermWin.parent[0]);
+  XMapWindow (disp, vt);
+  XMapWindow (disp, parent[0]);
 
   set_colorfgbg ();
 
@@ -520,57 +515,109 @@ rxvt_term::init (int argc, const char *const *argv)
 
   free (cmd_argv);
 
-  pty_ev.start (pty.pty, EVENT_READ);
+  if (pty->pty >= 0)
+    pty_ev.start (pty->pty, EVENT_READ);
 
   check_ev.start ();
 
+  HOOK_INVOKE ((this, HOOK_START, DT_END));
+
   return true;
 }
 
-void
-rxvt_init ()
+static struct sig_handlers
 {
+  sig_watcher sw_chld, sw_term, sw_int;
+  
+  void sig_chld (sig_watcher &w)
+  {
+    // we are being called for every SIGCHLD, find the corresponding term
+    int pid;
+
+    while ((pid = waitpid (-1, NULL, WNOHANG)) > 0)
+      for (rxvt_term **t = rxvt_term::termlist.begin (); t < rxvt_term::termlist.end (); t++)
+        if (pid == (*t)->cmd_pid)
+          {
+            (*t)->child_exit ();
+            break;
+          }
+  }
+
   /*
-   * Save and then give up any super-user privileges
-   * If we need privileges in any area then we must specifically request it.
-   * We should only need to be root in these cases:
-   *  1.  write utmp entries on some systems
-   *  2.  chown tty on some systems
+   * Catch a fatal signal and tidy up before quitting
    */
-  rxvt_privileges (SAVE);
-  rxvt_privileges (IGNORE);
+  void
+  sig_term (sig_watcher &w)
+  {
+#ifdef DEBUG_CMD
+    rxvt_warn ("caught signal %d, exiting.\n", w.signum);
+#endif
+    rxvt_emergency_cleanup ();
+    signal (w.signum, SIG_DFL);
+    kill (getpid (), w.signum);
+  }
+
+  sig_handlers ()
+  : sw_chld (this, &sig_handlers::sig_chld),
+    sw_term (this, &sig_handlers::sig_term),
+    sw_int  (this, &sig_handlers::sig_term)
+  {
+  }
+} sig_handlers;
+
+char **rxvt_environ; // startup environment
+
+void
+rxvt_init ()
+{
+  uid_t uid = getuid ();
+  gid_t gid = getgid ();
+      
+  // before doing anything else, check for setuid/setgid operation,
+  // start the helper process and drop privileges
+  if (uid != geteuid ()
+      || gid != getegid ())
+    {
+#if PTYTTY_HELPER
+      rxvt_ptytty_server ();
+#else
+      rxvt_warn ("running setuid/setgid without pty helper compiled in, continuing unprivileged.\n");
+#endif
+
+      // drop privileges
+#if HAVE_SETRESUID
+      setresgid (gid, gid, gid);
+      setresuid (uid, uid, uid);
+#elif HAVE_SETREUID
+      setregid (gid, gid);
+      setreuid (uid, uid);
+#elif HAVE_SETUID
+      setgid (gid);
+      setuid (uid);
+#endif
+
+      if (uid != geteuid ()
+          || gid != getegid ())
+        rxvt_fatal ("unable to drop privileges, aborting.\n");
+    }
+
+  rxvt_environ = environ;
 
   signal (SIGHUP,  SIG_IGN);
   signal (SIGPIPE, SIG_IGN);
 
+  sig_handlers.sw_chld.start (SIGCHLD);
+  sig_handlers.sw_term.start (SIGTERM);
+  sig_handlers.sw_int.start  (SIGINT);
+
   /* need to trap SIGURG for SVR4 (Unixware) rlogin */
   /* signal (SIGURG, SIG_DFL); */
 
   old_xerror_handler = XSetErrorHandler ((XErrorHandler) rxvt_xerror_handler);
   // TODO: handle this with exceptions and tolerate the memory loss
   XSetIOErrorHandler (rxvt_xioerror_handler);
-}
-
-/* ------------------------------------------------------------------------- *
- *                       SIGNAL HANDLING & EXIT HANDLER                      *
- * ------------------------------------------------------------------------- */
-/*
- * Catch a SIGCHLD signal and exit if the direct child has died
- */
 
-void
-rxvt_term::sig_chld (sig_watcher &w)
-{
-  // we are being called for every SIGCHLD, not just ours
-  int pid;
-
-  while ((pid = waitpid (-1, NULL, WNOHANG)) > 0)
-    for (rxvt_term **t = termlist.begin (); t < termlist.end (); t++)
-      if (pid == (*t)->cmd_pid)
-        {
-          (*t)->destroy ();
-          break;
-        }
+  XrmInitialize ();
 }
 
 /* ------------------------------------------------------------------------- *
@@ -587,7 +634,7 @@ rxvt_malloc (size_t size)
   return p;
 }
 
-void           *
+void *
 rxvt_calloc (size_t number, size_t size)
 {
   void *p = calloc (number, size);
@@ -609,118 +656,46 @@ rxvt_realloc (void *ptr, size_t size)
   return p;
 }
 
-/* ------------------------------------------------------------------------- *
- *                            PRIVILEGED OPERATIONS                          *
- * ------------------------------------------------------------------------- */
-/* take care of suid/sgid super-user (root) privileges */
-void
-rxvt_privileges (rxvt_privaction action)
-{
-#if (defined(HAVE_SETEUID) || defined(HAVE_SETREUID)) && !defined(__CYGWIN32__)
-  static uid_t euid;
-  static gid_t egid;
-#endif
-
-#if ! defined(__CYGWIN32__)
-# if !defined(HAVE_SETEUID) && defined(HAVE_SETREUID)
-  /* setreuid () is the poor man's setuid (), seteuid () */
-#  define seteuid(a)    setreuid(-1, (a))
-#  define setegid(a)    setregid(-1, (a))
-#  define HAVE_SETEUID
-# endif
-# ifdef HAVE_SETEUID
-  switch (action)
-    {
-      case IGNORE:
-        /*
-         * change effective uid/gid - not real uid/gid - so we can switch
-         * back to root later, as required
-         */
-        seteuid (getuid ());
-        setegid (getgid ());
-        break;
-      case SAVE:
-        euid = geteuid ();
-        egid = getegid ();
-        break;
-      case RESTORE:
-        seteuid (euid);
-        setegid (egid);
-        break;
-    }
-# else
-  switch (action)
-    {
-      case IGNORE:
-        setuid (getuid ());
-        setgid (getgid ());
-        /* FALLTHROUGH */
-      case SAVE:
-        /* FALLTHROUGH */
-      case RESTORE:
-        break;
-    }
-# endif
-#endif
-}
-
-#ifdef UTMP_SUPPORT
-void
-rxvt_term::privileged_utmp (rxvt_privaction action)
-{
-  if ((options & Opt_utmpInhibit)
-      || !pty.name || !*pty.name)
-    return;
-
-  rxvt_privileges (RESTORE);
-
-  if (action == SAVE)
-    makeutent (pty.name, rs[Rs_display_name]);
-  else
-    cleanutent ();
-
-  rxvt_privileges (IGNORE);
-}
-#endif
-
 /*----------------------------------------------------------------------*/
 /*
  * window size/position calculcations for XSizeHint and other storage.
  * if width/height are non-zero then override calculated width/height
  */
 void
-rxvt_term::window_calc (unsigned int width, unsigned int height)
+rxvt_term::window_calc (unsigned int newwidth, unsigned int newheight)
 {
   short recalc_x, recalc_y;
-  int x, y, sb_w, mb_h, flags;
+  int x, y, sb_w, flags;
   unsigned int w, h;
   unsigned int max_width, max_height;
   dDisp;
 
   D_SIZE ((stderr, "< Cols/Rows: %3d x %3d ; Width/Height: %4d x %4d",
-          TermWin.ncol, TermWin.nrow, szHint.width,
-          szHint.height));
+          ncol, nrow, szHint.width, szHint.height));
+
   szHint.flags = PMinSize | PResizeInc | PBaseSize | PWinGravity;
   szHint.win_gravity = NorthWestGravity;
   /* szHint.min_aspect.x = szHint.min_aspect.y = 1; */
 
   recalc_x = recalc_y = 0;
   flags = 0;
+
   if (!parsed_geometry)
     {
       parsed_geometry = 1;
+
       if (rs[Rs_geometry])
         flags = XParseGeometry (rs[Rs_geometry], &x, &y, &w, &h);
 
       if (flags & WidthValue)
         {
-          TermWin.ncol = BOUND_POSITIVE_INT16 (w);
+          ncol = clamp (w, 0, std::numeric_limits<int16_t>::max ());
           szHint.flags |= USSize;
         }
 
       if (flags & HeightValue)
         {
-          TermWin.nrow = BOUND_POSITIVE_INT16 (h);
+          nrow = clamp (h, 0, std::numeric_limits<int16_t>::max ());
           szHint.flags |= USSize;
         }
 
@@ -728,6 +703,7 @@ rxvt_term::window_calc (unsigned int width, unsigned int height)
         {
           szHint.x = x;
           szHint.flags |= USPosition;
+
           if (flags & XNegative)
             {
               recalc_x = 1;
@@ -739,9 +715,11 @@ rxvt_term::window_calc (unsigned int width, unsigned int height)
         {
           szHint.y = y;
           szHint.flags |= USPosition;
+
           if (flags & YNegative)
             {
               recalc_y = 1;
+
               if (szHint.win_gravity == NorthEastGravity)
                 szHint.win_gravity = SouthEastGravity;
               else
@@ -751,72 +729,63 @@ rxvt_term::window_calc (unsigned int width, unsigned int height)
     }
 
   /* TODO: BOUNDS */
-  TermWin.width = TermWin.ncol * TermWin.fwidth;
-  TermWin.height = TermWin.nrow * TermWin.fheight;
-  max_width = MAX_COLS * TermWin.fwidth;
-  max_height = MAX_ROWS * TermWin.fheight;
+  width = ncol * fwidth;
+  height = nrow * fheight;
+  max_width = MAX_COLS * fwidth;
+  max_height = MAX_ROWS * fheight;
 
-  szHint.base_width = szHint.base_height = 2 * TermWin.int_bwidth;
+  szHint.base_width = szHint.base_height = 2 * int_bwidth;
 
-  sb_w = mb_h = 0;
-  window_vt_x = window_vt_y = TermWin.int_bwidth;
+  sb_w = 0;
+  window_vt_x = window_vt_y = int_bwidth;
 
-  if (scrollbar_visible ())
+  if (scrollBar.state)
     {
       sb_w = scrollbar_TotalWidth ();
       szHint.base_width += sb_w;
-      if (!(options & Opt_scrollBar_right))
+      if (!OPTION (Opt_scrollBar_right))
         window_vt_x += sb_w;
     }
 
-  if (menubar_visible ())
-    {
-      mb_h = menuBar_TotalHeight ();
-      szHint.base_height += mb_h;
-      window_vt_y += mb_h;
-    }
-
-  szHint.width_inc = TermWin.fwidth;
-  szHint.height_inc = TermWin.fheight;
+  szHint.width_inc = fwidth;
+  szHint.height_inc = fheight;
   szHint.min_width = szHint.base_width + szHint.width_inc;
   szHint.min_height = szHint.base_height + szHint.height_inc;
 
-  if (width && width - szHint.base_width < max_width)
+  if (newwidth && newwidth - szHint.base_width < max_width)
     {
-      szHint.width = width;
-      TermWin.width = width - szHint.base_width;
+      szHint.width = newwidth;
+      width = newwidth - szHint.base_width;
     }
   else
     {
-      MIN_IT (TermWin.width, max_width);
-      szHint.width = szHint.base_width + TermWin.width;
+      min_it (width, max_width);
+      szHint.width = szHint.base_width + width;
     }
 
-  if (height && height - szHint.base_height < max_height)
+  if (newheight && newheight - szHint.base_height < max_height)
     {
-      szHint.height = height;
-      TermWin.height = height - szHint.base_height;
+      szHint.height = newheight;
+      height = newheight - szHint.base_height;
     }
   else
     {
-      MIN_IT (TermWin.height, max_height);
-      szHint.height = szHint.base_height + TermWin.height;
+      min_it (height, max_height);
+      szHint.height = szHint.base_height + height;
     }
 
-  if (scrollbar_visible () && (options & Opt_scrollBar_right))
+  if (scrollBar.state && OPTION (Opt_scrollBar_right))
     window_sb_x = szHint.width - sb_w;
 
   if (recalc_x)
-    szHint.x += (DisplayWidth (disp, display->screen)
-                 - szHint.width - 2 * TermWin.ext_bwidth);
+    szHint.x += DisplayWidth  (disp, display->screen) - szHint.width  - 2 * ext_bwidth;
   if (recalc_y)
-    szHint.y += (DisplayHeight (disp, display->screen)
-                 - szHint.height - 2 * TermWin.ext_bwidth);
+    szHint.y += DisplayHeight (disp, display->screen) - szHint.height - 2 * ext_bwidth;
 
-  TermWin.ncol = TermWin.width / TermWin.fwidth;
-  TermWin.nrow = TermWin.height / TermWin.fheight;
+  ncol = width / fwidth;
+  nrow = height / fheight;
   D_SIZE ((stderr, "> Cols/Rows: %3d x %3d ; Width/Height: %4d x %4d",
-          TermWin.ncol, TermWin.nrow, szHint.width,
+          ncol, nrow, szHint.width,
           szHint.height));
   return;
 }
@@ -829,16 +798,16 @@ rxvt_term::window_calc (unsigned int width, unsigned int height)
 void
 rxvt_term::tt_winch ()
 {
-  if (pty.pty < 0)
+  if (pty->pty < 0)
     return;
 
   struct winsize ws;
 
-  ws.ws_col = TermWin.ncol;
-  ws.ws_row = TermWin.nrow;
-  ws.ws_xpixel = TermWin.width;
-  ws.ws_ypixel = TermWin.height;
-  (void)ioctl (pty.pty, TIOCSWINSZ, &ws);
+  ws.ws_col = ncol;
+  ws.ws_row = nrow;
+  ws.ws_xpixel = width;
+  ws.ws_ypixel = height;
+  (void)ioctl (pty->pty, TIOCSWINSZ, &ws);
 
 #if 0
   // TIOCSWINSZ⎈ is supposed to do this automatically and correctly
@@ -849,7 +818,7 @@ rxvt_term::tt_winch ()
 
 /*----------------------------------------------------------------------*/
 /* set_fonts () - load and set the various fonts
-/*
+ *
  * init = 1   - initialize
  *
  * fontname == FONT_UP  - switch to bigger font
@@ -871,22 +840,20 @@ rxvt_term::set_fonts ()
 
 #if ENABLE_STYLES
   for (int i = RS_styleCount; --i; )
-    if (TermWin.fontset[i] != TermWin.fontset[0])
-      delete TermWin.fontset[i];
+    if (fontset[i] != fontset[0])
+      delete fontset[i];
 #endif
 
-  delete TermWin.fontset[0];
-  TermWin.fontset[0] = fs;
+  delete fontset[0];
+  fontset[0] = fs;
 
   prop = (*fs)[1]->properties ();
-  prop.height += TermWin.lineSpace;
+  prop.height += lineSpace;
   fs->set_prop (prop);
 
-  TermWin.fwidth  = prop.width;
-  TermWin.fheight = prop.height;
-  TermWin.fweight = prop.weight;
-  TermWin.fslant  = prop.slant;
-  TermWin.fbase   = (*fs)[1]->ascent;
+  fwidth  = prop.width;
+  fheight = prop.height;
+  fbase   = prop.ascent;
 
   for (int style = 1; style < 4; style++)
     {
@@ -894,17 +861,17 @@ rxvt_term::set_fonts ()
       const char *res = rs[Rs_font + style];
 
       if (res && !*res)
-        TermWin.fontset[style] = TermWin.fontset[0];
+        fontset[style] = fontset[0];
       else
         {
-          TermWin.fontset[style] = fs = new rxvt_fontset (this);
+          fontset[style] = fs = new rxvt_fontset (this);
           rxvt_fontprop prop2 = prop;
 
           if (res)
             prop2.weight = prop2.slant = rxvt_fontprop::unset;
           else
             {
-              res = TermWin.fontset[0]->fontdesc;
+              res = fontset[0]->fontdesc;
 
               if (SET_STYLE (0, style) & RS_Bold)   prop2.weight = rxvt_fontprop::bold;
               if (SET_STYLE (0, style) & RS_Italic) prop2.slant  = rxvt_fontprop::italic;
@@ -914,11 +881,11 @@ rxvt_term::set_fonts ()
           fs->set_prop (prop2);
         }
 #else
-      TermWin.fontset[style] = TermWin.fontset[0];
+      fontset[style] = fontset[0];
 #endif
     }
 
-  if (TermWin.parent[0])
+  if (parent[0])
     {
       resize_all_windows (0, 0, 0);
       scr_remap_chars ();
@@ -930,19 +897,17 @@ rxvt_term::set_fonts ()
 
 void rxvt_term::set_string_property (Atom prop, const char *str, int len)
 {
-  // TODO: SMART_WINDOW_TITLE
-  XChangeProperty (display->display, TermWin.parent[0],
+  XChangeProperty (display->display, parent[0],
                    prop, XA_STRING, 8, PropModeReplace,
                    (const unsigned char *)str, len >= 0 ? len : strlen (str));
 }
 
 void rxvt_term::set_utf8_property (Atom prop, const char *str, int len)
 {
-  // TODO: SMART_WINDOW_TITLE
   wchar_t *ws = rxvt_mbstowcs (str, len);
   char *s = rxvt_wcstoutf8 (ws);
 
-  XChangeProperty (display->display, TermWin.parent[0],
+  XChangeProperty (display->display, parent[0],
                    prop, xa[XA_UTF8_STRING], 8, PropModeReplace,
                    (const unsigned char *)s, strlen (s));
 
@@ -989,11 +954,9 @@ rxvt_term::set_window_color (int idx, const char *color)
       if (i >= 8 && i <= 15)
         {        /* bright colors */
           i -= 8;
-# ifndef NO_BRIGHTCOLOR
           pix_colors_focused[idx] = pix_colors_focused[minBrightCOLOR + i];
           SET_PIXCOLOR (idx);
           goto done;
-# endif
         }
 
       if (i >= 0 && i <= 7)
@@ -1115,16 +1078,14 @@ rxvt_term::rXParseAllocColor (rxvt_color *screen_in_out, const char *colour)
  * -                         WINDOW RESIZING                          - *
  * -------------------------------------------------------------------- */
 void
-rxvt_term::resize_all_windows (unsigned int width, unsigned int height, int ignoreparent)
+rxvt_term::resize_all_windows (unsigned int newwidth, unsigned int newheight, int ignoreparent)
 {
   int fix_screen;
-#ifdef SMART_RESIZE
   int old_width = szHint.width, old_height = szHint.height;
-#endif
   dDisp;
 
-  window_calc (width, height);
-  XSetWMNormalHints (disp, TermWin.parent[0], &szHint);
+  window_calc (newwidth, newheight);
+  XSetWMNormalHints (disp, parent[0], &szHint);
 
   if (!ignoreparent)
     {
@@ -1138,9 +1099,9 @@ rxvt_term::resize_all_windows (unsigned int width, unsigned int height, int igno
       unsigned int unused_w1, unused_h1, unused_b1, unused_d1;
       Window unused_cr;
 
-      XTranslateCoordinates (disp, TermWin.parent[0], display->root,
+      XTranslateCoordinates (disp, parent[0], display->root,
                              0, 0, &x, &y, &unused_cr);
-      XGetGeometry (disp, TermWin.parent[0], &unused_cr, &x1, &y1,
+      XGetGeometry (disp, parent[0], &unused_cr, &x1, &y1,
                     &unused_w1, &unused_h1, &unused_b1, &unused_d1);
       /*
        * if display->root isn't the parent window, a WM will probably have offset
@@ -1167,18 +1128,18 @@ rxvt_term::resize_all_windows (unsigned int width, unsigned int height, int igno
       else if (y == y1)       /* exact center */
         dy /= 2;
 
-      XMoveResizeWindow (disp, TermWin.parent[0], x + dx, y + dy,
+      XMoveResizeWindow (disp, parent[0], x + dx, y + dy,
                          szHint.width, szHint.height);
 #else
-      XResizeWindow (disp, TermWin.parent[0], szHint.width, szHint.height);
+      XResizeWindow (disp, parent[0], szHint.width, szHint.height);
 #endif
     }
 
-  fix_screen = TermWin.ncol != prev_ncol || TermWin.nrow != prev_nrow;
+  fix_screen = ncol != prev_ncol || nrow != prev_nrow;
 
-  if (fix_screen || width != old_width || height != old_height)
+  if (fix_screen || newwidth != old_width || newheight != old_height)
     {
-      if (scrollbar_visible ())
+      if (scrollBar.state)
         {
           XMoveResizeWindow (disp, scrollBar.win,
                              window_sb_x, 0,
@@ -1186,14 +1147,9 @@ rxvt_term::resize_all_windows (unsigned int width, unsigned int height, int igno
           resize_scrollbar ();
         }
 
-      if (menubar_visible ())
-        XMoveResizeWindow (disp, menuBar.win,
-                           window_vt_x, 0,
-                           TermWin_TotalWidth (), menuBar_TotalHeight ());
-
-      XMoveResizeWindow (disp, TermWin.vt,
+      XMoveResizeWindow (disp, vt,
                          window_vt_x, window_vt_y,
-                         TermWin_TotalWidth (), TermWin_TotalHeight ());
+                         width, height);
 
       scr_clear ();
 #ifdef XPM_BACKGROUND
@@ -1209,10 +1165,10 @@ rxvt_term::resize_all_windows (unsigned int width, unsigned int height, int igno
       /* scr_reset only works on the primary screen */
       if (old_height)      /* this is not the first time through */
         {
-          unsigned int ncol = TermWin.ncol;
-          TermWin.ncol = prev_ncol; // save b/c scr_blank_screen_mem uses this
+          unsigned int ocol = ncol;
+          ncol = prev_ncol; // save b/c scr_blank_screen_mem uses this
           curr_screen = scr_change_screen (PRIMARY);
-          TermWin.ncol = ncol;
+          ncol = ocol;
         }
 
       scr_reset ();
@@ -1220,7 +1176,7 @@ rxvt_term::resize_all_windows (unsigned int width, unsigned int height, int igno
       if (curr_screen >= 0) /* this is not the first time through */
         {
           scr_change_screen (curr_screen);
-          selection_check (old_ncol != TermWin.ncol ? 4 : 0);
+          selection_check (old_ncol != ncol ? 4 : 0);
         }
     }
 
@@ -1228,7 +1184,7 @@ rxvt_term::resize_all_windows (unsigned int width, unsigned int height, int igno
   old_height = szHint.height;
 
 #ifdef XPM_BACKGROUND
-  if (TermWin.pixmap)
+  if (pixmap)
     scr_touch (false);
 #endif
 
@@ -1242,25 +1198,25 @@ rxvt_term::resize_all_windows (unsigned int width, unsigned int height, int igno
  * good for toggling 80/132 columns
  */
 void
-rxvt_term::set_widthheight (unsigned int width, unsigned int height)
+rxvt_term::set_widthheight (unsigned int newwidth, unsigned int newheight)
 {
   XWindowAttributes wattr;
 
-  if (width == 0 || height == 0)
+  if (newwidth == 0 || newheight == 0)
     {
       XGetWindowAttributes (display->display, display->root, &wattr);
 
-      if (width == 0)
-        width = wattr.width - szHint.base_width;
-      if (height == 0)
-        height = wattr.height - szHint.base_height;
+      if (newwidth == 0)
+        newwidth = wattr.width - szHint.base_width;
+      if (newheight == 0)
+        newheight = wattr.height - szHint.base_height;
     }
 
-  if (width != TermWin.width || height != TermWin.height)
+  if (newwidth != width || newheight != height)
     {
-      width += szHint.base_width;
-      height += szHint.base_height;
-      resize_all_windows (width, height, 0);
+      newwidth += szHint.base_width;
+      newheight += szHint.base_height;
+      resize_all_windows (newwidth, newheight, 0);
     }
 }
 
@@ -1280,10 +1236,10 @@ void
 rxvt_term::im_set_size (XRectangle &size)
 {
   // the int_bwidth terms make no sense to me
-  size.x      = TermWin.int_bwidth;
-  size.y      = TermWin.int_bwidth;
-  size.width  = Width2Pixel (TermWin.ncol) + TermWin.int_bwidth;
-  size.height = Height2Pixel (TermWin.nrow) + TermWin.int_bwidth;
+  size.x      = int_bwidth;
+  size.y      = int_bwidth;
+  size.width  = Width2Pixel (ncol) + int_bwidth;
+  size.height = Height2Pixel (nrow) + int_bwidth;
 }
 
 void
@@ -1293,13 +1249,13 @@ rxvt_term::im_set_preedit_area (XRectangle &preedit_rect,
 {
   preedit_rect.x      = needed_rect.width;
   preedit_rect.y      = 0;
-  preedit_rect.width  = Width2Pixel (TermWin.ncol) - needed_rect.width + 1;
-  preedit_rect.height = TermWin.fheight;
+  preedit_rect.width  = Width2Pixel (ncol) - needed_rect.width + 1;
+  preedit_rect.height = fheight;
 
   status_rect.x       = 0;
   status_rect.y       = 0;
-  status_rect.width   = needed_rect.width ? needed_rect.width : Width2Pixel (TermWin.ncol) + 1;
-  status_rect.height  = TermWin.fheight;
+  status_rect.width   = needed_rect.width ? needed_rect.width : Width2Pixel (ncol) + 1;
+  status_rect.height  = fheight;
 }
 
 /* Checking whether input method is running. */
@@ -1337,7 +1293,7 @@ rxvt_term::IMSendSpot ()
   XVaNestedList preedit_attr;
 
   if (!Input_Context
-      || !TermWin.focus
+      || !focus
       || !(input_style & XIMPreeditPosition))
     return;
 
@@ -1384,6 +1340,8 @@ rxvt_term::IM_get_IC (const char *modifiers)
   char **s;
   XIMStyles *xim_styles;
 
+  set_environ (envv);
+
   if (! ((p = XSetLocaleModifiers (modifiers)) && *p))
     return false;
 
@@ -1467,9 +1425,9 @@ foundpet:
                "-*-*-*-R-*-*-%d-*-*-*-*-*-*,"
                "-*-*-*-R-*-*-%d-*-*-*-*-*-*,"
                "*",
-               TermWin.fheight,
-               TermWin.fheight + 1, TermWin.fheight - 1,
-               TermWin.fheight - 2, TermWin.fheight + 2);
+               fheight,
+               fheight + 1, fheight - 1,
+               fheight - 2, fheight + 2);
 
       fs = XCreateFontSet (display->display, rs[Rs_imFont] ? rs[Rs_imFont] : pat,
                            &missing_charset_list, &missing_charset_count, &def_string);
@@ -1525,8 +1483,8 @@ foundpet:
 
   Input_Context = XCreateIC (xim,
                              XNInputStyle, input_style,
-                             XNClientWindow, TermWin.vt,
-                             XNFocusWindow, TermWin.parent[0],
+                             XNClientWindow, vt,
+                             XNFocusWindow, parent[0],
                              preedit_attr ? XNPreeditAttributes : NULL,
                              preedit_attr,
                              status_attr ? XNStatusAttributes : NULL,
@@ -1553,12 +1511,12 @@ foundpet:
 void
 rxvt_term::im_cb ()
 {
-  int i, found, had_im;
+  int i;
   const char *p;
   char **s;
   char buf[IMBUFSIZ];
 
-  SET_R (this);
+  make_current ();
 
   im_destroy ();
 
@@ -1620,7 +1578,7 @@ rxvt_term::IMSetStatusPosition ()
   XVaNestedList preedit_attr, status_attr;
 
   if (!Input_Context
-      || !TermWin.focus
+      || !focus
       || !(input_style & XIMPreeditArea)
       || !IMisRunning ())
     return;