changeset 5639:1d1f385c9149

Call XKeysymToString() much less, it leaks. src/ChangeLog addition: 2012-01-08 Aidan Kehoe <kehoea@parhasard.net> * device-x.c: * device-x.c (syms_of_device_x): Move #'x-keysym-on-keyboard{,-sans-modifiers}-p to Lisp, the hash table no longer stores the X keysyms, so we need to manipulate any strings we have been handed. * event-Xt.c (x_has_keysym): Don't call XKeysymToString() here, it leaks; trust x_keysym_to_emacs_keysym() instead. * event-Xt.c (x_keysym_to_emacs_keysym): No longer leak when looking up the strings for keysyms of the form UABCD. lisp/ChangeLog addition: 2012-01-08 Aidan Kehoe <kehoea@parhasard.net> * x-init.el: * x-init.el (pseudo-canonicalize-keysym): New. * x-init.el: Move #'x-keysym-on-keyboard-sans-modifiers-p, #'x-keysym-on-keyboard-p here from device-x.c, some string manipulation it now needs to do is far easier in Lisp. * x-win-xfree86.el: * x-win-xfree86.el (x-win-init-xfree86): No longer call #'x-keysym-on-keyboard{,-sans-modifiers}-p, implement it ourselves cheaply.
author Aidan Kehoe <kehoea@parhasard.net>
date Sun, 08 Jan 2012 20:41:37 +0000
parents 4050bbef9bf6
children e6b5c49f9e13
files lisp/ChangeLog lisp/x-init.el lisp/x-win-xfree86.el src/ChangeLog src/device-x.c src/event-Xt.c
diffstat 6 files changed, 107 insertions(+), 88 deletions(-) [+]
line wrap: on
line diff
--- a/lisp/ChangeLog	Fri Jan 06 16:35:07 2012 +0000
+++ b/lisp/ChangeLog	Sun Jan 08 20:41:37 2012 +0000
@@ -1,3 +1,15 @@
+2012-01-08  Aidan Kehoe  <kehoea@parhasard.net>
+
+	* x-init.el:
+	* x-init.el (pseudo-canonicalize-keysym): New.
+	* x-init.el: Move #'x-keysym-on-keyboard-sans-modifiers-p,
+	#'x-keysym-on-keyboard-p here from device-x.c, some string
+	manipulation it now needs to do is far easier in Lisp.
+	* x-win-xfree86.el:
+	* x-win-xfree86.el (x-win-init-xfree86):
+	No longer call #'x-keysym-on-keyboard{,-sans-modifiers}-p,
+	implement it ourselves cheaply.
+
 2012-01-02  Aidan Kehoe  <kehoea@parhasard.net>
 
 	* bytecomp.el (cl-compile-time-init): Add an autoload for this,
--- a/lisp/x-init.el	Fri Jan 06 16:35:07 2012 +0000
+++ b/lisp/x-init.el	Sun Jan 08 20:41:37 2012 +0000
@@ -31,8 +31,7 @@
 ;;; Code:
 
 (globally-declare-fboundp
- '(x-keysym-on-keyboard-p
-   x-server-vendor x-init-specifier-from-resources init-mule-x-win))
+ '(x-server-vendor x-init-specifier-from-resources init-mule-x-win))
 
 (globally-declare-boundp
  '(x-initial-argv-list x-app-defaults-directory))
@@ -79,6 +78,56 @@
   (interactive)
   (ow-find t))
 
