Simplify rxvt_temp_buf usage.
[dana/urxvt.git] / src / main.C
index faecc11..58c4a25 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-2006 Marc Lehmann <pcg@goof.com>
+ * Copyright (c) 2003-2008 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 <csignal>
 #include <cstring>
 
-#ifdef TTY_GID_SUPPORT
-# include <grp.h>
-#endif
+#include <termios.h>
 
-#ifdef HAVE_TERMIOS_H
-# include <termios.h>
+#ifdef HAVE_XSETLOCALE
+# define X_LOCALE
+# include <X11/Xlocale.h>
+#else
+# ifdef HAVE_SETLOCALE
+#  include <clocale>
+# endif
 #endif
 
 vector<rxvt_term *> rxvt_term::termlist;
@@ -90,7 +93,7 @@ class rxvt_composite_vec rxvt_composite;
 text_t rxvt_composite_vec::compose (unicode_t c1, unicode_t c2)
 {
   compose_char *cc;
-  
+
   // break compose chains, as stupid readline really likes to duplicate
   // composing characters for some reason near the end of a line.
   cc = (*this)[c1];
@@ -149,49 +152,46 @@ int rxvt_composite_vec::expand (unicode_t c, wchar_t *r)
 #endif
 
 rxvt_term::rxvt_term ()
-    :
-#if ENABLE_TRANSPARENCY || ENABLE_PERL
-    rootwin_ev (this, &rxvt_term::rootwin_cb),
-#endif
+{
 #if HAVE_BG_PIXMAP
-    update_background_ev(this, &rxvt_term::update_background_cb),
-#endif
-#ifdef HAVE_SCROLLBARS
-    scrollbar_ev (this, &rxvt_term::x_cb),
+  update_background_ev.set<rxvt_term, &rxvt_term::update_background_cb> (this);
 #endif
 #ifdef CURSOR_BLINK
-    cursor_blink_ev (this, &rxvt_term::cursor_blink_cb),
+  cursor_blink_ev.set     <rxvt_term, &rxvt_term::cursor_blink_cb> (this); cursor_blink_ev.set (0., CURSOR_BLINK_INTERVAL);
 #endif
 #ifdef TEXT_BLINK
-    text_blink_ev (this, &rxvt_term::text_blink_cb),
+  text_blink_ev.set       <rxvt_term, &rxvt_term::text_blink_cb>   (this); text_blink_ev.set (0., TEXT_BLINK_INTERVAL);
 #endif
 #ifndef NO_SCROLLBAR_BUTTON_CONTINUAL_SCROLLING
-    cont_scroll_ev (this, &rxvt_term::cont_scroll_cb),
+  cont_scroll_ev.set      <rxvt_term, &rxvt_term::cont_scroll_cb>  (this);
 #endif
 #ifdef SELECTION_SCROLLING
-    sel_scroll_ev (this, &rxvt_term::sel_scroll_cb),
+  sel_scroll_ev.set       <rxvt_term, &rxvt_term::sel_scroll_cb>   (this);
 #endif
 #if defined(MOUSE_WHEEL) && defined(MOUSE_SLIP_WHEELING)
-    slip_wheel_ev (this, &rxvt_term::slip_wheel_cb),
+  slip_wheel_ev.set       <rxvt_term, &rxvt_term::slip_wheel_cb>   (this);
 #endif
-#ifdef POINTER_BLANK
-    pointer_ev (this, &rxvt_term::pointer_cb),
+#if ENABLE_TRANSPARENCY || ENABLE_PERL
+  rootwin_ev.set          <rxvt_term, &rxvt_term::rootwin_cb> (this),
 #endif
+  scrollbar_ev.set        <rxvt_term, &rxvt_term::x_cb>       (this),
 #ifdef USE_XIM
-    im_ev (this, &rxvt_term::im_cb),
+  im_ev.set               <rxvt_term, &rxvt_term::im_cb>      (this),
 #endif
-#ifndef NO_BELL     
-    bell_ev (this, &rxvt_term::bell_cb),
+#ifdef POINTER_BLANK
+  pointer_ev.set          <rxvt_term, &rxvt_term::pointer_cb> (this);
 #endif
-    termwin_ev (this, &rxvt_term::x_cb),
-    vt_ev (this, &rxvt_term::x_cb),
-    child_ev (this, &rxvt_term::child_cb),
-    check_ev (this, &rxvt_term::check_cb),
-    flush_ev (this, &rxvt_term::flush_cb),
-    destroy_ev (this, &rxvt_term::destroy_cb),
-    pty_ev (this, &rxvt_term::pty_cb),
-    incr_ev (this, &rxvt_term::incr_cb)
-{
+#ifndef NO_BELL
+  bell_ev.set             <rxvt_term, &rxvt_term::bell_cb>    (this);
+#endif
+  child_ev.set            <rxvt_term, &rxvt_term::child_cb>   (this);
+  flush_ev.set            <rxvt_term, &rxvt_term::flush_cb>   (this);
+  destroy_ev.set          <rxvt_term, &rxvt_term::destroy_cb> (this);
+  pty_ev.set              <rxvt_term, &rxvt_term::pty_cb>     (this);
+  incr_ev.set             <rxvt_term, &rxvt_term::incr_cb>    (this);
+  termwin_ev.set          <rxvt_term, &rxvt_term::x_cb>       (this);
+  vt_ev.set               <rxvt_term, &rxvt_term::x_cb>       (this);
+
   cmdbuf_ptr = cmdbuf_endp = cmdbuf_base;
 
   termlist.push_back (this);
@@ -203,7 +203,8 @@ rxvt_term::rxvt_term ()
 
 // clean up the most important stuff, do *not* call x or free mem etc.
 // for use before an emergency exit
-void rxvt_term::emergency_cleanup ()
+void
+rxvt_term::emergency_cleanup ()
 {
   if (cmd_pid)
     kill (-cmd_pid, SIGHUP);
@@ -225,37 +226,25 @@ rxvt_term::~rxvt_term ()
 #endif
   delete fontset[0];
 
+#ifdef HAVE_BG_PIXMAP
+  bgPixmap.destroy ();
+#endif
+#ifdef HAVE_AFTERIMAGE
+  if (asv)
+    destroy_asvisual (asv, 0);
+  if (asimman)
+    destroy_image_manager (asimman, 0);
+#endif
+
   if (display)
     {
       selection_clear ();
+      selection_clear (true);
 
 #ifdef USE_XIM
       im_destroy ();
 #endif
-#ifdef XTERM_SCROLLBAR
-      if (xscrollbarGC) XFreeGC (dpy, xscrollbarGC);
-      if (ShadowGC)     XFreeGC (dpy, ShadowGC);
-#endif
-#ifdef PLAIN_SCROLLBAR
-      if (pscrollbarGC) XFreeGC (dpy, pscrollbarGC);
-#endif
-#ifdef NEXT_SCROLLBAR
-      if (blackGC)      XFreeGC (dpy, blackGC);
-      if (whiteGC)      XFreeGC (dpy, whiteGC);
-      if (grayGC)       XFreeGC (dpy, grayGC);
-      if (darkGC)       XFreeGC (dpy, darkGC);
-      if (stippleGC)    XFreeGC (dpy, stippleGC);
-      if (dimple)       XFreePixmap (dpy, dimple);
-      if (upArrow)      XFreePixmap (dpy, upArrow);
-      if (downArrow)    XFreePixmap (dpy, downArrow);
-      if (upArrowHi)    XFreePixmap (dpy, upArrowHi);
-      if (downArrowHi)  XFreePixmap (dpy, downArrowHi);
-#endif
-#ifdef RXVT_SCROLLBAR
-      if (topShadowGC)  XFreeGC (dpy, topShadowGC);
-      if (botShadowGC)  XFreeGC (dpy, botShadowGC);
-      if (scrollbarGC)  XFreeGC (dpy, scrollbarGC);
-#endif
+      scrollBar.destroy ();
       if (gc)   XFreeGC (dpy, gc);
 
       delete drawable;
@@ -273,14 +262,10 @@ rxvt_term::~rxvt_term ()
           }
 
       clear ();
-    }
-
-  delete [] pix_colors_focused;
-#if OFF_FOCUS_FADING
-  delete [] pix_colors_unfocused;
-#endif
 
-  displays.put (display);
+      display->flush (); /* ideally .put should do this */
+      displays.put (display);
+    }
 
   scr_release ();
 
@@ -289,6 +274,7 @@ rxvt_term::~rxvt_term ()
     free (allocated [i]);
 
   free (selection.text);
+  free (selection.clip_text);
   // TODO: manage env vars in child only(!)
   free (env_display);
   free (env_term);
@@ -302,11 +288,14 @@ rxvt_term::~rxvt_term ()
 #ifdef KEYSYM_RESOURCE
   delete keyboard;
 #endif
+#ifndef NO_RESOURCES
+  XrmDestroyDatabase (option_db);
+#endif
 }
 
 // child has exited, usually destroys
 void
-rxvt_term::child_cb (child_watcher &w, int status)
+rxvt_term::child_cb (ev::child &w, int status)
 {
   HOOK_INVOKE ((this, HOOK_CHILD_EXIT, DT_INT, status, DT_END));
 
@@ -319,7 +308,7 @@ rxvt_term::child_cb (child_watcher &w, int status)
 void
 rxvt_term::destroy ()
 {
-  if (destroy_ev.active)
+  if (destroy_ev.is_active ())
     return;
 
   HOOK_INVOKE ((this, HOOK_DESTROY, DT_END));
@@ -333,9 +322,7 @@ rxvt_term::destroy ()
 #if USE_XIM
       im_ev.stop (display);
 #endif
-#if HAVE_SCROLLBARS
       scrollbar_ev.stop (display);
-#endif
 #if ENABLE_TRANSPARENCY || ENABLE_PERL
       rootwin_ev.stop (display);
 #endif
@@ -344,7 +331,7 @@ rxvt_term::destroy ()
       vt_ev.stop (display);
     }
 
-  check_ev.stop ();
+  flush_ev.stop ();
   pty_ev.stop ();
 #ifdef CURSOR_BLINK
   cursor_blink_ev.stop ();
@@ -362,11 +349,11 @@ rxvt_term::destroy ()
   pointer_ev.stop ();
 #endif
 
-  destroy_ev.start (0);
+  destroy_ev.start ();
 }
 
 void
-rxvt_term::destroy_cb (time_watcher &w)
+rxvt_term::destroy_cb (ev::idle &w, int revents)
 {
   make_current ();
 
@@ -430,7 +417,7 @@ print_x_error (Display *dpy, XErrorEvent *event)
                                  mesg, BUFSIZ);
        rxvt_warn (strncat (mesg, "\n", BUFSIZ), event->resourceid);
     }
