*** empty log message ***
[dana/urxvt.git] / src / command.C
index dda23c2..338e812 100644 (file)
@@ -1,5 +1,5 @@
 /*--------------------------------*-C-*---------------------------------*
- * File:       command.c
+ * File:       command.C
  *----------------------------------------------------------------------*
  *
  * All portions of code are copyright by their respective author/s.
 
 /*----------------------------------------------------------------------*/
 
+#define IS_CONTROL(ch) !((ch) & 0xffffff60UL)
+
+// exception thrown when the command parser runs out of input data
+class out_of_input { } out_of_input;
+
+#if ENABLE_FRILLS || ISO_14755
+
+#define ISO_14755_STARTED      0x80000000UL
+#define ISO_14755_51           0x40000000UL // basic (section 5.1)
+#define ISO_14755_52           0x20000000UL // keycap (section 5.2)
+#define ISO_14755_54           0x10000000UL // code feedback (section 5.4)
+#define ISO_14755_MASK         0x0fffffffUL
+
+#if ISO_14755
+static unsigned short iso14755_symtab[] = {
+  // keysym,           unicode
+  XK_Left,             0x2190,
+  XK_KP_Left,          0x2190,
+  XK_Up,               0x2191,
+  XK_KP_Up,            0x2191,
+  XK_Right,            0x2192,
+  XK_KP_Right,         0x2192,
+  XK_Down,             0x2193,
+  XK_KP_Down,          0x2193,
+  XK_Linefeed,         0x21b4,
+  XK_Return,           0x21b5,
+  XK_KP_Enter,         0x21b5,
+
+  XK_Prior,            0x21de,
+  XK_Next,             0x21df,
+  XK_Tab,              0x21e5,
+  XK_ISO_Left_Tab,     0x21e6,
+  XK_Shift_L,          0x21e7,
+  XK_Shift_R,          0x21e7,
+
+  XK_Shift_Lock,       0x21eb,
+  XK_ISO_Lock,         0x21eb,
+  XK_ISO_Lock,         0x21eb,
+  XK_Caps_Lock,                0x21ec,
+  XK_Num_Lock,         0x21ed,
+  XK_ISO_Level3_Shift, 0x21ee,
+  XK_ISO_Level3_Lock,  0x21ef,
+  XK_ISO_Group_Lock,   0x21f0,
+  XK_Home,             0x21f1,
+  XK_End,              0x21f2,
+
+  XK_Execute,          0x2318,
+  XK_Begin,            0x2320,
+  XK_Delete,           0x2326,
+  XK_Clear,            0x2327,
+  XK_BackSpace,                0x232b,
+  XK_Insert,           0x2380,
+  XK_Control_L,                0x2388,
+  XK_Control_R,                0x2388,
+  XK_Pause,            0x2389,
+  XK_Break,            0x238a,
+  XK_Escape,           0x238b,
+  XK_Undo,             0x238c,
+  XK_Print,            0x2399,
+
+  XK_space,            0x2423,
+  XK_KP_Space,         0x2422,
+  0,
+};
+
+void
+rxvt_term::iso14755_54 (int x, int y)
+{
+  x = Pixel2Col (x);
+  y = Pixel2Row (y);
+
+  if (x < 0 || x >= TermWin.ncol
+      || y < 0 || y >= TermWin.nrow)
+    return;
+
+  for (;;)
+    {
+      text_t t = screen.text[y + TermWin.saveLines - TermWin.view_start][x];
+
+      if (t != NOCHAR || !x)
+        {
+          iso14755_51 (screen.text[y + TermWin.saveLines - TermWin.view_start][x],
+                       screen.rend[y + TermWin.saveLines - TermWin.view_start][x]);
+          iso14755buf = ISO_14755_54;
+          break;
+        }
+
+      x--;
+    }
+
+}
+#endif
+
+#if ENABLE_OVERLAY
+void
+rxvt_term::iso14755_51 (unicode_t ch, rend_t r)
+{
+  rxvt_fontset *fs = FONTSET (r);
+  rxvt_font *f = (*fs)[fs->find_font (ch)];
+  wchar_t *chr, *alloc, ch2;
+  int len;
+
+#if ENABLE_COMBINING
+  if (IS_COMPOSE (ch))
+    {
+      len = rxvt_composite.expand (ch, 0);
+      alloc = chr = new wchar_t[len];
+      rxvt_composite.expand (ch, chr);
+    }
+  else
+#endif
+    {
+      ch2 = ch;
+
+      alloc = 0;
+      chr = &ch2;
+      len = 1;
+    }
+
+  int width = strlen (f->name);
+
+  scr_overlay_new (0, -1, width < 8+5 ? 8+5 : width, len + 1);
+
+  r = SET_STYLE (OVERLAY_RSTYLE, GET_STYLE (r));
+
+  for (int y = 0; y < len; y++)
+    {
+      char buf[9];
+
+      ch = *chr++;
+
+      sprintf (buf, "%8x", ch);
+      scr_overlay_set (0, y, buf);
+      scr_overlay_set (9, y, '=');
+#if !UNICODE3
+      if (ch >= 0x10000)
+        ch = 0xfffd;
+#endif
+      scr_overlay_set (11, y, ch, r);
+      scr_overlay_set (12, y, NOCHAR, r);
+    }
+
+  scr_overlay_set (0, len, f->name);
+
+#if ENABLE_COMBINING
+  if (alloc)
+    delete [] alloc;
+#endif
+}
+#endif
+
+void
+rxvt_term::commit_iso14755 ()
+{
+  wchar_t ch[2];
+
+  ch[0] = iso14755buf & ISO_14755_MASK;
+  ch[1] = 0;
+
+  if (iso14755buf & ISO_14755_51)
+    {
+      char mb[16];
+      int len;
+
+      // allow verbatim 0-bytes and control-bytes to be entered
+      if (ch[0] >= 0x20)
+        len = wcstombs (mb, ch, 16);
+      else
+        {
+          mb[0] = ch[0];
+          len = 1;
+        }
+
+      if (len > 0)
+        tt_write ((unsigned char *)mb, len);
+      else
+        scr_bell ();
+    }
+
+  iso14755buf = 0;
+}
+
+int
+rxvt_term::hex_keyval (XKeyEvent &ev)
+{
+  // check wether this event corresponds to a hex digit
+  // if the modifiers had not been pressed.
+  for (int index = 0; index < 8; index++)
+    {
+      KeySym k = XLookupKeysym (&ev, index);
+
+      if (k >= XK_KP_0 && k <= XK_KP_9) return k - XK_KP_0;
+      else if (k >= XK_0 && k <= XK_9)  return k - XK_0;
+      else if (k >= XK_a && k <= XK_f)  return k - XK_a + 10;
+      else if (k >= XK_A && k <= XK_F)  return k - XK_A + 10;
+    }
+
+  return -1;
+}
+#endif
+
 /*{{{ Convert the keypress event into a string */
 void
 rxvt_term::lookup_key (XKeyEvent &ev)