+(labels
+    ((pseudo-canonicalize-keysym (keysym)
+       "If KEYSYM (a string or a symbol) might describe a keysym on
+the current keyboard, return its canonical XEmacs form, a symbol;
+otherwise return nil.
+
+Does not intern new symbols, since if a string doesn't correspond to a
+keysym that XEmacs has seen, that string won't be in obarray."
+       (if (symbolp keysym)
+	   keysym
+	 (if (stringp keysym)
+             (or (intern-soft keysym)
+                 (intern-soft (nsubstitute ?- ?_ (downcase keysym))))))))
+  (declare (inline pseudo-canonicalize-keysym))
+
+  (defun x-keysym-on-keyboard-sans-modifiers-p (keysym &optional device)
+    "Return true if KEYSYM names a key on the keyboard of DEVICE.
+More precisely, return true if pressing a physical key
+on the keyboard of DEVICE without any modifier keys generates KEYSYM.
+Valid keysyms are listed in the files /usr/include/X11/keysymdef.h and in
+/usr/lib/X11/XKeysymDB, or whatever the equivalents are on your system.
+The keysym name can be provided in two forms:
+- if keysym is a string, it must be the name as known to X windows.
+- if keysym is a symbol, it must be the name as known to XEmacs.
+The two names differ in capitalization and underscoring."
+    (eq 'sans-modifiers (gethash (pseudo-canonicalize-keysym keysym)
+				 (x-keysym-hash-table device))))
+
+ (defun x-keysym-on-keyboard-p (keysym &optional device)
+   "Return true if KEYSYM names a key on the keyboard of DEVICE.
+More precisely, return true if some keystroke (possibly including modifiers)
+on the keyboard of DEVICE keys generates KEYSYM.
+Valid keysyms are listed in the files /usr/include/X11/keysymdef.h and in
+/usr/lib/X11/XKeysymDB, or whatever the equivalents are on your system.
+The keysym name can be provided in two forms:
+- if keysym is a string, it must be the name as known to X windows.
+- if keysym is a symbol, it must be the name as known to XEmacs.
+The two names differ in capitalization and underscoring.
+
+This function is not entirely trustworthy, in that Xlib compose processing
+can produce keysyms that XEmacs will not have seen when it examined the
+keysyms available on startup.  So pressing `dead-diaeresis' and then 'a' may
+pass `adiaeresis' to XEmacs, or (in some implementations) even `U00E4',
+where `(x-keysym-on-keyboard-p 'adiaeresis)' and `(x-keysym-on-keyboard-p
+'U00E4)' would both have returned nil.  Subsequent to XEmacs seeing a keysym
+it was previously unaware of, the predicate will take note of it, though."
+   (and	(gethash (pseudo-canonicalize-keysym keysym)
+                 (x-keysym-hash-table device))
+	t)))
+
 (eval-when-compile
   (load "x-win-sun"     nil t)
   (load "x-win-xfree86" nil t))
--- a/lisp/x-win-xfree86.el	Fri Jan 06 16:35:07 2012 +0000
+++ b/lisp/x-win-xfree86.el	Sun Jan 08 20:41:37 2012 +0000
@@ -39,9 +39,6 @@
 
 ;;; Code:
 
-(globally-declare-fboundp
- '(x-keysym-on-keyboard-p x-keysym-on-keyboard-sans-modifiers-p))
-
 (defun x-win-init-xfree86 (device)
 
   ;; We know this keyboard is an XFree86 keyboard. As such, we can predict
@@ -74,9 +71,6 @@
 	     nil nil nil nil nil ?/ nil nil nil nil nil nil nil nil 
 	     nil nil nil nil nil ?=])
 
