2000-11-17 Katsumi Yamaoka <yamaoka@jpl.org>
[bpt/emacs.git] / lisp / map-ynp.el
index 61a19a3..e986ae8 100644 (file)
@@ -1,38 +1,40 @@
 ;;; map-ynp.el --- General-purpose boolean question-asker.
 
-;;; Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+;; Copyright (C) 1991, 1992, 1993, 1994, 1995, 2000 Free Software Foundation, Inc.
 
-;; Author: Roland McGrath <roland@gnu.ai.mit.edu>
+;; Author: Roland McGrath <roland@gnu.org>
+;; Maintainer: FSF
 ;; Keywords: lisp, extensions
 
-;;; This program 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 2, or (at your option)
-;;; any later version.
-;;;
-;;; This program 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.
-;;;
-;;; A copy of the GNU General Public License can be obtained from this
-;;; program's author (send electronic mail to roland@ai.mit.edu) or from
-;;; the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA
-;;; 02139, USA.
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs 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 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs 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 GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
 
 ;;; Commentary:
 
-;;; map-y-or-n-p is a general-purpose question-asking function.
-;;; It asks a series of y/n questions (a la y-or-n-p), and decides to
-;;; applies an action to each element of a list based on the answer.
-;;; The nice thing is that you also get some other possible answers
-;;; to use, reminiscent of query-replace: ! to answer y to all remaining
-;;; questions; ESC or q to answer n to all remaining questions; . to answer
-;;; y once and then n for the remainder; and you can get help with C-h.
+;; map-y-or-n-p is a general-purpose question-asking function.
+;; It asks a series of y/n questions (a la y-or-n-p), and decides to
+;; apply an action to each element of a list based on the answer.
+;; The nice thing is that you also get some other possible answers
+;; to use, reminiscent of query-replace: ! to answer y to all remaining
+;; questions; ESC or q to answer n to all remaining questions; . to answer
+;; y once and then n for the remainder; and you can get help with C-h.
 
 ;;; Code:
 
-;;;###autoload
 (defun map-y-or-n-p (prompter actor list &optional help action-alist
                              no-cursor-in-echo-area)
   "Ask a series of boolean questions.
@@ -77,6 +79,8 @@ are meaningful here.
 Returns the number of actions taken."
   (let* ((actions 0)
         user-keys mouse-event map prompt char elt tail def
+        ;; Non-nil means we should use mouse menus to ask.
+        use-menus
         delayed-switch-frame
         (next (if (or (and list (symbolp list))
                       (subrp list)
@@ -92,21 +96,23 @@ Returns the number of actions taken."
                                         list (cdr list))
                                   t)
                               nil))))))
