--- ispell.el_original	2014-03-21 06:34:40.000000000 +0100
+++ ispell.el_changed	2015-06-27 12:16:49.335740151 +0200
@@ -2196,6 +2196,62 @@
   (setq ispell-pdict-modified-p nil))
 
 
+(defcustom ispell-option-keys
+  ["0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "b" "c" "d" "e" "f" "g" "h" "j"
+   "k" "n" "o" "p" "s" "t" "v" "w" "y" "z" "<" "^" "B" "C" "D" "E" "F" "G"
+   "H" "I" "J" "K" "L" "M" "N" "O" "P" "Q" "S" "T" "U" "V" "W" "Y" "Z" ":"
+   ";" "=" ">" "_" "`" "@" "[" "\\" "]" "{" "|" "}" "~" "C-0" "C-1" "C-2"
+   "C-3" "C-4" "C-5" "C-6" "C-7" "C-8" "C-9" "C-a" "C-b" "C-c" "C-d" "C-e"
+   "C-f" "C-i" "C-j" "C-k" "C-m" "C-n" "C-o" "C-p" "C-q" "C-s" "C-t" "C-u"
+   "C-v" "C-w" "C-x" "C-y" "C-<" "C-^" "C-A" "C-B" "C-C" "C-D" "C-E" "C-F"
+   "C-G" "C-H" "C-I" "C-J" "C-K" "C-L" "C-M" "C-N" "C-O" "C-P" "C-Q" "C-R"
+   "C-S" "C-T" "C-U" "C-V" "C-W" "C-X" "C-Y" "C-Z" "C-:" "C-;" "C-=" "C->"
+   "C-_" "C-`" "C-@" "C-[" "C-\\" "C-]" "C-{" "C-|" "C-}" "C-~"]
+  "Define the inventory of keys used in Ispell’s *Choices* buffer.
+
+Value is a vector of strings that describe keys when used as
+arguments in `kbd'. (Remember to escape backslashes: \"\\\\\" is
+as string with one backslash.) These keys are used in the given
+order to identify the options that Ispell offers in its *Choices*
+buffer.
+
+The number of keys defined here limits the number of options that
+Ispell will offer.
+
+It is in the responsibility of the user, not to include keys in
+this vector that Ispell’s command loop recognizes as commands.
+These are:
+
+   <SPC>, ?, A, R, X, a, i, l, m, q, r, u, x,
+   C-g, C-h, C-l, C-r, C-z
+
+and whatever key is associated with `help-char', which is in
+general equivalent to C-h. The documentation of `ispell-help'
+explains, what these command keys do."
+  :group 'ispell)
+
+
+(defsubst ispell-insert-choices ()
+  "Helper that inserts the options in Ispell's *Choices* buffer.
+
+The code of this inline function is used identically at several
+places in `ispell-command-loop'."
+  (while (and choices
+	      (< count nof-opt-keys)
+	      (< (if (> (+ 6 (current-column) (length (car choices))
+			   (length (setq key
+					 (elt ispell-option-keys count))))
+			(window-width))
+		     (progn
+		       (insert "\n")
+		       (setq line (1+ line)))
+		   line)
+		 max-lines))
+    (insert "(" key ") " (car choices) "  ")
+    (setq choices (cdr choices)
+	  count (1+ count))))
+
+
 (defun ispell-command-loop (miss guess word start end)
   "Display possible corrections from list MISS.
 GUESS lists possibly valid affix construction of WORD.
@@ -2210,17 +2266,19 @@
 indicates whether the dictionary has been modified when option `a'
 or `i' is used.
 Global `ispell-quit' set to start location to continue spell session."
-  (let ((count ?0)
+  (let ((count 0)
+	(nof-opt-keys (length ispell-option-keys))
 	(line ispell-choices-win-default-height)
 	;; ensure 4 context lines.
 	(max-lines (- (ispell-adjusted-window-height) 4))
 	(choices miss)
 	(window-min-height (min window-min-height
 				ispell-choices-win-default-height))
-	(command-characters '( ?  ?i ?a ?A ?r ?R ?? ?x ?X ?q ?l ?u ?m ))
+	(command-keys (list help-char
+			    ?  ?? ?A ?R ?X ?a ?i ?l ?m ?q ?r ?u ?x
+			    ?\C-g ?\C-h ?\C-l ?\C-r ?\C-z))
 	(dedicated (window-dedicated-p))
-	(skipped 0)
-	char num result textwin dedicated-win)
+	key num result textwin dedicated-win)
 
     ;; setup the *Choices* buffer with valid data.
     (with-current-buffer (get-buffer-create ispell-choices-buffer)
@@ -2250,24 +2308,7 @@
 	      (setq guess (cdr guess)))
 	    (insert "\nUse option `i' to accept this spelling and put it in your private dictionary.\n")
 	    (setq line (+ line (if choices 3 2)))))
