]> git.eshelyaron.com Git - emacs.git/commitdiff
Make `yank-media' work on Haiku
authorPo Lu <luangruo@yahoo.com>
Wed, 24 Nov 2021 12:48:01 +0000 (12:48 +0000)
committerPo Lu <luangruo@yahoo.com>
Wed, 24 Nov 2021 12:58:39 +0000 (12:58 +0000)
This works with what WebPositive does with images, at least.  I don't
know about other programs, but Haiku doesn't seem to standardize this
very well.

* lisp/term/haiku-win.el (haiku--selection-type-to-mime): Handle
regular symbols.
(gui-backend-get-selection): Handle special type `TARGETS'.
(gui-backend-set-selection): Always clear clipboard.

* src/haiku_select.cc (BClipboard_get_targets): New function.
(BClipboard_set_data): New argument `clear'.  All callers
changed.
(BClipboard_set_system_data)
(BClipboard_set_primary_selection_data)
(BClipboard_set_secondary_selection_data): New argument `clear'.

(BClipboard_system_targets, BClipboard_primary_targets)
(BClipboard_secondary_targets): New functions.

* src/haikuselect.c (haiku_selection_data_1): New function.
(Fhaiku_selection_targets): New function.
(Fhaiku_selection_put): Allow controlling if the clipboard is
cleared.
(syms_of_haikuselect): New symbols and subrs.