-    XGetErrorDatabaseText(dpy, mtype, "ErrorSerial", "Error Serial #%d", 
+    XGetErrorDatabaseText(dpy, mtype, "ErrorSerial", "Error Serial #%d",
                          mesg, BUFSIZ);
     rxvt_warn (strncat (mesg, "\n", BUFSIZ), event->serial);
 }
@@ -464,147 +451,30 @@ rxvt_xioerror_handler (Display *display)
   _exit (EXIT_FAILURE);
 }
 
-/*----------------------------------------------------------------------*/
-bool
-rxvt_term::init (int argc, const char *const *argv, stringvec *envv)
-{
-  this->envv = envv;
-
-  SET_R (this);
-  set_locale ("");
-  set_environ (envv); // few things in X do not call setlocale :(
-
-  if (!init_vars ())
-    return false;
-
-  init_secondary ();
-
-  const char **cmd_argv = init_resources (argc, argv);
-
-#ifdef KEYSYM_RESOURCE
-  keyboard->register_done ();
-#endif
-
-#ifdef HAVE_SCROLLBARS
-  if (option (Opt_scrollBar))
-    scrollBar.setIdle ();    /* set existence for size calculations */
-#endif
-
-  pty = ptytty::create ();
-
-  create_windows (argc, argv);
-
-  init_xlocale ();
-
-  scr_reset (); // initialize screen
-
-#if 0
-  XSynchronize (dpy, True);
-#endif
-
-#ifdef HAVE_SCROLLBARS
-  if (option (Opt_scrollBar))
-    resize_scrollbar ();      /* create and map scrollbar */
-#endif
-#ifdef HAVE_BG_PIXMAP
-  {
-    bgPixmap.set_target (this);
-
-#ifdef ENABLE_TRANSPARENCY
-    if (option (Opt_transparent))
-      {
-        bgPixmap.set_transparent ();
-#ifdef HAVE_AFTERIMAGE        
-        if (rs [Rs_blurradius])
-          bgPixmap.set_blur_radius (rs [Rs_blurradius]);
-#endif          
-        if (ISSET_PIXCOLOR (Color_tint))
-          bgPixmap.set_tint (pix_colors_focused [Color_tint]);
-        if (rs [Rs_shade])
-          bgPixmap.set_shade (rs [Rs_shade]);
-
-        bgPixmap.set_root_pixmap ();
-        XSelectInput (dpy, display->root, PropertyChangeMask);
-        rootwin_ev.start (display, display->root);
-      }
-#endif
-
-#ifdef XPM_BACKGROUND
-    if (rs[Rs_backgroundPixmap] != NULL)
-      {
-        const char *p = rs[Rs_backgroundPixmap];
-
-        if ((p = strchr (p, ';')) != NULL)
-          {
-            p++;
-            bgPixmap.set_geometry (p);
-          }
-        else
-          bgPixmap.set_defaultGeometry ();
-
-        if (bgPixmap.set_file (rs[Rs_backgroundPixmap]))
-          if (!bgPixmap.window_position_sensitive ())
-            update_background ();
-      }
-#endif
-  }
-#endif
-
-#if ENABLE_PERL
-  rootwin_ev.start (display, display->root);
-#endif
-
-  set_colorfgbg ();
-
-  init_command (cmd_argv);
-
-  free (cmd_argv);
-
-  if (pty->pty >= 0)
-    pty_ev.start (pty->pty, EVENT_READ);
-
-  check_ev.start ();
-
-  HOOK_INVOKE ((this, HOOK_START, DT_END));
-
-#if ENABLE_XEMBED
-  if (rs[Rs_embed])
-    {
-      long info[2] = { 0, XEMBED_MAPPED };
-
-      XChangeProperty (dpy, parent[0], xa[XA_XEMBED_INFO], xa[XA_XEMBED_INFO],
-                       32, PropModeReplace, (unsigned char *)&info, 2);
-    }
-#endif
-
-  XMapWindow (dpy, vt);
-  XMapWindow (dpy, parent[0]);
-
-  return true;
-}
-
 static struct sig_handlers
 {
-  sig_watcher sw_term, sw_int;
-  
+  ev::sig sw_term, sw_int;
+
   /*
    * Catch a fatal signal and tidy up before quitting
    */
-  void
-  sig_term (sig_watcher &w)
-  {
-    rxvt_emergency_cleanup ();
-    signal (w.signum, SIG_DFL);
-    kill (getpid (), w.signum);
-  }
+  void sig_term (ev::sig &w, int revents);
 
   sig_handlers ()
-  : sw_term (this, &sig_handlers::sig_term),
-    sw_int  (this, &sig_handlers::sig_term)
   {
+    sw_term.set<sig_handlers, &sig_handlers::sig_term> (this);
+    sw_int .set<sig_handlers, &sig_handlers::sig_term> (this);
   }
 } sig_handlers;
 
