emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master fed9a353db: Allow retrieving some more kinds of clipboard data on


From: Po Lu
Subject: master fed9a353db: Allow retrieving some more kinds of clipboard data on Haiku
Date: Wed, 23 Mar 2022 04:21:30 -0400 (EDT)

branch: master
commit fed9a353dbe79a7a6acc74c1e223c46e7541e627
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    Allow retrieving some more kinds of clipboard data on Haiku
    
    * src/haiku_select.cc (BClipboard_find_data): Handle NULL
    characters inside data correctly.
    (be_lock_clipboard_message, be_unlock_clipboard): New functions.
    * src/haikuselect.c (Fhaiku_selection_data): Return entire
    clipboard contents as a message when clipboard is NULL.
    (haiku_lisp_to_message): Allow quitting when iterating through
    potentially large or circular lists.
    * src/haikuselect.h (enum haiku_clipboard): New enum.
---
 src/haiku_select.cc | 47 +++++++++++++++++++++++++++--
 src/haikuselect.c   | 85 +++++++++++++++++++++++++++++++++++++----------------
 src/haikuselect.h   | 10 +++++++
 3 files changed, 114 insertions(+), 28 deletions(-)

diff --git a/src/haiku_select.cc b/src/haiku_select.cc
index 9012639d6a..bccc79da01 100644
--- a/src/haiku_select.cc
+++ b/src/haiku_select.cc
@@ -64,9 +64,17 @@ BClipboard_find_data (BClipboard *cb, const char *type, 
ssize_t *len)
   if (len)
     *len = bt;
 
-  cb->Unlock ();
+  void *data = malloc (bt);
+
+  if (!data)
+    {
+      cb->Unlock ();
+      return NULL;
+    }
 
-  return strndup (ptr, bt);
+  memcpy (data, ptr, bt);
+  cb->Unlock ();
+  return (char *) data;
 }
 
 static void
@@ -354,3 +362,38 @@ be_add_refs_data (void *message, const char *name,
 
   return msg->AddRef (name, &ref) != B_OK;
 }