-    (if (listp last-nonmenu-event)
+    (if (and (listp last-nonmenu-event)
+            use-dialog-box)
        ;; Make a list describing a dialog box.
-       (let ((object (capitalize (nth 0 help)))
-             (objects (capitalize (nth 1 help)))
-             (action (capitalize (nth 2 help))))
-         (setq map (` (("Yes" . act) ("No" . skip) ("Quit" . exit)
-                       ((, (if help (concat action " " object " And Quit")
-                             "Do it and Quit")) . act-and-exit)
-                       ((, (if help (concat action " All " objects)
-                             "Do All")) . automatic)
-                       (,@ (mapcar (lambda (elt)
-                                     (cons (capitalize (nth 2 elt))
-                                           (vector (nth 1 elt))))
-                                   action-alist))))
-               mouse-event last-nonmenu-event))                               
+       (let ((object (if help (capitalize (nth 0 help))))
+             (objects (if help (capitalize (nth 1 help))))
+             (action (if help (capitalize (nth 2 help)))))
+         (setq map `(("Yes" . act) ("No" . skip) ("Quit" . exit)
+                     (,(if help (concat action " " object " And Quit")
+                         "Do it and Quit") . act-and-exit)
+                     (,(if help (concat action " All " objects)
+                         "Do All") . automatic)
+                     ,@(mapcar (lambda (elt)
+                                 (cons (capitalize (nth 2 elt))
+                                       (vector (nth 1 elt))))
+                               action-alist))
+               use-menus t
+               mouse-event last-nonmenu-event))
       (setq user-keys (if action-alist
                          (concat (mapconcat (function
                                              (lambda (elt)
@@ -125,15 +131,15 @@ Returns the number of actions taken."
     (unwind-protect
        (progn
          (if (stringp prompter)
-             (setq prompter (` (lambda (object)
-                                 (format (, prompter) object)))))
+             (setq prompter `(lambda (object)
+                               (format ,prompter object))))
          (while (funcall next)
            (setq prompt (funcall prompter elt))
            (cond ((stringp prompt)
                   ;; Prompt the user about this object.
                   (setq quit-flag nil)
-                  (if mouse-event
-                      (setq def (or (x-popup-dialog mouse-event
+                  (if use-menus
+                      (setq def (or (x-popup-dialog (or mouse-event use-menus)
                                                     (cons prompt map))
                                     'quit))
                     ;; Prompt in the echo area.
@@ -142,7 +148,13 @@ Returns the number of actions taken."
                       (message "%s(y, n, !, ., q, %sor %s) "
                                prompt user-keys
                                (key-description (vector help-char)))
-                      (setq char (read-event))
+                      (if minibuffer-auto-raise
+                          (raise-frame (window-frame (minibuffer-window))))
+                      (while (progn
+                               (setq char (read-event))
+                               ;; If we get -1, from end of keyboard
+                               ;; macro, try again.
+                                (equal char -1)))
                       ;; Show the answer to the question.
                       (message "%s(y, n, !, ., q, %sor %s) %s"
                                prompt user-keys
@@ -165,9 +177,9 @@ Returns the number of actions taken."
                                next (function (lambda () nil))))
                         ((or (eq def 'quit) (eq def 'exit-prefix))
                          (setq quit-flag t)
-                         (setq next (` (lambda ()
-                                         (setq next '(, next))
-                                         '(, elt)))))
+                         (setq next `(lambda ()
+                                       (setq next ',next)
+                                       ',elt)))
                         ((eq def 'automatic)
                          ;; Act on this and all following objects.
                          (if (funcall prompter elt)
@@ -188,9 +200,11 @@ Returns the number of actions taken."
                               (concat
                                (format "Type SPC or `y' to %s the current %s;
 DEL or `n' to skip the current %s;
+RET or `q' to exit (skip all remaining %s);
 ! to %s all remaining %s;
 ESC or `q' to exit;\n"
-                                       action object object action objects)
+                                       action object object objects action
+                                       objects)
                                (mapconcat (function
                                            (lambda (elt)
                                              (format "%c to %s"
@@ -206,34 +220,34 @@ the current %s and exit."
                              (set-buffer standard-output)
                              (help-mode)))
 
-                         (setq next (` (lambda ()
-                                         (setq next '(, next))
-                                         '(, elt)))))
+                         (setq next `(lambda ()
+                                      (setq next ',next)
+                                      ',elt)))
                         ((vectorp def)
                          ;; A user-defined key.
                          (if (funcall (aref def 0) elt) ;Call its function.
                              ;; The function has eaten this object.
                              (setq actions (1+ actions))
                            ;; Regurgitated; try again.
-                           (setq next (` (lambda ()
-                                           (setq next '(, next))
-                                           '(, elt))))))
+                           (setq next `(lambda ()
+                                        (setq next ',next)
+                                        ',elt))))
                         ((and (consp char)
                               (eq (car char) 'switch-frame))
                          ;; switch-frame event.  Put it off until we're done.
                          (setq delayed-switch-frame char)
-                         (setq next (` (lambda ()
-                                         (setq next '(, next))
-                                         '(, elt)))))
+                         (setq next `(lambda ()
+                                      (setq next ',next)
+                                      ',elt)))
                         (t
                          ;; Random char.
                          (message "Type %s for help."
                                   (key-description (vector help-char)))
                          (beep)
                          (sit-for 1)
-                         (setq next (` (lambda ()
-                                         (setq next '(, next))
-                                         '(, elt)))))))
+                         (setq next `(lambda ()
+                                      (setq next ',next)
+                                      ',elt)))))
                  (prompt
                   (funcall actor elt)
                   (setq actions (1+ actions))))))