+void
+sig_handlers::sig_term (ev::sig &w, int revents)
+{
+  rxvt_emergency_cleanup ();
+  w.stop ();
+  kill (getpid (), w.signum);
+}
+
 char **rxvt_environ; // startup environment
 
 void
@@ -612,13 +482,16 @@ rxvt_init ()
 {
   ptytty::init ();
 
+  if (!ev_default_loop (0))
+    rxvt_fatal ("cannot initialise libev (bad value for LIBEV_METHODS?)\n");
+
   rxvt_environ = environ;
 
   signal (SIGHUP,  SIG_IGN);
   signal (SIGPIPE, SIG_IGN);
 
-  sig_handlers.sw_term.start (SIGTERM);
-  sig_handlers.sw_int.start  (SIGINT);
+  sig_handlers.sw_term.start (SIGTERM); ev_unref ();
+  sig_handlers.sw_int.start  (SIGINT);  ev_unref ();
 
   /* need to trap SIGURG for SVR4 (Unixware) rlogin */
   /* signal (SIGURG, SIG_DFL); */
@@ -630,42 +503,6 @@ rxvt_init ()
   XrmInitialize ();
 }
 
-/* ------------------------------------------------------------------------- *
- *                         MEMORY ALLOCATION WRAPPERS                        *
- * ------------------------------------------------------------------------- */
-void *
-rxvt_malloc (size_t size)
-{
-  void *p = malloc (size);
-
-  if (!p)
-    rxvt_fatal ("memory allocation failure. aborting.\n");
-
-  return p;
-}
-
-void *
-rxvt_calloc (size_t number, size_t size)
-{
-  void *p = calloc (number, size);
-
-  if (!p)
-    rxvt_fatal ("memory allocation failure. aborting.\n");
-
-  return p;
-}
-
-void *
-rxvt_realloc (void *ptr, size_t size)
-{
-  void *p = realloc (ptr, size);
-
-  if (!p)
-    rxvt_fatal ("memory allocation failure. aborting.\n");
-
-  return p;
-}
-
 /*----------------------------------------------------------------------*/
 /*
  * window size/position calculations for XSizeHint and other storage.
@@ -675,7 +512,7 @@ void
 rxvt_term::window_calc (unsigned int newwidth, unsigned int newheight)
 {
   short recalc_x, recalc_y;
-  int x, y, sb_w, flags;
+  int x, y, flags;
   unsigned int w, h;
   unsigned int max_width, max_height;
 
@@ -695,13 +532,19 @@ rxvt_term::window_calc (unsigned int newwidth, unsigned int newheight)
 
       if (flags & WidthValue)
         {
-          ncol = clamp (w, 0, std::numeric_limits<int16_t>::max ());
+          if (!w)
+            rxvt_fatal ("illegal window geometry (width and height must be non-zero), aborting.\n");
+
+          ncol = clamp (w, 1, std::numeric_limits<int16_t>::max ());
           szHint.flags |= USSize;
         }
 
       if (flags & HeightValue)
         {
-          nrow = clamp (h, 0, std::numeric_limits<int16_t>::max ());
+          if (!h)
+            rxvt_fatal ("illegal window geometry (width and height must be non-zero), aborting.\n");
+
+          nrow = clamp (h, 1, std::numeric_limits<int16_t>::max ());
           szHint.flags |= USSize;
         }
 
@@ -742,12 +585,11 @@ rxvt_term::window_calc (unsigned int newwidth, unsigned int newheight)
 
   szHint.base_width = szHint.base_height = 2 * int_bwidth;
 
-  sb_w = 0;
   window_vt_x = window_vt_y = int_bwidth;
 
   if (scrollBar.state)
     {
-      sb_w = scrollbar_TotalWidth ();
+      int sb_w = scrollBar.total_width ();
       szHint.base_width += sb_w;
 
       if (!option (Opt_scrollBar_right))
@@ -781,16 +623,13 @@ rxvt_term::window_calc (unsigned int newwidth, unsigned int newheight)
       szHint.height = szHint.base_height + height;
     }
 
-  if (scrollBar.state && option (Opt_scrollBar_right))
-    window_sb_x = szHint.width - sb_w;
-
   if (recalc_x)
     szHint.x += DisplayWidth  (dpy, display->screen) - szHint.width  - 2 * ext_bwidth;
 
   if (recalc_y)
     szHint.y += DisplayHeight (dpy, display->screen) - szHint.height - 2 * ext_bwidth;
 
-  ncol = width / fwidth;
+  ncol = width  / fwidth;
   nrow = height / fheight;
 }
 
@@ -811,10 +650,10 @@ rxvt_term::tt_winch ()
   ws.ws_row = nrow;
   ws.ws_xpixel = width;
   ws.ws_ypixel = height;
-  (void)ioctl (pty->pty, TIOCSWINSZ, &ws);
+  ioctl (pty->pty, TIOCSWINSZ, &ws);
 
 #if 0
-  // TIOCSWINSZ is supposed to do this automatically and correctly
+  // TIOCSWINSZ is supposed to do this automatically and correctly
   if (cmd_pid)               /* force through to the command */
     kill (-cmd_pid, SIGWINCH);
 #endif