@@ -90,12 +291,14 @@ rxvt_term::lookup_key (XKeyEvent &ev)
     {
       Status status_return;
 
+#if 0
 #ifdef X_HAVE_UTF8_STRING
       if (enc_utf8 && 0) // currently disabled, doesn't seem to work, nor is useful
         len = Xutf8LookupString (Input_Context, &ev, (char *)kbuf,
                                  KBUFSZ, &keysym, &status_return);
       else
 #endif
+#endif
         {
           wchar_t wkbuf[KBUFSZ + 1];
 
@@ -142,36 +345,14 @@ rxvt_term::lookup_key (XKeyEvent &ev)
 
   if (valid_keysym)
     {
-      /* for some backwards compatibility */
-#if defined(HOTKEY_CTRL) || defined(HOTKEY_META)
-# ifdef HOTKEY_CTRL
-      if (ctrl)
-# else
-      if (meta)
-# endif
-        {
-          if (keysym == ks_bigfont)
-            {
-              change_font (FONT_UP);
-              return;
-            }
-          else if (keysym == ks_smallfont)
-            {
-              change_font (FONT_DN);
-              return;
-            }
-        }
-#endif
-
       if (TermWin.saveLines)
         {
 #ifdef UNSHIFTED_SCROLLKEYS
           if (!ctrl && !meta)
-            {
 #else
           if (IS_SCROLL_MOD)
-            {
 #endif
+            {
               int lnsppg;
 
 #ifdef PAGING_CONTEXT_LINES
@@ -230,7 +411,7 @@ rxvt_term::lookup_key (XKeyEvent &ev)
               keysym += (XK_F11 - XK_F1);
               shft = 0;        /* turn off Shift */
             }
-          else if (!ctrl && !meta && (PrivateModes & PrivMode_ShiftKeys))
+          else if (!ctrl && !meta && (priv_modes & PrivMode_ShiftKeys))
             {
               switch (keysym)
                 {
@@ -238,6 +419,7 @@ rxvt_term::lookup_key (XKeyEvent &ev)
                   case XK_Insert:      /* Shift+Insert = paste mouse selection */
                     selection_request (ev.time, 0, 0);
                     return;
+#if TODO // TODO
                     /* rxvt extras */
                   case XK_KP_Add:      /* Shift+KP_Add = bigger font */
                     change_font (FONT_UP);
@@ -245,9 +427,57 @@ rxvt_term::lookup_key (XKeyEvent &ev)
                   case XK_KP_Subtract: /* Shift+KP_Subtract = smaller font */
                     change_font (FONT_DN);
                     return;
+#endif
                 }
             }
         }
+
+#if ENABLE_FRILLS || ISO_14755
+      // ISO 14755 support
+      if (shft && ctrl)
+        {
+          int hv;
+
+          if (iso14755buf & ISO_14755_51
+              && (keysym == XK_space || keysym == XK_KP_Space
+                  || keysym == XK_Return || keysym == XK_KP_Enter))
+            {
+              commit_iso14755 ();
+              iso14755buf = ISO_14755_51;
+# if ISO_14755
+              iso14755_51 (0);
+# endif
+              return;
+            }
+          else if ((hv = hex_keyval (ev)) >= 0)
+            {
+              iso14755buf = ((iso14755buf << 4) & ISO_14755_MASK)
+                          | hv | ISO_14755_51;
+# if ISO_14755
+              iso14755_51 (iso14755buf & ISO_14755_MASK);
+# endif
+              return;
+            }
+          else
+            {
+# if ENABLE_OVERLAY
+              scr_overlay_off ();
+# endif
+              iso14755buf = 0;
+            }
+        }
+      else if ((ctrl && (keysym == XK_Shift_L || keysym == XK_Shift_R))
+               || (shft && (keysym == XK_Control_L || keysym == XK_Control_R)))
+        if (!(iso14755buf & ISO_14755_STARTED))
+          {
+            iso14755buf |= ISO_14755_STARTED;
+# if ENABLE_OVERLAY
+            scr_overlay_new (0, -1, sizeof ("ISO 14755 mode") - 1, 1);
+            scr_overlay_set (0, 0, "ISO 14755 mode");
+# endif
+          }
+#endif
+      
 #ifdef PRINTPIPE
       if (keysym == XK_Print)
         {
@@ -263,17 +493,21 @@ rxvt_term::lookup_key (XKeyEvent &ev)
             {
               unsigned int    l;
               const unsigned char *kbuf0;
-              const unsigned char ch = C0_ESC;
 
               kbuf0 = (Keysym_map[keysym & 0xFF]);
               l = (unsigned int)*kbuf0++;
 
               /* escape prefix */
-              if (meta)
+              if (meta
 # ifdef META8_OPTION
-                if (meta_char == C0_ESC)
+                  && meta_char == C0_ESC
 # endif
+                 )
+                {
+                  const unsigned char ch = C0_ESC;
                   tt_write (&ch, 1);
+                }
+
               tt_write (kbuf0, l);
               return;
             }
@@ -285,48 +519,24 @@ rxvt_term::lookup_key (XKeyEvent &ev)
                 {
 #ifndef NO_BACKSPACE_KEY
                   case XK_BackSpace:
-                    if (PrivateModes & PrivMode_HaveBackSpace)
+                    if (priv_modes & PrivMode_HaveBackSpace)
                       {
-                        kbuf[0] = (!! (PrivateModes & PrivMode_BackSpace)
+                        kbuf[0] = (!! (priv_modes & PrivMode_BackSpace)
                                    ^ !!ctrl) ? '\b' : '\177';
                         kbuf[1] = '\0';
                       }
                     else
-                      STRCPY (kbuf, key_backspace);
-# ifdef MULTICHAR_SET
-                    if ((Options & Opt_mc_hack) && screen.cur.col > 0)
-                      {
-                        int             col, row;
-
-                        newlen = STRLEN (kbuf);
-                        col = screen.cur.col - 1;
-                        row = screen.cur.row + TermWin.saveLines;
-                        if (IS_MULTI2 (screen.rend[row][col]))
-                          MEMMOVE (kbuf + newlen, kbuf, newlen + 1);
-                      }
-# endif
+                      strcpy (kbuf, key_backspace);
                     break;
 #endif
 #ifndef NO_DELETE_KEY
                   case XK_Delete:
-                    STRCPY (kbuf, key_delete);
-# ifdef MULTICHAR_SET
-                    if (Options & Opt_mc_hack)
-                      {
-                        int             col, row;
-
-                        newlen = STRLEN (kbuf);
-                        col = screen.cur.col;
-                        row = screen.cur.row + TermWin.saveLines;
-                        if (IS_MULTI1 (screen.rend[row][col]))
-                          MEMMOVE (kbuf + newlen, kbuf, newlen + 1);
-                      }
-# endif
+                    strcpy (kbuf, key_delete);
                     break;
 #endif
                   case XK_Tab:
                     if (shft)
-                      STRCPY (kbuf, "\033[Z");
+                      strcpy (kbuf, "\033[Z");
                     else
                       {
 #ifdef CTRL_TAB_MAKES_META
@@ -342,13 +552,13 @@ rxvt_term::lookup_key (XKeyEvent &ev)
                     break;
 
 #ifdef XK_KP_Left
-                  case XK_KP_Up:               /* \033Ox or standard */
+                  case XK_KP_Up:       /* \033Ox or standard */
                   case XK_KP_Down:     /* \033Or or standard */
                   case XK_KP_Right:    /* \033Ov or standard */
                   case XK_KP_Left:     /* \033Ot or standard */
-                    if ((PrivateModes & PrivMode_aplKP) ? !shft : shft)
+                    if ((priv_modes & PrivMode_aplKP) ? !shft : shft)
                       {
-                        STRCPY (kbuf, "\033OZ");
+                        strcpy (kbuf, "\033OZ");
                         kbuf[2] = "txvr"[keysym - XK_KP_Left];
                         break;
                       }
@@ -361,7 +571,7 @@ rxvt_term::lookup_key (XKeyEvent &ev)
                   case XK_Down:        /* "\033[B" */
                   case XK_Right:       /* "\033[C" */
                   case XK_Left:        /* "\033[D" */
-                    STRCPY (kbuf, "\033[Z");
+                    strcpy (kbuf, "\033[Z");
                     kbuf[2] = "DACB"[keysym - XK_Left];
                     /* do Shift first */
                     if (shft)
@@ -371,104 +581,80 @@ rxvt_term::lookup_key (XKeyEvent &ev)
                         kbuf[1] = 'O';
                         kbuf[2] = "dacb"[keysym - XK_Left];
                       }
-                    else if (PrivateModes & PrivMode_aplCUR)
+                    else if (priv_modes & PrivMode_aplCUR)
                       kbuf[1] = 'O';
-#ifdef MULTICHAR_SET
-                    //TODO: ??
-                    if (Options & Opt_mc_hack)
-                      {
-                        int             col, row, m;
-
-                        col = screen.cur.col;
-                        row = screen.cur.row + TermWin.saveLines;
-                        m = 0;
-                        if (keysym == XK_Right
-                            && IS_MULTI1 (screen.rend[row][col]))
-                          m = 1;
-                        else if (keysym == XK_Left)
-                          {
-                            if (col > 0)
-                              {
-                                if (IS_MULTI2 (screen.rend[row][col - 1]))
-                                  m = 1;
-                              }
-                            else if (screen.cur.row > 0)
-                              {
-                                col = screen.tlen[--row];
-                                if (col == -1)
-                                  col = TermWin.ncol - 1;
-                                else
-                                  col--;
-                                if (col > 0
-                                    && IS_MULTI2 (screen.rend[row][col]))
-                                  m = 1;
-                              }
-                          }
-                        if (m)
-                          MEMMOVE (kbuf + 3, kbuf, 3 + 1);
-                      }
-#endif
                     break;
 
 #ifndef UNSHIFTED_SCROLLKEYS
 # ifdef XK_KP_Prior
                   case XK_KP_Prior:
                     /* allow shift to override */
-                    if ((PrivateModes & PrivMode_aplKP) ? !shft : shft)
+                    if ((priv_modes & PrivMode_aplKP) ? !shft : shft)
                       {
-                        STRCPY (kbuf, "\033Oy");
+                        strcpy (kbuf, "\033Oy");
                         break;
                       }
                     /* FALLTHROUGH */
 # endif
                   case XK_Prior:
-                    STRCPY (kbuf, "\033[5~");
+                    strcpy (kbuf, "\033[5~");
                     break;
 # ifdef XK_KP_Next
                   case XK_KP_Next:
                     /* allow shift to override */
-                    if ((PrivateModes & PrivMode_aplKP) ? !shft : shft)
+                    if ((priv_modes & PrivMode_aplKP) ? !shft : shft)
                       {
-                        STRCPY (kbuf, "\033Os");
+                        strcpy (kbuf, "\033Os");
                         break;
                       }
                     /* FALLTHROUGH */
 # endif
                   case XK_Next:
-                    STRCPY (kbuf, "\033[6~");
+                    strcpy (kbuf, "\033[6~");
                     break;
 #endif
                   case XK_KP_Enter:
                     /* allow shift to override */
-                    if ((PrivateModes & PrivMode_aplKP) ? !shft : shft)
+                    if ((priv_modes & PrivMode_aplKP) ? !shft : shft)
+                      {
+                        strcpy (kbuf, "\033OM");
+                        break;
+                      }
+
+                    /* FALLTHROUGH */
+
+                  case XK_Return:
+                    if (priv_modes & PrivMode_LFNL)
                       {
-                        STRCPY (kbuf, "\033OM");
+                        kbuf[0] = '\015';
+                        kbuf[1] = '\012';
+                        kbuf[2] = '\0';
                       }
                     else
                       {
-                        kbuf[0] = '\r';
+                        kbuf[0] = '\015';
                         kbuf[1] = '\0';
                       }
                     break;
 
 #ifdef XK_KP_Begin
                   case XK_KP_Begin:
-                    STRCPY (kbuf, "\033Ou");
+                    strcpy (kbuf, "\033Ou");
                     break;
 
                   case XK_KP_Insert:
-                    STRCPY (kbuf, "\033Op");
+                    strcpy (kbuf, "\033Op");
                     break;
 
                   case XK_KP_Delete:
-                    STRCPY (kbuf, "\033On");
+                    strcpy (kbuf, "\033On");
                     break;
 #endif
                   case XK_KP_F1:       /* "\033OP" */
                   case XK_KP_F2:       /* "\033OQ" */
                   case XK_KP_F3:       /* "\033OR" */
                   case XK_KP_F4:       /* "\033OS" */
-                    STRCPY (kbuf, "\033OP");
+                    strcpy (kbuf, "\033OP");
                     kbuf[2] += (keysym - XK_KP_F1);
                     break;
 
@@ -489,9 +675,9 @@ rxvt_term::lookup_key (XKeyEvent &ev)
                   case XK_KP_8:                /* "\033Ox" : "8" */
                   case XK_KP_9:                /* "\033Oy" : "9" */
                     /* allow shift to override */
-                    if ((PrivateModes & PrivMode_aplKP) ? !shft : shft)
+                    if ((priv_modes & PrivMode_aplKP) ? !shft : shft)
                       {
-                        STRCPY (kbuf, "\033Oj");
+                        strcpy (kbuf, "\033Oj");
                         kbuf[2] += (keysym - XK_KP_Multiply);
                       }
                     else
@@ -502,46 +688,46 @@ rxvt_term::lookup_key (XKeyEvent &ev)
                     break;
 
                   case XK_Find:
-                    STRCPY (kbuf, "\033[1~");
+                    strcpy (kbuf, "\033[1~");
                     break;
                   case XK_Insert:
-                    STRCPY (kbuf, "\033[2~");
+                    strcpy (kbuf, "\033[2~");
                     break;
 #ifdef DXK_Remove              /* support for DEC remove like key */
                   case DXK_Remove:
                     /* FALLTHROUGH */
 #endif
                   case XK_Execute:
-                    STRCPY (kbuf, "\033[3~");
+                    strcpy (kbuf, "\033[3~");
                     break;
                   case XK_Select:
-                    STRCPY (kbuf, "\033[4~");
+                    strcpy (kbuf, "\033[4~");
                     break;
 #ifdef XK_KP_End
                   case XK_KP_End:
                     /* allow shift to override */
-                    if ((PrivateModes & PrivMode_aplKP) ? !shft : shft)
+                    if ((priv_modes & PrivMode_aplKP) ? !shft : shft)
                       {
-                        STRCPY (kbuf, "\033Oq");
+                        strcpy (kbuf, "\033Oq");
                         break;
                       }
                     /* FALLTHROUGH */
 #endif
                   case XK_End:
-                    STRCPY (kbuf, KS_END);
+                    strcpy (kbuf, KS_END);
                     break;
 #ifdef XK_KP_Home
                   case XK_KP_Home:
                     /* allow shift to override */
-                    if ((PrivateModes & PrivMode_aplKP) ? !shft : shft)
+                    if ((priv_modes & PrivMode_aplKP) ? !shft : shft)
                       {
-                        STRCPY (kbuf, "\033Ow");
+                        strcpy (kbuf, "\033Ow");
                         break;
                       }
                     /* FALLTHROUGH */
 #endif
                   case XK_Home:
-                    STRCPY (kbuf, KS_HOME);
+                    strcpy (kbuf, KS_HOME);
                     break;
 
 #define FKEY(n, fkey)                                                  \
@@ -604,8 +790,9 @@ rxvt_term::lookup_key (XKeyEvent &ev)
                     break;
                 }
               if (newlen)
-                len = STRLEN (kbuf);
+                len = strlen (kbuf);
             }
+
           /*
            * Pass meta for all function keys, if 'meta' option set
            */
@@ -630,6 +817,7 @@ rxvt_term::lookup_key (XKeyEvent &ev)
 
               for (ch = kbuf; ch < kbuf + len; ch++)
                 *ch |= 0x80;
+
               meta = 0;
             }
 #endif
@@ -640,7 +828,7 @@ rxvt_term::lookup_key (XKeyEvent &ev)
   if (len <= 0)
     return;                    /* not mapped */
 
-  if (Options & Opt_scrollTtyKeypress)
+  if (options & Opt_scrollTtyKeypress)
     if (TermWin.view_start)
       {
         TermWin.view_start = 0;
@@ -692,14 +880,14 @@ rxvt_term::lookup_key (XKeyEvent &ev)
 unsigned int
 rxvt_term::cmd_write (const unsigned char *str, unsigned int count)
 {
-  unsigned int    n, s;
+  unsigned int n, s;
 
   n = cmdbuf_ptr - cmdbuf_base;
-  s = cmdbuf_base + BUFSIZ - 1 - cmdbuf_endp;
+  s = cmdbuf_base + CBUFSIZ - 1 - cmdbuf_endp;
 
   if (n > 0 && s < count)
     {
-      MEMMOVE (cmdbuf_base, cmdbuf_ptr,
+      memmove (cmdbuf_base, cmdbuf_ptr,
               (unsigned int) (cmdbuf_endp - cmdbuf_ptr));
       cmdbuf_ptr = cmdbuf_base;
       cmdbuf_endp -= n;
@@ -708,7 +896,7 @@ rxvt_term::cmd_write (const unsigned char *str, unsigned int count)
 
   if (count > s)
     {
-      rxvt_print_error ("data loss: cmd_write too large");
+      rxvt_warn ("data loss: cmd_write too large, continuing.\n");
       count = s;
     }
 
@@ -730,7 +918,6 @@ rxvt_term::flush ()
       want_full_refresh = 0;
       scr_clear ();
       scr_touch (false);
-      want_refresh = 1;
     }
 #endif
 
@@ -741,10 +928,11 @@ rxvt_term::flush ()
 #ifdef USE_XIM
       IMSendSpot ();
 #endif
-
     }
 
   display->flush ();
+
+  flush_ev.stop ();
 }
 
 void
@@ -753,6 +941,20 @@ rxvt_term::check_cb (check_watcher &w)
   SET_R (this);
   SET_LOCALE (locale);
 
+  display->flush ();
+
+  if (want_refresh && !flush_ev.active)
+    flush_ev.start (NOW + 0.01);
+}
+
+void
+rxvt_term::flush_cb (time_watcher &w)
+{
+  SET_R (this);
+  SET_LOCALE (locale);
+
+  refresh_limit = 1;
+  refresh_count = 0;
   flush ();
 }
 
@@ -780,16 +982,65 @@ rxvt_term::text_blink_cb (time_watcher &w)
 }
 #endif
 
+#ifndef NO_SCROLLBAR_BUTTON_CONTINUAL_SCROLLING
+void
+rxvt_term::cont_scroll_cb (time_watcher &w)
+{
+  if ((scrollbar_isUp() || scrollbar_isDn()) &&
+      scr_page (scrollbar_isUp() ? UP : DN, 1))
+    {
+      refresh_type |= SMOOTH_REFRESH;
+      want_refresh = 1;
+      w.start (w.at + SCROLLBAR_CONTINUOUS_DELAY);
+    }
+}
+#endif
+
+#ifdef SELECTION_SCROLLING
+void
+rxvt_term::sel_scroll_cb (time_watcher &w)
+{
+  if (scr_page (scroll_selection_dir, scroll_selection_lines))
+    {
+      selection_extend (selection_save_x, selection_save_y, selection_save_state);
+      refresh_type |= SMOOTH_REFRESH;
+      want_refresh = 1;
+      w.start (w.at + SCROLLBAR_CONTINUOUS_DELAY);
+    }
+}
+#endif
+
+#if defined(MOUSE_WHEEL) && defined(MOUSE_SLIP_WHEELING)
+void
+rxvt_term::slip_wheel_cb (time_watcher &w)
+{
+  if (mouse_slip_wheel_speed == 0
+      || mouse_slip_wheel_speed < 0 ? scr_page (DN, -mouse_slip_wheel_speed)
+                                    : scr_page (UP,  mouse_slip_wheel_speed))
+    {
+      refresh_type |= SMOOTH_REFRESH;
+      want_refresh = 1;
+      w.start (w.at + SCROLLBAR_CONTINUOUS_DELAY);
+    }
+}
+#endif
+
 bool
 rxvt_term::pty_fill ()
 {
   ssize_t n = cmdbuf_endp - cmdbuf_ptr;
 
+  if (CBUFSIZ == n)
+    {
+      rxvt_warn ("pty_fill on full buffer, draining input, continuing.\n");
+      n = 0;
+    }
+
   memmove (cmdbuf_base, cmdbuf_ptr, n);
   cmdbuf_ptr = cmdbuf_base;
   cmdbuf_endp = cmdbuf_ptr + n;
 
-  n = read (cmd_fd, cmdbuf_endp, BUFSIZ - n);
+  n = read (pty.pty, cmdbuf_endp, CBUFSIZ - n);
 
   if (n > 0)
     {
@@ -811,198 +1062,31 @@ rxvt_term::pty_cb (io_watcher &w, short revents)
   if (revents & EVENT_WRITE)
     tt_write (0, 0);
   else if (revents & EVENT_READ)
-    {
-      bool flag = true;
-
-      // loop, but don't allow a single term to monopolize us
-      // the number of loops is fully arbitrary, and thus wrong
-      while (flag && pty_fill ())
-        {
-          if (!seen_input)
-            {
-              seen_input = 1;
-              /* once we know the shell is running, send the screen size.  Again! */
-              tt_winch ();
-            }
-
-          if (cmd_parse ())
-            break;
-        }
-    }
-}
-
-bool
-rxvt_term::cmd_parse ()
-{
-  bool flag = false;
-  uint32_t ch = NOCHAR;
-
-  for (;;)
-    {
-      if (ch == NOCHAR)
-        ch = next_char ();
-
-      if (ch == NOCHAR) // TODO: improve
+    // loop, but don't allow a single term to monopolize us
+    while (pty_fill ())
+      if (cmd_parse ())
         break;
-
-      if (ch >= ' ' || ch == '\t' || ch == '\n' || ch == '\r')
-        {
-          /* Read a text string from the input buffer */
-          uint32_t buf[BUFSIZ];
-          bool refreshnow = false;
-          int nlines = 0;
-          uint32_t *str = buf;
-
-          *str++ = ch;
-
-          for (;;)
-            {
-              ch = next_char ();
-
-              if (ch == NOCHAR || (ch < ' ' && ch != '\t' && ch != '\n' && ch != '\r'))
-                break;
-              else
-                {
-                  *str++ = ch;
-
-                  if (ch == '\n')
-                    {
-                      nlines++;
-                      refresh_count++;
-
-                      if (! (Options & Opt_jumpScroll)
-                          || (refresh_count >= (refresh_limit * (TermWin.nrow - 1))))
-                        {
-                          refreshnow = true;
-                          flag = false;
-                          ch = NOCHAR;
-                          break;
-                        }
-
-                      // scr_add_lines only works for nlines < TermWin.nrow - 1.
-                      if (nlines >= TermWin.nrow - 1)
-                        {
-                          scr_add_lines (buf, nlines, str - buf);
-                          nlines = 0;
-                          str = buf;
-                        }
-                    }
-
-                  if (str >= buf + BUFSIZ)
-                    {
-                      ch = NOCHAR;
-                      break;
-                    }
-                }
-            }
-
-          scr_add_lines (buf, nlines, str - buf);
-
-          /*
-           * If there have been a lot of new lines, then update the screen
-           * What the heck I'll cheat and only refresh less than every page-full.
-           * the number of pages between refreshes is refresh_limit, which
-           * is incremented here because we must be doing flat-out scrolling.
-           *
-           * refreshing should be correct for small scrolls, because of the
-           * time-out
-           */
-          if (refreshnow)
-            {
-              if ((Options & Opt_jumpScroll) && refresh_limit < REFRESH_PERIOD)
-                refresh_limit++;
-
-              scr_refresh (refresh_type);
-            }
-
-        }
-      else
-        {
-          switch (ch)
-            {
-              default:
-                process_nonprinting (ch);
-                break;
-              case C0_ESC:     /* escape char */
-                process_escape_seq ();
-                break;
-                /*case 0x9b: */        /* CSI */
-                /*  process_csi_seq (); */
-            }
-
-          ch = NOCHAR;
-        }
-    }
-
-  return flag;
-}
-
-// read the next character, currently handles UTF-8
-// will probably handle all sorts of other stuff in the future
-uint32_t
-rxvt_term::next_char ()
-{
-  while (cmdbuf_ptr < cmdbuf_endp)
-    {
-      if (*cmdbuf_ptr < 0x80) // assume < 0x80 to be ascii ALWAYS (all shift-states etc.) uh-oh
-        return *cmdbuf_ptr++;
-
-      wchar_t wc;
-      size_t len = mbrtowc (&wc, (char *)cmdbuf_ptr, cmdbuf_endp - cmdbuf_ptr, mbstate);
-
-      if (len == (size_t)-2)
-        return NOCHAR;
-
-      if (len == (size_t)-1)
-        return *cmdbuf_ptr++; // the _occasional_ latin1 character is allowed to slip through
-
-      // assume wchar == unicode
-      cmdbuf_ptr += len;
-      return wc;
-    }
-
-  return NOCHAR;
 }
 
-/* rxvt_cmd_getc () - Return next input character */
-/*
- * Return the next input character after first passing any keyboard input
- * to the command.
- */
-uint32_t
-rxvt_term::cmd_getc ()
-{
-  for (;;)
-    {
-      uint32_t c = next_char ();
-      if (c != NOCHAR)
-        return c;
-
-      // incomplete sequences should occur rarely, still, a better solution
-      // would be preferred. either setjmp/longjmp or better design.
-      fcntl (cmd_fd, F_SETFL, 0);
-      pty_fill ();
-      fcntl (cmd_fd, F_SETFL, O_NONBLOCK);
-    }
-}
-
-#ifdef POINTER_BLANK
 void
 rxvt_term::pointer_unblank ()
 {
   XDefineCursor (display->display, TermWin.vt, TermWin_cursor);
   recolour_cursor ();
 
+#ifdef POINTER_BLANK
   hidden_pointer = 0;
 
-  if (Options & Opt_pointerBlank)
+  if (options & Opt_pointerBlank)
     pointer_ev.start (NOW + pointerBlankDelay);
+#endif
 }
 
+#ifdef POINTER_BLANK
 void
 rxvt_term::pointer_blank ()
 {
-  if (! (Options & Opt_pointerBlank))
+  if (! (options & Opt_pointerBlank))
     return;
 
   XDefineCursor (display->display, TermWin.vt, blank_cursor);
@@ -1032,9 +1116,7 @@ rxvt_term::mouse_report (XButtonEvent &ev)
   pixel_position (&x, &y);
 
   if (MEvent.button == AnyButton)
-    {
-      button_number = 3;
-    }
+    button_number = 3;
   else
     {
       button_number = MEvent.button - Button1;
@@ -1043,7 +1125,7 @@ rxvt_term::mouse_report (XButtonEvent &ev)
         button_number += (64 - 3);
     }
 
-  if (PrivateModes & PrivMode_MouseX10)
+  if (priv_modes & PrivMode_MouseX10)
     {
       /*
        * do not report ButtonRelease
@@ -1068,10 +1150,9 @@ rxvt_term::mouse_report (XButtonEvent &ev)
 #ifdef MOUSE_REPORT_DOUBLECLICK
       key_state += ((MEvent.clicks > 1) ? 32 : 0);
 #endif
-
     }
 
-#ifdef DEBUG_MOUSEREPORT
+#if DEBUG_MOUSEREPORT
   fprintf (stderr, "Mouse [");
   if (key_state & 16)
     fputc ('C', stderr);
@@ -1085,12 +1166,12 @@ rxvt_term::mouse_report (XButtonEvent &ev)
           button_number,
           x + 1,
           y + 1);
-#else
+#endif
+
   tt_printf ("\033[M%c%c%c",
             (32 + button_number + key_state),
             (32 + x + 1),
             (32 + y + 1));
-#endif
 }
 
 #ifdef USING_W11LIB
@@ -1111,7 +1192,7 @@ rxvt_term::x_cb (XEvent &ev)
   SET_LOCALE (locale);
 
 #if defined(CURSOR_BLINK)
-  if ((Options & Opt_cursorBlink) && ev.type == KeyPress)
+  if ((options & Opt_cursorBlink) && ev.type == KeyPress)
     {
       if (hidden_cursor)
         {
@@ -1124,7 +1205,7 @@ rxvt_term::x_cb (XEvent &ev)
 #endif
 
 #if defined(POINTER_BLANK)
-  if ((Options & Opt_pointerBlank) && pointerBlankDelay > 0)
+  if ((options & Opt_pointerBlank) && pointerBlankDelay > 0)
     {
       if (ev.type == MotionNotify
           || ev.type == ButtonPress
@@ -1146,77 +1227,86 @@ rxvt_term::x_cb (XEvent &ev)
   int             unused_root_x, unused_root_y;
   unsigned int    unused_mask;
 
-#ifdef DEBUG_X
-  const char *const eventnames[] =
-    {                          /* mason - this matches my system */
-      "",
-      "",
-      "KeyPress",
-      "KeyRelease",
-      "ButtonPress",
-      "ButtonRelease",
-      "MotionNotify",
-      "EnterNotify",
-      "LeaveNotify",
-      "FocusIn",
-      "FocusOut",
-      "KeymapNotify",
-      "Expose",
-      "GraphicsExpose",
-      "NoExpose",
-      "VisibilityNotify",
-      "CreateNotify",
-      "DestroyNotify",
-      "UnmapNotify",
-      "MapNotify",
-      "MapRequest",
-      "ReparentNotify",
-      "ConfigureNotify",
-      "ConfigureRequest",
-      "GravityNotify",
-      "ResizeRequest",
-      "CirculateNotify",
-      "CirculateRequest",
-      "PropertyNotify",
-      "SelectionClear",
-      "SelectionRequest",
-      "SelectionNotify",
-      "ColormapNotify",
-      "ClientMessage",
-      "MappingNotify"
-    };
-#endif
-
-#ifdef DEBUG_X
-  struct timeval  tp;
-  struct tm      *ltt;
-  (void)gettimeofday (&tp, NULL);
-  ltt = localtime (& (tp.tv_sec));
-  D_X ((stderr, "Event: %-16s %-7s %08lx (%4d-%02d-%02d %02d:%02d:%02d.%.6ld) %s %lu", eventnames[ev.type], (ev.xany.window == TermWin.parent[0] ? "parent" : (ev.xany.window == TermWin.vt ? "vt" : (ev.xany.window == scrollBar.win ? "scroll" : (ev.xany.window == menuBar.win ? "menubar" : "UNKNOWN")))), (ev.xany.window == TermWin.parent[0] ? TermWin.parent[0] : (ev.xany.window == TermWin.vt ? TermWin.vt : (ev.xany.window == scrollBar.win ? scrollBar.win : (ev.xany.window == menuBar.win ? menuBar.win : 0)))), ltt->tm_year + 1900, ltt->tm_mon + 1, ltt->tm_mday, ltt->tm_hour, ltt->tm_min, ltt->tm_sec, tp.tv_usec, ev.xany.send_event ? "S" : " ", ev.xany.serial));
-#endif
-
   switch (ev.type)
     {
       case KeyPress:
-        lookup_key (ev.xkey);
+#if ISO_14755
+        if (!(iso14755buf & ISO_14755_52))
+#endif
+          lookup_key (ev.xkey);
+
         break;
 
-#if defined(MOUSE_WHEEL) && defined(MOUSE_SLIP_WHEELING)
       case KeyRelease:
         {
-          if (! (ev.xkey.state & ControlMask))
-            mouse_slip_wheel_speed = 0;
-          else
-            {
-              KeySym          ks;
+#if (MOUSE_WHEEL && MOUSE_SLIP_WHEELING) || ISO_14755
+          KeySym ks;
 
-              ks = XKeycodeToKeysym (display->display, ev.xkey.keycode, 0);
-              if (ks == XK_Control_L || ks == XK_Control_R)
-                mouse_slip_wheel_speed = 0;
-            }
+          ks = XLookupKeysym (&ev.xkey, ev.xkey.state & ShiftMask ? 1 : 0); // sorry, only shift supported :/
+#endif
+
+#if ENABLE_FRILLS || ISO_14755
+          // ISO 14755 support
+          if (iso14755buf)
+            if (iso14755buf & ISO_14755_52)
+              {
+# if ENABLE_OVERLAY
+                scr_overlay_off ();
+# endif
+# if ISO_14755
+                // iso14755 part 5.2 handling: release time
+                // first: controls
+                if ((ev.xkey.state & ControlMask)
+                     && ((ks >= 0x40 && ks <= 0x5f)
+                         || (ks >= 0x61 && ks <= 0x7f)))
+                  {
+                    iso14755buf = ISO_14755_51 | 0x2400 | (ks & 0x1f);
+                    commit_iso14755 ();
+                    return; // case-break;
+                  }
+
+                for (unsigned short *i = iso14755_symtab; i[0]; i+= 2)
+                  if (i[0] == ks)
+                    {
+                      iso14755buf = ISO_14755_51 | i[1];
+                      commit_iso14755 ();
+                      return; // case-break;
+                    }
+
+                scr_bell ();
+# endif
+                iso14755buf = 0;
+                break;
+              }
+            else if ((ev.xkey.state & (ShiftMask | ControlMask)) != (ShiftMask | ControlMask))
+              {
+# if ENABLE_OVERLAY
+                scr_overlay_off ();
+# endif
+                if (iso14755buf & ISO_14755_51)
+                  commit_iso14755 ();
+#if ISO_14755
+                else if (iso14755buf & ISO_14755_STARTED)
+                  {
+                    iso14755buf = ISO_14755_52; // iso14755 part 5.2: remember empty begin/end pair
+
+                    scr_overlay_new (0, -1, sizeof ("KEYCAP PICTURE INSERT MODE") - 1, 1);
+                    scr_overlay_set (0, 0, "KEYCAP PICTURE INSERT MODE");
+                  }
+# endif
+                else
+                  iso14755buf = 0;
+              }
+#endif
+
+#if defined(MOUSE_WHEEL) && defined(MOUSE_SLIP_WHEELING)
+          if (!(ev.xkey.state & ControlMask))
+            slip_wheel_ev.stop ();
+          else if (ks == XK_Control_L || ks == XK_Control_R)
+            mouse_slip_wheel_speed = 0;
+#endif
           break;
         }
-#endif
 
       case ButtonPress:
         button_press (ev.xbutton);
@@ -1238,10 +1328,10 @@ rxvt_term::x_cb (XEvent &ev)
                      || ev.xclient.data.l[0] == DndLink))
           {
             /* Get Dnd data */
-            Atom            ActualType;
-            int             ActualFormat;
-            unsigned char  *data;
-            unsigned long   Size, RemainingBytes;
+            Atom ActualType;
+            int ActualFormat;
+            unsigned char *data;
+            unsigned long Size, RemainingBytes;
 
             XGetWindowProperty (display->display, display->root,
                                xa[XA_DNDSELECTION],
@@ -1253,7 +1343,8 @@ rxvt_term::x_cb (XEvent &ev)
             XChangeProperty (display->display, display->root,
                             XA_CUT_BUFFER0, XA_STRING,
                             8, PropModeReplace,
-                            data, STRLEN (data));
+                            data, strlen (data));
+            XFree (data);
             selection_paste (display->root, XA_CUT_BUFFER0, True);
             XSetInputFocus (display->display, display->root, RevertToNone, CurrentTime);
           }
@@ -1261,7 +1352,7 @@ rxvt_term::x_cb (XEvent &ev)
         break;
 
       case MappingNotify:
-        XRefreshKeyboardMapping (& (ev.xmapping));
+        XRefreshKeyboardMapping (&ev.xmapping);
         break;
 
         /*
@@ -1296,12 +1387,22 @@ rxvt_term::x_cb (XEvent &ev)
             want_refresh = 1;
 #ifdef USE_XIM
             if (Input_Context != NULL)
-              XSetICFocus (Input_Context);
+              {
+                IMSetStatusPosition ();
+                XSetICFocus (Input_Context);
+              }
 #endif
 #ifdef CURSOR_BLINK
-            if (Options & Opt_cursorBlink)
+            if (options & Opt_cursorBlink)
               cursor_blink_ev.start (NOW + BLINK_INTERVAL);
 #endif
+#ifdef OFF_FOCUS_FADING
+            if (rs[Rs_fade])
+              {
+                pix_colors = pix_colors_focused;
+                scr_recolour ();
+              }
+#endif
 
           }
         break;
@@ -1311,16 +1412,29 @@ rxvt_term::x_cb (XEvent &ev)
           {
             TermWin.focus = 0;
             want_refresh = 1;
+
+#if ENABLE_FRILLS || ISO_14755
+            iso14755buf = 0;
+#endif
+#if ENABLE_OVERLAY
+            scr_overlay_off ();
+#endif
 #ifdef USE_XIM
             if (Input_Context != NULL)
               XUnsetICFocus (Input_Context);
 #endif
 #ifdef CURSOR_BLINK
-            if (Options & Opt_cursorBlink)
+            if (options & Opt_cursorBlink)
               cursor_blink_ev.stop ();
             hidden_cursor = 0;
 #endif
-
+#ifdef OFF_FOCUS_FADING
+            if (rs[Rs_fade])
+              {
+                pix_colors = pix_colors_unfocused;
+                scr_recolour ();
+              }
+#endif
           }
         break;
 
@@ -1339,29 +1453,30 @@ rxvt_term::x_cb (XEvent &ev)
 
             if (szHint.width != width || szHint.height != height)
               {
-                D_SIZE ((stderr, "Size: Resizing from: %4d x %4d", szHint.width, szHint.height));
+                seen_resize = 1;
                 resize_all_windows (width, height, 1);
               }
-#ifdef DEBUG_SIZE
-            else
-              {
-                D_SIZE ((stderr, "Size: Not resizing"));
-              }
-#endif
+
 #ifdef TRANSPARENT             /* XXX: maybe not needed - leave in for now */
-            if (Options & Opt_transparent)
+            if (options & Opt_transparent)
               {
                 check_our_parents ();
                 if (am_transparent)
-                  want_full_refresh = 1;
+                  want_refresh = want_full_refresh = 1;
               }
 #endif
-
           }
         break;
 
+      case PropertyNotify:
+        if (ev.xproperty.atom == xa[XA_VT_SELECTION]
+            && ev.xproperty.state == PropertyNewValue)
+          selection_property (ev.xproperty.window, ev.xproperty.atom);
+
+        break;
+
       case SelectionClear:
-        display->set_selection_owner (0);
+        selection_clear ();
         break;
 
       case SelectionNotify:
@@ -1398,28 +1513,28 @@ rxvt_term::x_cb (XEvent &ev)
       case Expose:
         if (ev.xany.window == TermWin.vt)
           {
-#ifdef NO_SLOW_LINK_SUPPORT
-            scr_expose (ev.xexpose.x, ev.xexpose.y,
-                        ev.xexpose.width, ev.xexpose.height, False);
-#else
-            // don't understand this, so commented it out
-            scr_expose (ev.xexpose.x, ev.xexpose.y,
-                        ev.xexpose.width, ev.xexpose.height, False);
-            //scr_expose (ev.xexpose.x, 0,
-            //             ev.xexpose.width, TermWin.height, False);
-#endif
-            want_refresh = 1;
+            do
+              scr_expose (ev.xexpose.x, ev.xexpose.y,
+                          ev.xexpose.width, ev.xexpose.height, False);
+            while (XCheckTypedWindowEvent (display->display, TermWin.vt, ev.xany.type, &ev));
+
+            ev.xany.type = ev.xany.type == Expose ? GraphicsExpose : Expose;
+
+            while (XCheckTypedWindowEvent (display->display, TermWin.vt, ev.xany.type, &ev))
+              scr_expose (ev.xexpose.x, ev.xexpose.y,
+                          ev.xexpose.width, ev.xexpose.height, False);
+
+            scr_refresh (refresh_type);
           }
         else
           {
             XEvent unused_event;
 
-            while (XCheckTypedWindowEvent (display->display, ev.xany.window,
-                                          Expose,
-                                          &unused_event)) ;
-            while (XCheckTypedWindowEvent (display->display, ev.xany.window,
-                                          GraphicsExpose,
-                                          &unused_event)) ;
+            while (XCheckTypedWindowEvent (display->display, ev.xany.window, Expose, &unused_event))
+              ;
+            while (XCheckTypedWindowEvent (display->display, ev.xany.window, GraphicsExpose, &unused_event))
+              ;
+
             if (isScrollbarWindow (ev.xany.window))
               {
                 scrollBar.setIdle ();
@@ -1429,6 +1544,11 @@ rxvt_term::x_cb (XEvent &ev)
             if (menubar_visible () && isMenuBarWindow (ev.xany.window))
               menubar_expose ();
 #endif
+
+#ifdef TRANSPARENT
+            if (am_transparent && ev.xany.window == TermWin.parent[0])
+              XClearWindow (display->display, ev.xany.window);
+#endif
           }
         break;
 
@@ -1444,27 +1564,35 @@ rxvt_term::x_cb (XEvent &ev)
             break;
           }
 #endif
-        if ((PrivateModes & PrivMode_mouse_report) && ! (bypass_keystate))
+        if ((priv_modes & PrivMode_mouse_report) && ! (bypass_keystate))
           break;
 
         if (ev.xany.window == TermWin.vt)
           {
-            if ((ev.xbutton.state & (Button1Mask | Button3Mask)))
+            if (ev.xbutton.state & (Button1Mask | Button3Mask))
               {
                 while (XCheckTypedWindowEvent (display->display, TermWin.vt, MotionNotify, &ev))
                   ;
 
                 XQueryPointer (display->display, TermWin.vt,
-                              &unused_root, &unused_child,
-                              &unused_root_x, &unused_root_y,
-                              & (ev.xbutton.x), & (ev.xbutton.y),
-                              &unused_mask);
+                               &unused_root, &unused_child,
+                               &unused_root_x, &unused_root_y,
+                               & (ev.xbutton.x), & (ev.xbutton.y),
+                               &unused_mask);
 #ifdef MOUSE_THRESHOLD
                 /* deal with a `jumpy' mouse */
                 if ((ev.xmotion.time - MEvent.time) > MOUSE_THRESHOLD)
                   {
 #endif
-                    selection_extend ((ev.xbutton.x), (ev.xbutton.y),
+#if ISO_14755
+                    // 5.4
+                    if (iso14755buf & (ISO_14755_STARTED | ISO_14755_54))
+                      {
+                        iso14755_54 (ev.xbutton.x, ev.xbutton.y);
+                        break;
+                      }
+#endif
+                    selection_extend (ev.xbutton.x, ev.xbutton.y,
                                       (ev.xbutton.state & Button3Mask) ? 2 : 0);
 #ifdef SELECTION_SCROLLING
                     if (ev.xbutton.y < TermWin.int_bwidth
@@ -1472,21 +1600,18 @@ rxvt_term::x_cb (XEvent &ev)
                       {
                         int dist;
 
-                        pending_scroll_selection=1;
-
                         /* don't clobber the current delay if we are
                          * already in the middle of scrolling.
                          */
-                        if (scroll_selection_delay<=0)
-                          scroll_selection_delay=SCROLLBAR_CONTINUOUS_DELAY;
+                        if (!sel_scroll_ev.active)
+                          sel_scroll_ev.start (NOW + SCROLLBAR_INITIAL_DELAY);
 
                         /* save the event params so we can highlight
                          * the selection in the pending-scroll loop
                          */
-                        selection_save_x=ev.xbutton.x;
-                        selection_save_y=ev.xbutton.y;
-                        selection_save_state=
-                          (ev.xbutton.state & Button3Mask) ? 2 : 0;
+                        selection_save_x = ev.xbutton.x;
+                        selection_save_y = ev.xbutton.y;
+                        selection_save_state = (ev.xbutton.state & Button3Mask) ? 2 : 0;
 
                         /* calc number of lines to scroll */
                         if (ev.xbutton.y<TermWin.int_bwidth)
@@ -1497,33 +1622,33 @@ rxvt_term::x_cb (XEvent &ev)
                         else
                           {
                             scroll_selection_dir = DN;
-                            dist = ev.xbutton.y -
-                                   (TermWin.int_bwidth + TermWin.height);
+                            dist = ev.xbutton.y - (TermWin.int_bwidth + TermWin.height);
                           }
-                        scroll_selection_lines= (Pixel2Height (dist)/
-                                                SELECTION_SCROLL_LINE_SPEEDUP)+1;
+
+                        scroll_selection_lines = Pixel2Height (dist)
+                                                 / SELECTION_SCROLL_LINE_SPEEDUP
+                                                 + 1;
                         MIN_IT (scroll_selection_lines,
-                               SELECTION_SCROLL_MAX_LINES);
+                                SELECTION_SCROLL_MAX_LINES);
                       }
                     else
                       {
                         /* we are within the text window, so we
                          * shouldn't be scrolling
                          */
-                        pending_scroll_selection = 0;
+                        if (sel_scroll_ev.active)
+                          sel_scroll_ev.stop();
                       }
 #endif
 #ifdef MOUSE_THRESHOLD
-
                   }
 #endif
-
               }
           }
         else if (isScrollbarWindow (ev.xany.window) && scrollbar_isMotion ())
           {
             while (XCheckTypedWindowEvent (display->display, scrollBar.win,
-                                          MotionNotify, &ev)) ;
+                                           MotionNotify, &ev)) ;
             XQueryPointer (display->display, scrollBar.win,
                           &unused_root, &unused_child,
                           &unused_root_x, &unused_root_y,
@@ -1539,6 +1664,7 @@ rxvt_term::x_cb (XEvent &ev)
     }
 }
 
+#if TRANSPARENT
 void
 rxvt_term::rootwin_cb (XEvent &ev)
 {
@@ -1548,35 +1674,24 @@ rxvt_term::rootwin_cb (XEvent &ev)
   switch (ev.type)
     {
       case PropertyNotify:
-        if (ev.xproperty.atom == xa[XA_VT_SELECTION])
-          {
-            if (ev.xproperty.state == PropertyNewValue)
-              selection_property (ev.xproperty.window, ev.xproperty.atom);
-            break;
-          }
-#ifdef TRANSPARENT
-        else
-          {
-            /*
-             * if user used some Esetroot compatible prog to set the root bg,
-             * use the property to determine the pixmap.  We use it later on.
-             */
-            if (xa[XA_XROOTPMAPID] == 0)
-              xa[XA_XROOTPMAPID] = XInternAtom (display->display, "_XROOTPMAP_ID", False);
-
-            if (ev.xproperty.atom != xa[XA_XROOTPMAPID])
-              return;
-          }
+        /*
+         * if user used some Esetroot compatible prog to set the root bg,
+         * use the property to determine the pixmap.  We use it later on.
+         */
+        if (xa[XA_XROOTPMAPID] == 0)
+          xa[XA_XROOTPMAPID] = XInternAtom (display->display, "_XROOTPMAP_ID", False);
+
+        if (ev.xproperty.atom != xa[XA_XROOTPMAPID])
+          return;
 
         /* FALLTHROUGH */
       case ReparentNotify:
-        if ((Options & Opt_transparent) && check_our_parents ())
-          if (am_transparent)
-            want_full_refresh = 1;
+        if ((options & Opt_transparent) && check_our_parents () && am_transparent)
+          want_refresh = want_full_refresh = 1;
         break;
-#endif
     }
 }
+#endif
 
 void
 rxvt_term::button_press (XButtonEvent &ev)
@@ -1585,12 +1700,22 @@ rxvt_term::button_press (XButtonEvent &ev)
 
   bypass_keystate = ev.state & (ModMetaMask | ShiftMask);
   if (!bypass_keystate)
-    reportmode = !! (PrivateModes & PrivMode_mouse_report);
+    reportmode = !! (priv_modes & PrivMode_mouse_report);
+
   /*
    * VT window processing of button press
    */
   if (ev.window == TermWin.vt)
     {
+#if ISO_14755
+      // 5.4
+      if (iso14755buf & (ISO_14755_STARTED | ISO_14755_54))
+        {
+          iso14755_54 (ev.x, ev.y);
+          return;
+        }
+#endif
+
       clickintime = ev.time - MEvent.time < MULTICLICK_TIME;
       if (reportmode)
         {
@@ -1634,7 +1759,7 @@ rxvt_term::button_press (XButtonEvent &ev)
             {
               case Button1:
                 /* allow shift+left click to extend selection */
-                if (ev.state & ShiftMask && ! (PrivateModes & PrivMode_mouse_report))
+                if (ev.state & ShiftMask && ! (priv_modes & PrivMode_mouse_report))
                   {
                     if (MEvent.button == Button1 && clickintime)
                       selection_rotate (ev.x, ev.y);
@@ -1659,10 +1784,12 @@ rxvt_term::button_press (XButtonEvent &ev)
                   selection_rotate (ev.x, ev.y);
                 else
                   selection_extend (ev.x, ev.y, 1);
+
                 MEvent.button = Button3;
                 break;
             }
         }
+
       MEvent.time = ev.time;
       return;
     }
@@ -1738,7 +1865,7 @@ rxvt_term::button_press (XButtonEvent &ev)
           if (upordown)
             {
 #ifndef NO_SCROLLBAR_BUTTON_CONTINUAL_SCROLLING
-              scroll_arrow_delay = SCROLLBAR_INITIAL_DELAY;
+              cont_scroll_ev.start (NOW + SCROLLBAR_INITIAL_DELAY);
 #endif
               if (scr_page (upordown < 0 ? UP : DN, 1))
                 {
@@ -1764,11 +1891,12 @@ rxvt_term::button_press (XButtonEvent &ev)
                         csrO = scrollBar.bot - scrollBar.top;
                         break;
                     }
+
                   if (scrollBar.style == R_SB_XTERM
                       || scrollbar_above_slider (ev.y)
                       || scrollbar_below_slider (ev.y))
-                    scr_move_to (                                       scrollbar_position (ev.y) - csrO,
-                                       scrollbar_size ());
+                    scr_move_to (scrollbar_position (ev.y) - csrO, scrollbar_size ());
+
                   scrollBar.setMotion ();
                   break;
 
@@ -1802,6 +1930,7 @@ rxvt_term::button_press (XButtonEvent &ev)
                                  * scrollbar_position (ev.y)
                                  / scrollbar_size ()));
                     }
+
                   break;
               }
         }