-  (when (x-keysym-on-keyboard-p 'iso-left-tab device) 
-    (define-key function-key-map 'iso-left-tab [(shift tab)]))
-
   (loop for (key sane-key) in
     '((f13 f1)
       (f14 f2)
@@ -94,13 +88,17 @@
     with function-key-map = (symbol-value-in-console 'function-key-map
                                                      (device-console device)
                                                      function-key-map)
+    with x-keysym-hash-table = (x-keysym-hash-table device)
+
+    initially
+    (when (gethash 'iso-left-tab x-keysym-hash-table)
+      (define-key function-key-map 'iso-left-tab [(shift tab)]))
 
     do
-    (when (and (x-keysym-on-keyboard-p key device)
-	       (not (x-keysym-on-keyboard-sans-modifiers-p key device)))
+    (when (not (memq (gethash key x-keysym-hash-table) '(nil sans-modifiers)))
       ;; define also the control, meta, and meta-control versions.
       (loop for mods in '(() (control) (meta) (meta control)) do
-	(define-key function-key-map `[(,@mods ,key)] `[(shift ,@mods ,sane-key)])
-	))))
+	(define-key function-key-map `[(,@mods ,key)]
+          `[(shift ,@mods ,sane-key)])))))
 
 ;;; x-win-xfree86.el ends here
--- a/src/ChangeLog	Fri Jan 06 16:35:07 2012 +0000
+++ b/src/ChangeLog	Sun Jan 08 20:41:37 2012 +0000
@@ -1,3 +1,17 @@
+2012-01-08  Aidan Kehoe  <kehoea@parhasard.net>
+
+	* device-x.c:
+	* device-x.c (syms_of_device_x):
+	Move #'x-keysym-on-keyboard{,-sans-modifiers}-p to Lisp, the hash
+	table no longer stores the X keysyms, so we need to manipulate any
+	strings we have been handed.
+	* event-Xt.c (x_has_keysym):
+	Don't call XKeysymToString() here, it leaks; trust
+	x_keysym_to_emacs_keysym() instead.
+	* event-Xt.c (x_keysym_to_emacs_keysym):
+	No longer leak when looking up the strings for keysyms of the form
+	UABCD.
+
 2012-01-03  Didier Verna  <didier@xemacs.org>
 
 	* faces.c (complex_vars_of_faces): Add missing foreback specifier
--- a/src/device-x.c	Fri Jan 06 16:35:07 2012 +0000
+++ b/src/device-x.c	Sun Jan 08 20:41:37 2012 +0000
@@ -1830,60 +1830,6 @@
 
   return DEVICE_X_DATA (d)->x_keysym_map_hash_table;
 }
-
-DEFUN ("x-keysym-on-keyboard-sans-modifiers-p", Fx_keysym_on_keyboard_sans_modifiers_p,
-       1, 2, 0, /*
-Return true if KEYSYM names a key on the keyboard of DEVICE.
-More precisely, return true if pressing a physical key
-on the keyboard of DEVICE without any modifier keys generates KEYSYM.
-Valid keysyms are listed in the files /usr/include/X11/keysymdef.h and in
-/usr/lib/X11/XKeysymDB, or whatever the equivalents are on your system.
-The keysym name can be provided in two forms:
-- if keysym is a string, it must be the name as known to X windows.
-- if keysym is a symbol, it must be the name as known to XEmacs.
-The two names differ in capitalization and underscoring.
-*/
-       (keysym, device))
-{
-  struct device *d = decode_device (device);
-  if (!DEVICE_X_P (d))
-    gui_error ("Not an X device", device);
-
-  return (EQ (Qsans_modifiers,
-	      Fgethash (keysym, DEVICE_X_KEYSYM_MAP_HASH_TABLE (d), Qnil)) ?
-	  Qt : Qnil);
-}
-
-
-DEFUN ("x-keysym-on-keyboard-p", Fx_keysym_on_keyboard_p, 1, 2, 0, /*
-Return true if KEYSYM names a key on the keyboard of DEVICE.
-More precisely, return true if some keystroke (possibly including modifiers)
-on the keyboard of DEVICE keys generates KEYSYM.
-Valid keysyms are listed in the files /usr/include/X11/keysymdef.h and in
-/usr/lib/X11/XKeysymDB, or whatever the equivalents are on your system.
-The keysym name can be provided in two forms:
-- if keysym is a string, it must be the name as known to X windows.
-- if keysym is a symbol, it must be the name as known to XEmacs.
-The two names differ in capitalization and underscoring.
-
-This function is not entirely trustworthy, in that Xlib compose processing
-can produce keysyms that XEmacs will not have seen when it examined the
-keysyms available on startup.  So pressing `dead-diaeresis' and then 'a' may
-pass `adiaeresis' to XEmacs, or (in some implementations) even `U00E4',
-where `(x-keysym-on-keyboard-p 'adiaeresis)' and `(x-keysym-on-keyboard-p
-'U00E4)' would both have returned nil.  Subsequent to XEmacs seeing a keysym
-it was previously unaware of, the predicate will take note of it, though.
-*/
-       (keysym, device))
-{
-  struct device *d = decode_device (device);
-  if (!DEVICE_X_P (d))
-    gui_error ("Not an X device", device);
-
-  return (NILP (Fgethash (keysym, DEVICE_X_KEYSYM_MAP_HASH_TABLE (d), Qnil)) ?
-	  Qnil : Qt);
-}
-
 
 /************************************************************************/
 /*                          grabs and ungrabs                           */
@@ -2105,8 +2051,6 @@
   DEFSUBR (Fx_server_version);
   DEFSUBR (Fx_valid_keysym_name_p);
   DEFSUBR (Fx_keysym_hash_table);
-  DEFSUBR (Fx_keysym_on_keyboard_p);
-  DEFSUBR (Fx_keysym_on_keyboard_sans_modifiers_p);
 
   DEFSUBR (Fx_grab_pointer);
   DEFSUBR (Fx_ungrab_pointer);
--- a/src/event-Xt.c	Fri Jan 06 16:35:07 2012 +0000
+++ b/src/event-Xt.c	Sun Jan 08 20:41:37 2012 +0000
@@ -181,26 +181,17 @@
 
   for (j = 0; j < (upper_lower[0] == upper_lower[1] ? 1 : 2); j++)
     {
-      Extbyte *name;
-      keysym = upper_lower[j];
-
-      name = XKeysymToString (keysym);
-      if (name)
-	{
-	  /* X guarantees NAME to be in the Host Portable Character Encoding */
-	  Lisp_Object sym = x_keysym_to_emacs_keysym (keysym, 0);
-	  Lisp_Object new_value = with_modifiers ? Qt : Qsans_modifiers;
-	  Lisp_Object old_value = Fgethash (sym, hash_table, Qnil);
-
-	  if (! EQ (old_value, new_value)
-	      && ! (EQ (old_value, Qsans_modifiers) &&
-		    EQ (new_value, Qt)))
-	    {
-	      maybe_define_x_key_as_self_inserting_character (keysym, sym);
-	      Fputhash (build_extstring (name, Qbinary), new_value,
-			hash_table);
-	      Fputhash (sym, new_value, hash_table);
-	    }
+      KeySym ks = upper_lower[j];
+      Lisp_Object sym = x_keysym_to_emacs_keysym (ks, 0);
+      Lisp_Object new_value = with_modifiers ? Qt : Qsans_modifiers;
+      Lisp_Object old_value = Fgethash (sym, hash_table, Qnil);
+
+      if (! EQ (old_value, new_value)
+          && ! (EQ (old_value, Qsans_modifiers) &&
+                EQ (new_value, Qt)))
+        {
+          maybe_define_x_key_as_self_inserting_character (ks, sym);
+          Fputhash (sym, new_value, hash_table);
 	}
     }
 }
@@ -757,6 +748,17 @@
        characters are the same as their ASCII codes.  */
     return make_char (keysym);
 
+  if (keysym >= 0x01000000 && keysym <= 0x0110FFFF)
+    {
+      /* These keysyms malloc with XKeysymToString(), *every time the
+         function is called.* Avoid leaking, construct the keysym string
+         ourselves. */
+      Ascbyte buf [10];
+      qxesprintf ((Ibyte *) buf, keysym & 0xff0000 ? "U%06X" : "U%04X",
+                  (unsigned int) (keysym & 0xffffff));
+      return KEYSYM (buf);
+    }
+
   switch (keysym)
     {
       /* These would be handled correctly by the default case, but by