From: Po Lu Date: Wed, 24 Nov 2021 12:48:01 +0000 (+0000) Subject: Make `yank-media' work on Haiku X-Git-Tag: emacs-29.0.90~2852^2~72 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=fc35928ec2b3be40ff7323515f948fc82ca487ca;p=emacs.git Make `yank-media' work on Haiku 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. --- diff --git a/lisp/term/haiku-win.el b/lisp/term/haiku-win.el index 36af10d2c70..7861cfb9003 100644 --- a/lisp/term/haiku-win.el +++ b/lisp/term/haiku-win.el @@ -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)) diff --git a/src/haiku_select.cc b/src/haiku_select.cc index 8d345ca6617..6cd6ee879e5 100644 --- a/src/haiku_select.cc +++ b/src/haiku_select.cc @@ -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) { diff --git a/src/haikuselect.c b/src/haikuselect.c index 3f0441e0779..38cceb1de74 100644 --- a/src/haikuselect.c +++ b/src/haikuselect.c @@ -24,6 +24,46 @@ along with GNU Emacs. If not, see . */ #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); } diff --git a/src/haikuselect.h b/src/haikuselect.h index 542d550d64e..1a3a945f98d 100644 --- a/src/haikuselect.h +++ b/src/haikuselect.h @@ -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);