set _NET_WM_USER_TIME on the window
[dana/urxvt.git] / src / command.C
index b68b43a..78fa3b5 100644 (file)
@@ -164,12 +164,9 @@ void
 rxvt_term::iso14755_51 (unicode_t ch, rend_t r, int x, int y)
 {
   rxvt_fontset *fs = FONTSET (r);
-  rxvt_font *f = (*fs)[fs->find_font (ch)];
-  wchar_t *chr, *alloc, ch2, *fname;
+  wchar_t *chr, *alloc, ch2, **fname;
   int len;
 
-  fname = rxvt_utf8towcs (f->name);
-
 # if ENABLE_COMBINING
   if (IS_COMPOSE (ch))
     {
@@ -199,7 +196,14 @@ rxvt_term::iso14755_51 (unicode_t ch, rend_t r, int x, int y)
            r & RS_Uline   ? " uline"   : "",
            r & RS_Careful ? " careful" : "");
 
-  int width = wcswidth (fname, wcslen (fname));
+  int width = 0;
+  fname = rxvt_temp_buf<wchar_t *> (len);
+  for (int i = 0; i < len; i++)
+    {
+      rxvt_font *f = (*fs)[fs->find_font_idx (chr[i])];
+      fname[i] = rxvt_utf8towcs (f->name);
+      max_it (width, wcswidth (fname[i], wcslen (fname[i])));
+    }
 
   max_it (width, 8+5); // for char + hex
   max_it (width, strlen (attr));
@@ -210,7 +214,7 @@ rxvt_term::iso14755_51 (unicode_t ch, rend_t r, int x, int y)
       x = 0;
     }
 
-  scr_overlay_new (x, y, width, len + 2);
+  scr_overlay_new (x, y, width, len * 2 + 1);
 
   r = SET_STYLE (OVERLAY_RSTYLE, GET_STYLE (r));
 
@@ -239,9 +243,11 @@ rxvt_term::iso14755_51 (unicode_t ch, rend_t r, int x, int y)
 //    scr_overlay_set (0, 0, buf);
 //  }
   scr_overlay_set (0, len    , attr);
-  scr_overlay_set (0, len + 1, fname);
-
-  free (fname);
+  for (int i = 0; i < len; i++)
+    {
+      scr_overlay_set (0, len + 1 + i, fname[i]);
+      free (fname[i]);
+    }
 
 # if ENABLE_COMBINING
   if (alloc)
