diff options
| author | Po Lu | 2022-03-23 08:17:49 +0000 |
|---|---|---|
| committer | Po Lu | 2022-03-23 08:20:14 +0000 |
| commit | fed9a353dbe79a7a6acc74c1e223c46e7541e627 (patch) | |
| tree | 83d46eebdbdaf2cd612a1ba50cb069f8a03452be | |
| parent | 5f8a3ca9af70af926b284c98c3995e0743256721 (diff) | |
| download | emacs-fed9a353dbe79a7a6acc74c1e223c46e7541e627.tar.gz emacs-fed9a353dbe79a7a6acc74c1e223c46e7541e627.zip | |
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.
| -rw-r--r-- | src/haiku_select.cc | 47 | ||||
| -rw-r--r-- | src/haikuselect.c | 85 | ||||
| -rw-r--r-- | 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) | |||
| 64 | if (len) | 64 | if (len) |
| 65 | *len = bt; | 65 | *len = bt; |
| 66 | 66 | ||
| 67 | cb->Unlock (); | 67 | void *data = malloc (bt); |
| 68 | |||
| 69 | if (!data) | ||
| 70 | { | ||
| 71 | cb->Unlock (); | ||
| 72 | return NULL; | ||
| 73 | } | ||
| 68 | 74 | ||
| 69 | return strndup (ptr, bt); | 75 | memcpy (data, ptr, bt); |
| 76 | cb->Unlock (); | ||
| 77 | return (char *) data; | ||
| 70 | } | 78 | } |
| 71 | 79 | ||
| 72 | static void | 80 | static void |
| @@ -354,3 +362,38 @@ be_add_refs_data (void *message, const char *name, | |||
| 354 | 362 | ||
| 355 | return msg->AddRef (name, &ref) != B_OK; | 363 | return msg->AddRef (name, &ref) != B_OK; |
| 356 | } | 364 | } |
| 365 | |||
| 366 | int | ||
| 367 | be_lock_clipboard_message (enum haiku_clipboard clipboard, | ||
| 368 | void **message_return) | ||
| 369 | { | ||
| 370 | BClipboard *board; | ||
| 371 | |||
| 372 | if (clipboard == CLIPBOARD_PRIMARY) | ||
| 373 | board = primary; | ||
| 374 | else if (clipboard == CLIPBOARD_SECONDARY) | ||
| 375 | board = secondary; | ||
| 376 | else | ||
| 377 | board = system_clipboard; | ||
| 378 | |||
| 379 | if (!board->Lock ()) | ||
| 380 | return 1; | ||
| 381 | |||
| 382 | *message_return = board->Data (); | ||
| 383 | return 0; | ||
| 384 | } | ||
| 385 | |||
| 386 | void | ||
| 387 | be_unlock_clipboard (enum haiku_clipboard clipboard) | ||
| 388 | { | ||
| 389 | BClipboard *board; | ||
| 390 | |||
| 391 | if (clipboard == CLIPBOARD_PRIMARY) | ||
| 392 | board = primary; | ||
| 393 | else if (clipboard == CLIPBOARD_SECONDARY) | ||
| 394 | board = secondary; | ||
| 395 | else | ||
| 396 | board = system_clipboard; | ||
| 397 | |||
| 398 | board->Unlock (); | ||
| 399 | } | ||
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, | |||
| 71 | 2, 2, 0, | 71 | 2, 2, 0, |
| 72 | doc: /* Retrieve content typed as NAME from the clipboard | 72 | doc: /* Retrieve content typed as NAME from the clipboard |
| 73 | CLIPBOARD. CLIPBOARD is the symbol `PRIMARY', `SECONDARY' or | 73 | CLIPBOARD. CLIPBOARD is the symbol `PRIMARY', `SECONDARY' or |
| 74 | `CLIPBOARD'. NAME is a MIME type denoting the type of the data to | 74 | `CLIPBOARD'. NAME is a string describing the MIME type denoting the |
| 75 | fetch. */) | 75 | type of the data to fetch. If NAME is nil, then the entire contents |
| 76 | of the clipboard will be returned instead, as a serialized system | ||
| 77 | message in the format accepted by `haiku-drag-message', which see. */) | ||
| 76 | (Lisp_Object clipboard, Lisp_Object name) | 78 | (Lisp_Object clipboard, Lisp_Object name) |
| 77 | { | 79 | { |
| 78 | CHECK_SYMBOL (clipboard); | ||
| 79 | CHECK_STRING (name); | ||
| 80 | char *dat; | 80 | char *dat; |
| 81 | ssize_t len; | 81 | ssize_t len; |
| 82 | Lisp_Object str; | ||
| 83 | void *message; | ||
| 84 | enum haiku_clipboard clipboard_name; | ||
| 85 | int rc; | ||
| 82 | 86 | ||
| 83 | block_input (); | 87 | CHECK_SYMBOL (clipboard); |
| 84 | if (EQ (clipboard, QPRIMARY)) | 88 | |
| 85 | dat = BClipboard_find_primary_selection_data (SSDATA (name), &len); | 89 | if (!EQ (clipboard, QPRIMARY) && !EQ (clipboard, QSECONDARY) |
| 86 | else if (EQ (clipboard, QSECONDARY)) | 90 | && !EQ (clipboard, QCLIPBOARD)) |
| 87 | dat = BClipboard_find_secondary_selection_data (SSDATA (name), &len); | 91 | signal_error ("Invalid clipboard", clipboard); |
| 88 | else if (EQ (clipboard, QCLIPBOARD)) | 92 | |
| 89 | dat = BClipboard_find_system_data (SSDATA (name), &len); | 93 | if (!NILP (name)) |
| 90 | else | ||
| 91 | { | 94 | { |
| 95 | CHECK_STRING (name); | ||
| 96 | |||
| 97 | block_input (); | ||
| 98 | if (EQ (clipboard, QPRIMARY)) | ||
| 99 | dat = BClipboard_find_primary_selection_data (SSDATA (name), &len); | ||
| 100 | else if (EQ (clipboard, QSECONDARY)) | ||
| 101 | dat = BClipboard_find_secondary_selection_data (SSDATA (name), &len); | ||
| 102 | else | ||
| 103 | dat = BClipboard_find_system_data (SSDATA (name), &len); | ||
| 92 | unblock_input (); | 104 | unblock_input (); |
| 93 | signal_error ("Bad clipboard", clipboard); | ||
| 94 | } | ||
| 95 | unblock_input (); | ||
| 96 | 105 | ||
| 97 | if (!dat) | 106 | if (!dat) |
| 98 | return Qnil; | 107 | return Qnil; |
| 99 | 108 | ||
| 100 | Lisp_Object str = make_unibyte_string (dat, len); | 109 | str = make_unibyte_string (dat, len); |
| 101 | 110 | ||
| 102 | /* `foreign-selection' just means that the selection has to be | 111 | /* `foreign-selection' just means that the selection has to be |
| 103 | decoded by `gui-get-selection'. It has no other meaning, | 112 | decoded by `gui-get-selection'. It has no other meaning, |
| 104 | AFAICT. */ | 113 | AFAICT. */ |
| 105 | Fput_text_property (make_fixnum (0), make_fixnum (len), | 114 | Fput_text_property (make_fixnum (0), make_fixnum (len), |
| 106 | Qforeign_selection, Qt, str); | 115 | Qforeign_selection, Qt, str); |
| 107 | 116 | ||
| 108 | block_input (); | 117 | block_input (); |
| 109 | BClipboard_free_data (dat); | 118 | BClipboard_free_data (dat); |
| 110 | unblock_input (); | 119 | unblock_input (); |
| 120 | } | ||
| 121 | else | ||
| 122 | { | ||
| 123 | if (EQ (clipboard, QPRIMARY)) | ||
| 124 | clipboard_name = CLIPBOARD_PRIMARY; | ||
| 125 | else if (EQ (clipboard, QSECONDARY)) | ||
| 126 | clipboard_name = CLIPBOARD_SECONDARY; | ||
| 127 | else | ||
| 128 | clipboard_name = CLIPBOARD_CLIPBOARD; | ||
| 129 | |||
| 130 | block_input (); | ||
| 131 | rc = be_lock_clipboard_message (clipboard_name, &message); | ||
| 132 | unblock_input (); | ||
| 133 | |||
| 134 | if (rc) | ||
| 135 | signal_error ("Couldn't open clipboard", clipboard); | ||
| 136 | |||
| 137 | block_input (); | ||
| 138 | str = haiku_message_to_lisp (message); | ||
| 139 | be_unlock_clipboard (clipboard_name); | ||
| 140 | unblock_input (); | ||
| 141 | } | ||
| 111 | 142 | ||
| 112 | return str; | 143 | return str; |
| 113 | } | 144 | } |
| @@ -359,6 +390,7 @@ haiku_lisp_to_message (Lisp_Object obj, void *message) | |||
| 359 | CHECK_LIST (obj); | 390 | CHECK_LIST (obj); |
| 360 | for (tem = obj; CONSP (tem); tem = XCDR (tem)) | 391 | for (tem = obj; CONSP (tem); tem = XCDR (tem)) |
| 361 | { | 392 | { |
| 393 | maybe_quit (); | ||
| 362 | t1 = XCAR (tem); | 394 | t1 = XCAR (tem); |
| 363 | CHECK_CONS (t1); | 395 | CHECK_CONS (t1); |
| 364 | 396 | ||
| @@ -377,6 +409,7 @@ haiku_lisp_to_message (Lisp_Object obj, void *message) | |||
| 377 | CHECK_LIST (t1); | 409 | CHECK_LIST (t1); |
| 378 | for (t2 = XCDR (t1); CONSP (t2); t2 = XCDR (t2)) | 410 | for (t2 = XCDR (t1); CONSP (t2); t2 = XCDR (t2)) |
| 379 | { | 411 | { |
| 412 | maybe_quit (); | ||
| 380 | data = XCAR (t2); | 413 | data = XCAR (t2); |
| 381 | 414 | ||
| 382 | switch (type_code) | 415 | 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 <https://www.gnu.org/licenses/>. */ | |||
| 25 | 25 | ||
| 26 | #include <SupportDefs.h> | 26 | #include <SupportDefs.h> |
| 27 | 27 | ||
| 28 | enum haiku_clipboard | ||
| 29 | { | ||
| 30 | CLIPBOARD_PRIMARY, | ||
| 31 | CLIPBOARD_SECONDARY, | ||
| 32 | CLIPBOARD_CLIPBOARD | ||
| 33 | }; | ||
| 34 | |||
| 28 | #ifdef __cplusplus | 35 | #ifdef __cplusplus |
| 29 | #include <stdio.h> | 36 | #include <stdio.h> |
| 30 | extern "C" | 37 | extern "C" |
| @@ -93,6 +100,9 @@ extern "C" | |||
| 93 | ssize_t buf_size); | 100 | ssize_t buf_size); |
| 94 | extern int be_add_refs_data (void *message, const char *name, | 101 | extern int be_add_refs_data (void *message, const char *name, |
| 95 | const char *filename); | 102 | const char *filename); |
| 103 | extern int be_lock_clipboard_message (enum haiku_clipboard clipboard, | ||
| 104 | void **message_return); | ||
| 105 | extern void be_unlock_clipboard (enum haiku_clipboard clipboard); | ||
| 96 | #ifdef __cplusplus | 106 | #ifdef __cplusplus |
| 97 | }; | 107 | }; |
| 98 | #endif | 108 | #endif |