@@ -1823,7 +1952,7 @@ rxvt_term::button_release (XButtonEvent &ev)
 
   csrO = 0;            /* reset csr Offset */
   if (!bypass_keystate)
-    reportmode = !! (PrivateModes & PrivMode_mouse_report);
+    reportmode = !! (priv_modes & PrivMode_mouse_report);
 
   if (scrollbar_isUpDn ())
     {
@@ -1832,13 +1961,20 @@ rxvt_term::button_release (XButtonEvent &ev)
 #ifndef NO_SCROLLBAR_BUTTON_CONTINUAL_SCROLLING
       refresh_type &= ~SMOOTH_REFRESH;
 #endif
-
     }
+
 #ifdef SELECTION_SCROLLING
-  pending_scroll_selection=0;
+  if (sel_scroll_ev.active)
+    sel_scroll_ev.stop();
 #endif
+
   if (ev.window == TermWin.vt)
     {
+#if ISO_14755
+      // 5.4
+      if (iso14755buf & (ISO_14755_STARTED | ISO_14755_54))
+        return;
+#endif
       if (reportmode)
         {
           /* mouse report from vt window */
@@ -1862,11 +1998,12 @@ rxvt_term::button_release (XButtonEvent &ev)
 #endif                         /* MOUSE_REPORT_DOUBLECLICK */
           return;
         }
+
       /*
        * dumb hack to compensate for the failure of click-and-drag
        * when overriding mouse reporting
        */
-      if (PrivateModes & PrivMode_mouse_report
+      if (priv_modes & PrivMode_mouse_report
           && bypass_keystate
           && ev.button == Button1 && MEvent.clicks <= 1)
         selection_extend (ev.x, ev.y, 0);
@@ -1887,37 +2024,48 @@ rxvt_term::button_release (XButtonEvent &ev)
               int i;
               page_dirn v;
 
-              v = (ev.button == Button4) ? UP : DN;
+              v = ev.button == Button4 ? UP : DN;
+
               if (ev.state & ShiftMask)
                 i = 1;
-              else if ((Options & Opt_mouseWheelScrollPage))
+              else if (options & Opt_mouseWheelScrollPage)
                 i = TermWin.nrow - 1;
               else
                 i = 5;
+
 # ifdef MOUSE_SLIP_WHEELING
               if (ev.state & ControlMask)
                 {
-                  mouse_slip_wheel_speed += (v ? -1 : 1);
-                  mouse_slip_wheel_delay = SCROLLBAR_CONTINUOUS_DELAY;
+                  mouse_slip_wheel_speed += v ? -1 : 1;
+                  if (mouse_slip_wheel_speed < -TermWin.nrow) mouse_slip_wheel_speed = -TermWin.nrow;
+                  if (mouse_slip_wheel_speed > +TermWin.nrow) mouse_slip_wheel_speed = +TermWin.nrow;
+
+                  if (slip_wheel_ev.at < NOW)
+                    slip_wheel_ev.at = NOW + SCROLLBAR_CONTINUOUS_DELAY;
+
+                  slip_wheel_ev.start ();
                 }
+              else
+                {
 # endif
 # ifdef JUMP_MOUSE_WHEEL
-              scr_page (v, i);
-              scr_refresh (SMOOTH_REFRESH);
-              scrollbar_show (1);
-# else
-              while (i--)
-                {
-                  scr_page (v, 1);
+                  scr_page (v, i);
                   scr_refresh (SMOOTH_REFRESH);
                   scrollbar_show (1);
-                }
+# else
+                  while (i--)
+                    {
+                      scr_page (v, 1);
+                      scr_refresh (SMOOTH_REFRESH);
+                      scrollbar_show (1);
+                    }
 # endif
-
+# ifdef MOUSE_SLIP_WHEELING
+                }
+#endif
             }
             break;
 #endif
-
         }
     }
 #ifdef MENUBAR
