Add support for copying to clipboard (based on patch by Dana Jansens).
authorsf-exg <sf-exg>
Sun, 24 Jan 2010 21:53:13 +0000 (21:53 +0000)
committersf-exg <sf-exg>
Sun, 24 Jan 2010 21:53:13 +0000 (21:53 +0000)
src/command.C
src/main.C
src/rxvt.h
src/rxvtperl.xs
src/rxvttoolkit.C
src/rxvttoolkit.h
src/screen.C

index e9c2a16..60a87db 100644 (file)
@@ -1464,7 +1464,7 @@ rxvt_term::x_cb (XEvent &ev)
         break;
 
       case SelectionClear:
-        selection_clear ();
+        selection_clear (ev.xselectionclear.selection == xa[XA_CLIPBOARD]);
         break;
 
       case SelectionNotify:
index 88bd0e5..9d8acc6 100644 (file)
@@ -239,6 +239,7 @@ rxvt_term::~rxvt_term ()
   if (display)
     {
       selection_clear ();
+      selection_clear (true);
 
 #ifdef USE_XIM
       im_destroy ();
@@ -273,6 +274,7 @@ rxvt_term::~rxvt_term ()
     free (allocated [i]);
 
   free (selection.text);
+  free (selection.clip_text);
   // TODO: manage env vars in child only(!)
   free (env_display);
   free (env_term);
index 6897414..a8cd77c 100644 (file)
@@ -914,6 +914,8 @@ struct selection_t
   row_col_t         beg;        /* beginning of selection   <= mark          */
   row_col_t         mark;       /* point of initial click   <= end           */
   row_col_t         end;        /* one character past end point              */
+  wchar_t          *clip_text;  /* text copied to the clipboard              */
+  unsigned int      clip_len;   /* length of clipboard text                  */
 };
 
 /* ------------------------------------------------------------------------- */
@@ -1046,7 +1048,8 @@ struct rxvt_term : zero_initialized, rxvt_vars, rxvt_screen
   Atom            *xa;
 /* ---------- */
   Time            selection_time,
-                  selection_request_time;
+                  selection_request_time,
+                  clipboard_time;
   pid_t           cmd_pid;    /* process id of child */
   char *          incr_buf;
   size_t          incr_buf_size, incr_buf_fill;
@@ -1453,9 +1456,10 @@ struct rxvt_term : zero_initialized, rxvt_vars, rxvt_screen
   void selection_property (Window win, Atom prop) NOTHROW;
   void selection_request (Time tm, int selnum = Sel_Primary) NOTHROW;
   int selection_request_other (Atom target, int selnum) NOTHROW;
-  void selection_clear () NOTHROW;
+  void selection_clear (bool clipboard = false) NOTHROW;
+  void clipboard_copy (Time tm);
   void selection_make (Time tm);
-  bool selection_grab (Time tm) NOTHROW;
+  bool selection_grab (Time tm, bool clipboard = false) NOTHROW;
   void selection_start_colrow (int col, int row) NOTHROW;
   void selection_delimit_word (enum page_dirn dirn, const row_col_t *mark, row_col_t *ret) NOTHROW;
   void selection_extend_colrow (int32_t col, int32_t row, int button3, int buttonpress, int clickchange) NOTHROW;
index af2dfd9..dc2e555 100644 (file)
@@ -1596,7 +1596,10 @@ rxvt_term::selection_screen (int screen = -1)
         RETVAL
 
 void
-rxvt_term::selection_clear ()
+rxvt_term::selection_clear (bool clipboard = false)
+
+void
+rxvt_term::clipboard_copy (Time eventtime)
 
 void
 rxvt_term::selection_make (Time eventtime, bool rect = false)
@@ -1606,7 +1609,7 @@ rxvt_term::selection_make (Time eventtime, bool rect = false)
         THIS->selection_make (eventtime);
 
 int
-rxvt_term::selection_grab (Time eventtime)
+rxvt_term::selection_grab (Time eventtime, bool clipboard = false)
 
 void
 rxvt_term::selection (SV *newtext = 0)
index 4fb4ef9..6f999f3 100644 (file)
@@ -299,6 +299,7 @@ rxvt_screen::clear ()
 rxvt_display::rxvt_display (const char *id)
 : refcounted (id)
 , selection_owner (0)
+, clipboard_owner (0)
 {
   x_ev    .set<rxvt_display, &rxvt_display::x_cb    > (this);
   flush_ev.set<rxvt_display, &rxvt_display::flush_cb> (this);
@@ -602,17 +603,17 @@ void rxvt_display::unreg (xevent_watcher *w)
     }
 }
 
-void rxvt_display::set_selection_owner (rxvt_term *owner)
+void rxvt_display::set_selection_owner (rxvt_term *owner, bool clipboard)
 {
-  if (selection_owner && selection_owner != owner)
-    {
-      rxvt_term *owner = selection_owner;
+  rxvt_term * &cur_owner = !clipboard ? selection_owner : clipboard_owner;
 
-      owner->selection_clear ();
-      owner->flush ();
+  if (cur_owner && cur_owner != owner)
+    {
+      cur_owner->selection_clear (clipboard);
+      cur_owner->flush ();
     }
 
-  selection_owner = owner;
+  cur_owner = owner;
 }
 
 #ifdef USE_XIM
index 8b87e98..4f91564 100644 (file)
@@ -237,6 +237,7 @@ struct rxvt_display : refcounted
   int       screen;
   Window    root;
   rxvt_term *selection_owner;
+  rxvt_term *clipboard_owner;
   Atom      xa[NUM_XA];
   bool      is_local;
 #ifdef POINTER_BLANK
@@ -255,7 +256,7 @@ struct rxvt_display : refcounted
   }
 
   Atom atom (const char *name);
