changeset 5866:5ea790936de9

Automated merge with file:///Sources/xemacs-21.5-checked-out
author Aidan Kehoe <kehoea@parhasard.net>
date Mon, 16 Mar 2015 00:11:30 +0000
parents 15041705c196 (diff) a45722e74335 (current diff)
children e0f1dfaa821e
files lisp/ChangeLog src/ChangeLog tests/ChangeLog
diffstat 23 files changed, 240 insertions(+), 162 deletions(-) [+]
line wrap: on
line diff
--- a/lisp/ChangeLog	Thu Mar 12 16:27:13 2015 +0000
+++ b/lisp/ChangeLog	Mon Mar 16 00:11:30 2015 +0000
@@ -1,3 +1,42 @@
+2015-03-16  Aidan Kehoe  <kehoea@parhasard.net>
+
+	* obsolete.el (max-char):
+	Make this available for compatiblity with GNU, implement it in
+	terms of char-code-limit.
+
+2015-03-15  Aidan Kehoe  <kehoea@parhasard.net>
+
+	* tty-init.el (make-frame-after-init-entry-point):
+	Behave better when TERM was not set; use
+	#'console-tty-terminal-type instead of (getenv "TERM") so we get
+	the value that reflects the current console. Thank you Uwe Brauer!
+
+	* mule/mule-tty-init.el (mule-tty-win-initted): Removed.
+	* mule/mule-tty-init.el (init-mule-tty-win): Removed.
+	* mule/mule-tty-init.el: Remove this file in its entirety.
+	* mule/mule-x-init.el (x-use-halfwidth-roman-font): Removed.
+	* mule/mule-x-init.el: Remove this file in its entirety.
+	* dumped-lisp.el (preloaded-file-list): Remove them from the
+	dumped file list. The functions within haven't been used since
+	they were imported from Mule in 1999, and the functionality of
+	init-mule-tty-win was already in tty-init.el. If someone wants to
+	automatically use a halfwidth roman font, they can go hunting for
+	the code, but there are no users on http://searchco.de/ as of
+	20150315. Leaving them around is confusing and distracting.
+
+2015-03-14  Aidan Kehoe  <kehoea@parhasard.net>
+
+	* cmdloop.el (no-character-typed):
+	New error, for those cases when a keystroke is to be treated as a
+	character but has no character equivalent.
+	* cmdloop.el (read-char-1): Use it.
+	* keymap.el (synthesize-keysym): Use it.
+
+2015-03-14  Aidan Kehoe  <kehoea@parhasard.net>
+
+	* cus-start.el (all): Describe help-event-list for Custom.
+	* keydefs.el (help-event-list): Initialise it.
+
 2015-03-12  Aidan Kehoe  <kehoea@parhasard.net>
 
 	* simple.el (append-message): Be more careful about saving a
--- a/lisp/cmdloop.el	Thu Mar 12 16:27:13 2015 +0000
+++ b/lisp/cmdloop.el	Mon Mar 16 00:11:30 2015 +0000
@@ -280,6 +280,10 @@
          (princ (gettext " not defined.") stream) ; doo dah, doo dah.
          ))
 
+(put 'no-character-typed 'display-error
+     #'(lambda (error-object stream)
+         (write-sequence "Not a character keystroke, " stream)
+         (write-sequence (key-description (cadr error-object)) stream)))
 
 (defcustom teach-extended-commands-p t
   "*If true, then `\\[execute-extended-command]' will teach you keybindings.
@@ -593,8 +597,7 @@
                                     (aref (cdr binding) (caar binding)))))))
                       (return-from read-char-1 character)))
                 (if errorp
-                    (error 'invalid-key-binding "Not a character keystroke"
-                           (aref events 0)))
+                    (error 'no-character-typed (aref events 0)))
                 ;; If we're not erroring, loop until we get a character
                 (setq events []))
            (if timeout (disable-timeout timeout))))))