@@ -1926,8 +2074,238 @@ rxvt_term::button_release (XButtonEvent &ev)
 #endif
 }
 
-
 #ifdef TRANSPARENT
+#if TINTING
+/* taken from aterm-0.4.2 */
+
+typedef uint32_t RUINT32T;
+
+void ShadeXImage(rxvt_display *display, XImage* srcImage, int shade, int rm, int gm, int bm)
+{
+  int sh_r, sh_g, sh_b;
+  RUINT32T mask_r, mask_g, mask_b;
+  RUINT32T *lookup, *lookup_r, *lookup_g, *lookup_b;
+  unsigned int lower_lim_r, lower_lim_g, lower_lim_b;
+  unsigned int upper_lim_r, upper_lim_g, upper_lim_b;
+  int i;
+
+  Visual* visual = display->visual;
+
+  if( visual->c_class != TrueColor || srcImage->format != ZPixmap ) return ;
+
+  /* for convenience */
+  mask_r = visual->red_mask;
+  mask_g = visual->green_mask;
+  mask_b = visual->blue_mask;
+
+  /* boring lookup table pre-initialization */
+  switch (srcImage->bits_per_pixel) {
+    case 15:
+      if ((mask_r != 0x7c00) ||
+          (mask_g != 0x03e0) ||
+          (mask_b != 0x001f))
+        return;
+        lookup = (RUINT32T *) malloc (sizeof (RUINT32T)*(32+32+32));
+        lookup_r = lookup;
+        lookup_g = lookup+32;
+        lookup_b = lookup+32+32;
+        sh_r = 10;
+        sh_g = 5;
+        sh_b = 0;
+      break;
+    case 16:
+      if ((mask_r != 0xf800) ||
+          (mask_g != 0x07e0) ||
+          (mask_b != 0x001f))
+        return;
+        lookup = (RUINT32T *) malloc (sizeof (RUINT32T)*(32+64+32));
+        lookup_r = lookup;
+        lookup_g = lookup+32;
+        lookup_b = lookup+32+64;
+        sh_r = 11;
+        sh_g = 5;
+        sh_b = 0;
+      break;
+    case 24:
+      if ((mask_r != 0xff0000) ||
+          (mask_g != 0x00ff00) ||
+          (mask_b != 0x0000ff))
+        return;
+        lookup = (RUINT32T *) malloc (sizeof (RUINT32T)*(256+256+256));
+        lookup_r = lookup;
+        lookup_g = lookup+256;
+        lookup_b = lookup+256+256;
+        sh_r = 16;
+        sh_g = 8;
+        sh_b = 0;
+      break;
+    case 32:
+      if ((mask_r != 0xff0000) ||
+          (mask_g != 0x00ff00) ||
+          (mask_b != 0x0000ff))
+        return;
+        lookup = (RUINT32T *) malloc (sizeof (RUINT32T)*(256+256+256));
+        lookup_r = lookup;
+        lookup_g = lookup+256;
+        lookup_b = lookup+256+256;
+        sh_r = 16;
+        sh_g = 8;
+        sh_b = 0;
+      break;
+    default:
+      return; /* we do not support this color depth */
+  }
+
+  /* prepare limits for color transformation (each channel is handled separately) */
+  if (shade < 0) {
+    shade = -shade;
+    if (shade < 0) shade = 0;
+    if (shade > 100) shade = 100;
+
+    lower_lim_r = 65535-rm;
+    lower_lim_g = 65535-gm;
+    lower_lim_b = 65535-bm;
+
+    lower_lim_r = 65535-(unsigned int)(((RUINT32T)lower_lim_r)*((RUINT32T)shade)/100);
+    lower_lim_g = 65535-(unsigned int)(((RUINT32T)lower_lim_g)*((RUINT32T)shade)/100);
+    lower_lim_b = 65535-(unsigned int)(((RUINT32T)lower_lim_b)*((RUINT32T)shade)/100);
+
+    upper_lim_r = upper_lim_g = upper_lim_b = 65535;
+  } else {
+    if (shade < 0) shade = 0;
+    if (shade > 100) shade = 100;
+
+    lower_lim_r = lower_lim_g = lower_lim_b = 0;
+
+    upper_lim_r = (unsigned int)((((RUINT32T)rm)*((RUINT32T)shade))/100);
+    upper_lim_g = (unsigned int)((((RUINT32T)gm)*((RUINT32T)shade))/100);
+    upper_lim_b = (unsigned int)((((RUINT32T)bm)*((RUINT32T)shade))/100);
+  }
+
+  /* switch red and blue bytes if necessary, we need it for some weird XServers like XFree86 3.3.3.1 */
+  if ((srcImage->bits_per_pixel == 24) && (mask_r >= 0xFF0000 ))
+  {
+    unsigned int tmp;
+
+    tmp = lower_lim_r;
+    lower_lim_r = lower_lim_b;
+    lower_lim_b = tmp;
+
+    tmp = upper_lim_r;
+    upper_lim_r = upper_lim_b;
+    upper_lim_b = tmp;
+  }
+
+  /* fill our lookup tables */
+  for (i = 0; i <= mask_r>>sh_r; i++)
+  {
+    RUINT32T tmp;
+    tmp = ((RUINT32T)i)*((RUINT32T)(upper_lim_r-lower_lim_r));
+    tmp += ((RUINT32T)(mask_r>>sh_r))*((RUINT32T)lower_lim_r);
+    lookup_r[i] = (tmp/65535)<<sh_r;
+  }
+  for (i = 0; i <= mask_g>>sh_g; i++)
+  {
+    RUINT32T tmp;
+    tmp = ((RUINT32T)i)*((RUINT32T)(upper_lim_g-lower_lim_g));
+    tmp += ((RUINT32T)(mask_g>>sh_g))*((RUINT32T)lower_lim_g);
+    lookup_g[i] = (tmp/65535)<<sh_g;
+  }
+  for (i = 0; i <= mask_b>>sh_b; i++)
+  {
+    RUINT32T tmp;
+    tmp = ((RUINT32T)i)*((RUINT32T)(upper_lim_b-lower_lim_b));
+    tmp += ((RUINT32T)(mask_b>>sh_b))*((RUINT32T)lower_lim_b);
+    lookup_b[i] = (tmp/65535)<<sh_b;
+  }
+
+  /* apply table to input image (replacing colors by newly calculated ones) */
+  switch (srcImage->bits_per_pixel)
+  {
+    case 15:
+    {
+      unsigned short *p1, *pf, *p, *pl;
+      p1 = (unsigned short *) srcImage->data;
+      pf = (unsigned short *) (srcImage->data + srcImage->height * srcImage->bytes_per_line);
+      while (p1 < pf)
+      {
+        p = p1;
+        pl = p1 + srcImage->width;
+        for (; p < pl; p++)
+        {
+          *p = lookup_r[(*p & 0x7c00)>>10] |
+               lookup_g[(*p & 0x03e0)>> 5] |
+               lookup_b[(*p & 0x001f)];
+        }
+        p1 = (unsigned short *) ((char *) p1 + srcImage->bytes_per_line);
+      }
+      break;
+    }
+    case 16:
+    {
+      unsigned short *p1, *pf, *p, *pl;
+      p1 = (unsigned short *) srcImage->data;
+      pf = (unsigned short *) (srcImage->data + srcImage->height * srcImage->bytes_per_line);
+      while (p1 < pf)
+      {
+        p = p1;
+        pl = p1 + srcImage->width;
+        for (; p < pl; p++)
+        {
+          *p = lookup_r[(*p & 0xf800)>>11] |
+               lookup_g[(*p & 0x07e0)>> 5] |
+               lookup_b[(*p & 0x001f)];
+        }
+        p1 = (unsigned short *) ((char *) p1 + srcImage->bytes_per_line);
+      }
+      break;
+    }
+    case 24:
+    {
+      unsigned char *p1, *pf, *p, *pl;
+      p1 = (unsigned char *) srcImage->data;
+      pf = (unsigned char *) (srcImage->data + srcImage->height * srcImage->bytes_per_line);
+      while (p1 < pf)
+      {
+        p = p1;
+        pl = p1 + srcImage->width * 3;
+        for (; p < pl; p += 3)
+        {
+          p[0] = lookup_r[(p[0] & 0xff0000)>>16];
+          p[1] = lookup_r[(p[1] & 0x00ff00)>> 8];
+          p[2] = lookup_r[(p[2] & 0x0000ff)];
+        }
+        p1 = (unsigned char *) ((char *) p1 + srcImage->bytes_per_line);
+      }
+      break;
+    }
+    case 32:
+    {
+      RUINT32T *p1, *pf, *p, *pl;
+      p1 = (RUINT32T *) srcImage->data;
+      pf = (RUINT32T *) (srcImage->data + srcImage->height * srcImage->bytes_per_line);
+
+      while (p1 < pf)
+      {
+        p = p1;
+        pl = p1 + srcImage->width;
+        for (; p < pl; p++)
+        {
+          *p = lookup_r[(*p & 0xff0000)>>16] |
+               lookup_g[(*p & 0x00ff00)>> 8] |
+               lookup_b[(*p & 0x0000ff)] |
+               (*p & ~0xffffff);
+        }
+        p1 = (RUINT32T *) ((char *) p1 + srcImage->bytes_per_line);
+      }
+      break;
+    }
+  }
+
+  free (lookup);
+}
+#endif
+
 /*
  * Check our parents are still who we think they are.
  * Do transparency updates if required
@@ -1935,32 +2313,33 @@ rxvt_term::button_release (XButtonEvent &ev)
 int
 rxvt_term::check_our_parents ()
 {
-  int             i, pchanged, aformat, have_pixmap, rootdepth;
-  unsigned long   nitems, bytes_after;
-  Atom            atype;
-  unsigned char   *prop = NULL;
-  Window          root, oldp, *list;
-  Pixmap          rootpixmap = None;
+  int i, pchanged, aformat, have_pixmap, rootdepth;
+  unsigned long nitems, bytes_after;
+  Atom atype;
+  unsigned char *prop = NULL;
+  Window root, oldp, *list;
+  Pixmap rootpixmap = None;
   XWindowAttributes wattr, wrootattr;
 
   pchanged = 0;
 
-  if (! (Options & Opt_transparent))
+  if (!(options & Opt_transparent))
     return pchanged;   /* Don't try any more */
 
   XGetWindowAttributes (display->display, display->root, &wrootattr);
   rootdepth = wrootattr.depth;
 
   XGetWindowAttributes (display->display, TermWin.parent[0], &wattr);