-  void set_selection_owner (rxvt_term *owner);
+  void set_selection_owner (rxvt_term *owner, bool clipboard);
 
   void reg (xevent_watcher *w);
   void unreg (xevent_watcher *w);
index 83717e9..0b9ddf0 100644 (file)
@@ -233,6 +233,8 @@ rxvt_term::scr_reset ()
       selection.op = SELECTION_CLEAR;
       selection.screen = PRIMARY;
       selection.clicks = 0;
+      selection.clip_text = NULL;
+      selection.clip_len = 0;
     }
   else
     {
@@ -2946,16 +2948,42 @@ rxvt_term::selection_request_other (Atom target, int selnum) NOTHROW
  * EXT: SelectionClear
  */
 void
-rxvt_term::selection_clear () NOTHROW
+rxvt_term::selection_clear (bool clipboard) NOTHROW
 {
-  want_refresh = 1;
-  free (selection.text);
-  selection.text = NULL;
-  selection.len = 0;
-  CLEAR_SELECTION ();
+  if (!clipboard)
+    {
+      want_refresh = 1;
+      free (selection.text);
+      selection.text = NULL;
+      selection.len = 0;
+      CLEAR_SELECTION ();
 
-  if (display->selection_owner == this)
-    display->selection_owner = 0;
+      if (display->selection_owner == this)
+        display->selection_owner = 0;
+    }
+  else
+    {
+      free (selection.clip_text);
+      selection.clip_text = NULL;
+      selection.clip_len = 0;
+
+      if (display->clipboard_owner == this)
+        display->clipboard_owner = 0;
+    }
+}
+
+void
+rxvt_term::clipboard_copy (Time tm)
+{
+  if (selection.len > 0)
+    {
+      free (selection.clip_text);
+      selection.clip_len = selection.len;
+      selection.clip_text = (wchar_t *) malloc (sizeof (wchar_t) * selection.clip_len);
+      memcpy (selection.clip_text, selection.text,
+              sizeof (wchar_t) * selection.clip_len);
+      selection_grab (tm, true);
+    }
 }
 
 /* ------------------------------------------------------------------------- */
@@ -3091,19 +3119,30 @@ rxvt_term::selection_make (Time tm)
 }
 
 bool
-rxvt_term::selection_grab (Time tm) NOTHROW
+rxvt_term::selection_grab (Time tm, bool clipboard) NOTHROW
 {
-  selection_time = tm;
+  Atom sel;
 
-  XSetSelectionOwner (dpy, XA_PRIMARY, vt, tm);
-  if (XGetSelectionOwner (dpy, XA_PRIMARY) == vt)
+  if (!clipboard)
+    {
+      selection_time = tm;
+      sel = XA_PRIMARY;
+    }
+  else
     {
-      display->set_selection_owner (this);
+      clipboard_time = tm;
+      sel = xa[XA_CLIPBOARD];
+    }
+
+  XSetSelectionOwner (dpy, sel, vt, tm);
+  if (XGetSelectionOwner (dpy, sel) == vt)
+    {
+      display->set_selection_owner (this, clipboard);
       return true;
     }
   else
     {
-      selection_clear ();
+      selection_clear (clipboard);
       return false;
     }
 
@@ -3608,12 +3647,18 @@ rxvt_term::selection_send (const XSelectionRequestEvent &rq) NOTHROW
       /* TODO: Handle MULTIPLE */
     }
 #endif
-  else if (rq.target == xa[XA_TIMESTAMP] && selection.text)
+  else if (rq.target == xa[XA_TIMESTAMP] && rq.selection == XA_PRIMARY && selection.text)
     {
       XChangeProperty (dpy, rq.requestor, rq.property, rq.target,
                        32, PropModeReplace, (unsigned char *)&selection_time, 1);
       ev.property = rq.property;
     }
+  else if (rq.target == xa[XA_TIMESTAMP] && rq.selection == xa[XA_CLIPBOARD] && selection.clip_text)
+    {
+      XChangeProperty (dpy, rq.requestor, rq.property, rq.target,
+                       32, PropModeReplace, (unsigned char *)&clipboard_time, 1);
+      ev.property = rq.property;
+    }
   else if (rq.target == XA_STRING
            || rq.target == xa[XA_TEXT]
            || rq.target == xa[XA_COMPOUND_TEXT]
@@ -3654,11 +3699,16 @@ rxvt_term::selection_send (const XSelectionRequestEvent &rq) NOTHROW
           style = enc_compound_text;
         }
 
-      if (selection.text)
+      if (rq.selection == XA_PRIMARY && selection.text)
         {
           cl = selection.text;
           selectlen = selection.len;
         }
+      else if (rq.selection == xa[XA_CLIPBOARD] && selection.clip_text)
+        {
+          cl = selection.clip_text;
+          selectlen = selection.clip_len;
+        }
       else
         {
           cl = L"";