emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] master 7a6b3d0: Fix interpretation of signed vs unsigned v


From: Noah Friedman
Subject: [Emacs-diffs] master 7a6b3d0: Fix interpretation of signed vs unsigned values when retrieving X
Date: Sun, 21 Aug 2016 21:04:48 +0000 (UTC)

branch: master
commit 7a6b3d0fb793864a1f5deb5a22de78a4dced652d
Author: Noah Friedman <address@hidden>
Commit: Noah Friedman <address@hidden>

    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.
---
 src/xfns.c    |   60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 src/xselect.c |   59 ++++++++++++++++++++++++++++++++++++++++++++------------
 2 files changed, 106 insertions(+), 13 deletions(-)

diff --git a/src/xfns.c b/src/xfns.c
index ccea20e..8860a21 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -5113,6 +5113,7 @@ FRAME.  Default is to change on the edit X window.  */)
       if (INT_MAX < SBYTES (value))
        error ("VALUE too long");
       nelements = SBYTES (value);
+      element_format = 8; /* ignore any provided format */
     }
 
   block_input ();
@@ -5223,7 +5224,7 @@ x_window_property_intern (struct frame *f,
             }
 
           if (NILP (vector_ret_p))
-            prop_value = make_string ((char *) tmp_data, actual_size);
+            prop_value = make_string ((char *) tmp_data, (actual_format / 8) * 
actual_size);
           else
             prop_value = x_property_data_to_lisp (f,
                                                   tmp_data,
@@ -5310,6 +5311,62 @@ no value of TYPE (always string in the MS Windows case). 
 */)
   return prop_value;
 }
 
+DEFUN ("x-window-property-attributes", Fx_window_property_attributes, 
Sx_window_property_attributes,
+       1, 3, 0,
+       doc: /* Retrieve metadata about window property PROP on FRAME.
+If FRAME is nil or omitted, use the selected frame.
+If SOURCE is non-nil, get the property on that window instead of from
+FRAME.  The number 0 denotes the root window.
+
+Return value is nil if FRAME hasn't a property with name PROP.
+Otherwise, the return value is a vector with the following fields:
+
+0. The property type, as an integer.  The symbolic name of
+ the type can be obtained with `x-get-atom-name'.
+1. The format of each element; one of 8, 16, or 32.
+2. The length of the property, in number of elements. */)
+  (Lisp_Object prop, Lisp_Object frame, Lisp_Object source)
+{
+  struct frame *f = decode_window_system_frame (frame);
+  Window target_window = FRAME_X_WINDOW (f);
+  Atom prop_atom;
+  Lisp_Object prop_attr = Qnil;
+  Atom actual_type;
+  int actual_format;
+  unsigned long actual_size, bytes_remaining;
+  unsigned char *tmp_data = NULL;
+  int rc;
+
+  CHECK_STRING (prop);
+
+  if (! NILP (source))
+    {
+      CONS_TO_INTEGER (source, Window, target_window);
+      if (! target_window)
+       target_window = FRAME_DISPLAY_INFO (f)->root_window;
+    }
+
+  block_input ();
+
+  prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SSDATA (prop), False);
+  rc = XGetWindowProperty (FRAME_X_DISPLAY (f), target_window,
+                          prop_atom, 0, 0, False, AnyPropertyType,
+                          &actual_type, &actual_format, &actual_size,
+                          &bytes_remaining, &tmp_data);
+  if (rc == Success && actual_format != 0)
+    {
+      XFree (tmp_data);
+
+      prop_attr = Fmake_vector (make_number (3), Qnil);
+      ASET (prop_attr, 0, make_number (actual_type));
+      ASET (prop_attr, 1, make_number (actual_format));
+      ASET (prop_attr, 2, make_number (bytes_remaining / (actual_format / 8)));
+    }
+
+  unblock_input ();
+  return prop_attr;
+}
+
 /***********************************************************************
                                Tool tips
  ***********************************************************************/
@@ -6966,6 +7023,7 @@ When using Gtk+ tooltips, the tooltip face is not used.  
*/);
   defsubr (&Sx_change_window_property);
   defsubr (&Sx_delete_window_property);
   defsubr (&Sx_window_property);
+  defsubr (&Sx_window_property_attributes);
 
   defsubr (&Sxw_display_color_p);
   defsubr (&Sx_display_grayscale_p);
diff --git a/src/xselect.c b/src/xselect.c
index 616d12c..156888a 100644
--- a/src/xselect.c
+++ b/src/xselect.c
@@ -1612,11 +1612,24 @@ selection_data_to_lisp_data (struct x_display_info 
*dpyinfo,
   /* Convert a single 16-bit number or a small 32-bit number to a Lisp_Int.
      If the number is 32 bits and won't fit in a Lisp_Int,
      convert it to a cons of integers, 16 bits in each half.
+
+     INTEGER is a signed type, CARDINAL is unsigned.
+     Assume any other types are unsigned as well.
    */
   else if (format == 32 && size == sizeof (int))
-    return INTEGER_TO_CONS (((int *) data) [0]);
+    {
+      if (type == XA_INTEGER)
+        return INTEGER_TO_CONS (((int *) data) [0]);
+      else
+        return INTEGER_TO_CONS (((unsigned int *) data) [0]);
+    }
   else if (format == 16 && size == sizeof (short))
-    return make_number (((short *) data) [0]);
+    {
+      if (type == XA_INTEGER)
+        return make_number (((short *) data) [0]);
+      else
+        return make_number (((unsigned short *) data) [0]);
+    }
 
   /* Convert any other kind of data to a vector of numbers, represented
      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,
       ptrdiff_t i;
       Lisp_Object v = make_uninit_vector (size / 2);
 
-      for (i = 0; i < size / 2; i++)
-       {
-         short j = ((short *) data) [i];
-         ASET (v, i, make_number (j));
-       }
+      if (type == XA_INTEGER)
+        {
+          for (i = 0; i < size / 2; i++)
+            {
+              short j = ((short *) data) [i];
+              ASET (v, i, make_number (j));
+            }
+        }
+      else
+        {
+          for (i = 0; i < size / 2; i++)
+            {
+              unsigned short j = ((unsigned short *) data) [i];
+              ASET (v, i, make_number (j));
+            }
+        }
       return v;
     }
   else
@@ -1638,11 +1662,22 @@ selection_data_to_lisp_data (struct x_display_info 
*dpyinfo,
       ptrdiff_t i;
       Lisp_Object v = make_uninit_vector (size / X_LONG_SIZE);
 
-      for (i = 0; i < size / X_LONG_SIZE; i++)
-       {
-         int j = ((int *) data) [i];
-         ASET (v, i, INTEGER_TO_CONS (j));
-       }
+      if (type == XA_INTEGER)
+        {
+          for (i = 0; i < size / X_LONG_SIZE; i++)
+            {
+              int j = ((int *) data) [i];
+              ASET (v, i, INTEGER_TO_CONS (j));
+            }
+        }
+      else
+        {
+          for (i = 0; i < size / X_LONG_SIZE; i++)
+            {
+              unsigned int j = ((unsigned int *) data) [i];
+              ASET (v, i, INTEGER_TO_CONS (j));
+            }
+        }
       return v;
     }
 }



reply via email to

[Prev in Thread] Current Thread [Next in Thread]