@@ -853,6 +692,7 @@ rxvt_term::set_fonts ()
 
   prop = (*fs)[1]->properties ();
   prop.height += lineSpace;
+  prop.width += letterSpace;
 
   fs->set_prop (prop, false);
 
@@ -898,19 +738,21 @@ rxvt_term::set_fonts ()
       resize_all_windows (0, 0, 0);
       scr_remap_chars ();
       scr_touch (true);
-    }   
+    }
 
   return true;
 }
 
-void rxvt_term::set_string_property (Atom prop, const char *str, int len)
+void
+rxvt_term::set_string_property (Atom prop, const char *str, int len)
 {
   XChangeProperty (dpy, 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)
+void
+rxvt_term::set_utf8_property (Atom prop, const char *str, int len)
 {
   wchar_t *ws = rxvt_mbstowcs (str, len);
   char *s = rxvt_wcstoutf8 (ws);
@@ -944,13 +786,12 @@ rxvt_term::set_icon_name (const char *str)
 #endif
 }
 
-#ifdef XTERM_COLOR_CHANGE
 void
 rxvt_term::set_window_color (int idx, const char *color)
 {
+#ifdef XTERM_COLOR_CHANGE
   rxvt_color xcol;
-  int i;
-  
+
   if (color == NULL || *color == '\0')
     return;
 
@@ -961,17 +802,18 @@ rxvt_term::set_window_color (int idx, const char *color)
   /* handle color aliases */
   if (isdigit (*color))
     {
-      i = atoi (color);
+      int i = atoi (color);
 
       if (i >= 8 && i <= 15)
-        {        /* bright colors */
-          i -= 8;
-          pix_colors_focused[idx] = pix_colors_focused[minBrightCOLOR + i];
+        {
+          /* bright colors */
+          pix_colors_focused[idx] = pix_colors_focused[minBrightCOLOR + i - 8];
           goto done;
         }
 
       if (i >= 0 && i <= 7)
-        { /* normal colors */
+        {
+          /* normal colors */
           pix_colors_focused[idx] = pix_colors_focused[minCOLOR + i];
           goto done;
         }
@@ -986,20 +828,15 @@ rxvt_term::set_window_color (int idx, const char *color)
 
   pix_colors_focused[idx] = xcol;
 
-  /* XSetWindowAttributes attr; */
-  /* Cursor cursor; */
 done:
   /*TODO: handle Color_BD, scrollbar background, etc. */
 
   update_fade_color (idx);
   recolour_cursor ();
   scr_recolour ();
+#endif /* XTERM_COLOR_CHANGE */
 }
 
-#else
-# define set_window_color (idx,color)   ((void)0)
-#endif                          /* XTERM_COLOR_CHANGE */
-
 void
 rxvt_term::recolour_cursor ()
 {
@@ -1024,7 +861,7 @@ void
 rxvt_term::set_colorfgbg ()
 {
   unsigned int i;
-  const char *xpmb = "\0";
+  const char *xpmb = "";
   char fstr[sizeof ("default") + 1], bstr[sizeof ("default") + 1];
 
   strcpy (fstr, "default");
@@ -1040,7 +877,7 @@ rxvt_term::set_colorfgbg ()
     if (pix_colors[Color_bg] == pix_colors[i])
       {
         sprintf (bstr, "%d", (i - Color_Black));
-#ifdef XPM_BACKGROUND
+#ifdef BG_IMAGE_FROM_FILE
         xpmb = "default;";
 #endif
         break;
@@ -1079,8 +916,15 @@ rxvt_term::resize_all_windows (unsigned int newwidth, unsigned int newheight, in
 
   window_calc (newwidth, newheight);
 
-  if (!HOOK_INVOKE ((this, HOOK_RESIZE_ALL_WINDOWS, DT_INT, newwidth, DT_INT, newheight, DT_END)))
-    XSetWMNormalHints (dpy, parent[0], &szHint);
+  bool set_hint = !HOOK_INVOKE ((this, HOOK_RESIZE_ALL_WINDOWS, DT_INT, newwidth, DT_INT, newheight, DT_END));
+
+  // to avoid races between us and the wm, we clear the incremental size hints around the xresizewindow
+  if (set_hint)
+    {
+      szHint.flags &= ~(PBaseSize | PResizeInc);
+      XSetWMNormalHints (dpy, parent[0], &szHint);
+      szHint.flags |= PBaseSize | PResizeInc;
+    }
 
   if (!ignoreparent)
     {
@@ -1130,17 +974,15 @@ rxvt_term::resize_all_windows (unsigned int newwidth, unsigned int newheight, in
 #endif
     }
 
+  if (set_hint)
+    XSetWMNormalHints (dpy, parent[0], &szHint);
+
   fix_screen = ncol != prev_ncol || nrow != prev_nrow;
 
   if (fix_screen || newwidth != old_width || newheight != old_height)
     {
       if (scrollBar.state)
-        {
-          XMoveResizeWindow (dpy, scrollBar.win,
-                             window_sb_x, 0,
-                             scrollbar_TotalWidth (), szHint.height);
-          resize_scrollbar ();
-        }
+        scrollBar.resize ();
 
       XMoveResizeWindow (dpy, vt,
                          window_vt_x, window_vt_y,
@@ -1150,8 +992,6 @@ rxvt_term::resize_all_windows (unsigned int newwidth, unsigned int newheight, in
       if (bgPixmap.window_size_sensitive ())
         update_background ();
 #endif
-
-      scr_clear ();
     }
 
   if (fix_screen || old_height == 0)
@@ -1240,18 +1080,17 @@ rxvt_term::im_set_preedit_area (XRectangle &preedit_rect,
 bool
 rxvt_term::IMisRunning ()
 {
-  char *p;
   Atom atom;
   Window win;
   char server[IMBUFSIZ];
 
   /* get current locale modifier */
-  if ((p = XSetLocaleModifiers (NULL)) != NULL)
+  if (char *p = XSetLocaleModifiers (0))
     {
       strcpy (server, "@server=");
-      strncat (server, & (p[4]), IMBUFSIZ - 9); /* skip "@im=" */
+      strncat (server, p + 4, IMBUFSIZ - 9); /* skip "@im=" */
 
-      if ((p = strchr (server + 1, '@')) != NULL)      /* first one only */
+      if (p = strchr (server + 1, '@'))      /* first one only */
         *p = '\0';
 
       atom = XInternAtom (dpy, server, False);
@@ -1328,7 +1167,7 @@ xim_preedit_draw (XIC ic, XPointer client_data, XIMPreeditDrawCallbackStruct *ca
 
   if (text)
     {
-      void *str;
+      wchar_t *str;
 
       if (!text->encoding_is_wchar && text->string.multi_byte)
         {
@@ -1336,15 +1175,15 @@ xim_preedit_draw (XIC ic, XPointer client_data, XIMPreeditDrawCallbackStruct *ca
           if (term->rs[Rs_imLocale])
             SET_LOCALE (term->rs[Rs_imLocale]);
 
-          str = rxvt_temp_buf ((text->length + 1) * sizeof (wchar_t));
-          mbstowcs ((wchar_t *)str, text->string.multi_byte, text->length + 1);
+          str = rxvt_temp_buf<wchar_t> (text->length + 1);
+          mbstowcs (str, text->string.multi_byte, text->length + 1);
 
           if (term->rs[Rs_imLocale])
             SET_LOCALE (term->locale);
         }
       else
-        str = (void *)text->string.wide_char;
-      
+        str = text->string.wide_char;
+
       HOOK_INVOKE ((term, HOOK_XIM_PREEDIT_DRAW,
                     DT_INT, call_data->caret,
                     DT_INT, call_data->chg_first,
@@ -1673,7 +1512,7 @@ rxvt_term::IMSetPosition ()
     {
       im_set_size (preedit_rect);
       preedit_attr = XVaCreateNestedList (0, XNArea, &preedit_rect, NULL);
-    
+
       XSetICValues (Input_Context,
                     XNPreeditAttributes, preedit_attr, NULL);
     }
@@ -1700,6 +1539,73 @@ rxvt_term::IMSetPosition ()
 
    XFree (preedit_attr);
 }
-#endif                          /* USE_XIM */
+#endif /* USE_XIM */
+
+void
+rxvt_term::get_window_origin (int &x, int &y)
+{
+  Window cr;
+  XTranslateCoordinates (dpy, parent[0], display->root, 0, 0, &x, &y, &cr);
+/*  fprintf (stderr, "origin is %+d%+d\n", x, y);*/
+}
+
+Pixmap
+rxvt_term::get_pixmap_property (int prop_id)
+{
+  if (prop_id > 0 && prop_id < NUM_XA)
+    if (xa[prop_id])
+      {
+        int aformat;
+        unsigned long nitems, bytes_after;
+        Atom atype;
+        unsigned char *prop = NULL;
+        int result = XGetWindowProperty (dpy, display->root, xa[prop_id],
+                                         0L, 1L, False, XA_PIXMAP, &atype, &aformat,
+                                         &nitems, &bytes_after, &prop);
+        if (result == Success && prop && atype == XA_PIXMAP)
+          return *(Pixmap *)prop;
+      }
+
+  return None;
+}
+
+#ifdef HAVE_BG_PIXMAP
+# if TRACE_PIXMAPS
+#  undef update_background
+void
+rxvt_term::trace_update_background (const char *file, int line)
+{
+  fprintf (stderr, "%s:%d:update_background()\n", file, line);
+  update_background ();
+}
+# endif
+
+void
+rxvt_term::update_background ()
+{
+  if (update_background_ev.is_active ())
+    return;
+
+  bgPixmap.invalidate ();
+
+  ev_tstamp to_wait = 0.5 - (ev::now () - bgPixmap.valid_since);
+
+  if (to_wait <= 0.)
+    bgPixmap.render ();
+  else
+    update_background_ev.start (to_wait);
+}
+
+void
+rxvt_term::update_background_cb (ev::timer &w, int revents)
+{
+  make_current ();
+
+  update_background_ev.stop ();
+  bgPixmap.render ();
+  refresh_check ();
+}
+
+#endif /* HAVE_BG_PIXMAP */
 
 /*----------------------- end-of-file (C source) -----------------------*/