--- a/lisp/cus-start.el	Thu Mar 12 16:27:13 2015 +0000
+++ b/lisp/cus-start.el	Mon Mar 16 00:11:30 2015 +0000
@@ -152,6 +152,7 @@
 	     (focus-follows-mouse x boolean)
 	     (help-char keyboard (choice character
 					 (sexp :tag "Single key specifier")))
+	     (help-event-list keyboard (repeat (sexp :format "%v")))
 	     (max-lisp-eval-depth limits integer)
 	     (max-specpdl-size limits integer)
 	     (meta-prefix-char keyboard character)
--- a/lisp/dumped-lisp.el	Thu Mar 12 16:27:13 2015 +0000
+++ b/lisp/dumped-lisp.el	Mon Mar 16 00:11:30 2015 +0000
@@ -178,8 +178,6 @@
 	   "mule/mule-composite"
 	   ))
        ;; may initialize coding systems
-       (when (featurep '(and mule x)) "mule/mule-x-init")
-       (when (featurep '(and mule tty)) "mule/mule-tty-init")
        (when (and (featurep 'mule) (memq system-type '(windows-nt cygwin32)))
 	 "mule/mule-win32-init")
        "code-init" ; set up defaults
--- a/lisp/keydefs.el	Thu Mar 12 16:27:13 2015 +0000
+++ b/lisp/keydefs.el	Mon Mar 16 00:11:30 2015 +0000
@@ -162,6 +162,8 @@
 ;; do backspace.
 (define-key global-map '(meta ??) 'help-command)
 
+(setq help-event-list '(help f1 (meta ??)))
+
 ;; FSFmacs indent.el
 
 ;;(define-key global-map "\t" 'self-insert-command)
--- a/lisp/keymap.el	Thu Mar 12 16:27:13 2015 +0000
+++ b/lisp/keymap.el	Mon Mar 16 00:11:30 2015 +0000
@@ -512,7 +512,7 @@
 	     (error "Illegal character in keysym: %c" char))
 	    (t
 	     ;; Illegal event.
-	     (error "Event has no character equivalent: %s" event))))
+	     (error 'no-character-typed event))))
     (vector (intern (concat "" (nreverse list))))))
 
 (defun synthesize-unicode-codepoint (ignore-prompt)
--- a/lisp/mule/mule-tty-init.el	Thu Mar 12 16:27:13 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-;;; mule-tty-init.el --- Initialization code for console tty under MULE -*- coding: iso-2022-7bit; -*-
-
-;; Copyright (C) 1998 Free Software Foundation, Inc.
-;; Copyright (C) 1998 Kazuyuki IENAGA <kazz@imasy.or.jp>
-
-;; Author: Kazuyuki IENAGA <kazz@imasy.or.jp>
-;; Keywords: mule, tty, console, dumped
-
-;; This file is part of XEmacs.
-
-;; XEmacs is free software: you can redistribute it and/or modify it
-;; under the terms of the GNU General Public License as published by the
-;; Free Software Foundation, either version 3 of the License, or (at your
-;; option) any later version.
-
-;; XEmacs is distributed in the hope that it will be useful, but WITHOUT
-;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-;; FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-;; for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with XEmacs.  If not, see <http://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; This file is dumped with XEmacs when Mule and TTY support are enabled.
-
-;;; Code:
-
-(defvar mule-tty-win-initted nil)
-
-(defun init-mule-tty-win ()
-  "Initialize TTY for MULE at startup. Don't call this."
-  (unless mule-tty-win-initted
-    (add-hook
-     'before-init-hook
-     (lambda ()
-       (when (eq (device-type) 'tty)
-	 (when (string-match "^kterm" (getenv "TERM"))
-	   (set-terminal-coding-system 'euc-jp)
-	   (set-keyboard-coding-system 'euc-jp))
-	 (declare-fboundp (set-console-tty-coding-system)))))
-    (setq mule-tty-win-initted t)))
-
-;;; mule-tty-init.el ends here
--- a/lisp/mule/mule-x-init.el	Thu Mar 12 16:27:13 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-;;; mule-x-init.el --- initialization code for X Windows under MULE -*- coding: iso-2022-7bit; -*-
-;; Copyright (C) 1994 Free Software Foundation, Inc.
-;; Copyright (C) 1996, 2002 Ben Wing <ben@xemacs.org>
-
-;; Author: various
-;; Keywords: mule X11
-
-;; This file is part of XEmacs.
-
-;; XEmacs is free software: you can redistribute it and/or modify it
-;; under the terms of the GNU General Public License as published by the
-;; Free Software Foundation, either version 3 of the License, or (at your
-;; option) any later version.
-
-;; XEmacs is distributed in the hope that it will be useful, but WITHOUT
-;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-;; FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-;; for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with XEmacs.  If not, see <http://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;;; Code:
-
-;;; Work around what is arguably a Sun CDE bug.
-
-;; #### This is unused, apparently.
-(defun x-use-halfwidth-roman-font (fullwidth-charset roman-registry)
-  "Maybe set charset registry of the 'ascii charset to ROMAN-REGISTRY.
-
-Do this only if:
- - the current display is an X device
- - the displayed width of FULLWIDTH-CHARSET is twice the displayed
-   width of the 'ascii charset, but only when using ROMAN-REGISTRY.
-
-Traditionally, Asian characters have been displayed so that they
-occupy exactly twice the screen space of ASCII (`halfwidth')
-characters.  On many systems, e.g. Sun CDE systems, this can only be
-achieved by using a national variant roman font to display ASCII."
-  (labels ((charset-font-width (charset)
-             (font-instance-width
-              (face-font-instance 'default (selected-device) charset)))
-	 
-           (twice-as-wide (cs1 cs2)
-             (let ((width1 (charset-font-width cs1))
-                   (width2 (charset-font-width cs2)))
-               (and width1 width2 (eq (+ width1 width1) width2)))))
-    (declare (inline charset-font-width))
-    (when (eq 'x (device-type))
-      (let ((original-registries (charset-registries 'ascii)))
-        (condition-case nil
-            (unless (twice-as-wide 'ascii fullwidth-charset)
-              (set-charset-registries 'ascii (vector roman-registry))
-              (unless (twice-as-wide 'ascii fullwidth-charset)
-                ;; Restore if roman-registry didn't help
-                (set-charset-registries 'ascii original-registries)))
-          (error (set-charset-registries 'ascii original-registries)))))))
-
-;;;;
--- a/lisp/obsolete.el	Thu Mar 12 16:27:13 2015 +0000
+++ b/lisp/obsolete.el	Mon Mar 16 00:11:30 2015 +0000
@@ -485,5 +485,15 @@
 (make-obsolete 'remrassoc "use delete* with :test #'equal, :key #'cdr")
 (make-obsolete 'remrassq "use delete* with :test #'eq, :key #'cdr")
 
+(defun max-char ()
+  "Return a fixnum one less than `char-code-limit'.
+
+In contrast with GNU Emacs, this is not necessarily a valid character, but it
+is an inclusive upper bound on the possible values returned by `char-int'."
+  (1- char-code-limit))
+(make-compatible
+ 'max-char
+ "consider `char-code-limit', which gives an exclusive upper bound")
+
 (provide 'obsolete)
 ;;; obsolete.el ends here
--- a/lisp/tty-init.el	Thu Mar 12 16:27:13 2015 +0000
+++ b/lisp/tty-init.el	Mon Mar 16 00:11:30 2015 +0000
@@ -66,7 +66,10 @@
   ;; override term-file-prefix. (startup.el does it after
   ;; loading the init file.)
   (when (and (find-coding-system 'euc-jp)
-             (string-match "^kterm" (getenv "TERM")))
+             (member* (mismatch "kterm"
+                                (canoncase (or (console-tty-terminal-type
+                                                console) ""))
+                                '(nil 5))))
     (set-console-tty-coding-system console 'euc-jp))
   (when init-file-loaded
     ;; temporarily select the console so that the changes
--- a/man/ChangeLog	Thu Mar 12 16:27:13 2015 +0000
+++ b/man/ChangeLog	Mon Mar 16 00:11:30 2015 +0000
@@ -1,3 +1,13 @@
+2015-03-15  Aidan Kehoe  <kehoea@parhasard.net>
+
+	* lispref/strings.texi (Character Codes):
+	Document `char-code-limit' here too.
+
+2015-03-14  Aidan Kehoe  <kehoea@parhasard.net>
+
+	* lispref/help.texi (Help Functions):
+	Document help-event-list, just added.
+
 2015-02-23  Mike Kupfer  <mike.kupfer@xemacs.org>
 
 	* internals/internals.texi (The Redisplay Mechanism):
--- a/man/lispref/help.texi	Thu Mar 12 16:27:13 2015 +0000
+++ b/man/lispref/help.texi	Mon Mar 16 00:11:30 2015 +0000
@@ -584,6 +584,13 @@
 subcommands of the prefix key.
 @end defvar
 
+@defvar help-event-list
+This variable provides a means to specify other characters that should
+act in the same way @code{help-char} does, with regard to
+@code{help-form} and supplying help. It is usually set to include
+@kbd{f1}, so that this key is also treated as giving help.
+@end defvar
+
 @defvar help-form
 If this variable is non-@code{nil}, its value is a form to evaluate
 whenever the character @code{help-char} is read.  If evaluating the form
--- a/man/lispref/strings.texi	Thu Mar 12 16:27:13 2015 +0000
+++ b/man/lispref/strings.texi	Mon Mar 16 00:11:30 2015 +0000
@@ -330,6 +330,17 @@
 @code{nil} is returned.
 @end defun
 
+@defvar char-code-limit
+This is a constant integer describing an exclusive upper bound on the
+results return by @code{char-int} and that set of integers (fixnums) for
+which @code{int-char} will give non-nil. Without @sc{mule}
+(internationalization) support this will be @code{#x100}, as described
+under @code{char-int}, but with @sc{mule} support the range of values is
+much bigger, at least 21 bits' worth.  If an integer is less than
+@var{char-code-limit}, it may still not have an associated character, it
+is still necessary to check with the next function, @code{char-int-p}.
+@end defvar
+
 @defun char-int-p object
 This function returns @code{t} if @var{object} is an integer that can be
 converted into a character.
--- a/src/.gdbinit.in.in	Thu Mar 12 16:27:13 2015 +0000
+++ b/src/.gdbinit.in.in	Mon Mar 16 00:11:30 2015 +0000
@@ -470,6 +470,7 @@
   if $lrecord_type == lrecord_type_lcrecord_list
     pstructtype lcrecord_list
   else
+#else
   if $lrecord_type == lrecord_type_string_direct_data
     pptype Lisp_String_Direct_Data
   else
@@ -484,8 +485,6 @@
   end
 #ifndef NEW_GC
   end
-  end
-  end
 #endif
   end
   end
--- a/src/ChangeLog	Thu Mar 12 16:27:13 2015 +0000
+++ b/src/ChangeLog	Mon Mar 16 00:11:30 2015 +0000
@@ -1,3 +1,65 @@
+2015-03-15  Aidan Kehoe  <kehoea@parhasard.net>
+
+	* text.h: Make CHAR_CODE_LIMIT available as a #define.
+	* text.h (valid_ichar_p): Use it.
+	* text.c: Make a fixnum Vchar_code_limit available here.
+	* text.c (non_ascii_valid_ichar_p): Use CHAR_CODE_LIMIT.
+	* text.c (vars_of_text): Make `char-code-limit' available to
+	Lisp.
+
+2015-03-14  Aidan Kehoe  <kehoea@parhasard.net>
+
+	* general-slots.h (Qno_character_typed): New error symbol.
+	* event-stream.c (syms_of_event_stream): Define it.
+	New error, for those cases when a keystroke is to be treated as a
+	character in some context but has no character equivalent.
+	* cmds.c (Fself_insert_command):
+	Use it.
+
+2015-03-14  Aidan Kehoe  <kehoea@parhasard.net>
+
+	Add support for GNU's help-event-list here, useful for accepting
+	F1 and C-h as the help character at the same time.
+	* event-stream.c:
+	* event-stream.c (echo_key_event):
+	Be better about calculation, comments here, in passing.
+	* event-stream.c (help_char_p): New.
+	* event-stream.c (execute_help_form):
+	There's no need to reset the command builder here; the code that
+	did relied on zero-termination, which we can't anymore, and did
+	not actually discard the help character. Remove this.
+	* event-stream.c (Fnext_event): Use help_char_p ().
+	* event-stream.c (command_builder_find_leaf_no_jit_binding):
+	Use help_char_p ().
+	* event-stream.c (vars_of_event_stream):
+	Make help-event-list available.
+
+2015-03-14  Aidan Kehoe  <kehoea@parhasard.net>
+
+	* .gdbinit.in.in (Lisp): lrecord_type_lcrecord_list is specific to
+	non-NEW_GC, lrecord_type_string_direct_data and
+	lrecord_type_string_indirect_data are specific to NEW_GC, correct
+	this in this file.
+
+2015-03-14  Aidan Kehoe  <kehoea@parhasard.net>
+
+	* keymap.c (event_matches_key_specifier_p):
+	If on a TTY, check the keysym and modifiers too, before converting
+	both events to characters and comparing them. We may well have
+	seen a function key (by means of function-key-map) and it is
+	actively unhelpful for
+	(event-matches-key-specifier-p (character-to-event 'f1) 'f1)
+	to given nil when the current device is a TTY.
+
+2015-03-12  Aidan Kehoe  <kehoea@parhasard.net>
+
+	* event-stream.c (lookup_command_event):
+	Check whether echo_buf_fill_pointer is negative before using it in
+	arithmetic, avoiding a crash in GC.
+	Oddly the old code didn't do this check and didn't crash, but its
+	echo_buf was from malloced memory, not from our string data, so
+	there may have been more room to manoeuvre.
+
 2015-03-04  Aidan Kehoe  <kehoea@parhasard.net>
 
 	* sequence.c (count_with_tail):
--- a/src/cmds.c	Thu Mar 12 16:27:13 2015 +0000
+++ b/src/cmds.c	Mon Mar 16 00:11:30 2015 +0000
@@ -346,9 +346,9 @@
     c = Fevent_to_character (Vlast_command_event, Qnil, Qnil, Qnil);
 
   if (NILP (c))
-    invalid_operation (
-	    "Last typed key has no character equivalent (that we know of)",
-	    Fcopy_event (Vlast_command_event, Qnil));
+    {
+      Fsignal (Qno_character_typed, Fcopy_event (Vlast_command_event, Qnil));
+    }
 
   CHECK_CHAR_COERCE_INT (c);
 
--- a/src/event-stream.c	Thu Mar 12 16:27:13 2015 +0000
+++ b/src/event-stream.c	Mon Mar 16 00:11:30 2015 +0000
@@ -197,10 +197,13 @@
    of the last-command-event. */
 Lisp_Object Vlast_command_event_time;
 
-/* Character to recognize as the help char.  */
+/* Key specifier to recognize as the help char.  */
 Lisp_Object Vhelp_char;
 
-/* Form to execute when help char is typed.  */
+/* List of other key specifiers that work in the same way as Vhelp_char. */
+Lisp_Object Vhelp_event_list;
+
+/* Form to execute when Vhelp_char or one of Vhelp_event_list is typed.  */
 Lisp_Object Vhelp_form;
 
 /* Command to run when the help character follows a prefix key.  */
@@ -650,7 +653,7 @@
   len = eilen (buf);
 
   if (NILP (command_builder->echo_buf) ||
-      (len + buf_fill_pointer + 4 > XSTRING_LENGTH (command_builder->echo_buf)))
+      (len + buf_fill_pointer + 3 > XSTRING_LENGTH (command_builder->echo_buf)))
     {
       eifree (buf);
       return;
@@ -665,7 +668,7 @@
   sledgehammer_check_ascii_begin (command_builder->echo_buf);
 
   command_builder->echo_buf_end = buf_fill_pointer + eilen (buf);
-  /* *Not* including the trailing " - ". */
+  /* Including the first space of the trailing " - ". */
   command_builder->echo_buf_fill_pointer = buf_fill_pointer + len + 1;
   eifree (buf);
 }
@@ -790,6 +793,27 @@
   return Qnil;
 }
 
+/* Return true if should recognize C as "the help character".  */
+static Boolint
+help_char_p (Lisp_Object event)
+{
+  if (event_matches_key_specifier_p (event, Vhelp_char))
+    {
+      return 1;
+    }
+
+  {
+    EXTERNAL_LIST_LOOP_2 (key_sequence, Vhelp_event_list)
+      {
+        if (event_matches_key_specifier_p (event, key_sequence))
+          {
+            return 1;
+          }
+      }
+  }
+  return 0;
+}
+
 static void
 execute_help_form (struct command_builder *command_builder,
                    Lisp_Object event)
@@ -797,18 +821,13 @@
   /* This function can GC */
   Lisp_Object help = Qnil;
   int speccount = specpdl_depth ();
-  Bytecount buf_fill_pointer = command_builder->echo_buf_fill_pointer;
-  Bytecount buf_end = command_builder->echo_buf_end;
-  Lisp_Object echo = ((buf_fill_pointer <= 0) ? Qnil
-                      : Fcopy_sequence (command_builder->echo_buf));
-
-  struct gcpro gcpro1, gcpro2;
-  GCPRO2 (echo, help);
+
+  struct gcpro gcpro1;
+  GCPRO1 (help);
 
   record_unwind_protect (Feval,
                          list2 (Qset_window_configuration,
                                 call0 (Qcurrent_window_configuration)));
-  reset_key_echo (command_builder, 1);
 
   help = IGNORE_MULTIPLE_VALUES (Feval (Vhelp_form));
   if (STRINGP (help))
@@ -835,17 +854,11 @@
   if (event_matches_key_specifier_p (event, make_char (' ')))
     {
       /* Discard next key if it is a space */
-      reset_key_echo (command_builder, 1);
+      /* No need to reset the key echo here. */
+      /* reset_key_echo (command_builder, 1); */
       Fnext_command_event (event, Qnil);
     }
 
-  command_builder->echo_buf_fill_pointer = buf_fill_pointer;
-  command_builder->echo_buf_end = buf_end;
-
-  if (buf_fill_pointer > 0)
-    {
-      command_builder->echo_buf = echo;
-    }
   UNGCPRO;
 }
 
@@ -2379,8 +2392,7 @@
      the help form and swallow this character.  Note that
      execute_help_form() calls Fnext_command_event(), which calls this
      function, as well as Fdispatch_event.  */
-  if (!NILP (Vhelp_form) &&
-      event_matches_key_specifier_p (event, Vhelp_char))
+  if (!NILP (Vhelp_form) && help_char_p (event))
     {
       /* temporarily reenable quit checking here, because we could get stuck */
       Vquit_flag = Qnil; /* see begin_dont_check_for_quit() */
@@ -3396,8 +3408,8 @@
     }
 
   /* help-char is `auto-bound' in every keymap */
-  if (!NILP (Vprefix_help_command) &&
-      event_matches_key_specifier_p (builder->most_current_event, Vhelp_char))
+  if (!NILP (Vprefix_help_command)
+      && help_char_p (builder->most_current_event))
     return Vprefix_help_command;
 
   return Qnil;
@@ -4067,10 +4079,11 @@
 #endif
 	  {
 	    Lisp_Object prompt = Fkeymap_prompt (leaf, Qt);
-	    if (STRINGP (prompt))
+	    if (STRINGP (prompt) && STRINGP (command_builder->echo_buf))
 	      {
 		/* Append keymap prompt to key echo buffer */
-		int buf_fill_pointer = command_builder->echo_buf_fill_pointer;
+		Bytecount buf_fill_pointer
+                  = max (command_builder->echo_buf_fill_pointer, 0);
 		Bytecount len = XSTRING_LENGTH (prompt);
 
 		if (len + buf_fill_pointer + 1
@@ -4090,7 +4103,8 @@
                     /* Show the keymap prompt, but don't adjust the fill
                        pointer to reflect it. */
                     command_builder->echo_buf_end
-                      = command_builder->echo_buf_fill_pointer + len;
+                      = buf_fill_pointer + len;
+                    command_builder->echo_buf_fill_pointer = buf_fill_pointer;
 		  }
 		maybe_echo_keys (command_builder, 1);
 	      }
@@ -4906,6 +4920,7 @@
   DEFSYMBOL (Qcommand_event_p);
 
   DEFERROR_STANDARD (Qundefined_keystroke_sequence, Qsyntax_error);
+  DEFERROR_STANDARD (Qno_character_typed, Qundefined_keystroke_sequence);
   DEFERROR_STANDARD (Qinvalid_key_binding, Qinvalid_state);
 
   DEFSUBR (Frecent_keys);
@@ -5152,18 +5167,25 @@
   Vthis_command_properties = Qnil;
 
   DEFVAR_LISP ("help-char", &Vhelp_char /*
-Character to recognize as meaning Help.
+Key specifier to recognize as meaning Help.
 When it is read, do `(eval help-form)', and display result if it's a string.
-If the value of `help-form' is nil, this char can be read normally.
-This can be any form recognized as a single key specifier.
-The help-char cannot be a negative number in XEmacs.
+If the value of `help-form' is nil, this key can be read normally.
+This can be any form recognized as a single key specifier; see
+`event-matches-key-specifier-p' and `define-key'.
 */ );
   Vhelp_char = make_char (8); /* C-h */
 
+  DEFVAR_LISP ("help-event-list", &Vhelp_event_list /*
+List of extra key specifiers to recognize as meaning Help.
+These are in addition to the value of `help-char', which see.  They function
+in the same way, and can equally be suppressed by binding `help-form' to nil.
+*/ );
+  Vhelp_event_list = Qnil;
+
   DEFVAR_LISP ("help-form", &Vhelp_form /*
-Form to execute when character help-char is read.
+Form to execute when `help-char' or an element of `help-event-list' is read.
 If the form returns a string, that string is displayed.
-If `help-form' is nil, the help char is not recognized.
+If `help-form' is nil, `help-char' and `help-event-list' are ignored.
 */ );
   Vhelp_form = Qnil;
 
--- a/src/general-slots.h	Thu Mar 12 16:27:13 2015 +0000
+++ b/src/general-slots.h	Mon Mar 16 00:11:30 2015 +0000
@@ -213,6 +213,7 @@
 SYMBOL_MODULE_API (Qnative);
 SYMBOL (Qnatnum);
 SYMBOL (Qno);
+SYMBOL (Qno_character_typed);
 SYMBOL (Qnone);
 SYMBOL (Qnot);
 SYMBOL (Qnothing);
--- a/src/keymap.c	Thu Mar 12 16:27:13 2015 +0000
+++ b/src/keymap.c	Mon Mar 16 00:11:30 2015 +0000
@@ -1582,6 +1582,9 @@
     event2 = Fcharacter_to_event (key_specifier, Qnil, Qnil, Qnil);
   if (XEVENT (event2)->event_type != key_press_event)
     retval = 0;
+  else if (EQ (XEVENT_KEY_KEYSYM (event), XEVENT_KEY_KEYSYM (event2)) &&
+	   XEVENT_KEY_MODIFIERS (event) == XEVENT_KEY_MODIFIERS (event2))
+    retval = 1;
   else if (CONSOLE_TTY_P (XCONSOLE (XEVENT_CHANNEL (event))))
     {
       int ch1, ch2;
@@ -1590,9 +1593,6 @@
       ch2 = event_to_character (event2, 0, 0);
       retval = (ch1 >= 0 && ch2 >= 0 && ch1 == ch2);
     }
-  else if (EQ (XEVENT_KEY_KEYSYM (event), XEVENT_KEY_KEYSYM (event2)) &&
-	   XEVENT_KEY_MODIFIERS (event) == XEVENT_KEY_MODIFIERS (event2))
-    retval = 1;
   else
     retval = 0;
   Fdeallocate_event (event2);
--- a/src/text.c	Thu Mar 12 16:27:13 2015 +0000
+++ b/src/text.c	Mon Mar 16 00:11:30 2015 +0000
@@ -1322,6 +1322,7 @@
 Lisp_Object QSin_char_byte_conversion;
 Lisp_Object QSin_internal_external_conversion;
 
+Fixnum Vchar_code_limit;
 
 /************************************************************************/
 /*                          qxestr***() functions                       */
@@ -4677,7 +4678,7 @@
   int f1, f2, f3;
 
   /* Must have only lowest 21 bits set */
-  if (ch & ~0x1FFFFF)
+  if (ch & ~(CHAR_CODE_LIMIT - 1))
     return 0;
 
   f1 = ichar_field1 (ch);
@@ -5143,6 +5144,14 @@
     build_defer_string ("(in internal-external conversion)");
   staticpro (&QSin_internal_external_conversion);
 
+  DEFVAR_CONST_INT ("char-code-limit", &Vchar_code_limit /*
+Exclusive upper bound on the values return by `char-int'.
+
+Note that not every fixnum with a value below `char-code-limit' has an
+associated character; check with `char-int-p' if necessary.
+*/);
+  Vchar_code_limit = CHAR_CODE_LIMIT;
+
 #ifdef ENABLE_COMPOSITE_CHARS
   /* #### not dumped properly */
   composite_char_row_next = 32;
--- a/src/text.h	Thu Mar 12 16:27:13 2015 +0000
+++ b/src/text.h	Mon Mar 16 00:11:30 2015 +0000
@@ -121,6 +121,8 @@
 #define rep_bytes_by_first_byte(fb) 1
 #define byte_ascii_p(byte) 1
 #define MAX_ICHAR_LEN 1
+/* Exclusive upper bound on character codes. */
+#define CHAR_CODE_LIMIT 0x100 
 
 #else /* MULE */
 
@@ -212,12 +214,12 @@
 
 #define ichar_ascii_p(c) (!ichar_multibyte_p (c))
 
-/* Maximum number of bytes per Emacs character when represented as text, in
- any format.
- */
-
+/* Maximum number of bytes per Ichar when represented as text. */
 #define MAX_ICHAR_LEN 4
 
+/* Exclusive upper bound on char codes. */
+#define CHAR_CODE_LIMIT 0x200000 
+
 #endif /* not MULE */
 
 #ifdef MULE
@@ -239,7 +241,7 @@
 
 /* This works when CH is negative, and correctly returns non-zero only when CH
    is in the range [0, 255], inclusive. */
-#define valid_ichar_p(ch) (! (ch & ~0xFF))
+#define valid_ichar_p(ch) (! (ch & ~(CHAR_CODE_LIMIT - 1)))
 
 #endif /* not MULE */
 
--- a/tests/ChangeLog	Thu Mar 12 16:27:13 2015 +0000
+++ b/tests/ChangeLog	Mon Mar 16 00:11:30 2015 +0000
@@ -1,3 +1,9 @@
+2015-03-15  Aidan Kehoe  <kehoea@parhasard.net>
+
+	* automated/mule-tests.el (test-chars):
+	Use char-code-limit explicitly here, instead of hardcoding the
+	corresponding values.
+
 2015-03-04  Aidan Kehoe  <kehoea@parhasard.net>
 
 	* automated/lisp-tests.el:
--- a/tests/automated/mule-tests.el	Thu Mar 12 16:27:13 2015 +0000
+++ b/tests/automated/mule-tests.el	Mon Mar 16 00:11:30 2015 +0000
@@ -46,10 +46,9 @@
 
 If FOR-TEST-HARNESS is specified, a temporary buffer is used, and
 the Assert macro checks for correctness."
-  (let ((max (expt 2 (if (featurep 'mule) 21 8)))
-	(list nil)
+  (let ((list nil)
 	(i 0))
-    (while (< i max)
+    (while (< i char-code-limit)
       (and (not for-test-harness)
 	   (zerop (% i 1000))
 	   (message "%d" i))