+
   if (rootdepth != wattr.depth)
     {
       if (am_transparent)
         {
           pchanged = 1;
-          XSetWindowBackground (display->display, TermWin.vt,
-                               PixColors[Color_bg]);
+          XSetWindowBackground (display->display, TermWin.vt, pix_colors_focused[Color_bg]);
           am_transparent = am_pixmap_trans = 0;
         }
+
       return pchanged; /* Don't try any more */
     }
 
@@ -1972,55 +2351,71 @@ rxvt_term::check_our_parents ()
    * the root background. Some window managers put multiple nested frame
    * windows for each client, so we have to take care about that.
    */
-  i = (xa[XA_XROOTPMAPID] != 0
-       && (XGetWindowProperty (display->display, display->root, xa[XA_XROOTPMAPID],
+  i = (xa[XA_XROOTPMAPID]
+       && XGetWindowProperty (display->display, display->root, xa[XA_XROOTPMAPID],
                               0L, 1L, False, XA_PIXMAP, &atype, &aformat,
-                              &nitems, &bytes_after, &prop) == Success));
+                              &nitems, &bytes_after, &prop) == Success);
+
   if (!i || prop == NULL)
+     i = (xa[XA_XSETROOTID]
+          && XGetWindowProperty (display->display, display->root, xa[XA_XSETROOTID],
+                                 0L, 1L, False, XA_PIXMAP, &atype, &aformat,
+                                 &nitems, &bytes_after, &prop) == Success);
+
+  if (!i || prop == NULL
+#if TINTING
+      || !rs[Rs_color + Color_tint]
+#endif
+      )
     have_pixmap = 0;
   else
     {
       have_pixmap = 1;
-      rootpixmap = * ((Pixmap *)prop);
+      rootpixmap = *(Pixmap *)prop;
       XFree (prop);
     }
+
   if (have_pixmap)
     {
       /*
        * Copy display->root pixmap transparency
        */
-      int             sx, sy, nx, ny;
-      unsigned int    nw, nh;
-      Window          cr;
-      XImage         *image;
-      GC              gc;
-      XGCValues       gcvalue;
+      int sx, sy, nx, ny;
+      unsigned int nw, nh;
+      Window cr;
+      XImage *image;
+      GC gc;
+      XGCValues gcvalue;
 
       XTranslateCoordinates (display->display, TermWin.parent[0], display->root,
-                            0, 0, &sx, &sy, &cr);
+                             0, 0, &sx, &sy, &cr);
       nw = (unsigned int)szHint.width;
       nh = (unsigned int)szHint.height;
       nx = ny = 0;
+
       if (sx < 0)
         {
           nw += sx;
           nx = -sx;
           sx = 0;
         }
+
       if (sy < 0)
         {
           nh += sy;
           ny = -sy;
           sy = 0;
         }
+
       MIN_IT (nw, (unsigned int) (wrootattr.width - sx));
       MIN_IT (nh, (unsigned int) (wrootattr.height - sy));
       allowedxerror = -1;
-      image = XGetImage (display->display, rootpixmap, sx, sy, nw, nh, AllPlanes,
-                        ZPixmap);
+      image = XGetImage (display->display, rootpixmap, sx, sy, nw, nh, AllPlanes, ZPixmap);
+
       /* XXX: handle BadMatch - usually because we're outside the pixmap */
       /* XXX: may need a delay here? */
       allowedxerror = 0;
+
       if (image == NULL)
         {
           if (am_transparent && am_pixmap_trans)
@@ -2032,60 +2427,75 @@ rxvt_term::check_our_parents ()
                   TermWin.pixmap = None;
                 }
             }
+
           am_pixmap_trans = 0;
         }
       else
         {
           if (TermWin.pixmap != None)
             XFreePixmap (display->display, TermWin.pixmap);
+
+#if TINTING
+          if (ISSET_PIXCOLOR (Color_tint))
+            {
+              unsigned short rm, gm, bm;
+              int shade = rs[Rs_shade] ? atoi (rs[Rs_shade]) : 100;
+
+              pix_colors_focused[Color_tint].get (display, rm, gm, bm);
+
+              ShadeXImage (display, image, shade, rm, gm, bm);
+            }
+#endif
+
           TermWin.pixmap = XCreatePixmap (display->display, TermWin.vt,
-                                         (unsigned int)szHint.width,
-                                         (unsigned int)szHint.height,
-                                         (unsigned int)image->depth);
+                                          szHint.width, szHint.height, image->depth);
           gc = XCreateGC (display->display, TermWin.vt, 0UL, &gcvalue);
           XPutImage (display->display, TermWin.pixmap, gc, image, 0, 0,
-                    nx, ny, (unsigned int)image->width,
-                    (unsigned int)image->height);
+                     nx, ny, image->width, image->height);
           XFreeGC (display->display, gc);
           XDestroyImage (image);
-          XSetWindowBackgroundPixmap (display->display, TermWin.vt,
-                                     TermWin.pixmap);
+          XSetWindowBackgroundPixmap (display->display, TermWin.parent[0], TermWin.pixmap);
+          XClearWindow (display->display, TermWin.parent[0]);
+
           if (!am_transparent || !am_pixmap_trans)
             pchanged = 1;
+
           am_transparent = am_pixmap_trans = 1;
         }
     }
+
   if (!am_pixmap_trans)
     {
-      unsigned int    n;
+      unsigned int n;
       /*
        * InheritPixmap transparency
        */
-      D_X ((stderr, "InheritPixmap Seeking to  %08lx", display->root));
-      for (i = 1; i < (int) (sizeof (TermWin.parent) / sizeof (Window));
-           i++)
+      for (i = 1; i < (int) (sizeof (TermWin.parent) / sizeof (Window)); i++)
         {
           oldp = TermWin.parent[i];
           XQueryTree (display->display, TermWin.parent[i - 1], &root,
-                     &TermWin.parent[i], &list, &n);
+                      &TermWin.parent[i], &list, &n);
           XFree (list);
-          D_X ((stderr, "InheritPixmap Parent[%d] = %08lx", i, TermWin.parent[i]));
+
           if (TermWin.parent[i] == display->root)
             {
               if (oldp != None)
                 pchanged = 1;
+
               break;
             }
+
           if (oldp != TermWin.parent[i])
             pchanged = 1;
         }
+
       n = 0;
+
       if (pchanged)
         {
           for (; n < (unsigned int)i; n++)
             {
               XGetWindowAttributes (display->display, TermWin.parent[n], &wattr);
-              D_X ((stderr, "InheritPixmap Checking Parent[%d]: %s", n, (wattr.depth == rootdepth && wattr.class != InputOnly) ? "OK" : "FAIL"));
               if (wattr.depth != rootdepth || wattr.c_class == InputOnly)
                 {
                   n = (int) (sizeof (TermWin.parent) / sizeof (Window)) + 1;
@@ -2093,46 +2503,233 @@ rxvt_term::check_our_parents ()
                 }
             }
         }
-      if (n > (int) (sizeof (TermWin.parent)
-                    / sizeof (TermWin.parent[0])))
+
+      if (n > (int) (sizeof (TermWin.parent) / sizeof (TermWin.parent[0])))
         {
-          D_X ((stderr, "InheritPixmap Turning off"));
-          XSetWindowBackground (display->display, TermWin.parent[0],
-                               PixColors[Color_fg]);
-          XSetWindowBackground (display->display, TermWin.vt,
-                               PixColors[Color_bg]);
+          XSetWindowBackground (display->display, TermWin.parent[0], pix_colors_focused[Color_fg]);
+          XSetWindowBackground (display->display, TermWin.vt, pix_colors_focused[Color_bg]);
           am_transparent = 0;
           /* XXX: also turn off Opt_transparent? */
         }
-      else
-        {
-          /* wait (an arbitrary period) for the WM to do its thing
-           * needed for fvwm2.2.2 (and before?) */
-# ifdef HAVE_NANOSLEEP
-          struct timespec rqt;
+      else
+        {
+#if WAIT_FOR_WM
+          /* wait (an arbitrary period) for the WM to do its thing
+           * needed for fvwm2.2.2 (and before?) */
+          sleep (1);
+#endif
+          for (n = 0; n < (unsigned int)i; n++)
+            {
+              XSetWindowBackgroundPixmap (display->display, TermWin.parent[n], ParentRelative);
+              XClearWindow (display->display, TermWin.parent[n]);
+            }
+
+          XSetWindowBackgroundPixmap (display->display, TermWin.vt, ParentRelative);
+          am_transparent = 1;
+        }
+
+      for (; i < (int) (sizeof (TermWin.parent) / sizeof (Window)); i++)
+        TermWin.parent[i] = None;
+    }
+
+  if (scrollBar.win)
+    {
+      XSetWindowBackgroundPixmap (display->display, scrollBar.win, ParentRelative);
+      scrollBar.setIdle ();
+      scrollbar_show (0);
+    }
+
+  return pchanged;
+}
+#endif
+
+/*}}} */
+
+bool
+rxvt_term::cmd_parse ()
+{
+  bool flag = false;
+  unicode_t ch = NOCHAR;
+  unsigned char *seq_begin; // remember start of esc-sequence here
+
+  for (;;)
+    {
+      if (ch == NOCHAR)
+        {
+          seq_begin = cmdbuf_ptr;
+          ch = next_char ();
+        }
+
+      if (ch == NOCHAR) // TODO: improve
+        break;
+
+      if (!IS_CONTROL (ch) || ch == C0_LF || ch == C0_CR || ch == C0_HT)
+        {
+          if (!seen_input)
+            {
+              seen_input = 1;
+              // many badly-written programs (e.g. jed) contain a race condition:
+              // they first read the screensize and then install a SIGWINCH handler.
+              // some window managers resize the window early, and these programs
+              // then sometimes get the size wrong.
+              // unfortunately other programs are even more buggy and dislike
+              // being sent SIGWINCH, so only do it when we were in fact being
+              // resized.
+              if (seen_resize)
+                kill (-cmd_pid, SIGWINCH);
+            }
+
+          /* Read a text string from the input buffer */
+          unicode_t buf[UBUFSIZ];
+          bool refreshnow = false;
+          int nlines = 0;
+          unicode_t *str = buf;
+
+          for (;;)
+            {
+              if (ch == NOCHAR || (IS_CONTROL (ch) && ch != C0_LF && ch != C0_CR && ch != C0_HT))
+                break;
+
+              *str++ = ch;
+
+              if (ch == C0_LF)
+                {
+                  nlines++;
+                  refresh_count++;
+
+                  if (!(options & Opt_jumpScroll)
+                      || (refresh_count >= refresh_limit * (TermWin.nrow - 1)))
+                    {
+                      refreshnow = true;
+                      ch = NOCHAR;
+                      break;
+                    }
+
+                  // scr_add_lines only works for nlines <= TermWin.nrow - 1.
+                  if (nlines >= TermWin.nrow - 1)
+                    {
+                      scr_add_lines (buf, nlines, str - buf);
+                      nlines = 0;
+                      str = buf;
+                    }
+                }
+
+              if (str >= buf + UBUFSIZ)
+                {
+                  ch = NOCHAR;
+                  break;
+                }
+
+              seq_begin = cmdbuf_ptr;
+              ch = next_char ();
+            }
+
+          scr_add_lines (buf, nlines, str - buf);
+
+          /*
+           * If there have been a lot of new lines, then update the screen
+           * What the heck I'll cheat and only refresh less than every page-full.
+           * the number of pages between refreshes is refresh_limit, which
+           * is incremented here because we must be doing flat-out scrolling.
+           */
+          if (refreshnow)
+            {
+              if ((options & Opt_jumpScroll) && refresh_limit < REFRESH_PERIOD)
+                refresh_limit++;
+              else
+                {
+                  flag = true;
+                  scr_refresh (refresh_type);
+                }
+            }
+
+        }
+      else
+        {
+          try
+            {
+              process_nonprinting (ch);
+            }
+          catch (const class out_of_input &o)
+            {
+              // we ran out of input, retry later
+              cmdbuf_ptr = seq_begin;
+              break;
+            }
+
+          ch = NOCHAR;
+        }
+    }
 
-          rqt.tv_sec = 1;
-          rqt.tv_nsec = 0;
-          nanosleep (&rqt, NULL);
-# else
-          sleep (1);
-# endif
-          D_X ((stderr, "InheritPixmap Turning on (%d parents)", i - 1));
-          for (n = 0; n < (unsigned int)i; n++)
-            XSetWindowBackgroundPixmap (display->display, TermWin.parent[n],
-                                       ParentRelative);
-          XSetWindowBackgroundPixmap (display->display, TermWin.vt,
-                                     ParentRelative);
-          am_transparent = 1;
+  return flag;
+}
+
+// read the next octet
+unicode_t
+rxvt_term::next_octet ()
+{
+  return cmdbuf_ptr < cmdbuf_endp
+         ? *cmdbuf_ptr++
+         : NOCHAR;
+}
+
+// read the next character
+unicode_t
+rxvt_term::next_char ()
+{
+  while (cmdbuf_ptr < cmdbuf_endp)
+    {
+      // assume 7-bit to be ascii ALWAYS
+      if (*cmdbuf_ptr <= 0x7f && *cmdbuf_ptr != 0x1b)
+        return *cmdbuf_ptr++;
+
+      wchar_t wc;
+      size_t len = mbrtowc (&wc, (char *)cmdbuf_ptr, cmdbuf_endp - cmdbuf_ptr, mbstate);
+
+      if (len == (size_t)-2)
+        {
+          // the mbstate stores incomplete sequences. didn't know this :/
+          cmdbuf_ptr = cmdbuf_endp;
+          break;
         }
-      for (; i < (int) (sizeof (TermWin.parent) / sizeof (Window)); i++)
-        TermWin.parent[i] = None;
+
+      if (len == (size_t)-1)
+        return *cmdbuf_ptr++; // the _occasional_ latin1 character is allowed to slip through
+
+      // assume wchar == unicode
+      cmdbuf_ptr += len;
+      return wc;
     }
-  return pchanged;
+
+  return NOCHAR;
 }