* src/haikuselect.h (BClipboard_set_system_data)
(BClipboard_set_primary_selection_data)
(BClipboard_set_secondary_selection_data): New argument `clear'.

(BClipboard_system_targets, BClipboard_primary_targets)
(BClipboard_secondary_targets): New functions.

lisp/term/haiku-win.el
src/haiku_select.cc
src/haikuselect.c
src/haikuselect.h

index 36af10d2c70bd21438162b742bbd61e1bb40ce56..7861cfb9003f2082a0c1ab7b627080442ea928ac 100644 (file)
@@ -86,15 +86,19 @@ If TYPE is nil, return \"text/plain\"."
   (cond
    ((memq type '(TEXT COMPOUND_TEXT STRING UTF8_STRING)) "text/plain")
    ((stringp type) type)
+   ((symbolp type) (symbol-name type))
    (t "text/plain")))
 
 (cl-defmethod gui-backend-get-selection (type data-type
                                               &context (window-system haiku))
-  (haiku-selection-data type (haiku--selection-type-to-mime data-type)))
+  (if (eq data-type 'TARGETS)
+      (apply #'vector (mapcar #'intern
+                              (haiku-selection-targets type)))
+    (haiku-selection-data type (haiku--selection-type-to-mime data-type))))
 
 (cl-defmethod gui-backend-set-selection (type value
                                               &context (window-system haiku))
-  (haiku-selection-put type "text/plain" value))
+  (haiku-selection-put type "text/plain" value t))
 
 (cl-defmethod gui-backend-selection-exists-p (selection
                                               &context (window-system haiku))
index 8d345ca661760baf3f5d4979fac30afbab246cd7..6cd6ee879e53e900f74dba0dccba6f5cd88bc7f0 100644 (file)
@@ -63,13 +63,63 @@ BClipboard_find_data (BClipboard *cb, const char *type, ssize_t *len)
   return strndup (ptr, bt);
 }
 
+static void
+BClipboard_get_targets (BClipboard *cb, char **buf, int buf_size)
+{
+  BMessage *data;
+  char *name;
+  int32 count_found;
+  type_code type;
+  int32 i;
+  int index;
+
+  if (!cb->Lock ())
+    {
+      buf[0] = NULL;
+      return;
+    }
+
+  data = cb->Data ();
+  index = 0;
+
+  if (!data)
+    {
+      buf[0] = NULL;
+      cb->Unlock ();
+      return;
+    }
+
+  for (i = 0; (data->GetInfo (B_ANY_TYPE, i, &name,
+                            &type, &count_found)
+              == B_OK); ++i)
+    {
+      if (type == B_MIME_TYPE)
+       {
+         if (index < (buf_size - 1))
+           {
+             buf[index++] = strdup (name);
+
+             if (!buf[index - 1])
+               break;
+           }
+       }
+    }
+
+  buf[index] = NULL;
+
+  cb->Unlock ();
+}
+
 static void
 BClipboard_set_data (BClipboard *cb, const char *type, const char *dat,
-                    ssize_t len)
+                    ssize_t len, bool clear)
 {
   if (!cb->Lock ())
     return;
-  cb->Clear ();
+
+  if (clear)
+    cb->Clear ();
+
   BMessage *mdat = cb->Data ();
   if (!mdat)
     {
@@ -78,7 +128,13 @@ BClipboard_set_data (BClipboard *cb, const char *type, const char *dat,
     }
 
   if (dat)
-    mdat->AddData (type, B_MIME_TYPE, dat, len);
+    {
+      if (mdat->ReplaceData (type, B_MIME_TYPE, dat, len)
+         == B_NAME_NOT_FOUND)
+       mdat->AddData (type, B_MIME_TYPE, dat, len);
+    }
+  else
+    mdat->RemoveName (type);
   cb->Commit ();
   cb->Unlock ();
 }
@@ -112,32 +168,32 @@ BClipboard_find_secondary_selection_data (const char *type, ssize_t *len)
 
 void
 BClipboard_set_system_data (const char *type, const char *data,
-                           ssize_t len)
+                           ssize_t len, bool clear)
 {
   if (!system_clipboard)
     return;
 
-  BClipboard_set_data (system_clipboard, type, data, len);
+  BClipboard_set_data (system_clipboard, type, data, len, clear);
 }
 
 void
 BClipboard_set_primary_selection_data (const char *type, const char *data,
-                                      ssize_t len)
+                                      ssize_t len, bool clear)
 {
   if (!primary)
     return;
 
-  BClipboard_set_data (primary, type, data, len);
+  BClipboard_set_data (primary, type, data, len, clear);
 }
 
 void
 BClipboard_set_secondary_selection_data (const char *type, const char *data,
-                                        ssize_t len)
+                                        ssize_t len, bool clear)
 {
   if (!secondary)
     return;
 
-  BClipboard_set_data (secondary, type, data, len);
+  BClipboard_set_data (secondary, type, data, len, clear);
 }
 
 void
@@ -146,6 +202,24 @@ BClipboard_free_data (void *ptr)
   std::free (ptr);
 }
 
+void
+BClipboard_system_targets (char **buf, int len)
+{
+  BClipboard_get_targets (system_clipboard, buf, len);
+}
+
+void
+BClipboard_primary_targets (char **buf, int len)
+{
+  BClipboard_get_targets (primary, buf, len);
+}
+
+void
+BClipboard_secondary_targets (char **buf, int len)
+{
+  BClipboard_get_targets (secondary, buf, len);
+}
+
 void
 init_haiku_select (void)
 {
index 3f0441e077962c21789913b65edbdb987b687ed6..38cceb1de7444f15407a98fb7cc93184d8108318 100644 (file)
@@ -24,6 +24,46 @@ along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
 #include "haikuselect.h"
 #include "haikuterm.h"
 
+static Lisp_Object
+haiku_selection_data_1 (Lisp_Object clipboard)
+{
+  Lisp_Object result = Qnil;
+  char *targets[256];
+
+  block_input ();
+  if (EQ (clipboard, QPRIMARY))
+    BClipboard_primary_targets ((char **) &targets, 256);
+  else if (EQ (clipboard, QSECONDARY))
+    BClipboard_secondary_targets ((char **) &targets, 256);
+  else if (EQ (clipboard, QCLIPBOARD))
+    BClipboard_system_targets ((char **) &targets, 256);
+  else
+    {
+      unblock_input ();
+      signal_error ("Bad clipboard", clipboard);
+    }
+
+  for (int i = 0; targets[i]; ++i)
+    {
+      result = Fcons (build_unibyte_string (targets[i]),
+                     result);
+      free (targets[i]);
+    }
+  unblock_input ();
+
+  return result;
+}
+
+DEFUN ("haiku-selection-targets", Fhaiku_selection_targets,
+       Shaiku_selection_targets, 1, 1, 0,
+       doc: /* Find the types of data available from CLIPBOARD.
+CLIPBOARD should be the symbol `PRIMARY', `SECONDARY' or `CLIPBOARD'.
+Return the available types as a list of strings.  */)
+  (Lisp_Object clipboard)
+{
+  return haiku_selection_data_1 (clipboard);
+}
+
 DEFUN ("haiku-selection-data", Fhaiku_selection_data, Shaiku_selection_data,
        2, 2, 0,
        doc: /* Retrieve content typed as NAME from the clipboard
@@ -78,15 +118,17 @@ fetch.  */)
 }
 
 DEFUN ("haiku-selection-put", Fhaiku_selection_put, Shaiku_selection_put,
-       3, 3, 0,
+       3, 4, 0,
        doc: /* Add or remove content from the clipboard CLIPBOARD.
 CLIPBOARD is the symbol `PRIMARY', `SECONDARY' or `CLIPBOARD'.  NAME
 is a MIME type denoting the type of the data to add.  DATA is the
 string that will be placed in the clipboard, or nil if the content is
-to be removed.  If NAME is the string `text/utf-8' or the string
-`text/plain', encode it as UTF-8 before storing it into the
+to be removed.  If NAME is the string "text/utf-8" or the string
+"text/plain", encode it as UTF-8 before storing it into the clipboard.
+CLEAR, if non-nil, means to erase all the previous contents of the
 clipboard.  */)
-  (Lisp_Object clipboard, Lisp_Object name, Lisp_Object data)
+  (Lisp_Object clipboard, Lisp_Object name, Lisp_Object data,
+   Lisp_Object clear)
 {
   CHECK_SYMBOL (clipboard);
   CHECK_STRING (name);
@@ -105,11 +147,13 @@ clipboard.  */)
   ptrdiff_t len = !NILP (data) ? SBYTES (data) : 0;
 
   if (EQ (clipboard, QPRIMARY))
-    BClipboard_set_primary_selection_data (SSDATA (name), dat, len);
+    BClipboard_set_primary_selection_data (SSDATA (name), dat, len,
+                                          !NILP (clear));
   else if (EQ (clipboard, QSECONDARY))
-    BClipboard_set_secondary_selection_data (SSDATA (name), dat, len);
+    BClipboard_set_secondary_selection_data (SSDATA (name), dat, len,
+                                            !NILP (clear));
   else if (EQ (clipboard, QCLIPBOARD))
-    BClipboard_set_system_data (SSDATA (name), dat, len);
+    BClipboard_set_system_data (SSDATA (name), dat, len, !NILP (clear));
   else
     {
       unblock_input ();
@@ -128,7 +172,9 @@ syms_of_haikuselect (void)
   DEFSYM (QSTRING, "STRING");
   DEFSYM (QUTF8_STRING, "UTF8_STRING");
   DEFSYM (Qforeign_selection, "foreign-selection");
+  DEFSYM (QTARGETS, "TARGETS");
 
   defsubr (&Shaiku_selection_data);
   defsubr (&Shaiku_selection_put);
+  defsubr (&Shaiku_selection_targets);
 }
index 542d550d64ebb37dced3dec75b50d0207c39473e..1a3a945f98d570bcd34bec5e5c4193d1be06911b 100644 (file)
@@ -46,15 +46,25 @@ extern "C"
   BClipboard_find_secondary_selection_data (const char *type, ssize_t *len);
 
   extern void
-  BClipboard_set_system_data (const char *type, const char *data, ssize_t len);
+  BClipboard_set_system_data (const char *type, const char *data, ssize_t len,
+                             bool clear);
 
   extern void
   BClipboard_set_primary_selection_data (const char *type, const char *data,
-                                        ssize_t len);
+                                        ssize_t len, bool clear);
 
   extern void
   BClipboard_set_secondary_selection_data (const char *type, const char *data,
-                                          ssize_t len);
+                                          ssize_t len, bool clear);
+
+  extern void
+  BClipboard_system_targets (char **buf, int len);
+
+  extern void
+  BClipboard_primary_targets (char **buf, int len);
+
+  extern void
+  BClipboard_secondary_targets (char **buf, int len);
 
   /* Free the returned data.  */
   extern void BClipboard_free_data (void *ptr);