anchor.diff:       :unless (zerop (logand bit bits)) :collect modifier))
   
   
  -
   (let ((keymap *keymap*)
         (sequence '()))
     (defun editor-reset-key ()
       (setf keymap *keymap*
             sequence '()))
     (defun editor-process-key (key)
  -    (handler-bind
  -        ((error (function invoke-debugger)))
  -      (let ((binding (keymap-binding keymap key)))
  -        (push key sequence)
  -        (cond
  -          ((keymapp binding)
  -           (format *log* "~{~A ~}~%" (reverse sequence))
  -           (setf keymap binding))
  -          ((or (and (symbolp binding)
  -                    (fboundp binding)
  -                    (interactivep binding))
  -               (and (functionp binding)
  -                    (interactivep binding)))
  -           (format *log* "~{~A ~} --> ~S~%" (reverse sequence) binding)
  -           (setf *last-command-char*  (first sequence)
  -                 *this-command*       binding
  -                 *current-prefix-arg* *prefix-arg*
  -                 *prefix-arg*         nil)
  -           (call-interactively binding)
  -           (setf *last-command* *this-command*)
  -           (editor-reset-key))
  -          (t (message "~{~A ~} is bound to a non-command: ~S~%"
  -                      (reverse sequence) binding)
  -             (editor-reset-key)))))))
  -
  -
  +    (let ((binding (keymap-binding keymap key)))
  +      (push key sequence)
  +      (cond
  +        ((keymapp binding)
  +         (format *log* "~{~A ~}~%" (reverse sequence))
  +         (setf keymap binding))
  +        ((or (and (symbolp binding)
  +                  (fboundp binding)
  +                  (interactivep binding))
  +             (and (functionp binding)
  +                  (interactivep binding)))
  +         (format *log* "~{~A ~} --> ~S~%" (reverse sequence) binding)
  +         (setf *last-command-char*  (first sequence)
  +               *this-command*       binding
  +               *current-prefix-arg* *prefix-arg*
  +               *prefix-arg*         nil)
  +         (call-interactively binding)
  +         (setf *last-command* *this-command*)
  +         (editor-reset-key))
  +        (t (message "~{~A ~} is bound to a non-command: ~S~%"
  +                    (reverse sequence) binding)
  +           (editor-reset-key))))))
  +
  +
  +(defvar *condition*)
  +
  +(defun handle-editor-error (condition)
  +  (let* ((restarts (compute-restarts condition))
  +         (last-r   (1- (length restarts))))
  +    (flet ((print-restart-list (stream)
  +             (setf last-r (loop
  +                            :for r :in restarts
  +                            :for i :from 0
  +                            :do (format stream "~&~D: (~10A) ~A~%" i (restart-name r) r)
  +                            :until (eq (restart-name r) 'abort)
  +                            :finally (return i)))))
  +      (let ((restart (loop
  +                       :for n = (progn (print-restart-list *query-io*)
  +                                       (format *query-io* "~&Option: ")
  +                                       (finish-output *query-io*)
  +                                       (read *query-io*)
  +                                       (fresh-line *query-io*))
  +                       :until (and (typep n 'integer) (<= 0 n last-r))
  +                       :finally (return (nth n restarts)))))
  +        (print (list 'restart '= (restart-name restart)))
  +        (print (list '*debugger-hook* '= *debugger-hook*))
  +        (let ((*condition* condition))
  +          (handler-bind ((error (function invoke-debugger)))
  +            (invoke-restart-interactively restart)))))))
  +
  +
  +(defun reportly (string)
  +  (lambda (stream) (format stream "~A" string)))
   
   
   #+clisp
   (defun keyboard-loop ()
  -  (EXT:WITH-KEYBOARD
  +  (handler-bind ((error (function handle-editor-error)))
  +    (restart-bind ((debug    (lambda () (invoke-debugger *condition*))
  +                             :report-function (reportly "Invoke the debugger."))
  +                   (continue (lambda () (throw 'keyboard-quit (values)))
  +                             :report-function (reportly "Continue editing."))
  +                   (abort    (lambda () (throw 'editor-quit (values)))
  +                             :report-function (reportly "Quit the editor.")))
         (catch 'editor-quit
           (loop
  -           (catch 'keyboard-quit
  -             (LOOP
  -                :with redisplayed = t
  -                :with meta-seen-p = nil
  -                :for ki = (READ-CHAR-NO-HANG EXT:*KEYBOARD-INPUT*)
  -                :for modifiers = (and ki (keyboard-modifiers
  -                                          (logior (ext:char-bits ki)
  -                                                  (prog1 (if meta-seen-p EXT:CHAR-META-BIT 0)
  -                                                    (setf meta-seen-p nil)))))
  -                :for key = (and ki (funcall
  -                                    (if (member :control modifiers)
  -                                        (function char-downcase)
  -                                        (function identity))
  -                                         (or (ext:char-key ki) (character ki))))
  -                :initially (editor-reset-key) (redisplay)
  -                :do (if ki
  -                        (if (eql #\escape key)
  -                            (setf meta-seen-p t)
  -                            (progn
  -                              (editor-process-key
  -                               (if modifiers
  -                                   (append modifiers (list key))
  -                                   key))
  -                              (setf redisplayed nil)))
  -                        (unless redisplayed
  -                          (redisplay)
  -                          (setf redisplayed t)))))))))
  +          (catch 'keyboard-quit
  +            
  +                (LOOP
  +                  :with redisplayed = t
  +                  :with meta-seen-p = nil
  +                  :for ki = (ext:with-keyboard (read-char-no-hang ext:*keyboard-input*))
  +                  :for modifiers = (and ki (keyboard-modifiers
  +                                            (logior (ext:char-bits ki)
  +                                                    (prog1 (if meta-seen-p EXT:CHAR-META-BIT 0)
  +                                                      (setf meta-seen-p nil)))))
  +                  :for key = (and ki (funcall
  +                                      (if (member :control modifiers)
  +                                          (function char-downcase)
  +                                          (function identity))
  +                                      (or (ext:char-key ki) (character ki))))
  +                  :initially (editor-reset-key) (redisplay)
  +                  :do (if ki
  +                          (if (eql #\escape key)
  +                              (setf meta-seen-p t)
  +                              (progn
  +                                (editor-process-key
  +                                 (if modifiers
  +                                     (append modifiers (list key))
  +                                     key))
  +                                (setf redisplayed nil)))
  +                          (unless redisplayed
  +                            (redisplay)
  +                            (setf redisplayed t))))))))))
   
   ;; EXT:CHAR-BITS-LIMIT                        constant
   ;; EXT:CHAR-CONTROL-BIT                       constant
  
positive.code: 
  (defvar *interactive-decls* (make-hash-table #+clisp :weak #+clisp :key)
    #-(or french) "A map of commands name or functions to INTERACTIVE declarations."
    #+french  "Une association des noms de commande ou fonction vers leur
  déclaration INTERACTIVE.")
  
  
  (defmacro defun (name arguments &body body)
    #-(or french) "
  Do additionnal book-keeping over CL:DEFUN, for INTERACTIVE commands."
    #+french "
  En plus du traitement de CL:DEFUN, maintient les informations nécessaires 
  pour les commandes interactives.
  
negative.code: il n'y a qu'une instance de SCREEN, mais une version future pourrait être
  ''multitty'' (ou ''multiframe''), comme GNU emacs.")
  
  
  (defmacro with-screen (screen-object &body body)
    #-(or french) "Executes the BODY with *CURRENT-SCREEN* bound to SCREEN-OBJECT,
  while displaying this screen on the terminal."
  