-#endif
 
-/*}}} */
+/* rxvt_cmd_getc () - Return next input character */
+/*
+ * Return the next input character after first passing any keyboard input
+ * to the command.
+ */
+unicode_t
+rxvt_term::cmd_getc ()
+{
+  unicode_t c = next_char ();
+
+  if (c == NOCHAR)
+    throw out_of_input;
+
+  return c;
+}
+
+unicode_t
+rxvt_term::cmd_get8 ()
+{
+  unicode_t c = next_octet ();
+
+  if (c == NOCHAR)
+    throw out_of_input;
+
+  return c;
+}
 
 /*{{{ print pipe */
 /*----------------------------------------------------------------------*/
@@ -2140,10 +2737,11 @@ rxvt_term::check_our_parents ()
 FILE *
 rxvt_term::popen_printer ()
 {
-  FILE           *stream = popen (rs[Rs_print_pipe], "w");
+  FILE *stream = popen (rs[Rs_print_pipe], "w");
 
   if (stream == NULL)
-    rxvt_print_error ("can't open printer pipe");
+    rxvt_warn ("can't open printer pipe, not printing.\n");
+
   return stream;
 }
 
@@ -2151,13 +2749,7 @@ int
 rxvt_term::pclose_printer (FILE *stream)
 {
   fflush (stream);
-  /* pclose () reported not to work on SunOS 4.1.3 */
-# if defined (__sun__)         /* TODO: RESOLVE THIS */
-  /* pclose works provided SIGCHLD handler uses waitpid */
-  return pclose (stream);      /* return fclose (stream); */
-# else
   return pclose (stream);
-# endif
 }
 
 /*
@@ -2166,8 +2758,8 @@ rxvt_term::pclose_printer (FILE *stream)
 void
 rxvt_term::process_print_pipe ()
 {
-  int             done;
-  FILE           *fd;
+  int done;
+  FILE *fd;
 
   if ((fd = popen_printer ()) == NULL)
     return;
@@ -2178,9 +2770,9 @@ rxvt_term::process_print_pipe ()
    */
   for (done = 0; !done;)
     {
-      unsigned char   buf[8];
-      unsigned char   ch;
-      unsigned int    i, len;
+      unsigned char buf[8];
+      unicode_t ch;
+      unsigned int i, len;
 
       if ((ch = cmd_getc ()) != C0_ESC)
         {
@@ -2205,6 +2797,7 @@ rxvt_term::process_print_pipe ()
                     break;     /* done = 1 */
                 }
             }
+          
           for (i = 0; i < len; i++)
             if (putc (buf[i], fd) == EOF)
               {
@@ -2213,6 +2806,7 @@ rxvt_term::process_print_pipe ()
               }
         }
     }
+
   pclose_printer (fd);
 }
 #endif                         /* PRINTPIPE */
@@ -2221,27 +2815,29 @@ rxvt_term::process_print_pipe ()
 /* *INDENT-OFF* */
 enum {
   C1_40 = 0x40,
-  C1_41 , C1_BPH, C1_NBH, C1_44 , C1_NEL, C1_SSA, C1_ESA,
+          C1_41 , C1_BPH, C1_NBH, C1_44 , C1_NEL, C1_SSA, C1_ESA,
   C1_HTS, C1_HTJ, C1_VTS, C1_PLD, C1_PLU, C1_RI , C1_SS2, C1_SS3,
   C1_DCS, C1_PU1, C1_PU2, C1_STS, C1_CCH, C1_MW , C1_SPA, C1_EPA,
-  C1_SOS, C1_59 , C1_SCI, C1_CSI, CS_ST , C1_OSC, C1_PM , C1_APC
+  C1_SOS, C1_59 , C1_SCI, C1_CSI, CS_ST , C1_OSC, C1_PM , C1_APC,
 };
 /* *INDENT-ON* */
 
 /*{{{ process non-printing single characters */
 void
-rxvt_term::process_nonprinting (unsigned char ch)
+rxvt_term::process_nonprinting (unicode_t ch)
 {
   switch (ch)
     {
+      case C0_ESC:
+        process_escape_seq ();
+        break;
       case C0_ENQ:     /* terminal Status */
         if (rs[Rs_answerbackstring])
-          tt_write (
-            (const unsigned char *)rs[Rs_answerbackstring],
-            (unsigned int)STRLEN (rs[Rs_answerbackstring]));
+          tt_write ((const unsigned char *)rs[Rs_answerbackstring],
+                    (unsigned int)strlen (rs[Rs_answerbackstring]));
         else
           tt_write ((unsigned char *)VT100_ANS,
-                   (unsigned int)STRLEN (VT100_ANS));
+                    (unsigned int)strlen (VT100_ANS));
         break;
       case C0_BEL:     /* bell */
         scr_bell ();
@@ -2266,6 +2862,19 @@ rxvt_term::process_nonprinting (unsigned char ch)
       case C0_SI:              /* shift in - acs */
         scr_charset_choose (0);
         break;
+
+#ifdef EIGHT_BIT_CONTROLS
+      // 8-bit controls
+      case 0x90:       /* DCS */
+        process_dcs_seq ();
+        break;
+      case 0x9b:       /* CSI */
+        process_csi_seq ();
+        break;
+      case 0x9d:       /* CSI */
+        process_osc_seq ();
+        break;
+#endif
     }
 }
 /*}}} */
@@ -2273,7 +2882,7 @@ rxvt_term::process_nonprinting (unsigned char ch)
 
 /*{{{ process VT52 escape sequences */
 void
-rxvt_term::process_escape_vt52 (unsigned char ch)
+rxvt_term::process_escape_vt52 (unicode_t ch)
 {
   int row, col;
 
@@ -2335,9 +2944,9 @@ rxvt_term::process_escape_vt52 (unsigned char ch)
 void
 rxvt_term::process_escape_seq ()
 {
-  unsigned char   ch = cmd_getc ();
+  unicode_t ch = cmd_getc ();
 
-  if (PrivateModes & PrivMode_vt52)
+  if (priv_modes & PrivMode_vt52)
     {
       process_escape_vt52 (ch);
       return;
@@ -2362,12 +2971,7 @@ rxvt_term::process_escape_seq ()
       case '+':
         scr_charset_set (3, (unsigned int)cmd_getc ());
         break;
-#ifdef MULTICHAR_SET
-      case '$':
-        scr_charset_set (-2, (unsigned int)cmd_getc ());
-        break;
-#endif
-#ifndef NO_FRILLS
+#if ENABLE_FRILLS
       case '6':
         scr_backindex ();
         break;
@@ -2378,7 +2982,7 @@ rxvt_term::process_escape_seq ()
       case '8':
         scr_cursor (RESTORE);
         break;
-#ifndef NO_FRILLS
+#if ENABLE_FRILLS
       case '9':
         scr_forwardindex ();
         break;
@@ -2398,7 +3002,7 @@ rxvt_term::process_escape_seq ()
         /* 8.3.87: NEXT LINE */
       case C1_NEL:             /* ESC E */
         {
-          uint32_t nlcr[] = { '\n', '\r' };
+          unicode_t nlcr[] = { C0_LF, C0_CR };
           scr_add_lines (nlcr, 1, 2);
         }
         break;
@@ -2419,10 +3023,10 @@ rxvt_term::process_escape_seq ()
         break;
 
         /* 8.3.142: SINGLE-SHIFT TWO */
-        /*case C1_SS2: scr_single_shift (2);   break; */
+      /*case C1_SS2: scr_single_shift (2);   break; */
 
         /* 8.3.143: SINGLE-SHIFT THREE */
-        /*case C1_SS3: scr_single_shift (3);   break; */
+      /*case C1_SS3: scr_single_shift (3);   break; */
 
         /* 8.3.27: DEVICE CONTROL STRING */
       case C1_DCS:             /* ESC P */
@@ -2447,6 +3051,7 @@ rxvt_term::process_escape_seq ()
 
         /* 8.3.106: RESET TO INITIAL STATE */
       case 'c':
+        mbstate.reset ();
         scr_poweron ();
         scrollbar_show (1);
         break;
@@ -2468,7 +3073,7 @@ rxvt_term::process_escape_seq ()
 /* *INDENT-OFF* */
 enum {
   CSI_ICH = 0x40,
-  CSI_CUU, CSI_CUD, CSI_CUF, CSI_CUB, CSI_CNL, CSI_CPL, CSI_CHA,
+           CSI_CUU, CSI_CUD, CSI_CUF, CSI_CUB, CSI_CNL, CSI_CPL, CSI_CHA,
   CSI_CUP, CSI_CHT, CSI_ED , CSI_EL , CSI_IL , CSI_DL , CSI_EF , CSI_EA ,
   CSI_DCH, CSI_SEE, CSI_CPR, CSI_SU , CSI_SD , CSI_NP , CSI_PP , CSI_CTC,
   CSI_ECH, CSI_CVT, CSI_CBT, CSI_SRS, CSI_PTX, CSI_SDS, CSI_SIMD, CSI_5F,
@@ -2493,17 +3098,17 @@ const unsigned char csi_defaults[] =
     make_byte (1,1,1,0,1,1,1,0),       /* `, a, b, c, d, e, f, g, */
     make_byte (0,0,1,1,0,0,0,0),       /* h, i, j, k, l, m, n, o, */
     make_byte (0,0,0,0,0,0,0,0),       /* p, q, r, s, t, u, v, w, */
-    make_byte (0,0,0,0,0,0,0,0)        /* x, y, z, {, |, }, ~,    */
+    make_byte (0,0,0,0,0,0,0,0),       /* x, y, z, {, |, }, ~,    */
   };
 /* *INDENT-ON* */
 
 void
 rxvt_term::process_csi_seq ()
 {
-  unsigned char   ch, priv, i;
-  unsigned int    nargs, p;
-  int             n, ndef;
-  int             arg[ESC_ARGS];
+  unicode_t ch, priv, i;
+  unsigned int nargs, p;
+  int n, ndef;
+  int arg[ESC_ARGS];
 
   for (nargs = ESC_ARGS; nargs > 0;)
     arg[--nargs] = 0;
@@ -2515,6 +3120,7 @@ rxvt_term::process_csi_seq ()
       priv = ch;
       ch = cmd_getc ();
     }
+
   /* read any numerical arguments */
   for (n = -1; ch < CSI_ICH; )
     {
@@ -2531,19 +3137,9 @@ rxvt_term::process_csi_seq ()
             arg[nargs++] = n;
           n = -1;
         }
-      else if (ch == '\b')
-        {
-          scr_backspace ();
-        }
-      else if (ch == C0_ESC)
-        {
-          process_escape_seq ();
-          return;
-        }
-      else if (ch < ' ')
-        {
-          process_nonprinting (ch);
-        }
+      else if (IS_CONTROL (ch))
+        process_nonprinting (ch);
+
       ch = cmd_getc ();
     }
 
@@ -2695,7 +3291,7 @@ rxvt_term::process_csi_seq ()
 
       case CSI_DA:             /* 8.3.24: (0) DEVICE ATTRIBUTES */
         tt_write ((const unsigned char *)VT100_ANS,
-                 (unsigned int) (sizeof (VT100_ANS) - 1));
+                  (unsigned int) (sizeof (VT100_ANS) - 1));
         break;
 
       case CSI_SGR:            /* 8.3.118: (0) SELECT GRAPHIC RENDITION */
@@ -2711,13 +3307,12 @@ rxvt_term::process_csi_seq ()
             case 6:                    /* CPR requested */
               scr_report_position ();
               break;
-#if defined (ENABLE_DISPLAY_ANSWER)
             case 7:                    /* unofficial extension */
-              tt_printf ("%-.250s\n", rs[Rs_display_name]);
+              if (options & Opt_insecure)
+                tt_printf ("%-.250s\012", rs[Rs_display_name]);
               break;
-#endif
             case 8:                    /* unofficial extension */
-              xterm_seq (XTerm_title, APL_NAME "-" VERSION, CHAR_ST);
+              process_xterm_seq (XTerm_title, RESNAME "-" VERSION, CHAR_ST);
               break;
           }
         break;
@@ -2760,11 +3355,15 @@ rxvt_term::process_csi_seq ()
       case CSI_RM:             /* 8.3.107: RESET MODE */
         if (arg[0] == 4)
           scr_insert_mode (0);
+        else if (arg[0] == 20)
+          priv_modes &= ~PrivMode_LFNL;
         break;
 
       case CSI_SM:             /* 8.3.126: SET MODE */
         if (arg[0] == 4)
           scr_insert_mode (1);
+        else if (arg[0] == 20)
+          priv_modes |= PrivMode_LFNL;
         break;
 
         /*
@@ -2786,7 +3385,7 @@ rxvt_term::process_csi_seq ()
         scr_cursor (RESTORE);
         break;
 
-#ifndef NO_FRILLS
+#if ENABLE_FRILLS
       case CSI_74:
         process_window_ops (arg, nargs);
         break;
@@ -2795,7 +3394,7 @@ rxvt_term::process_csi_seq ()
       case CSI_78:             /* DECREQTPARM */
         if (arg[0] == 0 || arg[0] == 1)
           tt_printf ("\033[%d;1;1;128;128;1;0x", arg[0] + 2);
-        /* FALLTHROUGH */
+        break;
 
       default:
         break;
@@ -2803,25 +3402,23 @@ rxvt_term::process_csi_seq ()
 }
 /*}}} */
 
