diff options
| author | Po Lu | 2022-03-23 14:15:22 +0000 |
|---|---|---|
| committer | Po Lu | 2022-03-23 14:16:15 +0000 |
| commit | 7fa5d6c87d43926008c15a7f7ddc924bbf8d2e76 (patch) | |
| tree | 10291262a55f8d78e81c7e1f2d98b754cbe4cc71 /src | |
| parent | 36810a8164db12766f532f268f322afe1e601b6a (diff) | |
| download | emacs-7fa5d6c87d43926008c15a7f7ddc924bbf8d2e76.tar.gz emacs-7fa5d6c87d43926008c15a7f7ddc924bbf8d2e76.zip | |
Improvements to Haiku selection handling
* lisp/term/haiku-win.el (haiku-selection-targets): Implement in Lisp.
* src/haiku_select.cc (be_get_message_type):
(be_set_message_type):
(be_get_message_message):
(be_add_message_message): New functions.
* src/haiku_support.cc (MessageReceived): Fix typo.
* src/haikuselect.c (haiku_selection_data_1)
(Fhaiku_selection_targets): Delete functions.
(haiku_message_to_lisp, lisp_to_type_code)
(haiku_lisp_to_message): Correctly decode and encode nested
messages, and fix encoding specially decoded types via numeric
names. Also store and decode message types inside Lisp
messages.
(Fhaiku_drag_message): Update doc string.
(syms_of_haikuselect): Update subrs.
* src/haikuselect.h: Update prototypes.
Diffstat (limited to 'src')
| -rw-r--r-- | src/haiku_select.cc | 48 | ||||
| -rw-r--r-- | src/haiku_support.cc | 2 | ||||
| -rw-r--r-- | src/haikuselect.c | 127 | ||||
| -rw-r--r-- | src/haikuselect.h | 6 |
4 files changed, 139 insertions, 44 deletions
diff --git a/src/haiku_select.cc b/src/haiku_select.cc index bccc79da018..373ad321c4b 100644 --- a/src/haiku_select.cc +++ b/src/haiku_select.cc | |||
| @@ -330,6 +330,41 @@ be_get_message_data (void *message, const char *name, | |||
| 330 | index, buf_return, size_return) != B_OK; | 330 | index, buf_return, size_return) != B_OK; |
| 331 | } | 331 | } |
| 332 | 332 | ||
| 333 | uint32 | ||
| 334 | be_get_message_type (void *message) | ||
| 335 | { | ||
| 336 | BMessage *msg = (BMessage *) message; | ||
| 337 | |||
| 338 | return msg->what; | ||
| 339 | } | ||
| 340 | |||
| 341 | void | ||
| 342 | be_set_message_type (void *message, uint32 what) | ||
| 343 | { | ||
| 344 | BMessage *msg = (BMessage *) message; | ||
| 345 | |||
| 346 | msg->what = what; | ||
| 347 | } | ||
| 348 | |||
| 349 | void * | ||
| 350 | be_get_message_message (void *message, const char *name, | ||
| 351 | int32 index) | ||
| 352 | { | ||
| 353 | BMessage *msg = (BMessage *) message; | ||
| 354 | BMessage *out = new (std::nothrow) BMessage; | ||
| 355 | |||
| 356 | if (!out) | ||
| 357 | return NULL; | ||
| 358 | |||
| 359 | if (msg->FindMessage (name, index, out) != B_OK) | ||
| 360 | { | ||
| 361 | delete out; | ||
| 362 | return NULL; | ||
| 363 | } | ||
| 364 | |||
| 365 | return out; | ||
| 366 | } | ||
| 367 | |||
| 333 | void * | 368 | void * |
| 334 | be_create_simple_message (void) | 369 | be_create_simple_message (void) |
| 335 | { | 370 | { |
| @@ -364,6 +399,19 @@ be_add_refs_data (void *message, const char *name, | |||
| 364 | } | 399 | } |
| 365 | 400 | ||
| 366 | int | 401 | int |
| 402 | be_add_message_message (void *message, const char *name, | ||
| 403 | void *data) | ||
| 404 | { | ||
| 405 | BMessage *msg = (BMessage *) message; | ||
| 406 | BMessage *data_message = (BMessage *) data; | ||
| 407 | |||
| 408 | if (msg->AddMessage (name, data_message) != B_OK) | ||
| 409 | return 1; | ||
| 410 | |||
| 411 | return 0; | ||
| 412 | } | ||
| 413 | |||
| 414 | int | ||
| 367 | be_lock_clipboard_message (enum haiku_clipboard clipboard, | 415 | be_lock_clipboard_message (enum haiku_clipboard clipboard, |
| 368 | void **message_return) | 416 | void **message_return) |
| 369 | { | 417 | { |
diff --git a/src/haiku_support.cc b/src/haiku_support.cc index 3ded7a80f4d..24009c0ef6a 100644 --- a/src/haiku_support.cc +++ b/src/haiku_support.cc | |||
| @@ -726,7 +726,7 @@ public: | |||
| 726 | this->ConvertFromScreen (&whereto); | 726 | this->ConvertFromScreen (&whereto); |
| 727 | 727 | ||
| 728 | rq.window = this; | 728 | rq.window = this; |
| 729 | rq.message = DetachCurrentMessage ();; | 729 | rq.message = DetachCurrentMessage (); |
| 730 | rq.x = whereto.x; | 730 | rq.x = whereto.x; |
| 731 | rq.y = whereto.y; | 731 | rq.y = whereto.y; |
| 732 | 732 | ||
diff --git a/src/haikuselect.c b/src/haikuselect.c index d59b4512a46..5540f467c0d 100644 --- a/src/haikuselect.c +++ b/src/haikuselect.c | |||
| @@ -27,46 +27,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 27 | 27 | ||
| 28 | #include <stdlib.h> | 28 | #include <stdlib.h> |
| 29 | 29 | ||
| 30 | static Lisp_Object | ||
| 31 | haiku_selection_data_1 (Lisp_Object clipboard) | ||
| 32 | { | ||
| 33 | Lisp_Object result = Qnil; | ||
| 34 | char *targets[256]; | ||
| 35 | |||
| 36 | block_input (); | ||
| 37 | if (EQ (clipboard, QPRIMARY)) | ||
| 38 | BClipboard_primary_targets ((char **) &targets, 256); | ||
| 39 | else if (EQ (clipboard, QSECONDARY)) | ||
| 40 | BClipboard_secondary_targets ((char **) &targets, 256); | ||
| 41 | else if (EQ (clipboard, QCLIPBOARD)) | ||
| 42 | BClipboard_system_targets ((char **) &targets, 256); | ||
| 43 | else | ||
| 44 | { | ||
| 45 | unblock_input (); | ||
| 46 | signal_error ("Bad clipboard", clipboard); | ||
| 47 | } | ||
| 48 | |||
| 49 | for (int i = 0; targets[i]; ++i) | ||
| 50 | { | ||
| 51 | result = Fcons (build_unibyte_string (targets[i]), | ||
| 52 | result); | ||
| 53 | free (targets[i]); | ||
| 54 | } | ||
| 55 | unblock_input (); | ||
| 56 | |||
| 57 | return result; | ||
| 58 | } | ||
| 59 | |||
| 60 | DEFUN ("haiku-selection-targets", Fhaiku_selection_targets, | ||
| 61 | Shaiku_selection_targets, 1, 1, 0, | ||
| 62 | doc: /* Find the types of data available from CLIPBOARD. | ||
| 63 | CLIPBOARD should be the symbol `PRIMARY', `SECONDARY' or `CLIPBOARD'. | ||
| 64 | Return the available types as a list of strings. */) | ||
| 65 | (Lisp_Object clipboard) | ||
| 66 | { | ||
| 67 | return haiku_selection_data_1 (clipboard); | ||
| 68 | } | ||
| 69 | |||
| 70 | DEFUN ("haiku-selection-data", Fhaiku_selection_data, Shaiku_selection_data, | 30 | DEFUN ("haiku-selection-data", Fhaiku_selection_data, Shaiku_selection_data, |
| 71 | 2, 2, 0, | 31 | 2, 2, 0, |
| 72 | doc: /* Retrieve content typed as NAME from the clipboard | 32 | doc: /* Retrieve content typed as NAME from the clipboard |
| @@ -225,7 +185,11 @@ same as `SECONDARY'. */) | |||
| 225 | DATA is a 16-bit signed integer. If TYPE is `long', then DATA is a | 185 | DATA is a 16-bit signed integer. If TYPE is `long', then DATA is a |
| 226 | 32-bit signed integer. If TYPE is `llong', then DATA is a 64-bit | 186 | 32-bit signed integer. If TYPE is `llong', then DATA is a 64-bit |
| 227 | signed integer. If TYPE is `byte' or `char', then DATA is an 8-bit | 187 | signed integer. If TYPE is `byte' or `char', then DATA is an 8-bit |
| 228 | signed integer. If TYPE is `bool', then DATA is a boolean. */ | 188 | signed integer. If TYPE is `bool', then DATA is a boolean. |
| 189 | |||
| 190 | If the field name is not a string but the symbol `type', then it | ||
| 191 | associates to a 32-bit unsigned integer describing the type of the | ||
| 192 | system message. */ | ||
| 229 | Lisp_Object | 193 | Lisp_Object |
| 230 | haiku_message_to_lisp (void *message) | 194 | haiku_message_to_lisp (void *message) |
| 231 | { | 195 | { |
| @@ -236,6 +200,7 @@ haiku_message_to_lisp (void *message) | |||
| 236 | ssize_t buf_size; | 200 | ssize_t buf_size; |
| 237 | int32 i, j, count, type_code; | 201 | int32 i, j, count, type_code; |
| 238 | int rc; | 202 | int rc; |
| 203 | void *msg; | ||
| 239 | 204 | ||
| 240 | for (i = 0; !be_enum_message (message, &type_code, i, | 205 | for (i = 0; !be_enum_message (message, &type_code, i, |
| 241 | &count, &name); ++i) | 206 | &count, &name); ++i) |
| @@ -252,6 +217,15 @@ haiku_message_to_lisp (void *message) | |||
| 252 | 217 | ||
| 253 | switch (type_code) | 218 | switch (type_code) |
| 254 | { | 219 | { |
| 220 | case 'MSGG': | ||
| 221 | msg = be_get_message_message (message, name, j); | ||
| 222 | if (!msg) | ||
| 223 | memory_full (SIZE_MAX); | ||
| 224 | t1 = haiku_message_to_lisp (msg); | ||
| 225 | BMessage_delete (msg); | ||
| 226 | |||
| 227 | break; | ||
| 228 | |||
| 255 | case 'BOOL': | 229 | case 'BOOL': |
| 256 | t1 = (*(bool *) buf) ? Qt : Qnil; | 230 | t1 = (*(bool *) buf) ? Qt : Qnil; |
| 257 | break; | 231 | break; |
| @@ -335,6 +309,10 @@ haiku_message_to_lisp (void *message) | |||
| 335 | t2 = Qbool; | 309 | t2 = Qbool; |
| 336 | break; | 310 | break; |
| 337 | 311 | ||
| 312 | case 'MSGG': | ||
| 313 | t2 = Qmessage; | ||
| 314 | break; | ||
| 315 | |||
| 338 | default: | 316 | default: |
| 339 | t2 = make_int (type_code); | 317 | t2 = make_int (type_code); |
| 340 | } | 318 | } |
| @@ -343,7 +321,8 @@ haiku_message_to_lisp (void *message) | |||
| 343 | list = Fcons (Fcons (build_string_from_utf8 (name), tem), list); | 321 | list = Fcons (Fcons (build_string_from_utf8 (name), tem), list); |
| 344 | } | 322 | } |
| 345 | 323 | ||
| 346 | return list; | 324 | tem = Fcons (Qtype, make_uint (be_get_message_type (message))); |
| 325 | return Fcons (tem, list); | ||
| 347 | } | 326 | } |
| 348 | 327 | ||
| 349 | static int32 | 328 | static int32 |
| @@ -371,6 +350,8 @@ lisp_to_type_code (Lisp_Object obj) | |||
| 371 | return 'CHAR'; | 350 | return 'CHAR'; |
| 372 | else if (EQ (obj, Qbool)) | 351 | else if (EQ (obj, Qbool)) |
| 373 | return 'BOOL'; | 352 | return 'BOOL'; |
| 353 | else if (EQ (obj, Qmessage)) | ||
| 354 | return 'MSGG'; | ||
| 374 | else | 355 | else |
| 375 | return -1; | 356 | return -1; |
| 376 | } | 357 | } |
| @@ -384,8 +365,11 @@ haiku_lisp_to_message (Lisp_Object obj, void *message) | |||
| 384 | int64 llong_data; | 365 | int64 llong_data; |
| 385 | int8 char_data; | 366 | int8 char_data; |
| 386 | bool bool_data; | 367 | bool bool_data; |
| 368 | void *msg_data; | ||
| 387 | intmax_t t4; | 369 | intmax_t t4; |
| 370 | uintmax_t t5; | ||
| 388 | int rc; | 371 | int rc; |
| 372 | specpdl_ref ref; | ||
| 389 | 373 | ||
| 390 | CHECK_LIST (obj); | 374 | CHECK_LIST (obj); |
| 391 | for (tem = obj; CONSP (tem); tem = XCDR (tem)) | 375 | for (tem = obj; CONSP (tem); tem = XCDR (tem)) |
| @@ -395,6 +379,35 @@ haiku_lisp_to_message (Lisp_Object obj, void *message) | |||
| 395 | CHECK_CONS (t1); | 379 | CHECK_CONS (t1); |
| 396 | 380 | ||
| 397 | name = XCAR (t1); | 381 | name = XCAR (t1); |
| 382 | |||
| 383 | if (EQ (name, Qtype)) | ||
| 384 | { | ||
| 385 | t2 = XCDR (t1); | ||
| 386 | |||
| 387 | if (BIGNUMP (t2)) | ||
| 388 | { | ||
| 389 | t5 = bignum_to_uintmax (t2); | ||
| 390 | |||
| 391 | if (!t5 || t5 > TYPE_MAXIMUM (uint32)) | ||
| 392 | signal_error ("Value too large", t2); | ||
| 393 | |||
| 394 | block_input (); | ||
| 395 | be_set_message_type (message, t5); | ||
| 396 | unblock_input (); | ||
| 397 | } | ||
| 398 | else | ||
| 399 | { | ||
| 400 | if (!TYPE_RANGED_FIXNUMP (uint32, t2)) | ||
| 401 | signal_error ("Invalid data type", t2); | ||
| 402 | |||
| 403 | block_input (); | ||
| 404 | be_set_message_type (message, XFIXNAT (t2)); | ||
| 405 | unblock_input (); | ||
| 406 | } | ||
| 407 | |||
| 408 | continue; | ||
| 409 | } | ||
| 410 | |||
| 398 | CHECK_STRING (name); | 411 | CHECK_STRING (name); |
| 399 | 412 | ||
| 400 | t1 = XCDR (t1); | 413 | t1 = XCDR (t1); |
| @@ -412,8 +425,30 @@ haiku_lisp_to_message (Lisp_Object obj, void *message) | |||
| 412 | maybe_quit (); | 425 | maybe_quit (); |
| 413 | data = XCAR (t2); | 426 | data = XCAR (t2); |
| 414 | 427 | ||
| 428 | if (FIXNUMP (type_sym) || BIGNUMP (type_sym)) | ||
| 429 | goto decode_normally; | ||
| 430 | |||
| 415 | switch (type_code) | 431 | switch (type_code) |
| 416 | { | 432 | { |
| 433 | case 'MSGG': | ||
| 434 | ref = SPECPDL_INDEX (); | ||
| 435 | |||
| 436 | block_input (); | ||
| 437 | msg_data = be_create_simple_message (); | ||
| 438 | unblock_input (); | ||
| 439 | |||
| 440 | record_unwind_protect_ptr (BMessage_delete, msg_data); | ||
| 441 | haiku_lisp_to_message (data, msg_data); | ||
| 442 | |||
| 443 | block_input (); | ||
| 444 | rc = be_add_message_message (message, SSDATA (name), msg_data); | ||
| 445 | unblock_input (); | ||
| 446 | |||
| 447 | if (rc) | ||
| 448 | signal_error ("Invalid message", msg_data); | ||
| 449 | unbind_to (ref, Qnil); | ||
| 450 | break; | ||
| 451 | |||
| 417 | case 'RREF': | 452 | case 'RREF': |
| 418 | CHECK_STRING (data); | 453 | CHECK_STRING (data); |
| 419 | 454 | ||
| @@ -525,6 +560,7 @@ haiku_lisp_to_message (Lisp_Object obj, void *message) | |||
| 525 | break; | 560 | break; |
| 526 | 561 | ||
| 527 | default: | 562 | default: |
| 563 | decode_normally: | ||
| 528 | CHECK_STRING (data); | 564 | CHECK_STRING (data); |
| 529 | 565 | ||
| 530 | block_input (); | 566 | block_input (); |
| @@ -565,6 +601,10 @@ signed integer. If TYPE is `llong', then DATA is a 64-bit signed | |||
| 565 | integer. If TYPE is `byte' or `char', then DATA is an 8-bit signed | 601 | integer. If TYPE is `byte' or `char', then DATA is an 8-bit signed |
| 566 | integer. If TYPE is `bool', then DATA is a boolean. | 602 | integer. If TYPE is `bool', then DATA is a boolean. |
| 567 | 603 | ||
| 604 | If the field name is not a string but the symbol `type', then it | ||
| 605 | associates to a 32-bit unsigned integer describing the type of the | ||
| 606 | system message. | ||
| 607 | |||
| 568 | FRAME is a window system frame that must be visible, from which the | 608 | FRAME is a window system frame that must be visible, from which the |
| 569 | drag will originate. */) | 609 | drag will originate. */) |
| 570 | (Lisp_Object frame, Lisp_Object message) | 610 | (Lisp_Object frame, Lisp_Object message) |
| @@ -605,6 +645,7 @@ syms_of_haikuselect (void) | |||
| 605 | DEFSYM (QUTF8_STRING, "UTF8_STRING"); | 645 | DEFSYM (QUTF8_STRING, "UTF8_STRING"); |
| 606 | DEFSYM (Qforeign_selection, "foreign-selection"); | 646 | DEFSYM (Qforeign_selection, "foreign-selection"); |
| 607 | DEFSYM (QTARGETS, "TARGETS"); | 647 | DEFSYM (QTARGETS, "TARGETS"); |
| 648 | DEFSYM (Qmessage, "message"); | ||
| 608 | DEFSYM (Qstring, "string"); | 649 | DEFSYM (Qstring, "string"); |
| 609 | DEFSYM (Qref, "ref"); | 650 | DEFSYM (Qref, "ref"); |
| 610 | DEFSYM (Qshort, "short"); | 651 | DEFSYM (Qshort, "short"); |
| @@ -613,10 +654,10 @@ syms_of_haikuselect (void) | |||
| 613 | DEFSYM (Qbyte, "byte"); | 654 | DEFSYM (Qbyte, "byte"); |
| 614 | DEFSYM (Qchar, "char"); | 655 | DEFSYM (Qchar, "char"); |
| 615 | DEFSYM (Qbool, "bool"); | 656 | DEFSYM (Qbool, "bool"); |
| 657 | DEFSYM (Qtype, "type"); | ||
| 616 | 658 | ||
| 617 | defsubr (&Shaiku_selection_data); | 659 | defsubr (&Shaiku_selection_data); |
| 618 | defsubr (&Shaiku_selection_put); | 660 | defsubr (&Shaiku_selection_put); |
| 619 | defsubr (&Shaiku_selection_targets); | ||
| 620 | defsubr (&Shaiku_selection_owner_p); | 661 | defsubr (&Shaiku_selection_owner_p); |
| 621 | defsubr (&Shaiku_drag_message); | 662 | defsubr (&Shaiku_drag_message); |
| 622 | } | 663 | } |
diff --git a/src/haikuselect.h b/src/haikuselect.h index 42789949182..01e4ca327da 100644 --- a/src/haikuselect.h +++ b/src/haikuselect.h | |||
| @@ -94,12 +94,18 @@ extern "C" | |||
| 94 | ssize_t *size_return); | 94 | ssize_t *size_return); |
| 95 | extern int be_get_refs_data (void *message, const char *name, | 95 | extern int be_get_refs_data (void *message, const char *name, |
| 96 | int32 index, char **path_buffer); | 96 | int32 index, char **path_buffer); |
| 97 | extern uint32 be_get_message_type (void *message); | ||
| 98 | extern void be_set_message_type (void *message, uint32 what); | ||
| 99 | extern void *be_get_message_message (void *message, const char *name, | ||
| 100 | int32 index); | ||
| 97 | extern void *be_create_simple_message (void); | 101 | extern void *be_create_simple_message (void); |
| 98 | extern int be_add_message_data (void *message, const char *name, | 102 | extern int be_add_message_data (void *message, const char *name, |
| 99 | int32 type_code, const void *buf, | 103 | int32 type_code, const void *buf, |
| 100 | ssize_t buf_size); | 104 | ssize_t buf_size); |
| 101 | extern int be_add_refs_data (void *message, const char *name, | 105 | extern int be_add_refs_data (void *message, const char *name, |
| 102 | const char *filename); | 106 | const char *filename); |
| 107 | extern int be_add_message_message (void *message, const char *name, | ||
| 108 | void *data); | ||
| 103 | extern int be_lock_clipboard_message (enum haiku_clipboard clipboard, | 109 | extern int be_lock_clipboard_message (enum haiku_clipboard clipboard, |
| 104 | void **message_return); | 110 | void **message_return); |
| 105 | extern void be_unlock_clipboard (enum haiku_clipboard clipboard); | 111 | extern void be_unlock_clipboard (enum haiku_clipboard clipboard); |