diff options
Diffstat (limited to 'src/xselect.c')
| -rw-r--r-- | src/xselect.c | 439 |
1 files changed, 271 insertions, 168 deletions
diff --git a/src/xselect.c b/src/xselect.c index 7f4e0b40f62..173cf78bdaa 100644 --- a/src/xselect.c +++ b/src/xselect.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* X Selection processing for Emacs. | 1 | /* X Selection processing for Emacs. |
| 2 | Copyright (C) 1993-1997, 2000-2011 Free Software Foundation, Inc. | 2 | Copyright (C) 1993-1997, 2000-2012 Free Software Foundation, Inc. |
| 3 | 3 | ||
| 4 | This file is part of GNU Emacs. | 4 | This file is part of GNU Emacs. |
| 5 | 5 | ||
| @@ -66,22 +66,15 @@ static Lisp_Object wait_for_property_change_unwind (Lisp_Object); | |||
| 66 | static void wait_for_property_change (struct prop_location *); | 66 | static void wait_for_property_change (struct prop_location *); |
| 67 | static Lisp_Object x_get_foreign_selection (Lisp_Object, Lisp_Object, | 67 | static Lisp_Object x_get_foreign_selection (Lisp_Object, Lisp_Object, |
| 68 | Lisp_Object, Lisp_Object); | 68 | Lisp_Object, Lisp_Object); |
| 69 | static void x_get_window_property (Display *, Window, Atom, | ||
| 70 | unsigned char **, int *, | ||
| 71 | Atom *, int *, unsigned long *, int); | ||
| 72 | static void receive_incremental_selection (Display *, Window, Atom, | ||
| 73 | Lisp_Object, unsigned, | ||
| 74 | unsigned char **, int *, | ||
| 75 | Atom *, int *, unsigned long *); | ||
| 76 | static Lisp_Object x_get_window_property_as_lisp_data (Display *, | 69 | static Lisp_Object x_get_window_property_as_lisp_data (Display *, |
| 77 | Window, Atom, | 70 | Window, Atom, |
| 78 | Lisp_Object, Atom); | 71 | Lisp_Object, Atom); |
| 79 | static Lisp_Object selection_data_to_lisp_data (Display *, | 72 | static Lisp_Object selection_data_to_lisp_data (Display *, |
| 80 | const unsigned char *, | 73 | const unsigned char *, |
| 81 | int, Atom, int); | 74 | ptrdiff_t, Atom, int); |
| 82 | static void lisp_data_to_selection_data (Display *, Lisp_Object, | 75 | static void lisp_data_to_selection_data (Display *, Lisp_Object, |
| 83 | unsigned char **, Atom *, | 76 | unsigned char **, Atom *, |
| 84 | unsigned *, int *, int *); | 77 | ptrdiff_t *, int *, int *); |
| 85 | static Lisp_Object clean_local_selection_data (Lisp_Object); | 78 | static Lisp_Object clean_local_selection_data (Lisp_Object); |
| 86 | 79 | ||
| 87 | /* Printing traces to stderr. */ | 80 | /* Printing traces to stderr. */ |
| @@ -112,16 +105,42 @@ static Lisp_Object QUTF8_STRING; /* This is a type of selection. */ | |||
| 112 | static Lisp_Object Qcompound_text_with_extensions; | 105 | static Lisp_Object Qcompound_text_with_extensions; |
| 113 | 106 | ||
| 114 | static Lisp_Object Qforeign_selection; | 107 | static Lisp_Object Qforeign_selection; |
| 108 | static Lisp_Object Qx_lost_selection_functions, Qx_sent_selection_functions; | ||
| 109 | |||
| 110 | /* Bytes needed to represent 'long' data. This is as per libX11; it | ||
| 111 | is not necessarily sizeof (long). */ | ||
| 112 | #define X_LONG_SIZE 4 | ||
| 113 | |||
| 114 | /* Extreme 'short' and 'long' values suitable for libX11. */ | ||
| 115 | #define X_SHRT_MAX 0x7fff | ||
| 116 | #define X_SHRT_MIN (-1 - X_SHRT_MAX) | ||
| 117 | #define X_LONG_MAX 0x7fffffff | ||
| 118 | #define X_LONG_MIN (-1 - X_LONG_MAX) | ||
| 119 | #define X_ULONG_MAX 0xffffffffUL | ||
| 115 | 120 | ||
| 116 | /* If this is a smaller number than the max-request-size of the display, | 121 | /* If this is a smaller number than the max-request-size of the display, |
| 117 | emacs will use INCR selection transfer when the selection is larger | 122 | emacs will use INCR selection transfer when the selection is larger |
| 118 | than this. The max-request-size is usually around 64k, so if you want | 123 | than this. The max-request-size is usually around 64k, so if you want |
| 119 | emacs to use incremental selection transfers when the selection is | 124 | emacs to use incremental selection transfers when the selection is |
| 120 | smaller than that, set this. I added this mostly for debugging the | 125 | smaller than that, set this. I added this mostly for debugging the |
| 121 | incremental transfer stuff, but it might improve server performance. */ | 126 | incremental transfer stuff, but it might improve server performance. |
| 122 | #define MAX_SELECTION_QUANTUM 0xFFFFFF | ||
| 123 | 127 | ||
| 124 | #define SELECTION_QUANTUM(dpy) ((XMaxRequestSize(dpy) << 2) - 100) | 128 | This value cannot exceed INT_MAX / max (X_LONG_SIZE, sizeof (long)) |
| 129 | because it is multiplied by X_LONG_SIZE and by sizeof (long) in | ||
| 130 | subscript calculations. Similarly for PTRDIFF_MAX - 1 or SIZE_MAX | ||
| 131 | - 1 in place of INT_MAX. */ | ||
| 132 | #define MAX_SELECTION_QUANTUM \ | ||
| 133 | ((int) min (0xFFFFFF, (min (INT_MAX, min (PTRDIFF_MAX, SIZE_MAX) - 1) \ | ||
| 134 | / max (X_LONG_SIZE, sizeof (long))))) | ||
| 135 | |||
| 136 | static int | ||
| 137 | selection_quantum (Display *display) | ||
| 138 | { | ||
| 139 | long mrs = XMaxRequestSize (display); | ||
| 140 | return (mrs < MAX_SELECTION_QUANTUM / X_LONG_SIZE + 25 | ||
| 141 | ? (mrs - 25) * X_LONG_SIZE | ||
| 142 | : MAX_SELECTION_QUANTUM); | ||
| 143 | } | ||
| 125 | 144 | ||
| 126 | #define LOCAL_SELECTION(selection_symbol,dpyinfo) \ | 145 | #define LOCAL_SELECTION(selection_symbol,dpyinfo) \ |
| 127 | assq_no_quit (selection_symbol, dpyinfo->terminal->Vselection_alist) | 146 | assq_no_quit (selection_symbol, dpyinfo->terminal->Vselection_alist) |
| @@ -360,7 +379,8 @@ x_own_selection (Lisp_Object selection_name, Lisp_Object selection_value, | |||
| 360 | 379 | ||
| 361 | /* Given a selection-name and desired type, look up our local copy of | 380 | /* Given a selection-name and desired type, look up our local copy of |
| 362 | the selection value and convert it to the type. | 381 | the selection value and convert it to the type. |
| 363 | The value is nil or a string. | 382 | Return nil, a string, a vector, a symbol, an integer, or a cons |
| 383 | that CONS_TO_INTEGER could plausibly handle. | ||
| 364 | This function is used both for remote requests (LOCAL_REQUEST is zero) | 384 | This function is used both for remote requests (LOCAL_REQUEST is zero) |
| 365 | and for local x-get-selection-internal (LOCAL_REQUEST is nonzero). | 385 | and for local x-get-selection-internal (LOCAL_REQUEST is nonzero). |
| 366 | 386 | ||
| @@ -476,7 +496,7 @@ static struct x_display_info *selection_request_dpyinfo; | |||
| 476 | struct selection_data | 496 | struct selection_data |
| 477 | { | 497 | { |
| 478 | unsigned char *data; | 498 | unsigned char *data; |
| 479 | unsigned int size; | 499 | ptrdiff_t size; |
| 480 | int format; | 500 | int format; |
| 481 | Atom type; | 501 | Atom type; |
| 482 | int nofree; | 502 | int nofree; |
| @@ -496,7 +516,7 @@ static struct selection_data *converted_selections; | |||
| 496 | static Atom conversion_fail_tag; | 516 | static Atom conversion_fail_tag; |
| 497 | 517 | ||
| 498 | /* Used as an unwind-protect clause so that, if a selection-converter signals | 518 | /* Used as an unwind-protect clause so that, if a selection-converter signals |
| 499 | an error, we tell the requester that we were unable to do what they wanted | 519 | an error, we tell the requestor that we were unable to do what they wanted |
| 500 | before we throw to top-level or go into the debugger or whatever. */ | 520 | before we throw to top-level or go into the debugger or whatever. */ |
| 501 | 521 | ||
| 502 | static Lisp_Object | 522 | static Lisp_Object |
| @@ -574,20 +594,18 @@ static int x_reply_selection_request_cnt; | |||
| 574 | #endif /* TRACE_SELECTION */ | 594 | #endif /* TRACE_SELECTION */ |
| 575 | 595 | ||
| 576 | static void | 596 | static void |
| 577 | x_reply_selection_request (struct input_event *event, struct x_display_info *dpyinfo) | 597 | x_reply_selection_request (struct input_event *event, |
| 598 | struct x_display_info *dpyinfo) | ||
| 578 | { | 599 | { |
| 579 | XEvent reply_base; | 600 | XEvent reply_base; |
| 580 | XSelectionEvent *reply = &(reply_base.xselection); | 601 | XSelectionEvent *reply = &(reply_base.xselection); |
| 581 | Display *display = SELECTION_EVENT_DISPLAY (event); | 602 | Display *display = SELECTION_EVENT_DISPLAY (event); |
| 582 | Window window = SELECTION_EVENT_REQUESTOR (event); | 603 | Window window = SELECTION_EVENT_REQUESTOR (event); |
| 583 | int bytes_remaining; | 604 | ptrdiff_t bytes_remaining; |
| 584 | int max_bytes = SELECTION_QUANTUM (display); | 605 | int max_bytes = selection_quantum (display); |
| 585 | int count = SPECPDL_INDEX (); | 606 | int count = SPECPDL_INDEX (); |
| 586 | struct selection_data *cs; | 607 | struct selection_data *cs; |
| 587 | 608 | ||
| 588 | if (max_bytes > MAX_SELECTION_QUANTUM) | ||
| 589 | max_bytes = MAX_SELECTION_QUANTUM; | ||
| 590 | |||
| 591 | reply->type = SelectionNotify; | 609 | reply->type = SelectionNotify; |
| 592 | reply->display = display; | 610 | reply->display = display; |
| 593 | reply->requestor = window; | 611 | reply->requestor = window; |
| @@ -615,11 +633,12 @@ x_reply_selection_request (struct input_event *event, struct x_display_info *dpy | |||
| 615 | if (cs->property == None) | 633 | if (cs->property == None) |
| 616 | continue; | 634 | continue; |
| 617 | 635 | ||
| 618 | bytes_remaining = cs->size * (cs->format / 8); | 636 | bytes_remaining = cs->size; |
| 637 | bytes_remaining *= cs->format >> 3; | ||
| 619 | if (bytes_remaining <= max_bytes) | 638 | if (bytes_remaining <= max_bytes) |
| 620 | { | 639 | { |
| 621 | /* Send all the data at once, with minimal handshaking. */ | 640 | /* Send all the data at once, with minimal handshaking. */ |
| 622 | TRACE1 ("Sending all %d bytes", bytes_remaining); | 641 | TRACE1 ("Sending all %"pD"d bytes", bytes_remaining); |
| 623 | XChangeProperty (display, window, cs->property, | 642 | XChangeProperty (display, window, cs->property, |
| 624 | cs->type, cs->format, PropModeReplace, | 643 | cs->type, cs->format, PropModeReplace, |
| 625 | cs->data, cs->size); | 644 | cs->data, cs->size); |
| @@ -629,7 +648,7 @@ x_reply_selection_request (struct input_event *event, struct x_display_info *dpy | |||
| 629 | /* Send an INCR tag to initiate incremental transfer. */ | 648 | /* Send an INCR tag to initiate incremental transfer. */ |
| 630 | long value[1]; | 649 | long value[1]; |
| 631 | 650 | ||
| 632 | TRACE2 ("Start sending %d bytes incrementally (%s)", | 651 | TRACE2 ("Start sending %"pD"d bytes incrementally (%s)", |
| 633 | bytes_remaining, XGetAtomName (display, cs->property)); | 652 | bytes_remaining, XGetAtomName (display, cs->property)); |
| 634 | cs->wait_object | 653 | cs->wait_object |
| 635 | = expect_property_change (display, window, cs->property, | 654 | = expect_property_change (display, window, cs->property, |
| @@ -637,7 +656,7 @@ x_reply_selection_request (struct input_event *event, struct x_display_info *dpy | |||
| 637 | 656 | ||
| 638 | /* XChangeProperty expects an array of long even if long is | 657 | /* XChangeProperty expects an array of long even if long is |
| 639 | more than 32 bits. */ | 658 | more than 32 bits. */ |
| 640 | value[0] = bytes_remaining; | 659 | value[0] = min (bytes_remaining, X_LONG_MAX); |
| 641 | XChangeProperty (display, window, cs->property, | 660 | XChangeProperty (display, window, cs->property, |
| 642 | dpyinfo->Xatom_INCR, 32, PropModeReplace, | 661 | dpyinfo->Xatom_INCR, 32, PropModeReplace, |
| 643 | (unsigned char *) value, 1); | 662 | (unsigned char *) value, 1); |
| @@ -671,9 +690,10 @@ x_reply_selection_request (struct input_event *event, struct x_display_info *dpy | |||
| 671 | int had_errors = x_had_errors_p (display); | 690 | int had_errors = x_had_errors_p (display); |
| 672 | UNBLOCK_INPUT; | 691 | UNBLOCK_INPUT; |
| 673 | 692 | ||
| 674 | bytes_remaining = cs->size * format_bytes; | 693 | bytes_remaining = cs->size; |
| 694 | bytes_remaining *= format_bytes; | ||
| 675 | 695 | ||
| 676 | /* Wait for the requester to ack by deleting the property. | 696 | /* Wait for the requestor to ack by deleting the property. |
| 677 | This can run Lisp code (process handlers) or signal. */ | 697 | This can run Lisp code (process handlers) or signal. */ |
| 678 | if (! had_errors) | 698 | if (! had_errors) |
| 679 | { | 699 | { |
| @@ -712,7 +732,7 @@ x_reply_selection_request (struct input_event *event, struct x_display_info *dpy | |||
| 712 | 732 | ||
| 713 | if (had_errors) break; | 733 | if (had_errors) break; |
| 714 | 734 | ||
| 715 | /* Wait for the requester to ack this chunk by deleting | 735 | /* Wait for the requestor to ack this chunk by deleting |
| 716 | the property. This can run Lisp code or signal. */ | 736 | the property. This can run Lisp code or signal. */ |
| 717 | TRACE1 ("Waiting for increment ACK (deletion of %s)", | 737 | TRACE1 ("Waiting for increment ACK (deletion of %s)", |
| 718 | XGetAtomName (display, cs->property)); | 738 | XGetAtomName (display, cs->property)); |
| @@ -720,7 +740,7 @@ x_reply_selection_request (struct input_event *event, struct x_display_info *dpy | |||
| 720 | } | 740 | } |
| 721 | 741 | ||
| 722 | /* Now write a zero-length chunk to the property to tell the | 742 | /* Now write a zero-length chunk to the property to tell the |
| 723 | requester that we're done. */ | 743 | requestor that we're done. */ |
| 724 | BLOCK_INPUT; | 744 | BLOCK_INPUT; |
| 725 | if (! waiting_for_other_props_on_window (display, window)) | 745 | if (! waiting_for_other_props_on_window (display, window)) |
| 726 | XSelectInput (display, window, 0L); | 746 | XSelectInput (display, window, 0L); |
| @@ -737,7 +757,7 @@ x_reply_selection_request (struct input_event *event, struct x_display_info *dpy | |||
| 737 | /* The window we're communicating with may have been deleted | 757 | /* The window we're communicating with may have been deleted |
| 738 | in the meantime (that's a real situation from a bug report). | 758 | in the meantime (that's a real situation from a bug report). |
| 739 | In this case, there may be events in the event queue still | 759 | In this case, there may be events in the event queue still |
| 740 | refering to the deleted window, and we'll get a BadWindow error | 760 | referring to the deleted window, and we'll get a BadWindow error |
| 741 | in XTread_socket when processing the events. I don't have | 761 | in XTread_socket when processing the events. I don't have |
| 742 | an idea how to fix that. gerd, 2001-01-98. */ | 762 | an idea how to fix that. gerd, 2001-01-98. */ |
| 743 | /* 2004-09-10: XSync and UNBLOCK so that possible protocol errors are | 763 | /* 2004-09-10: XSync and UNBLOCK so that possible protocol errors are |
| @@ -809,7 +829,7 @@ x_handle_selection_request (struct input_event *event) | |||
| 809 | non-None property. */ | 829 | non-None property. */ |
| 810 | Window requestor = SELECTION_EVENT_REQUESTOR (event); | 830 | Window requestor = SELECTION_EVENT_REQUESTOR (event); |
| 811 | Lisp_Object multprop; | 831 | Lisp_Object multprop; |
| 812 | int j, nselections; | 832 | ptrdiff_t j, nselections; |
| 813 | 833 | ||
| 814 | if (property == None) goto DONE; | 834 | if (property == None) goto DONE; |
| 815 | multprop | 835 | multprop |
| @@ -855,7 +875,7 @@ x_handle_selection_request (struct input_event *event) | |||
| 855 | && !EQ (Vx_sent_selection_functions, Qunbound)) | 875 | && !EQ (Vx_sent_selection_functions, Qunbound)) |
| 856 | { | 876 | { |
| 857 | Lisp_Object args[4]; | 877 | Lisp_Object args[4]; |
| 858 | args[0] = Vx_sent_selection_functions; | 878 | args[0] = Qx_sent_selection_functions; |
| 859 | args[1] = selection_symbol; | 879 | args[1] = selection_symbol; |
| 860 | args[2] = target_symbol; | 880 | args[2] = target_symbol; |
| 861 | args[3] = success ? Qt : Qnil; | 881 | args[3] = success ? Qt : Qnil; |
| @@ -979,7 +999,7 @@ x_handle_selection_clear (struct input_event *event) | |||
| 979 | /* Run the `x-lost-selection-functions' abnormal hook. */ | 999 | /* Run the `x-lost-selection-functions' abnormal hook. */ |
| 980 | { | 1000 | { |
| 981 | Lisp_Object args[2]; | 1001 | Lisp_Object args[2]; |
| 982 | args[0] = Vx_lost_selection_functions; | 1002 | args[0] = Qx_lost_selection_functions; |
| 983 | args[1] = selection_symbol; | 1003 | args[1] = selection_symbol; |
| 984 | Frun_hook_with_args (2, args); | 1004 | Frun_hook_with_args (2, args); |
| 985 | } | 1005 | } |
| @@ -1020,7 +1040,7 @@ x_clear_frame_selections (FRAME_PTR f) | |||
| 1020 | { | 1040 | { |
| 1021 | /* Run the `x-lost-selection-functions' abnormal hook. */ | 1041 | /* Run the `x-lost-selection-functions' abnormal hook. */ |
| 1022 | Lisp_Object args[2]; | 1042 | Lisp_Object args[2]; |
| 1023 | args[0] = Vx_lost_selection_functions; | 1043 | args[0] = Qx_lost_selection_functions; |
| 1024 | args[1] = Fcar (Fcar (t->Vselection_alist)); | 1044 | args[1] = Fcar (Fcar (t->Vselection_alist)); |
| 1025 | Frun_hook_with_args (2, args); | 1045 | Frun_hook_with_args (2, args); |
| 1026 | 1046 | ||
| @@ -1033,7 +1053,7 @@ x_clear_frame_selections (FRAME_PTR f) | |||
| 1033 | && EQ (frame, XCAR (XCDR (XCDR (XCDR (XCAR (XCDR (rest)))))))) | 1053 | && EQ (frame, XCAR (XCDR (XCDR (XCDR (XCAR (XCDR (rest)))))))) |
| 1034 | { | 1054 | { |
| 1035 | Lisp_Object args[2]; | 1055 | Lisp_Object args[2]; |
| 1036 | args[0] = Vx_lost_selection_functions; | 1056 | args[0] = Qx_lost_selection_functions; |
| 1037 | args[1] = XCAR (XCAR (XCDR (rest))); | 1057 | args[1] = XCAR (XCAR (XCDR (rest))); |
| 1038 | Frun_hook_with_args (2, args); | 1058 | Frun_hook_with_args (2, args); |
| 1039 | XSETCDR (rest, XCDR (XCDR (rest))); | 1059 | XSETCDR (rest, XCDR (XCDR (rest))); |
| @@ -1062,7 +1082,8 @@ waiting_for_other_props_on_window (Display *display, Window window) | |||
| 1062 | this awaited property change. */ | 1082 | this awaited property change. */ |
| 1063 | 1083 | ||
| 1064 | static struct prop_location * | 1084 | static struct prop_location * |
| 1065 | expect_property_change (Display *display, Window window, Atom property, int state) | 1085 | expect_property_change (Display *display, Window window, |
| 1086 | Atom property, int state) | ||
| 1066 | { | 1087 | { |
| 1067 | struct prop_location *pl = (struct prop_location *) xmalloc (sizeof *pl); | 1088 | struct prop_location *pl = (struct prop_location *) xmalloc (sizeof *pl); |
| 1068 | pl->identifier = ++prop_location_identifier; | 1089 | pl->identifier = ++prop_location_identifier; |
| @@ -1268,19 +1289,28 @@ x_get_foreign_selection (Lisp_Object selection_symbol, Lisp_Object target_type, | |||
| 1268 | 1289 | ||
| 1269 | static void | 1290 | static void |
| 1270 | x_get_window_property (Display *display, Window window, Atom property, | 1291 | x_get_window_property (Display *display, Window window, Atom property, |
| 1271 | unsigned char **data_ret, int *bytes_ret, | 1292 | unsigned char **data_ret, ptrdiff_t *bytes_ret, |
| 1272 | Atom *actual_type_ret, int *actual_format_ret, | 1293 | Atom *actual_type_ret, int *actual_format_ret, |
| 1273 | unsigned long *actual_size_ret, int delete_p) | 1294 | unsigned long *actual_size_ret, int delete_p) |
| 1274 | { | 1295 | { |
| 1275 | int total_size; | 1296 | ptrdiff_t total_size; |
| 1276 | unsigned long bytes_remaining; | 1297 | unsigned long bytes_remaining; |
| 1277 | int offset = 0; | 1298 | ptrdiff_t offset = 0; |
| 1299 | unsigned char *data = 0; | ||
| 1278 | unsigned char *tmp_data = 0; | 1300 | unsigned char *tmp_data = 0; |
| 1279 | int result; | 1301 | int result; |
| 1280 | int buffer_size = SELECTION_QUANTUM (display); | 1302 | int buffer_size = selection_quantum (display); |
| 1281 | 1303 | ||
| 1282 | if (buffer_size > MAX_SELECTION_QUANTUM) | 1304 | /* Wide enough to avoid overflow in expressions using it. */ |
| 1283 | buffer_size = MAX_SELECTION_QUANTUM; | 1305 | ptrdiff_t x_long_size = X_LONG_SIZE; |
| 1306 | |||
| 1307 | /* Maximum value for TOTAL_SIZE. It cannot exceed PTRDIFF_MAX - 1 | ||
| 1308 | and SIZE_MAX - 1, for an extra byte at the end. And it cannot | ||
| 1309 | exceed LONG_MAX * X_LONG_SIZE, for XGetWindowProperty. */ | ||
| 1310 | ptrdiff_t total_size_max = | ||
| 1311 | ((min (PTRDIFF_MAX, SIZE_MAX) - 1) / x_long_size < LONG_MAX | ||
| 1312 | ? min (PTRDIFF_MAX, SIZE_MAX) - 1 | ||
| 1313 | : LONG_MAX * x_long_size); | ||
| 1284 | 1314 | ||
| 1285 | BLOCK_INPUT; | 1315 | BLOCK_INPUT; |
| 1286 | 1316 | ||
| @@ -1291,49 +1321,44 @@ x_get_window_property (Display *display, Window window, Atom property, | |||
| 1291 | actual_size_ret, | 1321 | actual_size_ret, |
| 1292 | &bytes_remaining, &tmp_data); | 1322 | &bytes_remaining, &tmp_data); |
| 1293 | if (result != Success) | 1323 | if (result != Success) |
| 1294 | { | 1324 | goto done; |
| 1295 | UNBLOCK_INPUT; | ||
| 1296 | *data_ret = 0; | ||
| 1297 | *bytes_ret = 0; | ||
| 1298 | return; | ||
| 1299 | } | ||
| 1300 | 1325 | ||
| 1301 | /* This was allocated by Xlib, so use XFree. */ | 1326 | /* This was allocated by Xlib, so use XFree. */ |
| 1302 | XFree ((char *) tmp_data); | 1327 | XFree ((char *) tmp_data); |
| 1303 | 1328 | ||
| 1304 | if (*actual_type_ret == None || *actual_format_ret == 0) | 1329 | if (*actual_type_ret == None || *actual_format_ret == 0) |
| 1305 | { | 1330 | goto done; |
| 1306 | UNBLOCK_INPUT; | ||
| 1307 | return; | ||
| 1308 | } | ||
| 1309 | 1331 | ||
| 1310 | total_size = bytes_remaining + 1; | 1332 | if (total_size_max < bytes_remaining) |
| 1311 | *data_ret = (unsigned char *) xmalloc (total_size); | 1333 | goto size_overflow; |
| 1334 | total_size = bytes_remaining; | ||
| 1335 | data = malloc (total_size + 1); | ||
| 1336 | if (! data) | ||
| 1337 | goto memory_exhausted; | ||
| 1312 | 1338 | ||
| 1313 | /* Now read, until we've gotten it all. */ | 1339 | /* Now read, until we've gotten it all. */ |
| 1314 | while (bytes_remaining) | 1340 | while (bytes_remaining) |
| 1315 | { | 1341 | { |
| 1316 | #ifdef TRACE_SELECTION | 1342 | ptrdiff_t bytes_gotten; |
| 1317 | unsigned long last = bytes_remaining; | 1343 | int bytes_per_item; |
| 1318 | #endif | ||
| 1319 | result | 1344 | result |
| 1320 | = XGetWindowProperty (display, window, property, | 1345 | = XGetWindowProperty (display, window, property, |
| 1321 | (long)offset/4, (long)buffer_size/4, | 1346 | offset / X_LONG_SIZE, |
| 1347 | buffer_size / X_LONG_SIZE, | ||
| 1322 | False, | 1348 | False, |
| 1323 | AnyPropertyType, | 1349 | AnyPropertyType, |
| 1324 | actual_type_ret, actual_format_ret, | 1350 | actual_type_ret, actual_format_ret, |
| 1325 | actual_size_ret, &bytes_remaining, &tmp_data); | 1351 | actual_size_ret, &bytes_remaining, &tmp_data); |
| 1326 | 1352 | ||
| 1327 | TRACE2 ("Read %lu bytes from property %s", | ||
| 1328 | last - bytes_remaining, | ||
| 1329 | XGetAtomName (display, property)); | ||
| 1330 | |||
| 1331 | /* If this doesn't return Success at this point, it means that | 1353 | /* If this doesn't return Success at this point, it means that |
| 1332 | some clod deleted the selection while we were in the midst of | 1354 | some clod deleted the selection while we were in the midst of |
| 1333 | reading it. Deal with that, I guess.... */ | 1355 | reading it. Deal with that, I guess.... */ |
| 1334 | if (result != Success) | 1356 | if (result != Success) |
| 1335 | break; | 1357 | break; |
| 1336 | 1358 | ||
| 1359 | bytes_per_item = *actual_format_ret >> 3; | ||
| 1360 | xassert (*actual_size_ret <= buffer_size / bytes_per_item); | ||
| 1361 | |||
| 1337 | /* The man page for XGetWindowProperty says: | 1362 | /* The man page for XGetWindowProperty says: |
| 1338 | "If the returned format is 32, the returned data is represented | 1363 | "If the returned format is 32, the returned data is represented |
| 1339 | as a long array and should be cast to that type to obtain the | 1364 | as a long array and should be cast to that type to obtain the |
| @@ -1347,32 +1372,61 @@ x_get_window_property (Display *display, Window window, Atom property, | |||
| 1347 | The bytes and offsets passed to XGetWindowProperty refers to the | 1372 | The bytes and offsets passed to XGetWindowProperty refers to the |
| 1348 | property and those are indeed in 32 bit quantities if format is 32. */ | 1373 | property and those are indeed in 32 bit quantities if format is 32. */ |
| 1349 | 1374 | ||
| 1375 | bytes_gotten = *actual_size_ret; | ||
| 1376 | bytes_gotten *= bytes_per_item; | ||
| 1377 | |||
| 1378 | TRACE2 ("Read %"pD"d bytes from property %s", | ||
| 1379 | bytes_gotten, XGetAtomName (display, property)); | ||
| 1380 | |||
| 1381 | if (total_size - offset < bytes_gotten) | ||
| 1382 | { | ||
| 1383 | unsigned char *data1; | ||
| 1384 | ptrdiff_t remaining_lim = total_size_max - offset - bytes_gotten; | ||
| 1385 | if (remaining_lim < 0 || remaining_lim < bytes_remaining) | ||
| 1386 | goto size_overflow; | ||
| 1387 | total_size = offset + bytes_gotten + bytes_remaining; | ||
| 1388 | data1 = realloc (data, total_size + 1); | ||
| 1389 | if (! data1) | ||
| 1390 | goto memory_exhausted; | ||
| 1391 | data = data1; | ||
| 1392 | } | ||
| 1393 | |||
| 1350 | if (32 < BITS_PER_LONG && *actual_format_ret == 32) | 1394 | if (32 < BITS_PER_LONG && *actual_format_ret == 32) |
| 1351 | { | 1395 | { |
| 1352 | unsigned long i; | 1396 | unsigned long i; |
| 1353 | int *idata = (int *) ((*data_ret) + offset); | 1397 | int *idata = (int *) (data + offset); |
| 1354 | long *ldata = (long *) tmp_data; | 1398 | long *ldata = (long *) tmp_data; |
| 1355 | 1399 | ||
| 1356 | for (i = 0; i < *actual_size_ret; ++i) | 1400 | for (i = 0; i < *actual_size_ret; ++i) |
| 1357 | { | 1401 | idata[i] = ldata[i]; |
| 1358 | idata[i]= (int) ldata[i]; | ||
| 1359 | offset += 4; | ||
| 1360 | } | ||
| 1361 | } | 1402 | } |
| 1362 | else | 1403 | else |
| 1363 | { | 1404 | memcpy (data + offset, tmp_data, bytes_gotten); |
| 1364 | *actual_size_ret *= *actual_format_ret / 8; | 1405 | |
| 1365 | memcpy ((*data_ret) + offset, tmp_data, *actual_size_ret); | 1406 | offset += bytes_gotten; |
| 1366 | offset += *actual_size_ret; | ||
| 1367 | } | ||
| 1368 | 1407 | ||
| 1369 | /* This was allocated by Xlib, so use XFree. */ | 1408 | /* This was allocated by Xlib, so use XFree. */ |
| 1370 | XFree ((char *) tmp_data); | 1409 | XFree ((char *) tmp_data); |
| 1371 | } | 1410 | } |
| 1372 | 1411 | ||
| 1373 | XFlush (display); | 1412 | XFlush (display); |
| 1413 | data[offset] = '\0'; | ||
| 1414 | |||
| 1415 | done: | ||
| 1374 | UNBLOCK_INPUT; | 1416 | UNBLOCK_INPUT; |
| 1417 | *data_ret = data; | ||
| 1375 | *bytes_ret = offset; | 1418 | *bytes_ret = offset; |
| 1419 | return; | ||
| 1420 | |||
| 1421 | size_overflow: | ||
| 1422 | free (data); | ||
| 1423 | UNBLOCK_INPUT; | ||
| 1424 | memory_full (SIZE_MAX); | ||
| 1425 | |||
| 1426 | memory_exhausted: | ||
| 1427 | free (data); | ||
| 1428 | UNBLOCK_INPUT; | ||
| 1429 | memory_full (total_size + 1); | ||
| 1376 | } | 1430 | } |
| 1377 | 1431 | ||
| 1378 | /* Use xfree, not XFree, to free the data obtained with this function. */ | 1432 | /* Use xfree, not XFree, to free the data obtained with this function. */ |
| @@ -1381,16 +1435,19 @@ static void | |||
| 1381 | receive_incremental_selection (Display *display, Window window, Atom property, | 1435 | receive_incremental_selection (Display *display, Window window, Atom property, |
| 1382 | Lisp_Object target_type, | 1436 | Lisp_Object target_type, |
| 1383 | unsigned int min_size_bytes, | 1437 | unsigned int min_size_bytes, |
| 1384 | unsigned char **data_ret, int *size_bytes_ret, | 1438 | unsigned char **data_ret, |
| 1439 | ptrdiff_t *size_bytes_ret, | ||
| 1385 | Atom *type_ret, int *format_ret, | 1440 | Atom *type_ret, int *format_ret, |
| 1386 | unsigned long *size_ret) | 1441 | unsigned long *size_ret) |
| 1387 | { | 1442 | { |
| 1388 | int offset = 0; | 1443 | ptrdiff_t offset = 0; |
| 1389 | struct prop_location *wait_object; | 1444 | struct prop_location *wait_object; |
| 1445 | if (min (PTRDIFF_MAX, SIZE_MAX) < min_size_bytes) | ||
| 1446 | memory_full (SIZE_MAX); | ||
| 1447 | *data_ret = (unsigned char *) xmalloc (min_size_bytes); | ||
| 1390 | *size_bytes_ret = min_size_bytes; | 1448 | *size_bytes_ret = min_size_bytes; |
| 1391 | *data_ret = (unsigned char *) xmalloc (*size_bytes_ret); | ||
| 1392 | 1449 | ||
| 1393 | TRACE1 ("Read %d bytes incrementally", min_size_bytes); | 1450 | TRACE1 ("Read %u bytes incrementally", min_size_bytes); |
| 1394 | 1451 | ||
| 1395 | /* At this point, we have read an INCR property. | 1452 | /* At this point, we have read an INCR property. |
| 1396 | Delete the property to ack it. | 1453 | Delete the property to ack it. |
| @@ -1415,7 +1472,7 @@ receive_incremental_selection (Display *display, Window window, Atom property, | |||
| 1415 | while (1) | 1472 | while (1) |
| 1416 | { | 1473 | { |
| 1417 | unsigned char *tmp_data; | 1474 | unsigned char *tmp_data; |
| 1418 | int tmp_size_bytes; | 1475 | ptrdiff_t tmp_size_bytes; |
| 1419 | 1476 | ||
| 1420 | TRACE0 (" Wait for property change"); | 1477 | TRACE0 (" Wait for property change"); |
| 1421 | wait_for_property_change (wait_object); | 1478 | wait_for_property_change (wait_object); |
| @@ -1428,7 +1485,7 @@ receive_incremental_selection (Display *display, Window window, Atom property, | |||
| 1428 | &tmp_data, &tmp_size_bytes, | 1485 | &tmp_data, &tmp_size_bytes, |
| 1429 | type_ret, format_ret, size_ret, 1); | 1486 | type_ret, format_ret, size_ret, 1); |
| 1430 | 1487 | ||
| 1431 | TRACE1 (" Read increment of %d bytes", tmp_size_bytes); | 1488 | TRACE1 (" Read increment of %"pD"d bytes", tmp_size_bytes); |
| 1432 | 1489 | ||
| 1433 | if (tmp_size_bytes == 0) /* we're done */ | 1490 | if (tmp_size_bytes == 0) /* we're done */ |
| 1434 | { | 1491 | { |
| @@ -1451,11 +1508,10 @@ receive_incremental_selection (Display *display, Window window, Atom property, | |||
| 1451 | XFlush (display); | 1508 | XFlush (display); |
| 1452 | UNBLOCK_INPUT; | 1509 | UNBLOCK_INPUT; |
| 1453 | 1510 | ||
| 1454 | if (*size_bytes_ret < offset + tmp_size_bytes) | 1511 | if (*size_bytes_ret - offset < tmp_size_bytes) |
| 1455 | { | 1512 | *data_ret = xpalloc (*data_ret, size_bytes_ret, |
| 1456 | *size_bytes_ret = offset + tmp_size_bytes; | 1513 | tmp_size_bytes - (*size_bytes_ret - offset), |
| 1457 | *data_ret = (unsigned char *) xrealloc (*data_ret, *size_bytes_ret); | 1514 | -1, 1); |
| 1458 | } | ||
| 1459 | 1515 | ||
| 1460 | memcpy ((*data_ret) + offset, tmp_data, tmp_size_bytes); | 1516 | memcpy ((*data_ret) + offset, tmp_data, tmp_size_bytes); |
| 1461 | offset += tmp_size_bytes; | 1517 | offset += tmp_size_bytes; |
| @@ -1481,7 +1537,7 @@ x_get_window_property_as_lisp_data (Display *display, Window window, | |||
| 1481 | int actual_format; | 1537 | int actual_format; |
| 1482 | unsigned long actual_size; | 1538 | unsigned long actual_size; |
| 1483 | unsigned char *data = 0; | 1539 | unsigned char *data = 0; |
| 1484 | int bytes = 0; | 1540 | ptrdiff_t bytes = 0; |
| 1485 | Lisp_Object val; | 1541 | Lisp_Object val; |
| 1486 | struct x_display_info *dpyinfo = x_display_info_for_display (display); | 1542 | struct x_display_info *dpyinfo = x_display_info_for_display (display); |
| 1487 | 1543 | ||
| @@ -1573,7 +1629,7 @@ x_get_window_property_as_lisp_data (Display *display, Window window, | |||
| 1573 | 1629 | ||
| 1574 | static Lisp_Object | 1630 | static Lisp_Object |
| 1575 | selection_data_to_lisp_data (Display *display, const unsigned char *data, | 1631 | selection_data_to_lisp_data (Display *display, const unsigned char *data, |
| 1576 | int size, Atom type, int format) | 1632 | ptrdiff_t size, Atom type, int format) |
| 1577 | { | 1633 | { |
| 1578 | struct x_display_info *dpyinfo = x_display_info_for_display (display); | 1634 | struct x_display_info *dpyinfo = x_display_info_for_display (display); |
| 1579 | 1635 | ||
| @@ -1606,7 +1662,7 @@ selection_data_to_lisp_data (Display *display, const unsigned char *data, | |||
| 1606 | /* Treat ATOM_PAIR type similar to list of atoms. */ | 1662 | /* Treat ATOM_PAIR type similar to list of atoms. */ |
| 1607 | || type == dpyinfo->Xatom_ATOM_PAIR) | 1663 | || type == dpyinfo->Xatom_ATOM_PAIR) |
| 1608 | { | 1664 | { |
| 1609 | int i; | 1665 | ptrdiff_t i; |
| 1610 | /* On a 64 bit machine sizeof(Atom) == sizeof(long) == 8. | 1666 | /* On a 64 bit machine sizeof(Atom) == sizeof(long) == 8. |
| 1611 | But the callers of these function has made sure the data for | 1667 | But the callers of these function has made sure the data for |
| 1612 | format == 32 is an array of int. Thus, use int instead | 1668 | format == 32 is an array of int. Thus, use int instead |
| @@ -1631,45 +1687,61 @@ selection_data_to_lisp_data (Display *display, const unsigned char *data, | |||
| 1631 | convert it to a cons of integers, 16 bits in each half. | 1687 | convert it to a cons of integers, 16 bits in each half. |
| 1632 | */ | 1688 | */ |
| 1633 | else if (format == 32 && size == sizeof (int)) | 1689 | else if (format == 32 && size == sizeof (int)) |
| 1634 | return INTEGER_TO_CONS (((unsigned int *) data) [0]); | 1690 | return INTEGER_TO_CONS (((int *) data) [0]); |
| 1635 | else if (format == 16 && size == sizeof (short)) | 1691 | else if (format == 16 && size == sizeof (short)) |
| 1636 | return make_number ((int) (((unsigned short *) data) [0])); | 1692 | return make_number (((short *) data) [0]); |
| 1637 | 1693 | ||
| 1638 | /* Convert any other kind of data to a vector of numbers, represented | 1694 | /* Convert any other kind of data to a vector of numbers, represented |
| 1639 | as above (as an integer, or a cons of two 16 bit integers.) | 1695 | as above (as an integer, or a cons of two 16 bit integers.) |
| 1640 | */ | 1696 | */ |
| 1641 | else if (format == 16) | 1697 | else if (format == 16) |
| 1642 | { | 1698 | { |
| 1643 | int i; | 1699 | ptrdiff_t i; |
| 1644 | Lisp_Object v; | 1700 | Lisp_Object v; |
| 1645 | v = Fmake_vector (make_number (size / 2), make_number (0)); | 1701 | v = Fmake_vector (make_number (size / 2), make_number (0)); |
| 1646 | for (i = 0; i < size / 2; i++) | 1702 | for (i = 0; i < size / 2; i++) |
| 1647 | { | 1703 | { |
| 1648 | int j = (int) ((unsigned short *) data) [i]; | 1704 | EMACS_INT j = ((short *) data) [i]; |
| 1649 | Faset (v, make_number (i), make_number (j)); | 1705 | Faset (v, make_number (i), make_number (j)); |
| 1650 | } | 1706 | } |
| 1651 | return v; | 1707 | return v; |
| 1652 | } | 1708 | } |
| 1653 | else | 1709 | else |
| 1654 | { | 1710 | { |
| 1655 | int i; | 1711 | ptrdiff_t i; |
| 1656 | Lisp_Object v = Fmake_vector (make_number (size / 4), make_number (0)); | 1712 | Lisp_Object v = Fmake_vector (make_number (size / X_LONG_SIZE), |
| 1657 | for (i = 0; i < size / 4; i++) | 1713 | make_number (0)); |
| 1714 | for (i = 0; i < size / X_LONG_SIZE; i++) | ||
| 1658 | { | 1715 | { |
| 1659 | unsigned int j = ((unsigned int *) data) [i]; | 1716 | int j = ((int *) data) [i]; |
| 1660 | Faset (v, make_number (i), INTEGER_TO_CONS (j)); | 1717 | Faset (v, make_number (i), INTEGER_TO_CONS (j)); |
| 1661 | } | 1718 | } |
| 1662 | return v; | 1719 | return v; |
| 1663 | } | 1720 | } |
| 1664 | } | 1721 | } |
| 1665 | 1722 | ||
| 1723 | /* Convert OBJ to an X long value, and return it as unsigned long. | ||
| 1724 | OBJ should be an integer or a cons representing an integer. | ||
| 1725 | Treat values in the range X_LONG_MAX + 1 .. X_ULONG_MAX as X | ||
| 1726 | unsigned long values: in theory these values are supposed to be | ||
| 1727 | signed but in practice unsigned 32-bit data are communicated via X | ||
| 1728 | selections and we need to support that. */ | ||
| 1729 | static unsigned long | ||
| 1730 | cons_to_x_long (Lisp_Object obj) | ||
| 1731 | { | ||
| 1732 | if (X_ULONG_MAX <= INTMAX_MAX | ||
| 1733 | || XINT (INTEGERP (obj) ? obj : XCAR (obj)) < 0) | ||
| 1734 | return cons_to_signed (obj, X_LONG_MIN, min (X_ULONG_MAX, INTMAX_MAX)); | ||
| 1735 | else | ||
| 1736 | return cons_to_unsigned (obj, X_ULONG_MAX); | ||
| 1737 | } | ||
| 1666 | 1738 | ||
| 1667 | /* Use xfree, not XFree, to free the data obtained with this function. */ | 1739 | /* Use xfree, not XFree, to free the data obtained with this function. */ |
| 1668 | 1740 | ||
| 1669 | static void | 1741 | static void |
| 1670 | lisp_data_to_selection_data (Display *display, Lisp_Object obj, | 1742 | lisp_data_to_selection_data (Display *display, Lisp_Object obj, |
| 1671 | unsigned char **data_ret, Atom *type_ret, | 1743 | unsigned char **data_ret, Atom *type_ret, |
| 1672 | unsigned int *size_ret, | 1744 | ptrdiff_t *size_ret, |
| 1673 | int *format_ret, int *nofree_ret) | 1745 | int *format_ret, int *nofree_ret) |
| 1674 | { | 1746 | { |
| 1675 | Lisp_Object type = Qnil; | 1747 | Lisp_Object type = Qnil; |
| @@ -1706,22 +1778,20 @@ lisp_data_to_selection_data (Display *display, Lisp_Object obj, | |||
| 1706 | } | 1778 | } |
| 1707 | else if (SYMBOLP (obj)) | 1779 | else if (SYMBOLP (obj)) |
| 1708 | { | 1780 | { |
| 1781 | *data_ret = (unsigned char *) xmalloc (sizeof (Atom) + 1); | ||
| 1709 | *format_ret = 32; | 1782 | *format_ret = 32; |
| 1710 | *size_ret = 1; | 1783 | *size_ret = 1; |
| 1711 | *data_ret = (unsigned char *) xmalloc (sizeof (Atom) + 1); | ||
| 1712 | (*data_ret) [sizeof (Atom)] = 0; | 1784 | (*data_ret) [sizeof (Atom)] = 0; |
| 1713 | (*(Atom **) data_ret) [0] = symbol_to_x_atom (dpyinfo, obj); | 1785 | (*(Atom **) data_ret) [0] = symbol_to_x_atom (dpyinfo, obj); |
| 1714 | if (NILP (type)) type = QATOM; | 1786 | if (NILP (type)) type = QATOM; |
| 1715 | } | 1787 | } |
| 1716 | else if (INTEGERP (obj) | 1788 | else if (RANGED_INTEGERP (X_SHRT_MIN, obj, X_SHRT_MAX)) |
| 1717 | && XINT (obj) < 0xFFFF | ||
| 1718 | && XINT (obj) > -0xFFFF) | ||
| 1719 | { | 1789 | { |
| 1790 | *data_ret = (unsigned char *) xmalloc (sizeof (short) + 1); | ||
| 1720 | *format_ret = 16; | 1791 | *format_ret = 16; |
| 1721 | *size_ret = 1; | 1792 | *size_ret = 1; |
| 1722 | *data_ret = (unsigned char *) xmalloc (sizeof (short) + 1); | ||
| 1723 | (*data_ret) [sizeof (short)] = 0; | 1793 | (*data_ret) [sizeof (short)] = 0; |
| 1724 | (*(short **) data_ret) [0] = (short) XINT (obj); | 1794 | (*(short **) data_ret) [0] = XINT (obj); |
| 1725 | if (NILP (type)) type = QINTEGER; | 1795 | if (NILP (type)) type = QINTEGER; |
| 1726 | } | 1796 | } |
| 1727 | else if (INTEGERP (obj) | 1797 | else if (INTEGERP (obj) |
| @@ -1730,11 +1800,11 @@ lisp_data_to_selection_data (Display *display, Lisp_Object obj, | |||
| 1730 | || (CONSP (XCDR (obj)) | 1800 | || (CONSP (XCDR (obj)) |
| 1731 | && INTEGERP (XCAR (XCDR (obj))))))) | 1801 | && INTEGERP (XCAR (XCDR (obj))))))) |
| 1732 | { | 1802 | { |
| 1803 | *data_ret = (unsigned char *) xmalloc (sizeof (unsigned long) + 1); | ||
| 1733 | *format_ret = 32; | 1804 | *format_ret = 32; |
| 1734 | *size_ret = 1; | 1805 | *size_ret = 1; |
| 1735 | *data_ret = (unsigned char *) xmalloc (sizeof (long) + 1); | 1806 | (*data_ret) [sizeof (unsigned long)] = 0; |
| 1736 | (*data_ret) [sizeof (long)] = 0; | 1807 | (*(unsigned long **) data_ret) [0] = cons_to_x_long (obj); |
| 1737 | (*(unsigned long **) data_ret) [0] = cons_to_unsigned (obj, ULONG_MAX); | ||
| 1738 | if (NILP (type)) type = QINTEGER; | 1808 | if (NILP (type)) type = QINTEGER; |
| 1739 | } | 1809 | } |
| 1740 | else if (VECTORP (obj)) | 1810 | else if (VECTORP (obj)) |
| @@ -1743,50 +1813,55 @@ lisp_data_to_selection_data (Display *display, Lisp_Object obj, | |||
| 1743 | a set of 16 or 32 bit INTEGERs; | 1813 | a set of 16 or 32 bit INTEGERs; |
| 1744 | or a set of ATOM_PAIRs (represented as [[A1 A2] [A3 A4] ...] | 1814 | or a set of ATOM_PAIRs (represented as [[A1 A2] [A3 A4] ...] |
| 1745 | */ | 1815 | */ |
| 1746 | int i; | 1816 | ptrdiff_t i; |
| 1817 | ptrdiff_t size = ASIZE (obj); | ||
| 1747 | 1818 | ||
| 1748 | if (SYMBOLP (XVECTOR (obj)->contents [0])) | 1819 | if (SYMBOLP (XVECTOR (obj)->contents [0])) |
| 1749 | /* This vector is an ATOM set */ | 1820 | /* This vector is an ATOM set */ |
| 1750 | { | 1821 | { |
| 1751 | if (NILP (type)) type = QATOM; | 1822 | if (NILP (type)) type = QATOM; |
| 1752 | *size_ret = ASIZE (obj); | 1823 | for (i = 0; i < size; i++) |
| 1753 | *format_ret = 32; | ||
| 1754 | for (i = 0; i < *size_ret; i++) | ||
| 1755 | if (!SYMBOLP (XVECTOR (obj)->contents [i])) | 1824 | if (!SYMBOLP (XVECTOR (obj)->contents [i])) |
| 1756 | signal_error ("All elements of selection vector must have same type", obj); | 1825 | signal_error ("All elements of selection vector must have same type", obj); |
| 1757 | 1826 | ||
| 1758 | *data_ret = (unsigned char *) xmalloc ((*size_ret) * sizeof (Atom)); | 1827 | *data_ret = xnmalloc (size, sizeof (Atom)); |
| 1759 | for (i = 0; i < *size_ret; i++) | 1828 | *format_ret = 32; |
| 1829 | *size_ret = size; | ||
| 1830 | for (i = 0; i < size; i++) | ||
| 1760 | (*(Atom **) data_ret) [i] | 1831 | (*(Atom **) data_ret) [i] |
| 1761 | = symbol_to_x_atom (dpyinfo, XVECTOR (obj)->contents [i]); | 1832 | = symbol_to_x_atom (dpyinfo, XVECTOR (obj)->contents [i]); |
| 1762 | } | 1833 | } |
| 1763 | else | 1834 | else |
| 1764 | /* This vector is an INTEGER set, or something like it */ | 1835 | /* This vector is an INTEGER set, or something like it */ |
| 1765 | { | 1836 | { |
| 1766 | int data_size = 2; | 1837 | int format = 16; |
| 1767 | *size_ret = ASIZE (obj); | 1838 | int data_size = sizeof (short); |
| 1768 | if (NILP (type)) type = QINTEGER; | 1839 | if (NILP (type)) type = QINTEGER; |
| 1769 | *format_ret = 16; | 1840 | for (i = 0; i < size; i++) |
| 1770 | for (i = 0; i < *size_ret; i++) | 1841 | { |
| 1771 | if (CONSP (XVECTOR (obj)->contents [i])) | 1842 | if (! RANGED_INTEGERP (X_SHRT_MIN, XVECTOR (obj)->contents[i], |
| 1772 | *format_ret = 32; | 1843 | X_SHRT_MAX)) |
| 1773 | else if (!INTEGERP (XVECTOR (obj)->contents [i])) | 1844 | { |
| 1774 | signal_error (/* Qselection_error */ | 1845 | /* Use sizeof (long) even if it is more than 32 bits. |
| 1775 | "Elements of selection vector must be integers or conses of integers", | 1846 | See comment in x_get_window_property and |
| 1776 | obj); | 1847 | x_fill_property_data. */ |
| 1777 | 1848 | data_size = sizeof (long); | |
| 1778 | /* Use sizeof(long) even if it is more than 32 bits. See comment | 1849 | format = 32; |
| 1779 | in x_get_window_property and x_fill_property_data. */ | 1850 | break; |
| 1780 | 1851 | } | |
| 1781 | if (*format_ret == 32) data_size = sizeof(long); | 1852 | } |
| 1782 | *data_ret = (unsigned char *) xmalloc (*size_ret * data_size); | 1853 | *data_ret = xnmalloc (size, data_size); |
| 1783 | for (i = 0; i < *size_ret; i++) | 1854 | *format_ret = format; |
| 1784 | if (*format_ret == 32) | 1855 | *size_ret = size; |
| 1785 | (*((unsigned long **) data_ret)) [i] = | 1856 | for (i = 0; i < size; i++) |
| 1786 | cons_to_unsigned (XVECTOR (obj)->contents [i], ULONG_MAX); | 1857 | { |
| 1787 | else | 1858 | if (format == 32) |
| 1788 | (*((unsigned short **) data_ret)) [i] = | 1859 | (*((unsigned long **) data_ret)) [i] = |
| 1789 | cons_to_unsigned (XVECTOR (obj)->contents [i], USHRT_MAX); | 1860 | cons_to_x_long (XVECTOR (obj)->contents[i]); |
| 1861 | else | ||
| 1862 | (*((short **) data_ret)) [i] = | ||
| 1863 | XINT (XVECTOR (obj)->contents[i]); | ||
| 1864 | } | ||
| 1790 | } | 1865 | } |
| 1791 | } | 1866 | } |
| 1792 | else | 1867 | else |
| @@ -1816,8 +1891,8 @@ clean_local_selection_data (Lisp_Object obj) | |||
| 1816 | } | 1891 | } |
| 1817 | if (VECTORP (obj)) | 1892 | if (VECTORP (obj)) |
| 1818 | { | 1893 | { |
| 1819 | int i; | 1894 | ptrdiff_t i; |
| 1820 | int size = ASIZE (obj); | 1895 | ptrdiff_t size = ASIZE (obj); |
| 1821 | Lisp_Object copy; | 1896 | Lisp_Object copy; |
| 1822 | if (size == 1) | 1897 | if (size == 1) |
| 1823 | return clean_local_selection_data (XVECTOR (obj)->contents [0]); | 1898 | return clean_local_selection_data (XVECTOR (obj)->contents [0]); |
| @@ -1907,7 +1982,9 @@ VALUE is typically a string, or a cons of two markers, but may be | |||
| 1907 | anything that the functions on `selection-converter-alist' know about. | 1982 | anything that the functions on `selection-converter-alist' know about. |
| 1908 | 1983 | ||
| 1909 | FRAME should be a frame that should own the selection. If omitted or | 1984 | FRAME should be a frame that should own the selection. If omitted or |
| 1910 | nil, it defaults to the selected frame. */) | 1985 | nil, it defaults to the selected frame. |
| 1986 | |||
| 1987 | On Nextstep, FRAME is unused. */) | ||
| 1911 | (Lisp_Object selection, Lisp_Object value, Lisp_Object frame) | 1988 | (Lisp_Object selection, Lisp_Object value, Lisp_Object frame) |
| 1912 | { | 1989 | { |
| 1913 | if (NILP (frame)) frame = selected_frame; | 1990 | if (NILP (frame)) frame = selected_frame; |
| @@ -1928,15 +2005,18 @@ nil, it defaults to the selected frame. */) | |||
| 1928 | DEFUN ("x-get-selection-internal", Fx_get_selection_internal, | 2005 | DEFUN ("x-get-selection-internal", Fx_get_selection_internal, |
| 1929 | Sx_get_selection_internal, 2, 4, 0, | 2006 | Sx_get_selection_internal, 2, 4, 0, |
| 1930 | doc: /* Return text selected from some X window. | 2007 | doc: /* Return text selected from some X window. |
| 1931 | SELECTION is a symbol, typically `PRIMARY', `SECONDARY', or `CLIPBOARD'. | 2008 | SELECTION-SYMBOL is typically `PRIMARY', `SECONDARY', or `CLIPBOARD'. |
| 1932 | \(Those are literal upper-case symbol names, since that's what X expects.) | 2009 | \(Those are literal upper-case symbol names, since that's what X expects.) |
| 1933 | TYPE is the type of data desired, typically `STRING'. | 2010 | TARGET-TYPE is the type of data desired, typically `STRING'. |
| 1934 | TIME_STAMP is the time to use in the XConvertSelection call for foreign | 2011 | |
| 2012 | TIME-STAMP is the time to use in the XConvertSelection call for foreign | ||
| 1935 | selections. If omitted, defaults to the time for the last event. | 2013 | selections. If omitted, defaults to the time for the last event. |
| 1936 | 2014 | ||
| 1937 | TERMINAL should be a terminal object or a frame specifying the X | 2015 | TERMINAL should be a terminal object or a frame specifying the X |
| 1938 | server to query. If omitted or nil, that stands for the selected | 2016 | server to query. If omitted or nil, that stands for the selected |
| 1939 | frame's display, or the first available X display. */) | 2017 | frame's display, or the first available X display. |
| 2018 | |||
| 2019 | On Nextstep, TIME-STAMP and TERMINAL are unused. */) | ||
| 1940 | (Lisp_Object selection_symbol, Lisp_Object target_type, | 2020 | (Lisp_Object selection_symbol, Lisp_Object target_type, |
| 1941 | Lisp_Object time_stamp, Lisp_Object terminal) | 2021 | Lisp_Object time_stamp, Lisp_Object terminal) |
| 1942 | { | 2022 | { |
| @@ -1977,9 +2057,15 @@ DEFUN ("x-disown-selection-internal", Fx_disown_selection_internal, | |||
| 1977 | doc: /* If we own the selection SELECTION, disown it. | 2057 | doc: /* If we own the selection SELECTION, disown it. |
| 1978 | Disowning it means there is no such selection. | 2058 | Disowning it means there is no such selection. |
| 1979 | 2059 | ||
| 2060 | Sets the last-change time for the selection to TIME-OBJECT (by default | ||
| 2061 | the time of the last event). | ||
| 2062 | |||
| 1980 | TERMINAL should be a terminal object or a frame specifying the X | 2063 | TERMINAL should be a terminal object or a frame specifying the X |
| 1981 | server to query. If omitted or nil, that stands for the selected | 2064 | server to query. If omitted or nil, that stands for the selected |
| 1982 | frame's display, or the first available X display. */) | 2065 | frame's display, or the first available X display. |
| 2066 | |||
| 2067 | On Nextstep, the TIME-OBJECT and TERMINAL arguments are unused. | ||
| 2068 | On MS-DOS, all this does is return non-nil if we own the selection. */) | ||
| 1983 | (Lisp_Object selection, Lisp_Object time_object, Lisp_Object terminal) | 2069 | (Lisp_Object selection, Lisp_Object time_object, Lisp_Object terminal) |
| 1984 | { | 2070 | { |
| 1985 | Time timestamp; | 2071 | Time timestamp; |
| @@ -2035,7 +2121,9 @@ and t is the same as `SECONDARY'. | |||
| 2035 | 2121 | ||
| 2036 | TERMINAL should be a terminal object or a frame specifying the X | 2122 | TERMINAL should be a terminal object or a frame specifying the X |
| 2037 | server to query. If omitted or nil, that stands for the selected | 2123 | server to query. If omitted or nil, that stands for the selected |
| 2038 | frame's display, or the first available X display. */) | 2124 | frame's display, or the first available X display. |
| 2125 | |||
| 2126 | On Nextstep, TERMINAL is unused. */) | ||
| 2039 | (Lisp_Object selection, Lisp_Object terminal) | 2127 | (Lisp_Object selection, Lisp_Object terminal) |
| 2040 | { | 2128 | { |
| 2041 | struct frame *f = frame_for_x_selection (terminal); | 2129 | struct frame *f = frame_for_x_selection (terminal); |
| @@ -2054,13 +2142,15 @@ DEFUN ("x-selection-exists-p", Fx_selection_exists_p, Sx_selection_exists_p, | |||
| 2054 | 0, 2, 0, | 2142 | 0, 2, 0, |
| 2055 | doc: /* Whether there is an owner for the given X selection. | 2143 | doc: /* Whether there is an owner for the given X selection. |
| 2056 | SELECTION should be the name of the selection in question, typically | 2144 | SELECTION should be the name of the selection in question, typically |
| 2057 | one of the symbols `PRIMARY', `SECONDARY', or `CLIPBOARD'. (X expects | 2145 | one of the symbols `PRIMARY', `SECONDARY', `CLIPBOARD', or |
| 2058 | these literal upper-case names.) The symbol nil is the same as | 2146 | `CLIPBOARD_MANAGER' (X expects these literal upper-case names.) The |
| 2059 | `PRIMARY', and t is the same as `SECONDARY'. | 2147 | symbol nil is the same as `PRIMARY', and t is the same as `SECONDARY'. |
| 2060 | 2148 | ||
| 2061 | TERMINAL should be a terminal object or a frame specifying the X | 2149 | TERMINAL should be a terminal object or a frame specifying the X |
| 2062 | server to query. If omitted or nil, that stands for the selected | 2150 | server to query. If omitted or nil, that stands for the selected |
| 2063 | frame's display, or the first available X display. */) | 2151 | frame's display, or the first available X display. |
| 2152 | |||
| 2153 | On Nextstep, TERMINAL is unused. */) | ||
| 2064 | (Lisp_Object selection, Lisp_Object terminal) | 2154 | (Lisp_Object selection, Lisp_Object terminal) |
| 2065 | { | 2155 | { |
| 2066 | Window owner; | 2156 | Window owner; |
| @@ -2183,8 +2273,14 @@ x_clipboard_manager_save_all (void) | |||
| 2183 | 2273 | ||
| 2184 | local_frame = XCAR (XCDR (XCDR (XCDR (local_selection)))); | 2274 | local_frame = XCAR (XCDR (XCDR (XCDR (local_selection)))); |
| 2185 | if (FRAME_LIVE_P (XFRAME (local_frame))) | 2275 | if (FRAME_LIVE_P (XFRAME (local_frame))) |
| 2186 | internal_condition_case_1 (x_clipboard_manager_save, local_frame, | 2276 | { |
| 2187 | Qt, x_clipboard_manager_error_2); | 2277 | Lisp_Object args[1]; |
| 2278 | args[0] = build_string ("Saving clipboard to X clipboard manager..."); | ||
| 2279 | Fmessage (1, args); | ||
| 2280 | |||
| 2281 | internal_condition_case_1 (x_clipboard_manager_save, local_frame, | ||
| 2282 | Qt, x_clipboard_manager_error_2); | ||
| 2283 | } | ||
| 2188 | } | 2284 | } |
| 2189 | } | 2285 | } |
| 2190 | 2286 | ||
| @@ -2212,6 +2308,8 @@ x_check_property_data (Lisp_Object data) | |||
| 2212 | else if (CONSP (o) && | 2308 | else if (CONSP (o) && |
| 2213 | (! NUMBERP (XCAR (o)) || ! NUMBERP (XCDR (o)))) | 2309 | (! NUMBERP (XCAR (o)) || ! NUMBERP (XCDR (o)))) |
| 2214 | return -1; | 2310 | return -1; |
| 2311 | if (size == INT_MAX) | ||
| 2312 | return -1; | ||
| 2215 | size++; | 2313 | size++; |
| 2216 | } | 2314 | } |
| 2217 | 2315 | ||
| @@ -2278,7 +2376,7 @@ x_fill_property_data (Display *dpy, Lisp_Object data, void *ret, int format) | |||
| 2278 | F is the frame to be used to look up X atoms if the TYPE is XA_ATOM. | 2376 | F is the frame to be used to look up X atoms if the TYPE is XA_ATOM. |
| 2279 | DATA is a C array of values to be converted. | 2377 | DATA is a C array of values to be converted. |
| 2280 | TYPE is the type of the data. Only XA_ATOM is special, it converts | 2378 | TYPE is the type of the data. Only XA_ATOM is special, it converts |
| 2281 | each number in DATA to its corresponfing X atom as a symbol. | 2379 | each number in DATA to its corresponding X atom as a symbol. |
| 2282 | FORMAT is 8, 16 or 32 and gives the size in bits for each C value to | 2380 | FORMAT is 8, 16 or 32 and gives the size in bits for each C value to |
| 2283 | be stored in RET. | 2381 | be stored in RET. |
| 2284 | SIZE is the number of elements in DATA. | 2382 | SIZE is the number of elements in DATA. |
| @@ -2293,8 +2391,11 @@ Lisp_Object | |||
| 2293 | x_property_data_to_lisp (struct frame *f, const unsigned char *data, | 2391 | x_property_data_to_lisp (struct frame *f, const unsigned char *data, |
| 2294 | Atom type, int format, long unsigned int size) | 2392 | Atom type, int format, long unsigned int size) |
| 2295 | { | 2393 | { |
| 2394 | ptrdiff_t format_bytes = format >> 3; | ||
| 2395 | if (PTRDIFF_MAX / format_bytes < size) | ||
| 2396 | memory_full (SIZE_MAX); | ||
| 2296 | return selection_data_to_lisp_data (FRAME_X_DISPLAY (f), | 2397 | return selection_data_to_lisp_data (FRAME_X_DISPLAY (f), |
| 2297 | data, size*format/8, type, format); | 2398 | data, size * format_bytes, type, format); |
| 2298 | } | 2399 | } |
| 2299 | 2400 | ||
| 2300 | /* Get the mouse position in frame relative coordinates. */ | 2401 | /* Get the mouse position in frame relative coordinates. */ |
| @@ -2380,7 +2481,7 @@ FRAME is on. If FRAME is nil, the selected frame is used. */) | |||
| 2380 | { | 2481 | { |
| 2381 | Atom x_atom; | 2482 | Atom x_atom; |
| 2382 | struct frame *f = check_x_frame (frame); | 2483 | struct frame *f = check_x_frame (frame); |
| 2383 | size_t i; | 2484 | ptrdiff_t i; |
| 2384 | struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); | 2485 | struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); |
| 2385 | 2486 | ||
| 2386 | 2487 | ||
| @@ -2400,12 +2501,9 @@ FRAME is on. If FRAME is nil, the selected frame is used. */) | |||
| 2400 | return Qnil; | 2501 | return Qnil; |
| 2401 | 2502 | ||
| 2402 | if (dpyinfo->x_dnd_atoms_length == dpyinfo->x_dnd_atoms_size) | 2503 | if (dpyinfo->x_dnd_atoms_length == dpyinfo->x_dnd_atoms_size) |
| 2403 | { | 2504 | dpyinfo->x_dnd_atoms = |
| 2404 | dpyinfo->x_dnd_atoms_size *= 2; | 2505 | xpalloc (dpyinfo->x_dnd_atoms, &dpyinfo->x_dnd_atoms_size, |
| 2405 | dpyinfo->x_dnd_atoms = xrealloc (dpyinfo->x_dnd_atoms, | 2506 | 1, -1, sizeof *dpyinfo->x_dnd_atoms); |
| 2406 | sizeof (*dpyinfo->x_dnd_atoms) | ||
| 2407 | * dpyinfo->x_dnd_atoms_size); | ||
| 2408 | } | ||
| 2409 | 2507 | ||
| 2410 | dpyinfo->x_dnd_atoms[dpyinfo->x_dnd_atoms_length++] = x_atom; | 2508 | dpyinfo->x_dnd_atoms[dpyinfo->x_dnd_atoms_length++] = x_atom; |
| 2411 | return Qnil; | 2509 | return Qnil; |
| @@ -2414,7 +2512,8 @@ FRAME is on. If FRAME is nil, the selected frame is used. */) | |||
| 2414 | /* Convert an XClientMessageEvent to a Lisp event of type DRAG_N_DROP_EVENT. */ | 2512 | /* Convert an XClientMessageEvent to a Lisp event of type DRAG_N_DROP_EVENT. */ |
| 2415 | 2513 | ||
| 2416 | int | 2514 | int |
| 2417 | x_handle_dnd_message (struct frame *f, XClientMessageEvent *event, struct x_display_info *dpyinfo, struct input_event *bufp) | 2515 | x_handle_dnd_message (struct frame *f, XClientMessageEvent *event, |
| 2516 | struct x_display_info *dpyinfo, struct input_event *bufp) | ||
| 2418 | { | 2517 | { |
| 2419 | Lisp_Object vec; | 2518 | Lisp_Object vec; |
| 2420 | Lisp_Object frame; | 2519 | Lisp_Object frame; |
| @@ -2423,7 +2522,7 @@ x_handle_dnd_message (struct frame *f, XClientMessageEvent *event, struct x_disp | |||
| 2423 | int x, y; | 2522 | int x, y; |
| 2424 | unsigned char *data = (unsigned char *) event->data.b; | 2523 | unsigned char *data = (unsigned char *) event->data.b; |
| 2425 | int idata[5]; | 2524 | int idata[5]; |
| 2426 | size_t i; | 2525 | ptrdiff_t i; |
| 2427 | 2526 | ||
| 2428 | for (i = 0; i < dpyinfo->x_dnd_atoms_length; ++i) | 2527 | for (i = 0; i < dpyinfo->x_dnd_atoms_length; ++i) |
| 2429 | if (dpyinfo->x_dnd_atoms[i] == event->message_type) break; | 2528 | if (dpyinfo->x_dnd_atoms[i] == event->message_type) break; |
| @@ -2440,7 +2539,7 @@ x_handle_dnd_message (struct frame *f, XClientMessageEvent *event, struct x_disp | |||
| 2440 | if (32 < BITS_PER_LONG && event->format == 32) | 2539 | if (32 < BITS_PER_LONG && event->format == 32) |
| 2441 | { | 2540 | { |
| 2442 | for (i = 0; i < 5; ++i) /* There are only 5 longs in a ClientMessage. */ | 2541 | for (i = 0; i < 5; ++i) /* There are only 5 longs in a ClientMessage. */ |
| 2443 | idata[i] = (int) event->data.l[i]; | 2542 | idata[i] = event->data.l[i]; |
| 2444 | data = (unsigned char *) idata; | 2543 | data = (unsigned char *) idata; |
| 2445 | } | 2544 | } |
| 2446 | 2545 | ||
| @@ -2492,22 +2591,24 @@ the Atom is sent. If a value is a cons, it is converted to a 32 bit number | |||
| 2492 | with the high 16 bits from the car and the lower 16 bit from the cdr. | 2591 | with the high 16 bits from the car and the lower 16 bit from the cdr. |
| 2493 | If more values than fits into the event is given, the excessive values | 2592 | If more values than fits into the event is given, the excessive values |
| 2494 | are ignored. */) | 2593 | are ignored. */) |
| 2495 | (Lisp_Object display, Lisp_Object dest, Lisp_Object from, Lisp_Object message_type, Lisp_Object format, Lisp_Object values) | 2594 | (Lisp_Object display, Lisp_Object dest, Lisp_Object from, |
| 2595 | Lisp_Object message_type, Lisp_Object format, Lisp_Object values) | ||
| 2496 | { | 2596 | { |
| 2497 | struct x_display_info *dpyinfo = check_x_display_info (display); | 2597 | struct x_display_info *dpyinfo = check_x_display_info (display); |
| 2498 | 2598 | ||
| 2499 | CHECK_STRING (message_type); | 2599 | CHECK_STRING (message_type); |
| 2500 | x_send_client_event(display, dest, from, | 2600 | x_send_client_event (display, dest, from, |
| 2501 | XInternAtom (dpyinfo->display, | 2601 | XInternAtom (dpyinfo->display, |
| 2502 | SSDATA (message_type), | 2602 | SSDATA (message_type), |
| 2503 | False), | 2603 | False), |
| 2504 | format, values); | 2604 | format, values); |
| 2505 | 2605 | ||
| 2506 | return Qnil; | 2606 | return Qnil; |
| 2507 | } | 2607 | } |
| 2508 | 2608 | ||
| 2509 | void | 2609 | void |
| 2510 | x_send_client_event (Lisp_Object display, Lisp_Object dest, Lisp_Object from, Atom message_type, Lisp_Object format, Lisp_Object values) | 2610 | x_send_client_event (Lisp_Object display, Lisp_Object dest, Lisp_Object from, |
| 2611 | Atom message_type, Lisp_Object format, Lisp_Object values) | ||
| 2511 | { | 2612 | { |
| 2512 | struct x_display_info *dpyinfo = check_x_display_info (display); | 2613 | struct x_display_info *dpyinfo = check_x_display_info (display); |
| 2513 | Window wdest; | 2614 | Window wdest; |
| @@ -2679,4 +2780,6 @@ A value of 0 means wait as long as necessary. This is initialized from the | |||
| 2679 | DEFSYM (QNULL, "NULL"); | 2780 | DEFSYM (QNULL, "NULL"); |
| 2680 | DEFSYM (Qcompound_text_with_extensions, "compound-text-with-extensions"); | 2781 | DEFSYM (Qcompound_text_with_extensions, "compound-text-with-extensions"); |
| 2681 | DEFSYM (Qforeign_selection, "foreign-selection"); | 2782 | DEFSYM (Qforeign_selection, "foreign-selection"); |
| 2783 | DEFSYM (Qx_lost_selection_functions, "x-lost-selection-functions"); | ||
| 2784 | DEFSYM (Qx_sent_selection_functions, "x-sent-selection-functions"); | ||
| 2682 | } | 2785 | } |