-#ifndef NO_FRILLS
+#if ENABLE_FRILLS
 /* ARGSUSED */
 void
 rxvt_term::process_window_ops (const int *args, unsigned int nargs)
 {
-  int             x, y;
-#if 0
-  char           *s;
-#endif
+  int x, y;
   XWindowAttributes wattr;
-  Window          wdummy;
+  Window wdummy;
 
   if (nargs == 0)
     return;
+
   switch (args[0])
     {
-        /*
-         * commands
-         */
+      /*
+       * commands
+       */
       case 1:                  /* deiconify window */
         XMapWindow (display->display, TermWin.parent[0]);
         break;
@@ -2848,14 +3445,18 @@ rxvt_term::process_window_ops (const int *args, unsigned int nargs)
         set_widthheight ((unsigned int) (args[2] * TermWin.fwidth),
                          (unsigned int) (args[1] * TermWin.fheight));
         break;
+
+      //case 9: NYI, TODO, restore maximized window or maximize window
       default:
         if (args[0] >= 24)     /* set height (chars) */
           set_widthheight ((unsigned int)TermWin.width,
                            (unsigned int) (args[1] * TermWin.fheight));
         break;
-        /*
-         * reports - some output format copied from XTerm
-         */
+
+
+      /*
+       * reports - some output format copied from XTerm
+       */
       case 11:                 /* report window state */
         XGetWindowAttributes (display->display, TermWin.parent[0], &wattr);
         tt_printf ("\033[%dt", wattr.map_state == IsViewable ? 1 : 2);
@@ -2863,28 +3464,36 @@ rxvt_term::process_window_ops (const int *args, unsigned int nargs)
       case 13:                 /* report window position */
         XGetWindowAttributes (display->display, TermWin.parent[0], &wattr);
         XTranslateCoordinates (display->display, TermWin.parent[0], wattr.root,
-                              -wattr.border_width, -wattr.border_width,
-                              &x, &y, &wdummy);
+                               -wattr.border_width, -wattr.border_width,
+                               &x, &y, &wdummy);
         tt_printf ("\033[3;%d;%dt", x, y);
         break;
       case 14:                 /* report window size (pixels) */
         XGetWindowAttributes (display->display, TermWin.parent[0], &wattr);
         tt_printf ("\033[4;%d;%dt", wattr.height, wattr.width);
         break;
-      case 18:                 /* report window size (chars) */
+      case 18:                 /* report text area size (chars) */
         tt_printf ("\033[8;%d;%dt", TermWin.nrow, TermWin.ncol);
         break;
-#if 0 /* XXX: currently disabled due to security concerns */
+      case 19:                 /* report window size (chars) */
+        tt_printf ("\033[9;%d;%dt", TermWin.nrow, TermWin.ncol);
+        break;
       case 20:                 /* report icon label */
-        XGetIconName (display->display, TermWin.parent[0], &s);
-        tt_printf ("\033]L%-.200s\234", s ? s : "");   /* 8bit ST */
+        {
+          char *s;
+          XGetIconName (display->display, TermWin.parent[0], &s);
+          tt_printf ("\033]L%-.250s\234", (options & Opt_insecure) && s ? s : "");     /* 8bit ST */
+          XFree (s);
+        }
         break;
       case 21:                 /* report window title */
-        XFetchName (display->display, TermWin.parent[0], &s);
-        tt_printf ("\033]l%-.200s\234", s ? s : "");   /* 8bit ST */
+        {
+          char *s;
+          XFetchName (display->display, TermWin.parent[0], &s);
+          tt_printf ("\033]l%-.250s\234", (options & Opt_insecure) && s ? s : "");     /* 8bit ST */
+          XFree (s);
+        }
         break;
-#endif
-
     }
 }
 #endif
@@ -2892,40 +3501,54 @@ rxvt_term::process_window_ops (const int *args, unsigned int nargs)
 /*----------------------------------------------------------------------*/
 /*
  * get input up until STRING TERMINATOR (or BEL)
- * ends_how is terminator used.  returned input must be free ()d
+ * ends_how is terminator used. returned input must be free()'d
  */
-unsigned char  *
-rxvt_term::get_to_st (unsigned char *ends_how)
+unsigned char *
+rxvt_term::get_to_st (unicode_t &ends_how)
 {
-  int             seen_esc = 0;        /* seen escape? */
-  unsigned int    n = 0;
-  unsigned char  *s;
-  unsigned char   ch, string[STRING_MAX];
+  unicode_t seen_esc = 0, ch;
+  unsigned int n = 0;
+  unsigned char *s;
+  unsigned char string[STRING_MAX];
 
-  for (; (ch = cmd_getc ());)
+  while ((ch = cmd_getc ()) != NOCHAR)
     {
-      if (ch == C0_BEL
-          || ch == CHAR_ST
-          || (ch == 0x5c && seen_esc)) /* 7bit ST */
-        break;
-      if (ch == C0_ESC)
+      if (seen_esc)
+        {
+          if (ch == 0x5c)      /* 7bit ST */
+            break;
+          else
+            return NULL;
+        }
+      else if (ch == C0_ESC)
         {
           seen_esc = 1;
           continue;
         }
-      else if (ch == '\t')
-        ch = ' ';      /* translate '\t' to space */
-      else if (ch < 0x08 || (ch > 0x0d && ch < 0x20))
+      else if (ch == C0_BEL || ch == CHAR_ST)
+        break;
+      else if (ch < 0x20)
         return NULL;   /* other control character - exit */
-      if (n < sizeof (string) - 1)
-        string[n++] = ch;
+
       seen_esc = 0;
+
+      if (n >= sizeof (string) - 1)
+        // stop at some sane length
+        return NULL;
+
+      if (ch == C0_SYN)
+        string[n++] = cmd_get8 ();
+      else
+        string[n++] = ch;
     }
+
   string[n++] = '\0';
+
   if ((s = (unsigned char *)rxvt_malloc (n)) == NULL)
     return NULL;
-  *ends_how = (ch == 0x5c ? C0_ESC : ch);
-  STRNCPY (s, string, n);
+
+  ends_how = (ch == 0x5c ? C0_ESC : ch);
+  strncpy (s, string, n);
   return s;
 }
 
@@ -2936,13 +3559,16 @@ rxvt_term::get_to_st (unsigned char *ends_how)
 void
 rxvt_term::process_dcs_seq ()
 {
-  unsigned char    eh, *s;
+  unsigned char *s;
+  unicode_t eh;
+
   /*
    * Not handled yet
    */
-  s = get_to_st (&eh);
+  s = get_to_st (eh);
   if (s)
     free (s);
+
   return;
 }
 
@@ -2953,8 +3579,8 @@ rxvt_term::process_dcs_seq ()
 void
 rxvt_term::process_osc_seq ()
 {
-  unsigned char   ch, eh, *s;
-  int             arg;
+  unicode_t ch, eh;
+  int arg;
 
   ch = cmd_getc ();
   for (arg = 0; isdigit (ch); ch = cmd_getc ())
@@ -2962,31 +3588,37 @@ rxvt_term::process_osc_seq ()
 
   if (ch == ';')
     {
-      s = get_to_st (&eh);
+      unsigned char *s = get_to_st (eh);
+
       if (s)
         {
-          /*
-           * rxvt_menubar_dispatch () violates the constness of the string,
-           * so do it here
-           */
-          if (arg == XTerm_Menu)
-#if 0 /* XXX: currently disabled due to security concerns */
-            menubar_dispatch ((char *)s);
-#else
-            (void)0;
-#endif
-          else
-            xterm_seq (arg, (char *)s, eh);
+          process_xterm_seq (arg, (char *)s, eh);
           free (s);
         }
     }
 }
+
+void
+rxvt_term::process_color_seq (int report, int color, const char *str, unsigned char resp)
+{
+  if (str[0] == '?' && !str[1])
+    {
+      unsigned short r, g, b;
+      pix_colors_focused[color].get (display, r, g, b);
+      tt_printf ("\033]%d;rgb:%04x/%04x/%04x%c", report, r, g, b, resp);
+    }
+  else
+    set_window_color (color, str);
+}
+
 /*
  * XTerm escape sequences: ESC ] Ps;Pt (ST|BEL)
  *       0 = change iconName/title
  *       1 = change iconName
  *       2 = change title
  *       4 = change color
+ *      10 = change fg color
+ *      11 = change bg color
  *      12 = change text color
  *      13 = change mouse foreground color 
  *      17 = change highlight character colour
@@ -2996,19 +3628,22 @@ rxvt_term::process_osc_seq ()
  *      50 = change font
  *
  * rxvt extensions:
- *       9 = change locale (NYI)
- *      10 = menu (may change in future)
  *      20 = bg pixmap
  *      39 = change default fg color
  *      49 = change default bg color
  *      55 = dump scrollback buffer and all of screen
+ *     701 = change locale
+ *     702 = find font
+ *     703 = menu
  */
 void
