diff options
| author | Noah Friedman | 2016-08-21 14:03:46 -0700 |
|---|---|---|
| committer | Noah Friedman | 2016-08-21 14:04:37 -0700 |
| commit | 7a6b3d0fb793864a1f5deb5a22de78a4dced652d (patch) | |
| tree | 2da0a23eff517e5b5aa8417936500b0586d98131 /src | |
| parent | 14a86f837762af8d16eef57c315da93b56699901 (diff) | |
| download | emacs-7a6b3d0fb793864a1f5deb5a22de78a4dced652d.tar.gz emacs-7a6b3d0fb793864a1f5deb5a22de78a4dced652d.zip | |
Fix interpretation of signed vs unsigned values when retrieving X
Window properties, and make sure the full value is returned when not
parsed.
New subr to export type and format information about X Window
properties to lisp.
* src/xselect.c (selection_data_to_lisp_data): Treat any data as
unsigned unless its actual type is INTEGER.
CARDINALs, in particular, are unsigned.
* src/xfns.c (Fx_change_window_property): If value is a string, ignore
any provided format and force to 8.
(x_window_property_intern): If returning value as a string, the length
is actual_size times the actual format of each element, which is not
necessarily bytes.
(Fx_window_property_attributes): New subr.
(syms_of_xfns): Declare it.
Diffstat (limited to 'src')
| -rw-r--r-- | src/xfns.c | 60 | ||||
| -rw-r--r-- | src/xselect.c | 59 |
2 files changed, 106 insertions, 13 deletions
diff --git a/src/xfns.c b/src/xfns.c index ccea20eef96..8860a21e670 100644 --- a/src/xfns.c +++ b/src/xfns.c | |||
| @@ -5113,6 +5113,7 @@ FRAME. Default is to change on the edit X window. */) | |||
| 5113 | if (INT_MAX < SBYTES (value)) | 5113 | if (INT_MAX < SBYTES (value)) |
| 5114 | error ("VALUE too long"); | 5114 | error ("VALUE too long"); |
| 5115 | nelements = SBYTES (value); | 5115 | nelements = SBYTES (value); |
| 5116 | element_format = 8; /* ignore any provided format */ | ||
| 5116 | } | 5117 | } |
| 5117 | 5118 | ||
| 5118 | block_input (); | 5119 | block_input (); |
| @@ -5223,7 +5224,7 @@ x_window_property_intern (struct frame *f, | |||
| 5223 | } | 5224 | } |
| 5224 | 5225 | ||
| 5225 | if (NILP (vector_ret_p)) | 5226 | if (NILP (vector_ret_p)) |
| 5226 | prop_value = make_string ((char *) tmp_data, actual_size); | 5227 | prop_value = make_string ((char *) tmp_data, (actual_format / 8) * actual_size); |
| 5227 | else | 5228 | else |
| 5228 | prop_value = x_property_data_to_lisp (f, | 5229 | prop_value = x_property_data_to_lisp (f, |
| 5229 | tmp_data, | 5230 | tmp_data, |
| @@ -5310,6 +5311,62 @@ no value of TYPE (always string in the MS Windows case). */) | |||
| 5310 | return prop_value; | 5311 | return prop_value; |
| 5311 | } | 5312 | } |
| 5312 | 5313 | ||
| 5314 | DEFUN ("x-window-property-attributes", Fx_window_property_attributes, Sx_window_property_attributes, | ||
| 5315 | 1, 3, 0, | ||
| 5316 | doc: /* Retrieve metadata about window property PROP on FRAME. | ||
| 5317 | If FRAME is nil or omitted, use the selected frame. | ||
| 5318 | If SOURCE is non-nil, get the property on that window instead of from | ||
| 5319 | FRAME. The number 0 denotes the root window. | ||
| 5320 | |||
| 5321 | Return value is nil if FRAME hasn't a property with name PROP. | ||
| 5322 | Otherwise, the return value is a vector with the following fields: | ||
| 5323 | |||
| 5324 | 0. The property type, as an integer. The symbolic name of | ||
| 5325 | the type can be obtained with `x-get-atom-name'. | ||
| 5326 | 1. The format of each element; one of 8, 16, or 32. | ||
| 5327 | 2. The length of the property, in number of elements. */) | ||
| 5328 | (Lisp_Object prop, Lisp_Object frame, Lisp_Object source) | ||
| 5329 | { | ||
| 5330 | struct frame *f = decode_window_system_frame (frame); | ||
| 5331 | Window target_window = FRAME_X_WINDOW (f); | ||
| 5332 | Atom prop_atom; | ||
| 5333 | Lisp_Object prop_attr = Qnil; | ||
| 5334 | Atom actual_type; | ||
| 5335 | int actual_format; | ||
| 5336 | unsigned long actual_size, bytes_remaining; | ||
| 5337 | unsigned char *tmp_data = NULL; | ||
| 5338 | int rc; | ||
| 5339 | |||
| 5340 | CHECK_STRING (prop); | ||
| 5341 | |||
| 5342 | if (! NILP (source)) | ||
| 5343 | { | ||
| 5344 | CONS_TO_INTEGER (source, Window, target_window); | ||
| 5345 | if (! target_window) | ||
| 5346 | target_window = FRAME_DISPLAY_INFO (f)->root_window; | ||
| 5347 | } | ||
| 5348 | |||
| 5349 | block_input (); | ||
| 5350 | |||
| 5351 | prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (prop), False); | ||
| 5352 | rc = XGetWindowProperty (FRAME_X_DISPLAY (f), target_window, | ||
| 5353 | prop_atom, 0, 0, False, AnyPropertyType, | ||
| 5354 | &actual_type, &actual_format, &actual_size, | ||
| 5355 | &bytes_remaining, &tmp_data); | ||
| 5356 | if (rc == Success && actual_format != 0) | ||
| 5357 | { | ||
| 5358 | XFree (tmp_data); | ||
| 5359 | |||
| 5360 | prop_attr = Fmake_vector (make_number (3), Qnil); | ||
| 5361 | ASET (prop_attr, 0, make_number (actual_type)); | ||
| 5362 | ASET (prop_attr, 1, make_number (actual_format)); | ||
| 5363 | ASET (prop_attr, 2, make_number (bytes_remaining / (actual_format / 8))); | ||
| 5364 | } | ||
| 5365 | |||
| 5366 | unblock_input (); | ||
| 5367 | return prop_attr; | ||
| 5368 | } | ||
| 5369 | |||
| 5313 | /*********************************************************************** | 5370 | /*********************************************************************** |
| 5314 | Tool tips | 5371 | Tool tips |
| 5315 | ***********************************************************************/ | 5372 | ***********************************************************************/ |
| @@ -6966,6 +7023,7 @@ When using Gtk+ tooltips, the tooltip face is not used. */); | |||
| 6966 | defsubr (&Sx_change_window_property); | 7023 | defsubr (&Sx_change_window_property); |
| 6967 | defsubr (&Sx_delete_window_property); | 7024 | defsubr (&Sx_delete_window_property); |
| 6968 | defsubr (&Sx_window_property); | 7025 | defsubr (&Sx_window_property); |
| 7026 | defsubr (&Sx_window_property_attributes); | ||
| 6969 | 7027 | ||
| 6970 | defsubr (&Sxw_display_color_p); | 7028 | defsubr (&Sxw_display_color_p); |
| 6971 | defsubr (&Sx_display_grayscale_p); | 7029 | defsubr (&Sx_display_grayscale_p); |
diff --git a/src/xselect.c b/src/xselect.c index 616d12c7cab..156888a540b 100644 --- a/src/xselect.c +++ b/src/xselect.c | |||
| @@ -1612,11 +1612,24 @@ selection_data_to_lisp_data (struct x_display_info *dpyinfo, | |||
| 1612 | /* Convert a single 16-bit number or a small 32-bit number to a Lisp_Int. | 1612 | /* Convert a single 16-bit number or a small 32-bit number to a Lisp_Int. |
| 1613 | If the number is 32 bits and won't fit in a Lisp_Int, | 1613 | If the number is 32 bits and won't fit in a Lisp_Int, |
| 1614 | convert it to a cons of integers, 16 bits in each half. | 1614 | convert it to a cons of integers, 16 bits in each half. |
| 1615 | |||
| 1616 | INTEGER is a signed type, CARDINAL is unsigned. | ||
| 1617 | Assume any other types are unsigned as well. | ||
| 1615 | */ | 1618 | */ |
| 1616 | else if (format == 32 && size == sizeof (int)) | 1619 | else if (format == 32 && size == sizeof (int)) |
| 1617 | return INTEGER_TO_CONS (((int *) data) [0]); | 1620 | { |
| 1621 | if (type == XA_INTEGER) | ||
| 1622 | return INTEGER_TO_CONS (((int *) data) [0]); | ||
| 1623 | else | ||
| 1624 | return INTEGER_TO_CONS (((unsigned int *) data) [0]); | ||
| 1625 | } | ||
| 1618 | else if (format == 16 && size == sizeof (short)) | 1626 | else if (format == 16 && size == sizeof (short)) |
| 1619 | return make_number (((short *) data) [0]); | 1627 | { |
| 1628 | if (type == XA_INTEGER) | ||
| 1629 | return make_number (((short *) data) [0]); | ||
| 1630 | else | ||
| 1631 | return make_number (((unsigned short *) data) [0]); | ||
| 1632 | } | ||
| 1620 | 1633 | ||
| 1621 | /* Convert any other kind of data to a vector of numbers, represented | 1634 | /* Convert any other kind of data to a vector of numbers, represented |
| 1622 | as above (as an integer, or a cons of two 16 bit integers.) | 1635 | as above (as an integer, or a cons of two 16 bit integers.) |
| @@ -1626,11 +1639,22 @@ selection_data_to_lisp_data (struct x_display_info *dpyinfo, | |||
| 1626 | ptrdiff_t i; | 1639 | ptrdiff_t i; |
| 1627 | Lisp_Object v = make_uninit_vector (size / 2); | 1640 | Lisp_Object v = make_uninit_vector (size / 2); |
| 1628 | 1641 | ||
| 1629 | for (i = 0; i < size / 2; i++) | 1642 | if (type == XA_INTEGER) |
| 1630 | { | 1643 | { |
| 1631 | short j = ((short *) data) [i]; | 1644 | for (i = 0; i < size / 2; i++) |
| 1632 | ASET (v, i, make_number (j)); | 1645 | { |
| 1633 | } | 1646 | short j = ((short *) data) [i]; |
| 1647 | ASET (v, i, make_number (j)); | ||
| 1648 | } | ||
| 1649 | } | ||
| 1650 | else | ||
| 1651 | { | ||
| 1652 | for (i = 0; i < size / 2; i++) | ||
| 1653 | { | ||
| 1654 | unsigned short j = ((unsigned short *) data) [i]; | ||
| 1655 | ASET (v, i, make_number (j)); | ||
| 1656 | } | ||
| 1657 | } | ||
| 1634 | return v; | 1658 | return v; |
| 1635 | } | 1659 | } |
| 1636 | else | 1660 | else |
| @@ -1638,11 +1662,22 @@ selection_data_to_lisp_data (struct x_display_info *dpyinfo, | |||
| 1638 | ptrdiff_t i; | 1662 | ptrdiff_t i; |
| 1639 | Lisp_Object v = make_uninit_vector (size / X_LONG_SIZE); | 1663 | Lisp_Object v = make_uninit_vector (size / X_LONG_SIZE); |
| 1640 | 1664 | ||
| 1641 | for (i = 0; i < size / X_LONG_SIZE; i++) | 1665 | if (type == XA_INTEGER) |
| 1642 | { | 1666 | { |
| 1643 | int j = ((int *) data) [i]; | 1667 | for (i = 0; i < size / X_LONG_SIZE; i++) |
| 1644 | ASET (v, i, INTEGER_TO_CONS (j)); | 1668 | { |
| 1645 | } | 1669 | int j = ((int *) data) [i]; |
| 1670 | ASET (v, i, INTEGER_TO_CONS (j)); | ||
| 1671 | } | ||
| 1672 | } | ||
| 1673 | else | ||
| 1674 | { | ||
| 1675 | for (i = 0; i < size / X_LONG_SIZE; i++) | ||
| 1676 | { | ||
| 1677 | unsigned int j = ((unsigned int *) data) [i]; | ||
| 1678 | ASET (v, i, INTEGER_TO_CONS (j)); | ||
| 1679 | } | ||
| 1680 | } | ||
| 1646 | return v; | 1681 | return v; |
| 1647 | } | 1682 | } |
| 1648 | } | 1683 | } |