aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPo Lu2022-03-23 14:15:22 +0000
committerPo Lu2022-03-23 14:16:15 +0000
commit7fa5d6c87d43926008c15a7f7ddc924bbf8d2e76 (patch)
tree10291262a55f8d78e81c7e1f2d98b754cbe4cc71 /src
parent36810a8164db12766f532f268f322afe1e601b6a (diff)
downloademacs-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.cc48
-rw-r--r--src/haiku_support.cc2
-rw-r--r--src/haikuselect.c127
-rw-r--r--src/haikuselect.h6
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
333uint32
334be_get_message_type (void *message)
335{
336 BMessage *msg = (BMessage *) message;
337
338 return msg->what;
339}
340
341void
342be_set_message_type (void *message, uint32 what)
343{
344 BMessage *msg = (BMessage *) message;
345
346 msg->what = what;
347}
348
349void *
350be_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
333void * 368void *
334be_create_simple_message (void) 369be_create_simple_message (void)
335{ 370{
@@ -364,6 +399,19 @@ be_add_refs_data (void *message, const char *name,
364} 399}
365 400
366int 401int
402be_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
414int
367be_lock_clipboard_message (enum haiku_clipboard clipboard, 415be_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
30static Lisp_Object
31haiku_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
60DEFUN ("haiku-selection-targets", Fhaiku_selection_targets,
61 Shaiku_selection_targets, 1, 1, 0,
62 doc: /* Find the types of data available from CLIPBOARD.
63CLIPBOARD should be the symbol `PRIMARY', `SECONDARY' or `CLIPBOARD'.
64Return the available types as a list of strings. */)
65 (Lisp_Object clipboard)
66{
67 return haiku_selection_data_1 (clipboard);
68}
69
70DEFUN ("haiku-selection-data", Fhaiku_selection_data, Shaiku_selection_data, 30DEFUN ("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. */
229Lisp_Object 193Lisp_Object
230haiku_message_to_lisp (void *message) 194haiku_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
349static int32 328static 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
565integer. If TYPE is `byte' or `char', then DATA is an 8-bit signed 601integer. If TYPE is `byte' or `char', then DATA is an 8-bit signed
566integer. If TYPE is `bool', then DATA is a boolean. 602integer. If TYPE is `bool', then DATA is a boolean.
567 603
604If the field name is not a string but the symbol `type', then it
605associates to a 32-bit unsigned integer describing the type of the
606system message.
607
568FRAME is a window system frame that must be visible, from which the 608FRAME is a window system frame that must be visible, from which the
569drag will originate. */) 609drag 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);