-rxvt_term::xterm_seq (int op, const char *str, unsigned char resp __attribute__ ((unused)))
+rxvt_term::process_xterm_seq (int op, const char *str, unsigned char resp)
 {
-  int             changed = 0;
-  int             color;
-  char           *buf, *name;
+  int changed = 0;
+  int color;
+  char *buf, *name;
+  bool query = str[0] == '?' && !str[1];
+  int saveop = op;
 
   assert (str != NULL);
   switch (op)
@@ -3017,51 +3652,118 @@ rxvt_term::xterm_seq (int op, const char *str, unsigned char resp __attribute__
         set_title (str);
         /* FALLTHROUGH */
       case XTerm_iconName:
-        set_iconName (str);
+        set_icon_name (str);
         break;
       case XTerm_title:
         set_title (str);
         break;
+      case XTerm_property:
+        if (str[0] == '?')
+          {
+            Atom prop = XInternAtom (display->display, str + 1, True);
+            Atom actual_type;
+            int actual_format;
+            unsigned long nitems;
+            unsigned long bytes_after;
+            unsigned char *value = 0;
+            const char *str = "";
+
+            if (prop
+                && XGetWindowProperty (display->display, TermWin.parent[0],
+                                       prop, 0, 1<<16, 0, AnyPropertyType,
+                                       &actual_type, &actual_format,
+                                       &nitems, &bytes_after, &value) == Success
+                && actual_type != None
+                && actual_format == 8)
+              str = (const char *)(value);
+
+            tt_printf ("\033]%d;%s%c", XTerm_property, str, resp);
+
+            XFree (value);
+          }
+        else
+          {
+            char *eq = strchr (str, '='); // constness lost, but verified to be ok
+
+            if (eq)
+              {
+                *eq = 0;
+                XChangeProperty (display->display, TermWin.parent[0],
+                                 display->atom (str), XA_STRING, 8,
+                                 PropModeReplace, (unsigned char *)eq + 1,
+                                 strlen (eq + 1));
+              }
+            else
+              XDeleteProperty (display->display, TermWin.parent[0],
+                               display->atom (str));
+          }
+        break;
+
       case XTerm_Color:
         for (buf = (char *)str; buf && *buf;)
           {
-            if ((name = STRCHR (buf, ';')) == NULL)
+            if ((name = strchr (buf, ';')) == NULL)
               break;
+
             *name++ = '\0';
             color = atoi (buf);
+
             if (color < 0 || color >= TOTAL_COLORS)
               break;
-            if ((buf = STRCHR (name, ';')) != NULL)
+
+            if ((buf = strchr (name, ';')) != NULL)
               *buf++ = '\0';
-            set_window_color (color + minCOLOR, name);
+
+            if (name[0] == '?' && !name[1])
+              {
+                unsigned short r, g, b;
+                pix_colors_focused[color + minCOLOR].get (display, r, g, b);
+                tt_printf ("\033]%d;%d;rgb:%04x/%04x/%04x%c", XTerm_Color, color, r, g, b, resp);
+              }
+            else
+              set_window_color (color + minCOLOR, name);
           }
         break;
+      case XTerm_Color00:
+        process_color_seq (XTerm_Color00, Color_fg, str, resp);
+        break;
+      case XTerm_Color01:
+        process_color_seq (XTerm_Color00, Color_bg, str, resp);
+        break;
 #ifndef NO_CURSORCOLOR
       case XTerm_Color_cursor:
-        set_window_color (Color_cursor, str);
+        process_color_seq (XTerm_Color_cursor, Color_cursor, str, resp);
         break;
 #endif
-      case XTerm_Color_pointer:
-        set_window_color (Color_pointer, str);
+      case XTerm_Color_pointer_fg:
+        process_color_seq (XTerm_Color_pointer_fg, Color_pointer_fg, str, resp);
+        break;
+      case XTerm_Color_pointer_bg:
+        process_color_seq (XTerm_Color_pointer_bg, Color_pointer_bg, str, resp);
         break;
 #ifndef NO_BOLD_UNDERLINE_REVERSE
       case XTerm_Color_BD:
-        set_window_color (Color_BD, str);
+        process_color_seq (XTerm_Color_BD, Color_BD, str, resp);
+        break;
+      case XTerm_Color_IT:
+        process_color_seq (XTerm_Color_IT, Color_IT, str, resp);
         break;
       case XTerm_Color_UL:
-        set_window_color (Color_UL, str);
+        process_color_seq (XTerm_Color_UL, Color_UL, str, resp);
         break;
       case XTerm_Color_RV:
-        set_window_color (Color_RV, str);
+        process_color_seq (XTerm_Color_RV, Color_RV, str, resp);
         break;
 #endif
-
-      case XTerm_Menu:
-        /*
-         * rxvt_menubar_dispatch () violates the constness of the string,
-         * so DON'T do it here
-         */
+#if TRANSPARENT || TINTING
+      case XTerm_Color_tint:
+        process_color_seq (XTerm_Color_tint, Color_tint, str, resp);
+        check_our_parents ();
+        if (am_transparent)
+          want_full_refresh = want_refresh = 1;
         break;
+#endif
+
       case XTerm_Pixmap:
         if (*str != ';')
           {
@@ -3071,7 +3773,7 @@ rxvt_term::xterm_seq (int op, const char *str, unsigned char resp __attribute__
 #endif
             scr_touch (true);
           }
-        while ((str = STRCHR (str, ';')) != NULL)
+        while ((str = strchr (str, ';')) != NULL)
           {
             str++;
 #if XPM_BACKGROUND
@@ -3094,29 +3796,58 @@ rxvt_term::xterm_seq (int op, const char *str, unsigned char resp __attribute__
       case XTerm_restoreBG:
         set_window_color (Color_bg, str);
         break;
+
       case XTerm_logfile:
+        // TODO, when secure mode?
         break;
+
       case XTerm_font:
-        change_font (str);
+        op = URxvt_font;
+      case URxvt_font:
+#if ENABLE_STYLES
+      case URxvt_boldFont:
+      case URxvt_italicFont:
+      case URxvt_boldItalicFont:
+#endif
+        if (query)
+          tt_printf ("\33]%d;%-.250s%c", saveop,
+                     (options & Opt_insecure) && TermWin.fontset[op - URxvt_font]->fontdesc
+                       ? TermWin.fontset[op - URxvt_font]->fontdesc : "",
+                     resp);
+        else
+          {
+            const char *&res = rs[Rs_font + (op - URxvt_font)];
+
+            res = strdup (str);
+            allocated.push_back ((void *)res);
+            set_fonts ();
+          }
         break;
+
+#if ENABLE_FRILLS
       case XTerm_locale:
-        if (str[0] == '?' && !str[1])
-          tt_printf ("%-.250s\n", locale);
+        if (query)
+          tt_printf ("\33]%d;%-.250s%c", XTerm_locale, (options & Opt_insecure) ? locale : "", resp);
         else
           {
             set_locale (str);
+# ifdef USE_XIM
             im_cb ();
-
-            // TODO: call selection_make with the right values set
-            // to re-fresh the selection.
-            if (display->selection_owner == this)
-              display->set_selection_owner (0);
+# endif
           }
         break;
+#endif
+
+#ifdef MENUBAR
+     case XTerm_Menu:
+       if (options & Opt_insecure)
+         menubar_dispatch (const_cast<char *>(str)); // casting away constness is checked
+       break;
+#endif
 #if 0
       case XTerm_dumpscreen:   /* no error notices */
         {
-          int             fd;
+          int fd;
           if ((fd = open (str, O_RDWR | O_CREAT | O_EXCL, 0600)) >= 0)
             {
               scr_dump (fd);
@@ -3125,7 +3856,6 @@ rxvt_term::xterm_seq (int op, const char *str, unsigned char resp __attribute__
         }
         break;
 #endif
-
     }
 }
 /*----------------------------------------------------------------------*/
@@ -3143,11 +3873,11 @@ rxvt_term::xterm_seq (int op, const char *str, unsigned char resp __attribute__
 int
 rxvt_term::privcases (int mode, unsigned long bit)
 {
-  int             state;
+  int state;
 
   if (mode == 's')
     {
-      SavedModes |= (PrivateModes & bit);
+      SavedModes |= (priv_modes & bit);
       return -1;
     }
   else
@@ -3155,9 +3885,10 @@ rxvt_term::privcases (int mode, unsigned long bit)
       if (mode == 'r')
         state = (SavedModes & bit) ? 1 : 0;    /* no overlapping */
       else
-        state = (mode == 't') ? ! (PrivateModes & bit) : mode;
+        state = (mode == 't') ? ! (priv_modes & bit) : mode;
       PrivMode (state, bit);
     }
+
   return state;
 }
 
@@ -3165,13 +3896,15 @@ rxvt_term::privcases (int mode, unsigned long bit)
 void
 rxvt_term::process_terminal_mode (int mode, int priv __attribute__ ((unused)), unsigned int nargs, const int *arg)
 {
-  unsigned int    i, j;
-  int             state;
+  unsigned int i, j;
+  int state;
+
   static const struct
     {
       const int       argval;
       const unsigned long bit;
     }
+
   argtopriv[] = {
                   { 1, PrivMode_aplCUR },
                   { 2, PrivMode_vt52 },
@@ -3180,26 +3913,39 @@ rxvt_term::process_terminal_mode (int mode, int priv __attribute__ ((unused)), u
                   { 5, PrivMode_rVideo },
                   { 6, PrivMode_relOrigin },
                   { 7, PrivMode_Autowrap },
+                 // 8, bi-directional support mode
                   { 9, PrivMode_MouseX10 },
 #ifdef menuBar_esc
                   { menuBar_esc, PrivMode_menuBar },
 #endif
+                 // 18, 19 printing-related
+                  { 25, PrivMode_VisibleCursor },
 #ifdef scrollBar_esc
                   { scrollBar_esc, PrivMode_scrollBar },
 #endif
-                  { 25, PrivMode_VisibleCursor },
-                  { 35, PrivMode_ShiftKeys },
+                  { 35, PrivMode_ShiftKeys }, // rxvt extension
                   { 40, PrivMode_132OK },
+                 // 41 xterm more fixes NYI
+                 // 45 margin bell NYI
+                 // 46 start logging
                   { 47, PrivMode_Screen },
                   { 66, PrivMode_aplKP },
 #ifndef NO_BACKSPACE_KEY
                   { 67, PrivMode_BackSpace },
 #endif
                   { 1000, PrivMode_MouseX11 },
-                  { 1010, PrivMode_TtyOutputInh },
-                  { 1011, PrivMode_Keypress },
+                 // 1001 Use Hilite Mouse Tracking. NYI, TODO
+                 // 1002 Use Cell Motion Mouse Tracking. NYI, TODO
+                 // 1003 Use All Motion Mouse Tracking. NYI, TODO
+                  { 1010, PrivMode_TtyOutputInh }, // rxvt extension
+                  { 1011, PrivMode_Keypress }, // rxvt extension
+                 // 1035 enable modifiers for alt, numlock NYI
+                 // 1036 send ESC for meta keys NYI
+                 // 1037 send DEL for keypad delete NYI
                   { 1047, PrivMode_Screen },
-                  { 1049, PrivMode_Screen }, /* xterm extension, not fully implemented */
+                 // 1048 save and restore cursor
+                  { 1049, PrivMode_Screen }, /* xterm extension, clear screen on ti rather than te */
+                 // 1051, 1052, 1060, 1061 keyboard emulation NYI
                 };
 
   if (nargs == 0)
@@ -3224,110 +3970,115 @@ rxvt_term::process_terminal_mode (int mode, int priv __attribute__ ((unused)), u
           }
 
       /* extra handling for values with state unkept  */
-      if (state == -1)
-        switch (arg[i])
-          {
-            case 1048:         /* alternative cursor save */
+      switch (arg[i])
+        {
+          case 1048:           /* alternative cursor save */
+          case 1049:
+            if (options & Opt_secondaryScreen)
               if (mode == 0)
                 scr_cursor (RESTORE);
               else if (mode == 1)
                 scr_cursor (SAVE);
-              /* FALLTHROUGH */
-            default:
-              continue;        /* for (;i;) */
-          }
-
-      /* extra handling for values with valid 0 or 1 state */
-      switch (arg[i])
-        {
-            /* case 1: - application cursor keys */
-          case 2:                      /* VT52 mode */
-            /* oddball mode.  should be set regardless of set/reset
-             * parameter.  Return from VT52 mode with an ESC < from
-             * within VT52 mode
-             */
-            PrivMode (1, PrivMode_vt52);
-            break;
-          case 3:                      /* 80/132 */
-            if (PrivateModes & PrivMode_132OK)
-              set_widthheight (                    (unsigned int) ((state ? 132 : 80) * TermWin.fwidth),
-                                     (unsigned int)TermWin.height);
-            break;
-          case 4:                      /* smooth scrolling */
-            if (state)
-              Options &= ~Opt_jumpScroll;
-            else
-              Options |= Opt_jumpScroll;
-            break;
-          case 5:                      /* reverse video */
-            scr_rvideo_mode (state);
-            break;
-          case 6:                      /* relative/absolute origins  */
-            scr_relative_origin (state);
-            break;
-          case 7:                      /* autowrap */
-            scr_autowrap (state);
             break;
+        }
+
+      if (state >= 0)
+        /* extra handling for values with valid 0 or 1 state */
+        switch (arg[i])
+          {
+              /* case 1:       - application cursor keys */
+            case 2:                    /* VT52 mode */
+              /* oddball mode.  should be set regardless of set/reset
+               * parameter.  Return from VT52 mode with an ESC < from
+               * within VT52 mode
+               */
+              PrivMode (1, PrivMode_vt52);
+              break;
+            case 3:                    /* 80/132 */
+              if (priv_modes & PrivMode_132OK)
+                set_widthheight (((state ? 132 : 80) * TermWin.fwidth), TermWin.height);
+              break;
+            case 4:                    /* smooth scrolling */
+              if (state)
+                options &= ~Opt_jumpScroll;
+              else
+                options |= Opt_jumpScroll;
+              break;
+            case 5:                    /* reverse video */
+              scr_rvideo_mode (state);
+              break;
+            case 6:                    /* relative/absolute origins  */
+              scr_relative_origin (state);
+              break;
+            case 7:                    /* autowrap */
+              scr_autowrap (state);
+              break;
             /* case 8: - auto repeat, can't do on a per window basis */
-          case 9:                      /* X10 mouse reporting */
-            if (state)         /* orthogonal */
-              PrivateModes &= ~ (PrivMode_MouseX11);
-            break;
+            case 9:                    /* X10 mouse reporting */
+              if (state)               /* orthogonal */
+                priv_modes &= ~PrivMode_MouseX11;
+              break;
 #ifdef menuBar_esc
-          case menuBar_esc:
+            case menuBar_esc:
 #ifdef MENUBAR
-            map_menuBar (state);
+              map_menuBar (state);
 #endif
-            break;
+              break;
 #endif
 #ifdef scrollBar_esc
-          case scrollBar_esc:
-            if (scrollbar_mapping (state))
-              {
-                resize_all_windows (0, 0, 0);
-                scr_touch (true);
-              }
-            break;
+            case scrollBar_esc:
+              if (scrollbar_mapping (state))
+                {
+                  resize_all_windows (0, 0, 0);
+                  scr_touch (true);
+                }
+              break;
 #endif
-          case 25:             /* visible/invisible cursor */
-            scr_cursor_visible (state);
-            break;
+            case 25:           /* visible/invisible cursor */
+              scr_cursor_visible (state);
+              break;
             /* case 35:        - shift keys */
             /* case 40:        - 80 <--> 132 mode */
-          case 47:             /* secondary screen */
-            scr_change_screen (state);
-            break;
+            case 47:           /* secondary screen */
+              scr_change_screen (state);
+              break;
             /* case 66:        - application key pad */
             /* case 67:        - backspace key */
-          case 1000:           /* X11 mouse reporting */
-            if (state)         /* orthogonal */
-              PrivateModes &= ~ (PrivMode_MouseX10);
-            break;
+            case 1000:         /* X11 mouse reporting */
+              if (state)               /* orthogonal */
+                priv_modes &= ~PrivMode_MouseX10;
+              break;
 #if 0
-          case 1001:
-            break;             /* X11 mouse highlighting */
+            case 1001:
+              break;           /* X11 mouse highlighting */
 #endif
-          case 1010:           /* scroll to bottom on TTY output inhibit */
-            if (state)
-              Options &= ~Opt_scrollTtyOutput;
-            else
-              Options |= Opt_scrollTtyOutput;
-            break;
-          case 1011:           /* scroll to bottom on key press */
-            if (state)
-              Options |= Opt_scrollTtyKeypress;
-            else
-              Options &= ~Opt_scrollTtyKeypress;
-            break;
-          case 1047:           /* secondary screen w/ clearing */
-          case 1049:           /* better secondary screen w/ clearing, but not fully implemented */
-            if (current_screen != PRIMARY)
-              scr_erase_screen (2);
-            scr_change_screen (state);
-            /* FALLTHROUGH */
-          default:
-            break;
-        }
+            case 1010:         /* scroll to bottom on TTY output inhibit */
+              if (state)
+                options &= ~Opt_scrollTtyOutput;
+              else
+                options |= Opt_scrollTtyOutput;
+              break;
+            case 1011:         /* scroll to bottom on key press */
+              if (state)
+                options |= Opt_scrollTtyKeypress;
+              else
+                options &= ~Opt_scrollTtyKeypress;
+              break;
+            case 1047:         /* secondary screen w/ clearing last */
+              if (options & Opt_secondaryScreen)
+                if (current_screen != PRIMARY)
+                  scr_erase_screen (2);
+              scr_change_screen (state);
+              break;
+            case 1049:         /* secondary screen w/ clearing first */
+              scr_change_screen (state);
+              if (options & Opt_secondaryScreen)
+                if (current_screen != PRIMARY)
+                  scr_erase_screen (2);
+              break;
+            default:
+              break;
+          }
     }
 }
 /*}}} */
@@ -3336,15 +4087,16 @@ rxvt_term::process_terminal_mode (int mode, int priv __attribute__ ((unused)), u
 void
 rxvt_term::process_sgr_mode (unsigned int nargs, const int *arg)
 {
-  unsigned int    i;
-  short           rendset;
-  int             rendstyle;
+  unsigned int i;
+  short rendset;
+  int rendstyle;
 
   if (nargs == 0)
     {
       scr_rendition (0, ~RS_None);
       return;
     }
+
   for (i = 0; i < nargs; i++)
     {
       rendset = -1;
@@ -3356,28 +4108,56 @@ rxvt_term::process_sgr_mode (unsigned int nargs, const int *arg)
           case 1:
             rendset = 1, rendstyle = RS_Bold;
             break;
+          //case 2: // low intensity
+          case 3:
+            rendset = 1, rendstyle = RS_Italic;
+            break;
           case 4:
             rendset = 1, rendstyle = RS_Uline;
             break;
-          case 5:
+          case 5: // slowly blinking
+          case 6: // rapidly blinking
             rendset = 1, rendstyle = RS_Blink;
             break;
+          //case 6: // scoansi light background
           case 7:
             rendset = 1, rendstyle = RS_RVid;
             break;
-          case 22:
+          case 8:
+            // invisible. NYI
+            break;
+          //case 9: // crossed out
+          //case 10: // scoansi acs off, primary font
+          //case 11: // scoansi acs on, first alt font
+          //case 12: // scoansi acs on, |0x80, second alt font
+          //...
+          //case 19: // ninth alt font
+          //case 20: // gothic
+          case 21: // disable bold, faint, sometimes doubly underlined (iso 8613)
+            rendset = 0, rendstyle = RS_Bold;
+            break;
+          case 22: // normal intensity
             rendset = 0, rendstyle = RS_Bold;
             break;
+          case 23: // disable italic
+            rendset = 0, rendstyle = RS_Italic;
+            break;
           case 24:
             rendset = 0, rendstyle = RS_Uline;
             break;
           case 25:
             rendset = 0, rendstyle = RS_Blink;
             break;
+          case 26: // variable spacing (iso 8613)
+            rendset = 0, rendstyle = RS_Blink;
+            break;
           case 27:
             rendset = 0, rendstyle = RS_RVid;
             break;
+          //case 28: // visible. NYI
+          //case 29: // not crossed-out
         }
+
       if (rendset != -1)
         {
           scr_rendition (rendset, rendstyle);
@@ -3394,19 +4174,15 @@ rxvt_term::process_sgr_mode (unsigned int nargs, const int *arg)
           case 35:
           case 36:
           case 37:
-            scr_color ((unsigned int) (minCOLOR + (arg[i] - 30)),
-                       Color_fg);
+            scr_color ((unsigned int) (minCOLOR + (arg[i] - 30)), Color_fg);
             break;
-#ifdef TTY_256COLOR
-          case 38:
+          case 38: // set fg color, ISO 8613-6
             if (nargs > i + 2 && arg[i + 1] == 5)
               {
-                scr_color ((unsigned int) (minCOLOR + arg[i + 2]),
-                           Color_fg);
+                scr_color ((unsigned int) (minCOLOR + arg[i + 2]), Color_fg);
                 i += 2;
               }
             break;
-#endif
           case 39:             /* default fg */
             scr_color (Color_fg, Color_fg);
             break;
@@ -3419,23 +4195,21 @@ rxvt_term::process_sgr_mode (unsigned int nargs, const int *arg)
           case 45:
           case 46:
           case 47:
-            scr_color ((unsigned int) (minCOLOR + (arg[i] - 40)),
-                       Color_bg);
+            scr_color ((unsigned int) (minCOLOR + (arg[i] - 40)), Color_bg);
             break;
-#ifdef TTY_256COLOR
-          case 48:
+          case 48: // set bg color, ISO 8613-6
             if (nargs > i + 2 && arg[i + 1] == 5)
               {
-                scr_color ((unsigned int) (minCOLOR + arg[i + 2]),
-                           Color_bg);
+                scr_color ((unsigned int) (minCOLOR + arg[i + 2]), Color_bg);
                 i += 2;
               }
             break;
-#endif
           case 49:             /* default bg */
             scr_color (Color_bg, Color_bg);
             break;
 
+          //case 50: // not variable spacing
+
 #ifndef NO_BRIGHTCOLOR
           case 90:
           case 91:             /* set bright fg color */
@@ -3445,8 +4219,7 @@ rxvt_term::process_sgr_mode (unsigned int nargs, const int *arg)
           case 95:
           case 96:
           case 97:
-            scr_color ((unsigned int) (minBrightCOLOR + (arg[i] - 90)),
-                       Color_fg);
+            scr_color ((unsigned int) (minBrightCOLOR + (arg[i] - 90)), Color_fg);
             break;
           case 100:
           case 101:            /* set bright bg color */
@@ -3456,8 +4229,7 @@ rxvt_term::process_sgr_mode (unsigned int nargs, const int *arg)
           case 105:
           case 106:
           case 107:
-            scr_color ((unsigned int) (minBrightCOLOR + (arg[i] - 100)),
-                       Color_bg);
+            scr_color ((unsigned int) (minBrightCOLOR + (arg[i] - 100)), Color_bg);
             break;
 #endif
 
@@ -3466,15 +4238,15 @@ rxvt_term::process_sgr_mode (unsigned int nargs, const int *arg)
 }
 /*}}} */
 
-/*{{{ process Rob Nation's own graphics mode sequences */
+/*{{{ (do not) process Rob Nation's own graphics mode sequences */
 void
 rxvt_term::process_graphics ()
 {
-  unsigned char   ch, cmd = cmd_getc ();
+  unicode_t ch, cmd = cmd_getc ();
 
   if (cmd == 'Q')
     {          /* query graphics */
-      tt_printf ("\033G0\n");  /* no graphics */
+      tt_printf ("\033G0\012");        /* no graphics */
       return;
     }
   /* swallow other graphics sequences until terminating ':' */
@@ -3499,7 +4271,7 @@ rxvt_term::tt_printf (const char *fmt,...)
   va_start (arg_ptr, fmt);
   vsnprintf ((char *)buf, 256, fmt, arg_ptr);
   va_end (arg_ptr);
-  tt_write (buf, STRLEN (buf));
+  tt_write (buf, strlen (buf));
 }
 
 /* ---------------------------------------------------------------------- */
@@ -3509,13 +4281,13 @@ rxvt_term::tt_printf (const char *fmt,...)
 void
 rxvt_term::tt_write (const unsigned char *data, unsigned int len)
 {
-  enum { MAX_PTY_WRITE = 255 }; // minimum MAX_INPUT
+  const unsigned int MAX_PTY_WRITE = 255; // minimum MAX_INPUT
 
   if (len)
     {
       if (v_buflen == 0)
         {
-          ssize_t written = write (cmd_fd, data, min (MAX_PTY_WRITE, len));
+          ssize_t written = write (pty.pty, data, min (len, MAX_PTY_WRITE));
 
           if ((unsigned int)written == len)
             return;
@@ -3533,7 +4305,7 @@ rxvt_term::tt_write (const unsigned char *data, unsigned int len)
 
   for (;;)
     {
-      int written = write (cmd_fd, v_buffer, min (MAX_PTY_WRITE, v_buflen));
+      int written = write (pty.pty, v_buffer, min (v_buflen, MAX_PTY_WRITE));
 
       if (written > 0)
         {