@@ -284,7 +290,7 @@ rxvt_term::commit_iso14755 ()
 static int
 hex_keyval (XKeyEvent &ev)
 {
-  // check wether this event corresponds to a hex digit
+  // check whether this event corresponds to a hex digit
   // if the modifiers had not been pressed.
   for (int index = 0; index < 8; index++)
     {
@@ -396,6 +402,13 @@ map_function_key (KeySym keysym)
 }
 
 void
+rxvt_term::update_user_time (Time time)
+{
+  XChangeProperty (dpy, parent[0], xa[XA_NET_WM_USER_TIME], XA_CARDINAL,
+                   32, PropModeReplace, (unsigned char*)&time, 1);
+}
+
+void
 rxvt_term::key_press (XKeyEvent &ev)
 {
   int ctrl, meta, shft, len;
@@ -418,12 +431,6 @@ rxvt_term::key_press (XKeyEvent &ev)
   ctrl = ev.state & ControlMask;
   meta = ev.state & ModMetaMask;
 
-  if (numlock_state || (ev.state & ModNumLockMask))
-    {
-      numlock_state = (ev.state & ModNumLockMask);
-      set_privmode (PrivMode_aplKP, !numlock_state);
-    }
-
   kbuf[0] = 0;
 
 #ifdef USE_XIM
@@ -507,6 +514,8 @@ rxvt_term::key_press (XKeyEvent &ev)
 #else
               lnsppg = nrow * 4 / 5;
 #endif
+              max_it (lnsppg, 1);
+
               if (keysym == XK_Prior)
                 {
                   scr_page (UP, lnsppg);
@@ -581,7 +590,7 @@ rxvt_term::key_press (XKeyEvent &ev)
 
 #if ENABLE_FRILLS || ISO_14755
       // ISO 14755 support
-      if (shft && ctrl)
+      if (iso14755buf & (ISO_14755_STARTED | ISO_14755_51))
         {
           int hv;
 
@@ -596,6 +605,24 @@ rxvt_term::key_press (XKeyEvent &ev)
 # endif
               return;
             }
+          else if (keysym == XK_C)
+            {
+              selection_make (ev.time, true);
+# if ISO_14755
+              scr_overlay_off ();
+# endif
+              iso14755buf = 0;
+              return;
+            }
+          else if (keysym == XK_V)
+            {
+              selection_request (ev.time, Sel_Clipboard);
+# if ISO_14755
+              scr_overlay_off ();
+# endif
+              iso14755buf = 0;
+              return;
+            }
           else if (keysym == XK_BackSpace)
             {
               iso14755buf = ((iso14755buf & ISO_14755_MASK) >> 4) | ISO_14755_51;
@@ -621,8 +648,9 @@ rxvt_term::key_press (XKeyEvent &ev)
               iso14755buf = 0;
             }
         }
-      else if ((ctrl && (keysym == XK_Shift_L || keysym == XK_Shift_R))
-               || (shft && (keysym == XK_Control_L || keysym == XK_Control_R)))
+      else if (option (Opt_iso14755) &&
+               ((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;
@@ -646,7 +674,12 @@ rxvt_term::key_press (XKeyEvent &ev)
           bool kp = priv_modes & PrivMode_aplKP ? !shft : shft;
           unsigned int newlen = 1;
 
-          switch (translate_keypad (keysym, kp))
+          if (ev.state & ModNumLockMask)
+            kp = false;
+
+          keysym = translate_keypad (keysym, kp);
+
+          switch (keysym)
             {
 #ifndef NO_BACKSPACE_KEY
               case XK_BackSpace:
@@ -1026,7 +1059,7 @@ rxvt_term::flush ()
   display->flush ();
 }
 
-/* checks wether a refresh is requested and starts the refresh timer */
+/* checks whether a refresh is requested and starts the refresh timer */
 void
 rxvt_term::refresh_check ()
 {
@@ -1130,7 +1163,7 @@ static struct event_handler
     // ones with high nice levels is a useful thing to do. It surely is is
     // allowed by the sus... as is returning ENOSYS.
     // since the linux guys additionally thought that breaking the only
-    // known workaroudn against their unusable sched_yield hack is cool,
+    // known workaround against their unusable sched_yield hack is cool,
     // we just nanosleep a bit and hope for the best.
 
     struct timespec ts = { 0, 1000 };
@@ -1336,6 +1369,7 @@ rxvt_term::x_cb (XEvent &ev)
   switch (ev.type)
     {
       case KeyPress:
+        update_user_time (ev.xkey.time);
         key_press (ev.xkey);
         break;
 
@@ -1344,6 +1378,7 @@ rxvt_term::x_cb (XEvent &ev)
         break;
 
       case ButtonPress:
+        update_user_time (ev.xbutton.time);
         button_press (ev.xbutton);
         break;
 
@@ -1463,7 +1498,7 @@ rxvt_term::x_cb (XEvent &ev)
         break;
 
       case SelectionClear:
-        selection_clear ();
+        selection_clear (ev.xselectionclear.selection == xa[XA_CLIPBOARD]);
         break;
 
       case SelectionNotify:
@@ -1686,6 +1721,7 @@ rxvt_term::x_cb (XEvent &ev)
   refresh_check ();
 }
 
+#if ENABLE_FRILLS
 void
 rxvt_term::set_urgency (bool enable)
 {
@@ -1699,6 +1735,7 @@ rxvt_term::set_urgency (bool enable)
       urgency_hint = enable;
     }
 }
+#endif
 
 void
 rxvt_term::focus_in ()
@@ -1829,6 +1866,8 @@ rxvt_term::button_press (XButtonEvent &ev)
 {
   int reportmode = 0, clickintime;
 
+  button_state[ev.button - Button1] = true;
+
   bypass_keystate = ev.state & (ModMetaMask | ShiftMask);
 
   if (!bypass_keystate)
@@ -2075,6 +2114,11 @@ rxvt_term::button_release (XButtonEvent &ev)
 {
   int reportmode = 0;
 
+  if (button_state[ev.button - Button1] == false)
+      return; /* it wasn't pressed so why is it released? */
+
+  button_state[ev.button - Button1] = false;
+
   csrO = 0;            /* reset csr Offset */
   if (!bypass_keystate)
     reportmode = !! (priv_modes & PrivMode_mouse_report);
@@ -2142,7 +2186,7 @@ rxvt_term::button_release (XButtonEvent &ev)
 
           case Button2:
             if (IN_RANGE_EXC (ev.x, 0, width) && IN_RANGE_EXC (ev.y, 0, height)) // inside window?
-             selection_request (ev.time, ev.state & ModMetaMask ? Sel_Clipboard : Sel_Primary);
+              selection_request (ev.time, ev.state & ModMetaMask ? Sel_Clipboard : Sel_Primary);
             break;
 
 #ifdef MOUSE_WHEEL
@@ -2336,7 +2380,7 @@ rxvt_term::next_char () NOTHROW
 
       if (len == (size_t)-1)
         {
-          mbrtowc (0, 0, 0, mbstate); // reset now undefined conversion state
+          mbstate.reset (); // reset now undefined conversion state
           return (unsigned char)*cmdbuf_ptr++; // the _occasional_ latin1 character is allowed to slip through
         }
 
@@ -2690,17 +2734,17 @@ rxvt_term::process_escape_seq ()
         tt_write (ESCZ_ANSWER, sizeof (ESCZ_ANSWER) - 1);
         break;                 /* steal obsolete ESC [ c */
 
-        /* 8.3.16: CONTROL SEQUENCE INTRODUCER */
+        /* 8.3.16: CONTROL SEQUENCE INTRODUCER (CSI) */
       case C1_CSI:             /* ESC [ */
         process_csi_seq ();
         break;
 
-        /* 8.3.90: OPERATING SYSTEM COMMAND */
+        /* 8.3.90: OPERATING SYSTEM COMMAND (OSC) */
       case C1_OSC:             /* ESC ] */
         process_osc_seq ();
         break;
 
-        /* 8.3.106: RESET TO INITIAL STATE */
+        /* 8.3.106: RESET TO INITIAL STATE (RIS) */
       case 'c':
         mbstate.reset ();
         scr_poweron ();
@@ -2765,9 +2809,9 @@ rxvt_term::process_csi_seq ()
 
   priv = 0;
   ch = cmd_getc ();
-  if (ch >= '<' && ch <= '?')
+  if ((ch >= '<' && ch <= '?') || ch == '!')
     {
-      /* '<' '=' '>' '?' */
+      /* '<' '=' '>' '?' '!' */
       priv = ch;
       ch = cmd_getc ();
     }
@@ -2831,7 +2875,22 @@ rxvt_term::process_csi_seq ()
             if (ch == 'h' || ch == 'l' || ch == 'r' || ch == 's' || ch == 't')
               process_terminal_mode (ch, priv, nargs, arg);
             break;
+
+          case '!':
+            if (ch == CSI_70)
+              {
+                /* DECSTR: soft terminal reset, used by our terminfo since 9.06 */
+                scr_soft_reset ();
+
+                static const int pm_h[] = { 7, 25 };
+                static const int pm_l[] = { 1, 3, 4, 5, 6, 9, 66, 1000, 1001, 1049 };
+
+                process_terminal_mode ('h', 0, sizeof (pm_h) / sizeof (pm_h[0]), pm_h);
+                process_terminal_mode ('l', 0, sizeof (pm_l) / sizeof (pm_l[0]), pm_l);
+              }
+          break;
         }
+
       return;
     }
 
@@ -3270,7 +3329,7 @@ rxvt_term::process_color_seq (int report, int color, const char *str, char resp)
  * XTerm escape sequences: ESC ] Ps;Pt (ST|BEL)
  */
 void
-rxvt_term::process_xterm_seq (int op, const char *str, char resp)
+rxvt_term::process_xterm_seq (int op, char *str, char resp)
 {
   int color;
   char *buf, *name;
@@ -3321,7 +3380,7 @@ rxvt_term::process_xterm_seq (int op, const char *str, char resp)
           }
         else
           {
-            char *eq = strchr (str, '='); // constness lost, but verified to be ok
+            char *eq = strchr (str, '=');
 
             if (eq)
               {
@@ -3371,15 +3430,18 @@ rxvt_term::process_xterm_seq (int op, const char *str, char resp)
       case XTerm_Color_pointer_bg:
         process_color_seq (op, Color_pointer_bg, str, resp);
         break;
-#ifndef NO_BOLD_UNDERLINE_REVERSE
-      case XTerm_Color_RV:
-        process_color_seq (op, Color_RV, str, resp);
+#ifdef OPTION_HC
+      case XTerm_Color_HC:
+        process_color_seq (op, Color_HC, str, resp);
+        break;
+      case XTerm_Color_HTC:
+        process_color_seq (op, Color_HTC, str, resp);
         break;
-      case Rxvt_Color_BD:
+#endif
+#ifndef NO_BOLD_UNDERLINE_REVERSE
       case URxvt_Color_BD:
         process_color_seq (op, Color_BD, str, resp);
         break;
-      case Rxvt_Color_UL:
       case URxvt_Color_UL:
         process_color_seq (op, Color_UL, str, resp);
         break;
@@ -3387,6 +3449,9 @@ rxvt_term::process_xterm_seq (int op, const char *str, char resp)
         process_color_seq (op, Color_IT, str, resp);
         break;
 #endif
+      case URxvt_Color_border:
+        process_color_seq (op, Color_border, str, resp);
+        break;
 #if ENABLE_TRANSPARENCY
       case URxvt_Color_tint:
         process_color_seq (op, Color_tint, str, resp);
@@ -3411,7 +3476,7 @@ rxvt_term::process_xterm_seq (int op, const char *str, char resp)
           {
             char str[256];
 
-            sprintf (str, "[%dx%d+%d+%d]",     /* can't presume snprintf () ! */
+            sprintf (str, "[%dx%d+%d+%d]",
                      min (bgPixmap.h_scale, 32767), min (bgPixmap.v_scale, 32767),
                      min (bgPixmap.h_align, 32767), min (bgPixmap.v_align, 32767));
             process_xterm_seq (XTerm_title, str, CHAR_ST);
@@ -3571,29 +3636,31 @@ rxvt_term::process_terminal_mode (int mode, int priv UNUSED, unsigned int nargs,
     const int       argval;
     const unsigned long bit;
   } argtopriv[] = {
-                  { 1, PrivMode_aplCUR },
+                  { 1, PrivMode_aplCUR },       // DECCKM
                   { 2, PrivMode_vt52 },
-                  { 3, PrivMode_132 },
-                  { 4, PrivMode_smoothScroll },
-                  { 5, PrivMode_rVideo },
-                  { 6, PrivMode_relOrigin },
-                  { 7, PrivMode_Autowrap },
-                 // 8, bi-directional support mode
+                  { 3, PrivMode_132 },          // DECCOLM
+                  { 4, PrivMode_smoothScroll }, // DECSCLM
+                  { 5, PrivMode_rVideo },       // DECSCNM
+                  { 6, PrivMode_relOrigin },    // DECOM
+                  { 7, PrivMode_Autowrap },     // DECAWM
+                 // 8, auto-repeat keys         // DECARM
                   { 9, PrivMode_MouseX10 },
-                 // 18, 19 printing-related
-                  { 25, PrivMode_VisibleCursor },
+                 // 18 end FF to printer after print screen
+                 // 19 Print screen prints full screen/scorll region
+                  { 25, PrivMode_VisibleCursor }, // cnorm/cvvis/civis
 #ifdef scrollBar_esc
                   { scrollBar_esc, PrivMode_scrollBar },
 #endif
-                  { 35, PrivMode_ShiftKeys }, // rxvt extension
+                  { 35, PrivMode_ShiftKeys },   // rxvt extension
+                 // 38, tektronix mode          // DECTEK
                   { 40, PrivMode_132OK },
                  // 41 xterm more fixes NYI
                  // 45 margin bell NYI
                  // 46 start logging
                   { 47, PrivMode_Screen },
-                  { 66, PrivMode_aplKP },
+                  { 66, PrivMode_aplKP },       // DECPAM/DECPNM
 #ifndef NO_BACKSPACE_KEY
-                  { 67, PrivMode_BackSpace },
+                  { 67, PrivMode_BackSpace },   // DECBKM
 #endif
                   { 1000, PrivMode_MouseX11 },
                   { 1002, PrivMode_MouseBtnEvent },
@@ -3642,7 +3709,6 @@ rxvt_term::process_terminal_mode (int mode, int priv UNUSED, unsigned int nargs,
             break;
 #endif
           case 1048:           /* alternative cursor save */
-          case 1049:
             if (option (Opt_secondaryScreen))
               if (mode == 0)
                 scr_cursor (RESTORE);
@@ -3665,10 +3731,7 @@ rxvt_term::process_terminal_mode (int mode, int priv UNUSED, unsigned int nargs,
               break;
             case 3:                    /* 80/132 */
               if (priv_modes & PrivMode_132OK)
-                {
-                  scr_poweron ();
-                  set_widthheight (((state ? 132 : 80) * fwidth), 24 * fheight);
-                }
+                set_widthheight ((state ? 132 : 80) * fwidth, 24 * fheight);
               break;
             case 4:                    /* smooth scrolling */
               set_option (Opt_jumpScroll, !state);
@@ -3720,6 +3783,7 @@ rxvt_term::process_terminal_mode (int mode, int priv UNUSED, unsigned int nargs,
                 }
               else
                 vt_emask_mouse = NoEventMask;
+
               vt_select_input ();
               break;
             case 1010:         /* scroll to bottom on TTY output inhibit */
@@ -3730,15 +3794,23 @@ rxvt_term::process_terminal_mode (int mode, int priv UNUSED, unsigned int nargs,
               break;
             case 1047:         /* secondary screen w/ clearing last */
               if (option (Opt_secondaryScreen))
-                if (current_screen != PRIMARY)
+                if (!state)
                   scr_erase_screen (2);
+
               scr_change_screen (state);
               break;
             case 1049:         /* secondary screen w/ clearing first */
+              if (option (Opt_secondaryScreen))
+                if (state)
+                  scr_cursor (SAVE);
+
               scr_change_screen (state);
+
               if (option (Opt_secondaryScreen))
-                if (current_screen != PRIMARY)
+                if (state)
                   scr_erase_screen (2);
+                else
+                  scr_cursor (RESTORE);
               break;
             default:
               break;