-      (while (and choices
-		  (< (if (> (+ 7 (current-column) (length (car choices))
-			       (if (> count ?~) 3 0))
-			    (window-width))
-			 (progn
-			   (insert "\n")
-			   (setq line (1+ line)))
-		       line)
-		     max-lines))
-	;; not so good if there are over 20 or 30 options, but then, if
-	;; there are that many you don't want to scan them all anyway...
-	(while (memq count command-characters) ; skip command characters.
-	  (setq count (ispell-int-char (1+ count))
-		skipped (1+ skipped)))
-	(insert "(" count ") " (car choices) "  ")
-	(setq choices (cdr choices)
-	      count (ispell-int-char (1+ count))))
-      (setq count (ispell-int-char (- count ?0 skipped))))
+      (ispell-insert-choices))
 
     ;; ensure word is visible
     (if (not (pos-visible-in-window-p end))
@@ -2301,38 +2342,35 @@
 				     "unchanged, Character to replace word")))
 		  (let ((inhibit-quit t)
 			(input-valid t))
-		    (setq char nil skipped 0)
+		    (setq key nil)
 		    ;; If the user types C-g, or generates some other
-		    ;; non-character event (such as a frame switch
+		    ;; non-keyboard event (such as a frame switch
 		    ;; event), stop ispell.  As a special exception,
 		    ;; ignore mouse events occurring in the same frame.
-		    (while (and input-valid (not (characterp char)))
-		      (setq char (read-key))
+		    (while (and input-valid (not (natnump key)))
+		      (setq key (read-key))
 		      (setq input-valid
-			    (or (characterp char)
-				(and (mouse-event-p char)
+			    (or (natnump key)
+				(and (mouse-event-p key)
 				     (eq (selected-frame)
 					 (window-frame
-					  (posn-window (event-start char))))))))
-		    (when (or quit-flag (not input-valid) (= char ?\C-g))
-		      (setq char ?X quit-flag nil)))
-		  ;; Adjust num to array offset skipping command characters.
-		  (let ((com-chars command-characters))
-		    (while com-chars
-		      (if (and (> (car com-chars) ?0) (< (car com-chars) char))
-			  (setq skipped (1+ skipped)))
-		      (setq com-chars (cdr com-chars)))
-		    (setq num (- char ?0 skipped)))
+					  (posn-window (event-start key))))))))
+		    (when (or quit-flag (not input-valid) (= key ?\C-g))
+		      (setq key ?X quit-flag nil)))
+		  ;; We could look up key in ispell-option-keys right now.
+		  ;; But for performance reasons, we do this in the cond form
+		  ;; below and only after it has turned out, that key is none
+		  ;; of the command keys.
 
 		  (cond
-		   ((= char ? ) nil)	; accept word this time only
-		   ((= char ?i)		; accept and insert word into pers dict
+		   ((= key ? ) nil)	; accept word this time only
+		   ((= key ?i)		; accept and insert word into pers dict
 		    (ispell-send-string (concat "*" word "\n"))
 		    (setq ispell-pdict-modified-p '(t)) ; dictionary modified!
 		    (and (fboundp 'flyspell-unhighlight-at)
 			 (flyspell-unhighlight-at start))
 		    nil)
-		   ((or (= char ?a) (= char ?A)) ; accept word without insert
+		   ((or (= key ?a) (= key ?A)) ; accept word without insert
 		    (ispell-send-string (concat "@" word "\n"))
 		    (add-to-list 'ispell-buffer-session-localwords word)
 		    (and (fboundp 'flyspell-unhighlight-at)
@@ -2342,12 +2380,12 @@
 		    (if (null ispell-pdict-modified-p)
 			(setq ispell-pdict-modified-p
 			      (list ispell-pdict-modified-p)))
-		    (if (= char ?A) 0))	; return 0 for ispell-add buffer-local
-		   ((or (= char ?r) (= char ?R)) ; type in replacement
+		    (if (= key ?A) 0))	; return 0 for ispell-add buffer-local
+		   ((or (= key ?r) (= key ?R)) ; type in replacement
 		    (and (eq 'block ispell-highlight-p) ; refresh tty's
 			 (ispell-highlight-spelling-error start end nil t))
 		    (let ((result
-			   (if (or (= char ?R) ispell-query-replace-choices)
+			   (if (or (= key ?R) ispell-query-replace-choices)
 			       (list (read-string
 				      (format "Query-replacement for %s: "word)
 				      word)
@@ -2358,7 +2396,7 @@
 			   (ispell-highlight-spelling-error start end nil
 							    'block))
 		      result))
-		   ((or (= char ??) (= char help-char) (= char ?\C-h))
+		   ((or (= key ??) (= key help-char) (= key ?\C-h))
 		    (and (eq 'block ispell-highlight-p)
 			 (ispell-highlight-spelling-error start end nil t))
 		    (ispell-help)
@@ -2367,13 +2405,13 @@
 							  'block))
 		    t)
 		   ;; Quit and move point back.
-		   ((= char ?x)
+		   ((= key ?x)
 		    (ispell-pdict-save ispell-silently-savep)
 		    (message "Exited spell-checking")
 		    (setq ispell-quit t)
 		    nil)
 		   ;; Quit and preserve point.
-		   ((= char ?X)
+		   ((= key ?X)
 		    (ispell-pdict-save ispell-silently-savep)
 		    (message "%s"
 		     (substitute-command-keys
@@ -2381,7 +2419,7 @@
 			      " use C-u \\[ispell-word] to resume")))
 		    (setq ispell-quit start)
 		    nil)
-		   ((= char ?q)
+		   ((= key ?q)
 		    (if (y-or-n-p "Really kill Ispell process? ")
 			(progn
 			  (ispell-kill-ispell t) ; terminate process.
@@ -2389,7 +2427,7 @@
 						(point))
 				ispell-pdict-modified-p nil))
 		      t))		; continue if they don't quit.
-		   ((= char ?l)
+		   ((= key ?l)
 		    (and (eq 'block ispell-highlight-p) ; refresh tty displays
 			 (ispell-highlight-spelling-error start end nil t))
 		    (let ((new-word (read-string
@@ -2400,8 +2438,7 @@
 			    (with-current-buffer (get-buffer-create
                                                   ispell-choices-buffer)
 			      (erase-buffer)
-			      (setq count ?0
-				    skipped 0
+			      (setq count 0
 				    mode-line-format ;; setup the *Choices* buffer with valid data.
 				    (concat "--  %b  --  word: " new-word
 					    "  --  word-list: "
@@ -2410,46 +2447,25 @@
 				    miss (ispell-lookup-words new-word)
 				    choices miss
 				    line ispell-choices-win-default-height)
-			      (while (and choices ; adjust choices window.
-					  (< (if (> (+ 7 (current-column)
-						       (length (car choices))
-						       (if (> count ?~) 3 0))
-						    (window-width))
-						 (progn
-						   (insert "\n")
-						   (setq line (1+ line)))
-					       line)
-					     max-lines))
-				(while (memq count command-characters)
-				  (setq count (ispell-int-char (1+ count))
-					skipped (1+ skipped)))
-				(insert "(" count ") " (car choices) "  ")
-				(setq choices (cdr choices)
-				      count (ispell-int-char (1+ count))))
-			      (setq count (ispell-int-char
-					   (- count ?0 skipped))))
+			      (ispell-insert-choices))
 			    (ispell-show-choices line end)
 			    (select-window (next-window)))))
 		    (and (eq 'block ispell-highlight-p)
 			 (ispell-highlight-spelling-error start end nil
 							  'block))
 		    t)			; reselect from new choices
-		   ((= char ?u)		; insert lowercase into dictionary
+		   ((= key ?u)		; insert lowercase into dictionary
 		    (ispell-send-string (concat "*" (downcase word) "\n"))
 		    (setq ispell-pdict-modified-p '(t)) ; dictionary modified!
 		    nil)
-		   ((= char ?m)		; type in what to insert
+		   ((= key ?m)		; type in what to insert
 		    (ispell-send-string
 		     (concat "*" (read-string "Insert: " word) "\n"))
 		    (setq ispell-pdict-modified-p '(t))
 		    (cons word nil))
-		   ((and (>= num 0) (< num count))
-		    (if ispell-query-replace-choices ; Query replace flag
-			(list (nth num miss) 'query-replace)
-		      (nth num miss)))
-		   ((= char ?\C-l)
+		   ((= key ?\C-l)
 		    (redraw-display) t)
-		   ((= char ?\C-r)
+		   ((= key ?\C-r)
 		    ;; This may have alignment errors if current line is edited
 		    (if (marker-position ispell-recursive-edit-marker)
 			(progn
@@ -2480,10 +2496,27 @@
 			       "Cannot continue ispell from this buffer.")))
 			(set-marker ispell-recursive-edit-marker nil)))
 		    (list word nil))	; recheck starting at this word.
-		   ((= char ?\C-z)
+		   ((= key ?\C-z)
 		    (funcall (key-binding "\C-z"))
 		    t)
-		   (t (ding) t))))))
+		   (t
+		    ;; key is none of the command keys, but might be one of
+		    ;; those in ispell-option-keys: Look up.
+		    (setq num 0)
+		    (while (and (< num nof-opt-keys)
+				(not (equal
+				      (elt (kbd (elt ispell-option-keys num))
+					   0)
+				      key)))
+		      (setq num (1+ num)))
+		    ;; If key was found in ispell-option-keys, num equals its
+		    ;; index now. Otherwise num equals nof-opt-keys >= count.
+		    (if (< num count)
+			(if ispell-query-replace-choices ; Query replace flag
+			    (list (nth num miss) 'query-replace)
+			  (nth num miss))
+		      ;; else--key is not defined
+		      (ding) t)))))))
 	  result)
       ;; protected
       (and ispell-highlight-p		; unhighlight
