Simplify rxvt_temp_buf usage.
[dana/urxvt.git] / src / main.C
index 3433b80..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
@@ -40,9 +40,7 @@
 #include <csignal>
 #include <cstring>
 
-#ifdef HAVE_TERMIOS_H
-# include <termios.h>
-#endif
+#include <termios.h>
 
 #ifdef HAVE_XSETLOCALE
 # define X_LOCALE
@@ -154,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
+#ifdef POINTER_BLANK
+  pointer_ev.set          <rxvt_term, &rxvt_term::pointer_cb> (this);
 #endif
 #ifndef NO_BELL
-    bell_ev (this, &rxvt_term::bell_cb),
+  bell_ev.set             <rxvt_term, &rxvt_term::bell_cb>    (this);
 #endif
-    termwin_ev (this, &rxvt_term::x_cb),
-    vt_ev (this, &rxvt_term::x_cb),
-    child_ev (this, &rxvt_term::child_cb),
-    prepare_ev (this, &rxvt_term::prepare_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)
-{
+  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);
@@ -231,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;
@@ -279,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 ();
 
@@ -295,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);
@@ -308,6 +288,9 @@ rxvt_term::~rxvt_term ()
 #ifdef KEYSYM_RESOURCE
   delete keyboard;
 #endif
+#ifndef NO_RESOURCES
+  XrmDestroyDatabase (option_db);
+#endif
 }
 
 // child has exited, usually destroys
@@ -325,7 +308,7 @@ rxvt_term::child_cb (ev::child &w, int status)
 void
 rxvt_term::destroy ()
 {
-  if (destroy_ev.active)
+  if (destroy_ev.is_active ())
     return;
 
   HOOK_INVOKE ((this, HOOK_DESTROY, DT_END));
@@ -339,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
@@ -350,7 +331,7 @@ rxvt_term::destroy ()
       vt_ev.stop (display);
     }
 
-  prepare_ev.stop ();
+  flush_ev.stop ();
   pty_ev.stop ();
 #ifdef CURSOR_BLINK
   cursor_blink_ev.stop ();
@@ -372,7 +353,7 @@ rxvt_term::destroy ()
 }
 
 void
-rxvt_term::destroy_cb (ev::check &w, int revents)
+rxvt_term::destroy_cb (ev::idle &w, int revents)
 {
   make_current ();
 
@@ -470,125 +451,6 @@ 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 BG_IMAGE_FROM_FILE
-    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, ev::READ);
-
-  prepare_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
 {
   ev::sig sw_term, sw_int;
@@ -596,36 +458,40 @@ static struct sig_handlers
   /*
    * Catch a fatal signal and tidy up before quitting
    */
-  void
-  sig_term (ev::sig &w, int revents)
-  {
-    rxvt_emergency_cleanup ();
-    w.stop ();
-    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
 rxvt_init ()
 {
   ptytty::init ();
-  ev::ev_default_loop (0);
+
+  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); ev::ev_unref ();
-  sig_handlers.sw_int.start  (SIGINT);  ev::ev_unref ();
+  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); */
@@ -637,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.
@@ -682,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;
 
@@ -702,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;
         }
 
@@ -749,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))
@@ -788,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;
 }
 
@@ -818,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
@@ -860,6 +692,7 @@ rxvt_term::set_fonts ()
 
   prop = (*fs)[1]->properties ();
   prop.height += lineSpace;
+  prop.width += letterSpace;
 
   fs->set_prop (prop, false);
 
@@ -958,7 +791,6 @@ 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;
@@ -970,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;
         }
@@ -995,15 +828,13 @@ 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 */
+#endif /* XTERM_COLOR_CHANGE */
 }
 
 void
@@ -1030,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");
@@ -1085,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)
     {
@@ -1136,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,
@@ -1156,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)
@@ -1246,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);
@@ -1334,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)
         {
@@ -1342,14 +1175,14 @@ 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,
@@ -1706,14 +1539,14 @@ 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);
-/*  fprintfstderr, "origin is %+d%+d\n", x, y);*/
+/*  fprintf (stderr, "origin is %+d%+d\n", x, y);*/
 }
 
 Pixmap
@@ -1730,41 +1563,47 @@ rxvt_term::get_pixmap_property (int prop_id)
                                          0L, 1L, False, XA_PIXMAP, &atype, &aformat,
                                          &nitems, &bytes_after, &prop);
         if (result == Success && prop && atype == XA_PIXMAP)
-          {
-            return *(Pixmap *)prop;
-          }
+          return *(Pixmap *)prop;
       }
+
   return None;
 }
 
 #ifdef HAVE_BG_PIXMAP
-int
+# 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 ();
 
-  /* no chance of real time refresh if we are blurring! */
-  if (bgPixmap.invalid_since + 0.5 < ev::now () && !(bgPixmap.flags & bgPixmap_t::blurNeeded))
+  ev_tstamp to_wait = 0.5 - (ev::now () - bgPixmap.valid_since);
+
+  if (to_wait <= 0.)
     bgPixmap.render ();
   else
-    {
-      update_background_ev.stop ();
-
-      if (!bgPixmap.need_client_side_rendering())
-        update_background_ev.start (.05);
-      else if (bgPixmap.flags & bgPixmap_t::blurNeeded)
-        update_background_ev.start (.20); /* very slow !!! */
-      else
-        update_background_ev.start (.07);
-    }
-
-  return 0;
+    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 */