diff options
| author | Jan Djärv | 2005-02-07 19:59:36 +0000 |
|---|---|---|
| committer | Jan Djärv | 2005-02-07 19:59:36 +0000 |
| commit | e22cf39c6670462a155f8535075a5e5bc937065a (patch) | |
| tree | 3c67377459c51290b743e35c103ea9b1334635f2 /src | |
| parent | 3a4415260fb5aaac2b188f35479d99d8002c4dba (diff) | |
| download | emacs-e22cf39c6670462a155f8535075a5e5bc937065a.tar.gz emacs-e22cf39c6670462a155f8535075a5e5bc937065a.zip | |
* xselect.c (x_reply_selection_request): Pass long array to
XChangeProperty so that 64 bit longs are handeled correctly.
(x_get_window_property): If format is 32 and long is bigger than 32
bits convert data from XGetWindowProperty from long array to int array.
(lisp_data_to_selection_data): When the input is a vector and the
format is 32, allocate a long array even if long is bigger than 32 bits.
(x_fill_property_data): Use char, short and long as the man page
for XChangeProperty specifies. This way the data returned is OK for
both 32 and 64 bit machines.
(x_handle_dnd_message): Calculate size correctly even for 64 bit
machines.
(Fx_send_client_event): Undo change from 2005-02-05,
x_fill_property_data now handles that case.
Diffstat (limited to 'src')
| -rw-r--r-- | src/xselect.c | 125 |
1 files changed, 71 insertions, 54 deletions
diff --git a/src/xselect.c b/src/xselect.c index daae84b276c..f54e685873a 100644 --- a/src/xselect.c +++ b/src/xselect.c | |||
| @@ -173,12 +173,6 @@ static Lisp_Object Vselection_converter_alist; | |||
| 173 | /* If the selection owner takes too long to reply to a selection request, | 173 | /* If the selection owner takes too long to reply to a selection request, |
| 174 | we give up on it. This is in milliseconds (0 = no timeout.) */ | 174 | we give up on it. This is in milliseconds (0 = no timeout.) */ |
| 175 | static EMACS_INT x_selection_timeout; | 175 | static EMACS_INT x_selection_timeout; |
| 176 | |||
| 177 | /* Utility functions */ | ||
| 178 | |||
| 179 | static void lisp_data_to_selection_data (); | ||
| 180 | static Lisp_Object selection_data_to_lisp_data (); | ||
| 181 | static Lisp_Object x_get_window_property_as_lisp_data (); | ||
| 182 | 176 | ||
| 183 | 177 | ||
| 184 | 178 | ||
| @@ -769,9 +763,17 @@ x_reply_selection_request (event, format, data, size, type) | |||
| 769 | 763 | ||
| 770 | TRACE1 ("Set %s to number of bytes to send", | 764 | TRACE1 ("Set %s to number of bytes to send", |
| 771 | XGetAtomName (display, reply.property)); | 765 | XGetAtomName (display, reply.property)); |
| 772 | XChangeProperty (display, window, reply.property, dpyinfo->Xatom_INCR, | 766 | { |
| 773 | 32, PropModeReplace, | 767 | /* XChangeProperty expects an array of long even if long is more than |
| 774 | (unsigned char *) &bytes_remaining, 1); | 768 | 32 bits. */ |
| 769 | long value[1]; | ||
| 770 | |||
| 771 | value[0] = bytes_remaining; | ||
| 772 | XChangeProperty (display, window, reply.property, dpyinfo->Xatom_INCR, | ||
| 773 | 32, PropModeReplace, | ||
| 774 | (unsigned char *) value, 1); | ||
| 775 | } | ||
| 776 | |||
| 775 | XSelectInput (display, window, PropertyChangeMask); | 777 | XSelectInput (display, window, PropertyChangeMask); |
| 776 | 778 | ||
| 777 | /* Tell 'em the INCR data is there... */ | 779 | /* Tell 'em the INCR data is there... */ |
| @@ -796,9 +798,9 @@ x_reply_selection_request (event, format, data, size, type) | |||
| 796 | TRACE0 ("Got ACK"); | 798 | TRACE0 ("Got ACK"); |
| 797 | while (bytes_remaining) | 799 | while (bytes_remaining) |
| 798 | { | 800 | { |
| 799 | int i = ((bytes_remaining < max_bytes) | 801 | int i = ((bytes_remaining < max_bytes) |
| 800 | ? bytes_remaining | 802 | ? bytes_remaining |
| 801 | : max_bytes); | 803 | : max_bytes); |
| 802 | 804 | ||
| 803 | BLOCK_INPUT; | 805 | BLOCK_INPUT; |
| 804 | 806 | ||
| @@ -1523,9 +1525,38 @@ x_get_window_property (display, window, property, data_ret, bytes_ret, | |||
| 1523 | reading it. Deal with that, I guess.... */ | 1525 | reading it. Deal with that, I guess.... */ |
| 1524 | if (result != Success) | 1526 | if (result != Success) |
| 1525 | break; | 1527 | break; |
| 1526 | *actual_size_ret *= *actual_format_ret / 8; | 1528 | |
| 1527 | bcopy (tmp_data, (*data_ret) + offset, *actual_size_ret); | 1529 | /* The man page for XGetWindowProperty says: |
| 1528 | offset += *actual_size_ret; | 1530 | "If the returned format is 32, the returned data is represented |
| 1531 | as a long array and should be cast to that type to obtain the | ||
| 1532 | elements." | ||
| 1533 | This applies even if long is more than 32 bits, the X library | ||
| 1534 | converts from 32 bit elements received from the X server to long | ||
| 1535 | and passes the long array to us. Thus, for that case bcopy can not | ||
| 1536 | be used. We convert to a 32 bit type here, because so much code | ||
| 1537 | assume on that. | ||
| 1538 | |||
| 1539 | The bytes and offsets passed to XGetWindowProperty refers to the | ||
| 1540 | property and those are indeed in 32 bit quantities if format is 32. */ | ||
| 1541 | |||
| 1542 | if (*actual_format_ret == 32 && *actual_format_ret < BITS_PER_LONG) | ||
| 1543 | { | ||
| 1544 | unsigned long i; | ||
| 1545 | int *idata = (int *) ((*data_ret) + offset); | ||
| 1546 | long *ldata = (long *) tmp_data; | ||
| 1547 | |||
| 1548 | for (i = 0; i < *actual_size_ret; ++i) | ||
| 1549 | { | ||
| 1550 | idata[i]= (int) ldata[i]; | ||
| 1551 | offset += 4; | ||
| 1552 | } | ||
| 1553 | } | ||
| 1554 | else | ||
| 1555 | { | ||
| 1556 | *actual_size_ret *= *actual_format_ret / 8; | ||
| 1557 | bcopy (tmp_data, (*data_ret) + offset, *actual_size_ret); | ||
| 1558 | offset += *actual_size_ret; | ||
| 1559 | } | ||
| 1529 | 1560 | ||
| 1530 | /* This was allocated by Xlib, so use XFree. */ | 1561 | /* This was allocated by Xlib, so use XFree. */ |
| 1531 | XFree ((char *) tmp_data); | 1562 | XFree ((char *) tmp_data); |
| @@ -1970,6 +2001,7 @@ lisp_data_to_selection_data (display, obj, | |||
| 1970 | else | 2001 | else |
| 1971 | /* This vector is an INTEGER set, or something like it */ | 2002 | /* This vector is an INTEGER set, or something like it */ |
| 1972 | { | 2003 | { |
| 2004 | int data_size = 2; | ||
| 1973 | *size_ret = XVECTOR (obj)->size; | 2005 | *size_ret = XVECTOR (obj)->size; |
| 1974 | if (NILP (type)) type = QINTEGER; | 2006 | if (NILP (type)) type = QINTEGER; |
| 1975 | *format_ret = 16; | 2007 | *format_ret = 16; |
| @@ -1982,7 +2014,11 @@ lisp_data_to_selection_data (display, obj, | |||
| 1982 | ("elements of selection vector must be integers or conses of integers"), | 2014 | ("elements of selection vector must be integers or conses of integers"), |
| 1983 | Fcons (obj, Qnil))); | 2015 | Fcons (obj, Qnil))); |
| 1984 | 2016 | ||
| 1985 | *data_ret = (unsigned char *) xmalloc (*size_ret * (*format_ret/8)); | 2017 | /* Use sizeof(long) even if it is more than 32 bits. See comment |
| 2018 | in x_get_window_property and x_fill_property_data. */ | ||
| 2019 | |||
| 2020 | if (*format_ret == 32) data_size = sizeof(long); | ||
| 2021 | *data_ret = (unsigned char *) xmalloc (*size_ret * data_size); | ||
| 1986 | for (i = 0; i < *size_ret; i++) | 2022 | for (i = 0; i < *size_ret; i++) |
| 1987 | if (*format_ret == 32) | 2023 | if (*format_ret == 32) |
| 1988 | (*((unsigned long **) data_ret)) [i] | 2024 | (*((unsigned long **) data_ret)) [i] |
| @@ -2469,8 +2505,10 @@ x_check_property_data (data) | |||
| 2469 | DATA is a Lisp list of values to be converted. | 2505 | DATA is a Lisp list of values to be converted. |
| 2470 | RET is the C array that contains the converted values. It is assumed | 2506 | RET is the C array that contains the converted values. It is assumed |
| 2471 | it is big enough to hold all values. | 2507 | it is big enough to hold all values. |
| 2472 | FORMAT is 8, 16 or 32 and gives the size in bits for each C value to | 2508 | FORMAT is 8, 16 or 32 and denotes char/short/long for each C value to |
| 2473 | be stored in RET. */ | 2509 | be stored in RET. Note that long is used for 32 even if long is more |
| 2510 | than 32 bits (see man pages for XChangeProperty, XGetWindowProperty and | ||
| 2511 | XClientMessageEvent). */ | ||
| 2474 | 2512 | ||
| 2475 | void | 2513 | void |
| 2476 | x_fill_property_data (dpy, data, ret, format) | 2514 | x_fill_property_data (dpy, data, ret, format) |
| @@ -2479,10 +2517,10 @@ x_fill_property_data (dpy, data, ret, format) | |||
| 2479 | void *ret; | 2517 | void *ret; |
| 2480 | int format; | 2518 | int format; |
| 2481 | { | 2519 | { |
| 2482 | CARD32 val; | 2520 | long val; |
| 2483 | CARD32 *d32 = (CARD32 *) ret; | 2521 | long *d32 = (long *) ret; |
| 2484 | CARD16 *d16 = (CARD16 *) ret; | 2522 | short *d16 = (short *) ret; |
| 2485 | CARD8 *d08 = (CARD8 *) ret; | 2523 | char *d08 = (char *) ret; |
| 2486 | Lisp_Object iter; | 2524 | Lisp_Object iter; |
| 2487 | 2525 | ||
| 2488 | for (iter = data; CONSP (iter); iter = XCDR (iter)) | 2526 | for (iter = data; CONSP (iter); iter = XCDR (iter)) |
| @@ -2490,24 +2528,24 @@ x_fill_property_data (dpy, data, ret, format) | |||
| 2490 | Lisp_Object o = XCAR (iter); | 2528 | Lisp_Object o = XCAR (iter); |
| 2491 | 2529 | ||
| 2492 | if (INTEGERP (o)) | 2530 | if (INTEGERP (o)) |
| 2493 | val = (CARD32) XFASTINT (o); | 2531 | val = (long) XFASTINT (o); |
| 2494 | else if (FLOATP (o)) | 2532 | else if (FLOATP (o)) |
| 2495 | val = (CARD32) XFLOAT_DATA (o); | 2533 | val = (long) XFLOAT_DATA (o); |
| 2496 | else if (CONSP (o)) | 2534 | else if (CONSP (o)) |
| 2497 | val = (CARD32) cons_to_long (o); | 2535 | val = (long) cons_to_long (o); |
| 2498 | else if (STRINGP (o)) | 2536 | else if (STRINGP (o)) |
| 2499 | { | 2537 | { |
| 2500 | BLOCK_INPUT; | 2538 | BLOCK_INPUT; |
| 2501 | val = XInternAtom (dpy, (char *) SDATA (o), False); | 2539 | val = (long) XInternAtom (dpy, (char *) SDATA (o), False); |
| 2502 | UNBLOCK_INPUT; | 2540 | UNBLOCK_INPUT; |
| 2503 | } | 2541 | } |
| 2504 | else | 2542 | else |
| 2505 | error ("Wrong type, must be string, number or cons"); | 2543 | error ("Wrong type, must be string, number or cons"); |
| 2506 | 2544 | ||
| 2507 | if (format == 8) | 2545 | if (format == 8) |
| 2508 | *d08++ = (CARD8) val; | 2546 | *d08++ = (char) val; |
| 2509 | else if (format == 16) | 2547 | else if (format == 16) |
| 2510 | *d16++ = (CARD16) val; | 2548 | *d16++ = (short) val; |
| 2511 | else | 2549 | else |
| 2512 | *d32++ = val; | 2550 | *d32++ = val; |
| 2513 | } | 2551 | } |
| @@ -2633,7 +2671,8 @@ x_handle_dnd_message (f, event, dpyinfo, bufp) | |||
| 2633 | { | 2671 | { |
| 2634 | Lisp_Object vec; | 2672 | Lisp_Object vec; |
| 2635 | Lisp_Object frame; | 2673 | Lisp_Object frame; |
| 2636 | unsigned long size = (8*sizeof (event->data))/event->format; | 2674 | /* format 32 => size 5, format 16 => size 10, format 8 => size 20 */ |
| 2675 | unsigned long size = 160/event->format; | ||
| 2637 | int x, y; | 2676 | int x, y; |
| 2638 | unsigned char *data = (unsigned char *) event->data.b; | 2677 | unsigned char *data = (unsigned char *) event->data.b; |
| 2639 | int idata[5]; | 2678 | int idata[5]; |
| @@ -2712,8 +2751,6 @@ are ignored. */) | |||
| 2712 | struct frame *f = check_x_frame (from); | 2751 | struct frame *f = check_x_frame (from); |
| 2713 | int count; | 2752 | int count; |
| 2714 | int to_root; | 2753 | int to_root; |
| 2715 | int idata[5]; | ||
| 2716 | void *data; | ||
| 2717 | 2754 | ||
| 2718 | CHECK_STRING (message_type); | 2755 | CHECK_STRING (message_type); |
| 2719 | CHECK_NUMBER (format); | 2756 | CHECK_NUMBER (format); |
| @@ -2774,30 +2811,10 @@ are ignored. */) | |||
| 2774 | event.xclient.window = to_root ? FRAME_OUTER_WINDOW (f) : wdest; | 2811 | event.xclient.window = to_root ? FRAME_OUTER_WINDOW (f) : wdest; |
| 2775 | 2812 | ||
| 2776 | 2813 | ||
| 2777 | if (event.xclient.format == 32 && event.xclient.format < BITS_PER_LONG) | 2814 | memset (event.xclient.data.b, 0, sizeof (event.xclient.data.b)); |
| 2778 | { | 2815 | x_fill_property_data (dpyinfo->display, values, event.xclient.data.b, |
| 2779 | /* x_fill_property_data expects data to hold 32 bit values when | 2816 | event.xclient.format); |
| 2780 | format == 32, but on a 64 bit machine long is 64 bits. | ||
| 2781 | event.xclient.l is an array of long, so we must compensate. */ | ||
| 2782 | |||
| 2783 | memset (idata, 0, sizeof (idata)); | ||
| 2784 | data = idata; | ||
| 2785 | } | ||
| 2786 | else | ||
| 2787 | { | ||
| 2788 | memset (event.xclient.data.b, 0, sizeof (event.xclient.data.b)); | ||
| 2789 | data = event.xclient.data.b; | ||
| 2790 | } | ||
| 2791 | 2817 | ||
| 2792 | x_fill_property_data (dpyinfo->display, values, data, event.xclient.format); | ||
| 2793 | |||
| 2794 | if (data == idata) | ||
| 2795 | { | ||
| 2796 | int i; | ||
| 2797 | for (i = 0; i < 5; ++i) /* There are only 5 longs in a ClientMessage. */ | ||
| 2798 | event.xclient.data.l[i] = (long) idata[i]; | ||
| 2799 | } | ||
| 2800 | |||
| 2801 | /* If event mask is 0 the event is sent to the client that created | 2818 | /* If event mask is 0 the event is sent to the client that created |
| 2802 | the destination window. But if we are sending to the root window, | 2819 | the destination window. But if we are sending to the root window, |
| 2803 | there is no such client. Then we set the event mask to 0xffff. The | 2820 | there is no such client. Then we set the event mask to 0xffff. The |