+
+int
+be_lock_clipboard_message (enum haiku_clipboard clipboard,
+                          void **message_return)
+{
+  BClipboard *board;
+
+  if (clipboard == CLIPBOARD_PRIMARY)
+    board = primary;
+  else if (clipboard == CLIPBOARD_SECONDARY)
+    board = secondary;
+  else
+    board = system_clipboard;
+
+  if (!board->Lock ())
+    return 1;
+
+  *message_return = board->Data ();
+  return 0;
+}
+
+void
+be_unlock_clipboard (enum haiku_clipboard clipboard)
+{
+  BClipboard *board;
+
+  if (clipboard == CLIPBOARD_PRIMARY)
+    board = primary;
+  else if (clipboard == CLIPBOARD_SECONDARY)
+    board = secondary;
+  else
+    board = system_clipboard;
+
+  board->Unlock ();
+}
diff --git a/src/haikuselect.c b/src/haikuselect.c
index 5a90fe37d2..d59b4512a4 100644
--- a/src/haikuselect.c
+++ b/src/haikuselect.c
@@ -71,43 +71,74 @@ DEFUN ("haiku-selection-data", Fhaiku_selection_data, 
Shaiku_selection_data,
        2, 2, 0,
        doc: /* Retrieve content typed as NAME from the clipboard
 CLIPBOARD.  CLIPBOARD is the symbol `PRIMARY', `SECONDARY' or
-`CLIPBOARD'.  NAME is a MIME type denoting the type of the data to
-fetch.  */)
+`CLIPBOARD'.  NAME is a string describing the MIME type denoting the
+type of the data to fetch.  If NAME is nil, then the entire contents
+of the clipboard will be returned instead, as a serialized system
+message in the format accepted by `haiku-drag-message', which see.  */)
   (Lisp_Object clipboard, Lisp_Object name)
 {
-  CHECK_SYMBOL (clipboard);
-  CHECK_STRING (name);
   char *dat;
   ssize_t len;
+  Lisp_Object str;
+  void *message;
+  enum haiku_clipboard clipboard_name;
+  int rc;
 
-  block_input ();
-  if (EQ (clipboard, QPRIMARY))
-    dat = BClipboard_find_primary_selection_data (SSDATA (name), &len);
-  else if (EQ (clipboard, QSECONDARY))
-    dat = BClipboard_find_secondary_selection_data (SSDATA (name), &len);
-  else if (EQ (clipboard, QCLIPBOARD))
-    dat = BClipboard_find_system_data (SSDATA (name), &len);
-  else
+  CHECK_SYMBOL (clipboard);
+
+  if (!EQ (clipboard, QPRIMARY) && !EQ (clipboard, QSECONDARY)
+      && !EQ (clipboard, QCLIPBOARD))
+    signal_error ("Invalid clipboard", clipboard);
+
+  if (!NILP (name))
     {
+      CHECK_STRING (name);
+
+      block_input ();
+      if (EQ (clipboard, QPRIMARY))
+       dat = BClipboard_find_primary_selection_data (SSDATA (name), &len);
+      else if (EQ (clipboard, QSECONDARY))
+       dat = BClipboard_find_secondary_selection_data (SSDATA (name), &len);
+      else
+       dat = BClipboard_find_system_data (SSDATA (name), &len);
       unblock_input ();
-      signal_error ("Bad clipboard", clipboard);
-    }
-  unblock_input ();
 
-  if (!dat)
-    return Qnil;
+      if (!dat)
+       return Qnil;
 
-  Lisp_Object str = make_unibyte_string (dat, len);
+      str = make_unibyte_string (dat, len);
 
-  /* `foreign-selection' just means that the selection has to be
-     decoded by `gui-get-selection'.  It has no other meaning,
-     AFAICT.  */
-  Fput_text_property (make_fixnum (0), make_fixnum (len),
-                     Qforeign_selection, Qt, str);
+      /* `foreign-selection' just means that the selection has to be
+        decoded by `gui-get-selection'.  It has no other meaning,
+        AFAICT.  */
+      Fput_text_property (make_fixnum (0), make_fixnum (len),
+                         Qforeign_selection, Qt, str);
 
-  block_input ();
-  BClipboard_free_data (dat);
-  unblock_input ();
+      block_input ();
+      BClipboard_free_data (dat);
+      unblock_input ();
+    }
+  else
+    {
+      if (EQ (clipboard, QPRIMARY))
+       clipboard_name = CLIPBOARD_PRIMARY;
+      else if (EQ (clipboard, QSECONDARY))
+       clipboard_name = CLIPBOARD_SECONDARY;
+      else
+       clipboard_name = CLIPBOARD_CLIPBOARD;
+
+      block_input ();
+      rc = be_lock_clipboard_message (clipboard_name, &message);
+      unblock_input ();
+
+      if (rc)
+       signal_error ("Couldn't open clipboard", clipboard);
+
+      block_input ();
+      str = haiku_message_to_lisp (message);
+      be_unlock_clipboard (clipboard_name);
+      unblock_input ();
+    }
 
   return str;
 }
@@ -359,6 +390,7 @@ haiku_lisp_to_message (Lisp_Object obj, void *message)
   CHECK_LIST (obj);
   for (tem = obj; CONSP (tem); tem = XCDR (tem))
     {
+      maybe_quit ();
       t1 = XCAR (tem);
       CHECK_CONS (t1);
 
@@ -377,6 +409,7 @@ haiku_lisp_to_message (Lisp_Object obj, void *message)
       CHECK_LIST (t1);
       for (t2 = XCDR (t1); CONSP (t2); t2 = XCDR (t2))
        {
+         maybe_quit ();
          data = XCAR (t2);
 
          switch (type_code)
diff --git a/src/haikuselect.h b/src/haikuselect.h
index 4869d9d33c..4278994918 100644
--- a/src/haikuselect.h
+++ b/src/haikuselect.h
@@ -25,6 +25,13 @@ along with GNU Emacs.  If not, see 
<https://www.gnu.org/licenses/>.  */
 
 #include <SupportDefs.h>
 
+enum haiku_clipboard
+  {
+    CLIPBOARD_PRIMARY,
+    CLIPBOARD_SECONDARY,
+    CLIPBOARD_CLIPBOARD
+  };
+
 #ifdef __cplusplus
 #include <stdio.h>
 extern "C"
@@ -93,6 +100,9 @@ extern "C"
                                  ssize_t buf_size);
   extern int be_add_refs_data (void *message, const char *name,
                               const char *filename);
+  extern int be_lock_clipboard_message (enum haiku_clipboard clipboard,
+                                       void **message_return);
+  extern void be_unlock_clipboard (enum haiku_clipboard clipboard);
 #ifdef __cplusplus
 };
 #endif



reply via email to

[Prev in Thread] Current Thread [Next in Thread]