From fed9a353dbe79a7a6acc74c1e223c46e7541e627 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Wed, 23 Mar 2022 08:17:49 +0000 Subject: [PATCH] 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 9012639d6af..bccc79da018 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 5a90fe37d22..d59b4512a46 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 4869d9d33c2..42789949182 100644 --- a/src/haikuselect.h +++ b/src/haikuselect.h @@ -25,6 +25,13 @@ along with GNU Emacs. If not, see . */ #include +enum haiku_clipboard + { + CLIPBOARD_PRIMARY, + CLIPBOARD_SECONDARY, + CLIPBOARD_CLIPBOARD + }; + #ifdef __cplusplus #include 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 -- 2.39.5