(follow-mode): Don't run hooks twice. Use `when'.
[bpt/emacs.git] / lisp / printing.el
index ddfe6fd..0f58956 100644 (file)
@@ -1,17 +1,16 @@
 ;;; printing.el --- printing utilities
 
-;; Copyright (C) 2000, 2001, 2002, 2003, 2004
-;; Free Software Foundation, Inc.
+;; Copyright (C) 2000, 2001, 2003, 2004, 2005,
+;;   2006, 2007 Free Software Foundation, Inc.
 
 ;; Author: Vinicius Jose Latorre <viniciusjl@ig.com.br>
 ;; Maintainer: Vinicius Jose Latorre <viniciusjl@ig.com.br>
-;; Time-stamp: <2004/11/21 20:56:53 vinicius>
 ;; Keywords: wp, print, PostScript
-;; Version: 6.8.3
-;; X-URL: http://www.cpqd.com.br/~vinicius/emacs/
+;; Version: 6.9.1
+;; X-URL: http://www.emacswiki.org/cgi-bin/wiki/ViniciusJoseLatorre
 
-(defconst pr-version "6.8.3"
-  "printing.el, v 6.8.3 <2004/11/17 vinicius>
+(defconst pr-version "6.9.1"
+  "printing.el, v 6.9.1 <2007/08/02 vinicius>
 
 Please send all bug fixes and enhancements to
        Vinicius Jose Latorre <viniciusjl@ig.com.br>
@@ -21,7 +20,7 @@ Please send all bug fixes and enhancements to
 
 ;; 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
+;; Software Foundation; either version 3, or (at your option) any later
 ;; version.
 
 ;; GNU Emacs is distributed in the hope that it will be useful, but WITHOUT ANY
@@ -31,7 +30,7 @@ Please send all bug fixes and enhancements to
 
 ;; 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.
+;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 
 ;;; Commentary:
 
@@ -68,7 +67,7 @@ Please send all bug fixes and enhancements to
 ;; interface to ps-print package and it also provides some extra stuff.
 ;;
 ;; To download the latest ps-print package see
-;; `http://www.cpqd.com.br/~vinicius/emacs/ps-print.tar.gz'.
+;; `http://www.emacswiki.org/cgi-bin/wiki/PsPrintPackage'.
 ;; Please, see README file for ps-print installation instructions.
 ;;
 ;; `printing' was inspired on:
@@ -143,7 +142,7 @@ Please send all bug fixes and enhancements to
 ;; One way to set variables is by calling `pr-customize', customize all
 ;; variables and save the customization by future sessions (see Options
 ;; section).  Other way is by coding your settings on Emacs init file (that is,
-;; .emacs file), see below for a first setting template that it should be
+;; ~/.emacs file), see below for a first setting template that it should be
 ;; inserted on your ~/.emacs file (or c:/_emacs, if you're using Windows 9x/NT
 ;; or MS-DOS):
 ;;
@@ -259,9 +258,9 @@ Please send all bug fixes and enhancements to
 ;;    PostScript printer.  So, please, don't include this printer in
 ;;    `pr-txt-printer-alist' (which see).
 ;;
-;; 5. Use gsprint instead of ghostscript to print monochrome PostScript files
-;;    in Windows.  The gsprint utility is faster than ghostscript to print
-;;    monochrome PostScript.
+;; 5. You can use gsprint instead of ghostscript to print monochrome PostScript
+;;    files in Windows.  The gsprint utility documentation says that it is more
+;;    efficient than ghostscript to print monochrome PostScript.
 ;;
 ;;    To print non-monochrome PostScript file, the efficiency of ghostscript
 ;;    is similar to gsprint.
@@ -271,6 +270,31 @@ Please send all bug fixes and enhancements to
 ;;    For more information about gsprint see
 ;;    `http://www.cs.wisc.edu/~ghost/gsview/gsprint.htm'.
 ;;
+;;    As an example of gsprint declaration:
+;;
+;;    (setq pr-ps-printer-alist
+;;          '((A "gsprint" ("-all" "-twoup") "-printer " "my-b/w-printer-name")
+;;            (B "gsprint" ("-all" "-twoup") nil "-printer my-b/w-printer-name")
+;;            ;; some other printer declaration
+;;            ))
+;;
+;;    The example above declares that printer A prints all pages (-all) and two
+;;    pages per sheet (-twoup).  The printer B declaration does the same as the
+;;    printer A declaration, the only difference is the printer name selection.
+;;
+;;    There are other command line options like:
+;;
+;;    -mono    Render in monochrome as 1bit/pixel (only black and white).
+;;    -grey    Render in greyscale as 8bits/pixel.
+;;    -color   Render in color as 24bits/pixel.
+;;
+;;    The default is `-mono'.  So, printer A and B in the example above are
+;;    using implicitly the `-mono' option.  Note that in `-mono' no gray tone
+;;    or color is printed, this includes the zebra stripes, that is, in `-mono'
+;;    the zebra stripes are not printed.
+;;
+;;    See also documentation for `pr-ps-printer-alist'.
+;;
 ;;
 ;; Using `printing'
 ;; ----------------
@@ -279,8 +303,10 @@ Please send all bug fixes and enhancements to
 ;; using Windows 9x/NT or MS-DOS):
 ;;
 ;;    (require 'printing)
+;;    ;; ...some user settings...
+;;    (pr-update-menus t)
 ;;
-;; When `printing' is loaded:
+;; During `pr-update-menus' evaluation:
 ;;   * On Emacs 20:
 ;;      it replaces the Tools/Print menu by Tools/Printing menu.
 ;;   * On Emacs 21:
@@ -885,6 +911,7 @@ Please send all bug fixes and enhancements to
 ;;            (lps_06b  "print"     nil nil   "\\\\printers\\lps_06b")
 ;;            (lps_07c  "print"     nil ""    "/D:\\\\printers\\lps_07c")
 ;;            (lps_08c  nil         nil nil   "\\\\printers\\lps_08c")
+;;            (b/w      "gsprint" ("-all" "-twoup") "-printer " "b/w-pr-name")
 ;;            (LPT1     ""          nil ""    "LPT1:")
 ;;            (PRN      ""          nil ""    "PRN")
 ;;            (standard "redpr.exe" nil ""    "")
@@ -923,18 +950,21 @@ Please send all bug fixes and enhancements to
 ;;
 ;;    `pr-update-menus'        Update utility, PostScript and text printer menus.
 ;;
+;;    `pr-menu-bind'   Install `printing' menu in the menubar.
+;;
+;;
 ;; Below are some URL where you can find good utilities.
 ;;
 ;; * For `printing' package:
 ;;
-;;    printing `http://www.cpqd.com.br/~vinicius/emacs/printing.el.gz'
-;;    ps-print `http://www.cpqd.com.br/~vinicius/emacs/ps-print.tar.gz'
+;;    printing `http://www.emacswiki.org/cgi-bin/emacs/download/printing.el'
+;;    ps-print `http://www.emacswiki.org/cgi-bin/wiki/PsPrintPackage'
 ;;
 ;; * For GNU or Unix system:
 ;;
 ;;    gs, gv         `http://www.gnu.org/software/ghostscript/ghostscript.html'
 ;;    enscript       `http://people.ssh.fi/mtr/genscript/'
-;;    psnup          `http://www.dcs.ed.ac.uk/home/ajcd/psutils/index.html'
+;;    psnup          `http://www.knackered.org/angus/psutils/'
 ;;    mpage          `http://www.mesa.nl/pub/mpage/'
 ;;
 ;; * For Windows system:
@@ -943,7 +973,7 @@ Please send all bug fixes and enhancements to
 ;;                   `http://www.gnu.org/software/ghostscript/ghostscript.html'
 ;;    gsprint        `http://www.cs.wisc.edu/~ghost/gsview/gsprint.htm'.
 ;;    enscript       `http://people.ssh.fi/mtr/genscript/'
-;;    psnup          `http://www.dcs.ed.ac.uk/home/ajcd/psutils/index.html'
+;;    psnup          `http://gnuwin32.sourceforge.net/packages/psutils.htm'
 ;;    redmon         `http://www.cs.wisc.edu/~ghost/redmon/'
 ;;
 ;;
@@ -1012,12 +1042,6 @@ Please send all bug fixes and enhancements to
 ;; To avoid compilation gripes
 
 
-(or (fboundp 'easy-menu-intern)                ; hacked from easymenu.el
-    (defsubst easy-menu-intern (s)
-      (if (stringp s) (intern s) s)))
-
-
-
 (or (fboundp 'subst-char-in-string)    ; hacked from subr.el
     (defun subst-char-in-string (fromchar tochar string &optional inplace)
       "Replace FROMCHAR with TOCHAR in STRING each time it occurs.
@@ -1069,46 +1093,457 @@ If SUFFIX is non-nil, add that at the end of the file name."
          (set-default-file-modes umask)))))
 
 
-;; GNU Emacs
-(defalias 'pr-e-frame-char-height    'frame-char-height)
-(defalias 'pr-e-frame-char-width     'frame-char-width)
-(defalias 'pr-e-mouse-pixel-position 'mouse-pixel-position)
-;; XEmacs
-(defalias 'pr-x-add-submenu             'add-submenu)
-(defalias 'pr-x-event-function          'event-function)
-(defalias 'pr-x-event-object            'event-object)
-(defalias 'pr-x-find-menu-item          'find-menu-item)
-(defalias 'pr-x-font-height             'font-height)
-(defalias 'pr-x-font-width              'font-width)
-(defalias 'pr-x-get-popup-menu-response 'get-popup-menu-response)
-(defalias 'pr-x-make-event              'make-event)
-(defalias 'pr-x-misc-user-event-p       'misc-user-event-p)
-(defalias 'pr-x-relabel-menu-item       'relabel-menu-item)
-(defalias 'pr-x-event-x-pixel           'event-x-pixel)
-(defalias 'pr-x-event-y-pixel           'event-y-pixel)
+\f
+;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; XEmacs Definitions
+
 
 (cond
  ((featurep 'xemacs)                   ; XEmacs
-  (defvar current-menubar     nil)
-  (defvar current-mouse-event nil)
-  (defvar zmacs-region-stays  nil)
+  ;; XEmacs
   (defalias 'pr-f-set-keymap-parents 'set-keymap-parents)
   (defalias 'pr-f-set-keymap-name    'set-keymap-name)
+
+  ;; XEmacs
   (defun pr-f-read-string (prompt initial history default)
     (let ((str (read-string prompt initial)))
       (if (and str (not (string= str "")))
          str
        default)))
+
+  ;; XEmacs
+  (defvar zmacs-region-stays  nil)
+
+  ;; XEmacs
   (defun pr-keep-region-active ()
-    (setq zmacs-region-stays t)))
+    (setq zmacs-region-stays t))
+
+  ;; XEmacs
+  (defun pr-region-active-p ()
+    (and pr-auto-region (not zmacs-region-stays) (ps-mark-active-p)))
+
+  ;; XEmacs
+  (defun pr-menu-char-height ()
+    (font-height (face-font 'default)))
+
+  ;; XEmacs
+  (defun pr-menu-char-width ()
+    (font-width (face-font 'default)))
+
+  ;; XEmacs
+  (defmacro pr-xemacs-global-menubar (&rest body)
+    `(save-excursion
+       (let ((temp (get-buffer-create (make-temp-name " *Temp"))))
+        ;; be sure to access global menubar
+        (set-buffer temp)
+        ,@body
+        (kill-buffer temp))))
+
+  ;; XEmacs
+  (defun pr-global-menubar (pr-menu-spec)
+    ;; Menu binding
+    (pr-xemacs-global-menubar
+     (add-submenu nil (cons "Printing" pr-menu-spec) "Apps"))
+    (setq pr-menu-print-item nil))
+
+  ;; XEmacs
+  (defvar current-mouse-event nil)
+  (defun pr-menu-position (entry index horizontal)
+    (make-event
+     'button-release
+     (list 'button 1
+          'x (- (event-x-pixel current-mouse-event) ; X
+                (* horizontal pr-menu-char-width))
+          'y (- (event-y-pixel current-mouse-event) ; Y
+                (* (pr-menu-index entry index) pr-menu-char-height)))))
+
+  (defvar pr-menu-position nil)
+  (defvar pr-menu-state nil)
+
+  ;; XEmacs
+  (defvar current-menubar nil)         ; to avoid compilation gripes
+  (defun pr-menu-lookup (path)
+    (car (find-menu-item current-menubar (cons "Printing" path))))
+
+  ;; XEmacs
+  (defun pr-menu-lock (entry index horizontal state path)
+    (when pr-menu-lock
+      (or (and pr-menu-position (eq state pr-menu-state))
+         (setq pr-menu-position (pr-menu-position entry index horizontal)
+               pr-menu-state    state))
+      (let* ((menu   (pr-menu-lookup path))
+            (result (get-popup-menu-response menu pr-menu-position)))
+       (and (misc-user-event-p result)
+            (funcall (event-function result)
+                     (event-object result))))
+      (setq pr-menu-position nil)))
+
+  ;; XEmacs
+  (defalias 'pr-update-mode-line 'set-menubar-dirty-flag)
+
+  ;; XEmacs
+  (defvar pr-ps-name-old     "PostScript Printers")
+  (defvar pr-txt-name-old    "Text Printers")
+  (defvar pr-ps-utility-old  "PostScript Utility")
+  (defvar pr-even-or-odd-old "Print All Pages")
+
+  ;; XEmacs
+  (defun pr-do-update-menus (&optional force)
+    (pr-menu-alist pr-ps-printer-alist
+                  'pr-ps-name
+                  'pr-menu-set-ps-title
+                  '("Printing")
+                  'pr-ps-printer-menu-modified
+                  force
+                  pr-ps-name-old
+                  'postscript 2)
+    (pr-menu-alist pr-txt-printer-alist
+                  'pr-txt-name
+                  'pr-menu-set-txt-title
+                  '("Printing")
+                  'pr-txt-printer-menu-modified
+                  force
+                  pr-txt-name-old
+                  'text 2)
+    (let ((save-var pr-ps-utility-menu-modified))
+      (pr-menu-alist pr-ps-utility-alist
+                    'pr-ps-utility
+                    'pr-menu-set-utility-title
+                    '("Printing" "PostScript Print" "File")
+                    'save-var
+                    force
+                    pr-ps-utility-old
+                    nil 1))
+    (pr-menu-alist pr-ps-utility-alist
+                  'pr-ps-utility
+                  'pr-menu-set-utility-title
+                  '("Printing" "PostScript Preview" "File")
+                  'pr-ps-utility-menu-modified
+                  force
+                  pr-ps-utility-old
+                  nil 1)
+    (pr-even-or-odd-pages ps-even-or-odd-pages force))
+
+  ;; XEmacs
+  (defun pr-menu-alist (alist var-sym fun menu-path modified-sym force name
+                             entry index)
+    (when (and alist (or force (symbol-value modified-sym)))
+      (pr-xemacs-global-menubar
+       (add-submenu menu-path
+                   (pr-menu-create name alist var-sym
+                                   fun entry index)))
+      (funcall fun (symbol-value var-sym))
+      (set modified-sym nil)))
+
+  ;; XEmacs
+  (defun pr-relabel-menu-item (newname var-sym)
+    (pr-xemacs-global-menubar
+     (relabel-menu-item
+      (list "Printing" (symbol-value var-sym))
+      newname)
+     (set var-sym newname)))
+
+  ;; XEmacs
+  (defun pr-menu-set-ps-title (value &optional item entry index)
+    (pr-relabel-menu-item (format "PostScript Printer: %s" value)
+                         'pr-ps-name-old)
+    (pr-ps-set-printer value)
+    (and index
+        (pr-menu-lock entry index 12 'toggle nil)))
+
+  ;; XEmacs
+  (defun pr-menu-set-txt-title (value &optional item entry index)
+    (pr-relabel-menu-item (format "Text Printer: %s" value)
+                         'pr-txt-name-old)
+    (pr-txt-set-printer value)
+    (and index
+        (pr-menu-lock entry index 12 'toggle nil)))
+
+  ;; XEmacs
+  (defun pr-menu-set-utility-title (value &optional item entry index)
+    (pr-xemacs-global-menubar
+     (let ((newname (format "%s" value)))
+       (relabel-menu-item
+       (list "Printing" "PostScript Print" "File" pr-ps-utility-old)
+       newname)
+       (relabel-menu-item
+       (list "Printing" "PostScript Preview" "File" pr-ps-utility-old)
+       newname)
+       (setq pr-ps-utility-old newname)))
+    (pr-ps-set-utility value)
+    (and index
+        (pr-menu-lock entry index 5 nil '("PostScript Print" "File"))))
+
+  ;; XEmacs
+  (defun pr-even-or-odd-pages (value &optional no-lock)
+    (pr-relabel-menu-item (cdr (assq value pr-even-or-odd-alist))
+                         'pr-even-or-odd-old)
+    (setq ps-even-or-odd-pages value)
+    (or no-lock
+       (pr-menu-lock 'postscript-options 8 12 'toggle nil)))
+
+  )
+ (t                                    ; GNU Emacs
+  ;; Do nothing
+  ))                                   ; end cond featurep
+
+
+\f
+;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; GNU Emacs Definitions
 
+
+(cond
+ ((featurep 'xemacs)                   ; XEmacs
+  ;; Do nothing
+  )
  (t                                    ; GNU Emacs
-  (defvar deactivate-mark nil)
+  ;; GNU Emacs
   (defalias 'pr-f-set-keymap-parents 'set-keymap-parent)
   (defalias 'pr-f-set-keymap-name    'ignore)
   (defalias 'pr-f-read-string        'read-string)
+
+  ;; GNU Emacs
+  (defvar deactivate-mark)
+
+  ;; GNU Emacs
   (defun pr-keep-region-active ()
-    (setq deactivate-mark nil))))
+    (setq deactivate-mark nil))
+
+  ;; GNU Emacs
+  (defun pr-region-active-p ()
+    (and pr-auto-region transient-mark-mode mark-active))
+
+  ;; GNU Emacs
+  (defun pr-menu-char-height ()
+    (frame-char-height))
+
+  ;; GNU Emacs
+  (defun pr-menu-char-width ()
+    (frame-char-width))
+
+  ;; GNU Emacs
+  ;; Menu binding
+  ;; Replace existing "print" item by "Printing" item.
+  ;; If you're changing this file, you'll load it a second,
+  ;; third... time, but "print" item exists only in the first load.
+  (eval-and-compile
+    (cond
+     ;; GNU Emacs 20
+     ((< emacs-major-version 21)
+      (defun pr-global-menubar (pr-menu-spec)
+       (require 'easymenu)
+       (easy-menu-change '("tools") "Printing" pr-menu-spec pr-menu-print-item)
+       (when pr-menu-print-item
+         (easy-menu-remove-item nil '("tools") pr-menu-print-item)
+         (setq pr-menu-print-item nil
+               pr-menu-bar (vector 'menu-bar 'tools
+                                   (pr-get-symbol "Printing")))))
+      )
+     ;; GNU Emacs 21 & 22
+     (t
+      (defun pr-global-menubar (pr-menu-spec)
+       (require 'easymenu)
+       (let ((menu-file (if (= emacs-major-version 21)
+                            '("menu-bar" "files") ; GNU Emacs 21
+                          '("menu-bar" "file")))) ; GNU Emacs 22 or higher
+         (cond
+          (pr-menu-print-item
+           (easy-menu-add-item global-map menu-file
+                               (easy-menu-create-menu "Print" pr-menu-spec)
+                               "print-buffer")
+           (dolist (item '("print-buffer"          "print-region"
+                           "ps-print-buffer-faces" "ps-print-region-faces"
+                           "ps-print-buffer"       "ps-print-region"))
+             (easy-menu-remove-item global-map menu-file item))
+           (setq pr-menu-print-item nil
+                 pr-menu-bar (vector 'menu-bar
+                                     (pr-get-symbol (nth 1 menu-file))
+                                     (pr-get-symbol "Print"))))
+          (t
+           (easy-menu-add-item global-map menu-file
+                               (easy-menu-create-menu "Print" pr-menu-spec)))
+          )))
+      )))
+
+  (eval-and-compile
+    (cond
+     (ps-windows-system
+      ;; GNU Emacs for Windows 9x/NT
+      (defun pr-menu-position (entry index horizontal)
+       (let ((pos (cdr (mouse-pixel-position))))
+         (list
+          (list (or (car pos) 0)       ; X
+                (- (or (cdr pos) 0)    ; Y
+                   (* (pr-menu-index entry index) pr-menu-char-height)))
+          (selected-frame))))          ; frame
+      )
+     (t
+      ;; GNU Emacs
+      (defun pr-menu-position (entry index horizontal)
+       (let ((pos (cdr (mouse-pixel-position))))
+         (list
+          (list (- (or (car pos) 0)    ; X
+                   (* horizontal pr-menu-char-width))
+                (- (or (cdr pos) 0)    ; Y
+                   (* (pr-menu-index entry index) pr-menu-char-height)))
+          (selected-frame))))          ; frame
+      )))
+
+  (defvar pr-menu-position nil)
+  (defvar pr-menu-state nil)
+
+  ;; GNU Emacs
+  (defun pr-menu-lookup (path)
+    (lookup-key global-map
+               (if path
+                   (vconcat pr-menu-bar
+                            (mapcar 'pr-get-symbol
+                                    (if (listp path)
+                                        path
+                                      (list path))))
+                 pr-menu-bar)))
+
+  ;; GNU Emacs
+  (defun pr-menu-lock (entry index horizontal state path)
+    (when pr-menu-lock
+      (or (and pr-menu-position (eq state pr-menu-state))
+         (setq pr-menu-position (pr-menu-position entry index horizontal)
+               pr-menu-state    state))
+      (let* ((menu   (pr-menu-lookup path))
+            (result (x-popup-menu pr-menu-position menu)))
+       (and result
+            (let ((command (lookup-key menu (vconcat result))))
+              (if (fboundp command)
+                  (funcall command)
+                (eval command)))))
+      (setq pr-menu-position nil)))
+
+  ;; GNU Emacs
+  (defalias 'pr-update-mode-line 'force-mode-line-update)
+
+  ;; GNU Emacs
+  (defun pr-do-update-menus (&optional force)
+    (pr-menu-alist pr-ps-printer-alist
+                  'pr-ps-name
+                  'pr-menu-set-ps-title
+                  "PostScript Printers"
+                  'pr-ps-printer-menu-modified
+                  force
+                  "PostScript Printers"
+                  'postscript 2)
+    (pr-menu-alist pr-txt-printer-alist
+                  'pr-txt-name
+                  'pr-menu-set-txt-title
+                  "Text Printers"
+                  'pr-txt-printer-menu-modified
+                  force
+                  "Text Printers"
+                  'text 2)
+    (let ((save-var pr-ps-utility-menu-modified))
+      (pr-menu-alist pr-ps-utility-alist
+                    'pr-ps-utility
+                    'pr-menu-set-utility-title
+                    '("PostScript Print" "File" "PostScript Utility")
+                    'save-var
+                    force
+                    "PostScript Utility"
+                    nil 1))
+    (pr-menu-alist pr-ps-utility-alist
+                  'pr-ps-utility
+                  'pr-menu-set-utility-title
+                  '("PostScript Preview" "File" "PostScript Utility")
+                  'pr-ps-utility-menu-modified
+                  force
+                  "PostScript Utility"
+                  nil 1)
+    (pr-even-or-odd-pages ps-even-or-odd-pages force))
+
+  ;; GNU Emacs
+  (defun pr-menu-get-item (name-list)
+    ;; NAME-LIST is a string or a list of strings.
+    (or (listp name-list)
+       (setq name-list (list name-list)))
+    (and name-list
+        (let* ((reversed (reverse name-list))
+               (name (pr-get-symbol (car reversed)))
+               (path (nreverse (cdr reversed)))
+               (menu (lookup-key
+                      global-map
+                      (vconcat pr-menu-bar
+                               (mapcar 'pr-get-symbol path)))))
+          (assq name (nthcdr 2 menu)))))
+
+  ;; GNU Emacs
+  (defvar pr-temp-menu nil)
+
+  ;; GNU Emacs
+  (defun pr-menu-alist (alist var-sym fun menu-path modified-sym force name
+                             entry index)
+    (when (and alist (or force (symbol-value modified-sym)))
+      (easy-menu-define pr-temp-menu nil ""
+       (pr-menu-create name alist var-sym fun entry index))
+      (let ((item (pr-menu-get-item menu-path)))
+       (and item
+            (let* ((binding     (nthcdr 3 item))
+                   (key-binding (cdr binding)))
+              (setcar binding pr-temp-menu)
+              (and key-binding (listp (car key-binding))
+                   (setcdr binding (cdr key-binding))) ; skip KEY-BINDING
+              (funcall fun (symbol-value var-sym) item))))
+      (set modified-sym nil)))
+
+  ;; GNU Emacs
+  (defun pr-menu-set-item-name (item name)
+    (and item
+        (setcar (nthcdr 2 item) name))) ; ITEM-NAME
+
+  ;; GNU Emacs
+  (defun pr-menu-set-ps-title (value &optional item entry index)
+    (pr-menu-set-item-name (or item
+                              (pr-menu-get-item "PostScript Printers"))
+                          (format "PostScript Printer: %s" value))
+    (pr-ps-set-printer value)
+    (and index
+        (pr-menu-lock entry index 12 'toggle nil)))
+
+  ;; GNU Emacs
+  (defun pr-menu-set-txt-title (value &optional item entry index)
+    (pr-menu-set-item-name (or item
+                              (pr-menu-get-item "Text Printers"))
+                          (format "Text Printer: %s" value))
+    (pr-txt-set-printer value)
+    (and index
+        (pr-menu-lock entry index 12 'toggle nil)))
+
+  ;; GNU Emacs
+  (defun pr-menu-set-utility-title (value &optional item entry index)
+    (let ((name (symbol-name value)))
+      (if item
+         (pr-menu-set-item-name item name)
+       (pr-menu-set-item-name
+        (pr-menu-get-item
+         '("PostScript Print"   "File" "PostScript Utility"))
+        name)
+       (pr-menu-set-item-name
+        (pr-menu-get-item
+         '("PostScript Preview" "File" "PostScript Utility"))
+        name)))
+    (pr-ps-set-utility value)
+    (and index
+        (pr-menu-lock entry index 5 nil '("PostScript Print" "File"))))
+
+  ;; GNU Emacs
+  (defun pr-even-or-odd-pages (value &optional no-lock)
+    (pr-menu-set-item-name (pr-menu-get-item "Print All Pages")
+                          (cdr (assq value pr-even-or-odd-alist)))
+    (setq ps-even-or-odd-pages value)
+    (or no-lock
+       (pr-menu-lock 'postscript-options 8 12 'toggle nil)))
+
+  ))                                   ; end cond featurep
 
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -1148,7 +1583,7 @@ If SUFFIX is non-nil, add that at the end of the file name."
 
 
 (defgroup printing nil
-  "Printing Utilities group"
+  "Printing Utilities group."
   :tag "Printing Utilities"
   :link '(emacs-library-link :tag "Source Lisp File" "printing.el")
   :prefix "pr-"
@@ -1400,7 +1835,27 @@ Examples:
      (prt_07c  nil         nil \"/D:\\\\\\\\printers\\\\prt_07c\")
      (PRN      \"\"          nil \"PRN\")
      (standard \"redpr.exe\" nil \"\")
-     )"
+     )
+
+Useful links:
+
+* Information about the print command (print.exe)
+  `http://www.computerhope.com/printhlp.htm'
+
+* RedMon - Redirection Port Monitor (redpr.exe)
+  `http://www.cs.wisc.edu/~ghost/redmon/index.htm'
+
+* Redirection Port Monitor (redpr.exe on-line help)
+  `http://www.cs.wisc.edu/~ghost/redmon/en/redmon.htm'
+
+* UNIX man pages: lpr (or type `man lpr')
+  `http://bama.ua.edu/cgi-bin/man-cgi?lpr'
+  `http://www.mediacollege.com/cgi-bin/man/page.cgi?section=all&topic=lpr'
+
+* UNIX man pages: lp (or type `man lp')
+  `http://bama.ua.edu/cgi-bin/man-cgi?lp'
+  `http://www.mediacollege.com/cgi-bin/man/page.cgi?section=all&topic=lp'
+"
   :type '(repeat
          (list :tag "Text Printer"
                (symbol :tag "Printer Symbol Name")
@@ -1448,6 +1903,7 @@ function (see it for documentation) to update PostScript printer menu."
   ;;      (lps_06b  "print"     nil nil   "\\\\printers\\lps_06b")
   ;;      (lps_07c  "print"     nil ""    "/D:\\\\printers\\lps_07c")
   ;;      (lps_08c  nil         nil nil   "\\\\printers\\lps_08c")
+  ;;      (b/w      "gsprint" ("-all" "-twoup") "-printer " "b/w-pr-name")
   ;;      (LPT1     ""          nil ""    "LPT1:")
   ;;      (PRN      ""          nil ""    "PRN")
   ;;      (standard "redpr.exe" nil ""    "")
@@ -1486,6 +1942,7 @@ COMMAND           Name of the program for printing a PostScript file.  On MS-DOS
                        \"lpr\"
                        \"lp\"
                        \"cp\"
+                       \"gsprint\"
 
 SWITCHES       List of sexp's to pass as extra options for PostScript printer
                program.  It is recommended to set NAME (see text below)
@@ -1495,6 +1952,9 @@ SWITCHES  List of sexp's to pass as extra options for PostScript printer
                        '(\"-#3\" \"-l\")
                        nil
 
+                  . for gsprint.exe
+                       '(\"-all\" \"-twoup\")
+
 PRINTER-SWITCH A string that specifies PostScript printer name switch.  If
                it's necessary to have a space between PRINTER-SWITCH and NAME,
                it should be inserted at the end of PRINTER-SWITCH string.
@@ -1511,6 +1971,9 @@ PRINTER-SWITCH    A string that specifies PostScript printer name switch.  If
                   . for print.exe
                        \"/D:\"
 
+                  . for gsprint.exe
+                       \"-printer \"
+
 NAME           A string that specifies a PostScript printer name.
                On Unix-like systems, a string value should be a name
                understood by lpr's -P option (or lp's -d option).
@@ -1526,7 +1989,7 @@ NAME              A string that specifies a PostScript printer name.
                   . for cp.exe
                        \"\\\\\\\\host\\\\share-name\"
 
-                  . for print.exe
+                  . for print.exe or gsprint.exe
                        \"/D:\\\\\\\\host\\\\share-name\"
                        \"\\\\\\\\host\\\\share-name\"
                        \"LPT1:\"
@@ -1540,7 +2003,7 @@ DEFAULT           It's a way to set default values when this entry is selected.
 
                   (VARIABLE . VALUE)
 
-               That associates VARIABLE with VALUE.  when this entry is
+               Which associates VARIABLE with VALUE.  When this entry is
                selected, it's executed the following command:
 
                   (set VARIABLE (eval VALUE))
@@ -1575,10 +2038,80 @@ Examples:
      (lps_06b  \"print\"     nil nil   \"\\\\\\\\printers\\\\lps_06b\")
      (lps_07c  \"print\"     nil \"\"    \"/D:\\\\\\\\printers\\\\lps_07c\")
      (lps_08c  nil         nil nil   \"\\\\\\\\printers\\\\lps_08c\")
+     (b/w1 \"gsprint\" (\"-all\" \"-twoup\") \"-printer \" \"b/w-pr-name\")
+     (b/w2 \"gsprint\" (\"-all\" \"-twoup\") nil \"-printer \\\\\\\\printers\\\\lps_06a\")
      (LPT1     \"\"          nil \"\"    \"LPT1:\")
      (PRN      \"\"          nil \"\"    \"PRN\")
      (standard \"redpr.exe\" nil \"\"    \"\")
-     )"
+     )
+
+
+gsprint:
+
+You can use gsprint instead of ghostscript to print monochrome PostScript files
+in Windows.  The gsprint utility documentation says that it is more efficient
+than ghostscript to print monochrome PostScript.
+
+To print non-monochrome PostScript file, the efficiency of ghostscript is
+similar to gsprint.
+
+Also the gsprint utility comes together with gsview distribution.
+
+As an example of gsprint declaration:
+
+   (setq pr-ps-printer-alist
+        '((A \"gsprint\" (\"-all\" \"-twoup\") \"-printer \" \"lps_015\")
+          (B \"gsprint\" (\"-all\" \"-twoup\") nil \"-printer lps_015\")
+          ;; some other printer declaration
+          ))
+
+The example above declares that printer A prints all pages (-all) and two pages
+per sheet (-twoup).  The printer B declaration does the same as the printer A
+declaration, the only difference is the printer name selection.
+
+There are other command line options like:
+
+   -mono       Render in monochrome as 1bit/pixel (only black and white).
+   -grey       Render in greyscale as 8bits/pixel.
+   -color      Render in color as 24bits/pixel.
+
+The default is `-mono'.  So, printer A and B in the example above are using
+implicitly the `-mono' option.  Note that in `-mono' no gray tone or color is
+printed, this includes the zebra stripes, that is, in `-mono' the zebra stripes
+are not printed.
+
+
+Useful links:
+
+* GSPRINT - Ghostscript print to Windows printer
+  `http://www.cs.wisc.edu/~ghost/gsview/gsprint.htm'
+
+* Introduction to Ghostscript
+  `http://www.cs.wisc.edu/~ghost/doc/intro.htm'
+
+* How to use Ghostscript
+  `http://www.cs.wisc.edu/~ghost/doc/cvs/Use.htm'
+
+* Information about the print command (print.exe)
+  `http://www.computerhope.com/printhlp.htm'
+
+* RedMon - Redirection Port Monitor (redpr.exe)
+  `http://www.cs.wisc.edu/~ghost/redmon/index.htm'
+
+* Redirection Port Monitor (redpr.exe on-line help)
+  `http://www.cs.wisc.edu/~ghost/redmon/en/redmon.htm'
+
+* UNIX man pages: lpr (or type `man lpr')
+  `http://bama.ua.edu/cgi-bin/man-cgi?lpr'
+  `http://www.mediacollege.com/cgi-bin/man/page.cgi?section=all&topic=lpr'
+
+* UNIX man pages: lp (or type `man lp')
+  `http://bama.ua.edu/cgi-bin/man-cgi?lp'
+  `http://www.mediacollege.com/cgi-bin/man/page.cgi?section=all&topic=lp'
+
+* GNU utilities for Win32 (cp.exe)
+  `http://unxutils.sourceforge.net/'
+"
   :type '(repeat
          (list
           :tag "PostScript Printer"
@@ -1674,7 +2207,37 @@ See also `pr-temp-dir' and `pr-ps-temp-file'."
     "gv")
   "*Specify path and name of the gsview/gv utility.
 
-See also `pr-path-alist'."
+See also `pr-path-alist'.
+
+Useful links:
+
+* GNU gv manual
+  `http://www.gnu.org/software/gv/manual/gv.html'
+
+* GSview Help
+  `http://www.cs.wisc.edu/~ghost/gsview/gsviewen.htm'
+
+* GSview Help - Common Problems
+  `http://www.cs.wisc.edu/~ghost/gsview/gsviewen.htm#Common_Problems'
+
+* GSview Readme (compilation & installation)
+  `http://www.cs.wisc.edu/~ghost/gsview/Readme.htm'
+
+* GSview (main site)
+  `http://www.cs.wisc.edu/~ghost/gsview/index.htm'
+
+* Ghostscript, Ghostview and GSview
+  `http://www.cs.wisc.edu/~ghost/'
+
+* Ghostview
+  `http://www.cs.wisc.edu/~ghost/gv/index.htm'
+
+* gv 3.5, June 1997
+  `http://www.cs.wisc.edu/~ghost/gv/gv_doc/gv.html'
+
+* MacGSView (MacOS)
+  `http://www.cs.wisc.edu/~ghost/macos/index.htm'
+"
   :type '(string :tag "Ghostview Utility")
   :version "20"
   :group 'printing)
@@ -1686,7 +2249,22 @@ See also `pr-path-alist'."
     "gs")
   "*Specify path and name of the ghostscript utility.
 
-See also `pr-path-alist'."
+See also `pr-path-alist'.
+
+Useful links:
+
+* Ghostscript, Ghostview and GSview
+  `http://www.cs.wisc.edu/~ghost/'
+
+* Introduction to Ghostscript
+  `http://www.cs.wisc.edu/~ghost/doc/intro.htm'
+
+* How to use Ghostscript
+  `http://www.cs.wisc.edu/~ghost/doc/cvs/Use.htm'
+
+* Printer compatibility
+  `http://www.cs.wisc.edu/~ghost/doc/printer.htm'
+"
   :type '(string :tag "Ghostscript Utility")
   :version "20"
   :group 'printing)
@@ -1717,7 +2295,19 @@ To see ghostscript documentation for more information:
    - for full documentation, see in a browser the file
      c:/gstools/gs5.50/index.html, that is, the file index.html which is
      located in the same directory as gswin32.exe.
-   - for brief documentation, type: gswin32.exe -h"
+   - for brief documentation, type: gswin32.exe -h
+
+Useful links:
+
+* Introduction to Ghostscript
+  `http://www.cs.wisc.edu/~ghost/doc/intro.htm'
+
+* How to use Ghostscript
+  `http://www.cs.wisc.edu/~ghost/doc/cvs/Use.htm'
+
+* Printer compatibility
+  `http://www.cs.wisc.edu/~ghost/doc/printer.htm'
+"
   :type '(repeat (string :tag "Ghostscript Switch"))
   :version "20"
   :group 'printing)
@@ -1968,7 +2558,7 @@ DEFAULT           It's a way to set default values when this entry is selected.
 
                   (VARIABLE-SYM . VALUE)
 
-               That associates VARIABLE-SYM with VALUE.  when this entry is
+               Which associates VARIABLE-SYM with VALUE.  When this entry is
                selected, it's executed the following command:
 
                   (set (make-local-variable VARIABLE-SYM) (eval VALUE))
@@ -2148,7 +2738,7 @@ DEFAULT           It's a way to set default values when this entry is selected.
 
                   (VARIABLE . VALUE)
 
-               That associates VARIABLE with VALUE.  when this entry is
+               Which associates VARIABLE with VALUE.  When this entry is
                selected, it's executed the following command:
 
                   (set VARIABLE (eval VALUE))
@@ -2184,7 +2774,35 @@ Examples:
 
    '((psnup \"c:/psutils/psnup\" (\"-q\") \"-P%s\" \"-%d\" \"-l\" nil nil \" \"
            nil (pr-file-duplex . nil) (pr-file-tumble . nil))
-     )"
+     )
+
+Useful links:
+
+* mpage download (GNU or Unix)
+  `http://www.mesa.nl/pub/mpage/'
+
+* mpage documentation (GNU or Unix - or type `man mpage')
+  `http://www.cs.umd.edu/faq/guides/manual_unix/node48.html'
+  `http://www.rt.com/man/mpage.1.html'
+
+* psnup (Windows, GNU or Unix)
+  `http://www.knackered.org/angus/psutils/'
+  `http://gershwin.ens.fr/vdaniel/Doc-Locale/Outils-Gnu-Linux/PsUtils/'
+
+* psnup (PsUtils for Windows)
+  `http://gnuwin32.sourceforge.net/packages/psutils.htm'
+
+* psnup documentation (GNU or Unix - or type `man psnup')
+  `http://linux.about.com/library/cmd/blcmdl1_psnup.htm'
+  `http://amath.colorado.edu/computing/software/man/psnup.html'
+
+* GNU Enscript (Windows, GNU or Unix)
+  `http://people.ssh.com/mtr/genscript/'
+
+* GNU Enscript documentation (Windows, GNU or Unix)
+  `http://people.ssh.com/mtr/genscript/enscript.man.html'
+  (on GNU or Unix, type `man enscript')
+"
   :type '(repeat
          (list :tag "PS File Utility"
                (symbol :tag "Utility Symbol")
@@ -2245,11 +2863,7 @@ See also `pr-menu-char-height' and `pr-menu-char-width'."
   :group 'printing)
 
 
-(defcustom pr-menu-char-height
-  (cond ((featurep 'xemacs)            ; XEmacs
-        (pr-x-font-height (face-font 'default)))
-       (t                              ; GNU Emacs
-        (pr-e-frame-char-height)))
+(defcustom pr-menu-char-height (pr-menu-char-height)
   "*Specify menu char height in pixels.
 
 This variable is used to guess which vertical position should be locked the
@@ -2261,11 +2875,7 @@ See also `pr-menu-lock' and `pr-menu-char-width'."
   :group 'printing)
 
 
-(defcustom pr-menu-char-width
-  (cond ((featurep 'xemacs)            ; XEmacs
-        (pr-x-font-width (face-font 'default)))
-       (t                              ; GNU Emacs
-        (pr-e-frame-char-width)))
+(defcustom pr-menu-char-width (pr-menu-char-width)
   "*Specify menu char width in pixels.
 
 This variable is used to guess which horizontal position should be locked the
@@ -2337,7 +2947,7 @@ SETTING           It's a cons like:
 
                   (VARIABLE . VALUE)
 
-               That associates VARIABLE with VALUE.  when this entry is
+               Which associates VARIABLE with VALUE.  When this entry is
                selected, it's executed the following command:
 
                  * If LOCAL is non-nil:
@@ -2565,15 +3175,6 @@ See `pr-ps-printer-alist'.")
 ;; Keys & Menus
 
 
-(defmacro pr-xemacs-global-menubar (&rest body)
-  `(save-excursion
-     (let ((temp (get-buffer-create (make-temp-name " *Temp"))))
-       ;; be sure to access global menubar
-       (set-buffer temp)
-       ,@body
-       (kill-buffer temp))))
-
-
 (defsubst pr-visible-p (key)
   (memq key pr-visible-entry-list))
 
@@ -2590,18 +3191,10 @@ See `pr-ps-printer-alist'.")
   (and pr-print-using-ghostscript (not pr-spool-p)))
 
 
-(defun pr-get-symbol (name)
-  (easy-menu-intern name))
-
-(cond
- ((featurep 'xemacs)                   ; XEmacs
-  (defvar zmacs-region-stays nil)      ; to avoid compilation gripes
-  (defun pr-region-active-p ()
-    (and pr-auto-region (not zmacs-region-stays) (ps-mark-active-p))))
-
- (t                                    ; GNU Emacs
-  (defun pr-region-active-p ()
-    (and pr-auto-region transient-mark-mode mark-active))))
+(defalias 'pr-get-symbol
+  (if (fboundp 'easy-menu-intern)      ; hacked from easymenu.el
+      'easy-menu-intern
+    (lambda (s) (if (stringp s) (intern s) s))))
 
 
 (defconst pr-menu-spec
@@ -2845,43 +3438,24 @@ See `pr-ps-printer-alist'.")
       )))
 
 
-(cond
- ((featurep 'xemacs)                   ; XEmacs
-  ;; Menu binding
-  (pr-xemacs-global-menubar
-   (pr-x-add-submenu nil (cons "Printing" pr-menu-spec) "Apps")))
+(defvar pr-menu-print-item "print"
+  "Non-nil means that menu binding was not done.
 
+Used by `pr-menu-bind' and `pr-update-menus'.")
 
- (t                                    ; GNU Emacs
-  ;; Menu binding
-  (require 'easymenu)
-  ;; Replace existing "print" item by "Printing" item.
-  ;; If you're changing this file, you'll load it a second,
-  ;; third... time, but "print" item exists only in the first load.
-  (defvar pr-menu-print-item "print")
-  (cond
-   ;; Emacs 20
-   ((string< emacs-version "21.")
-    (easy-menu-change '("tools") "Printing" pr-menu-spec pr-menu-print-item)
-    (when pr-menu-print-item
-      (easy-menu-remove-item nil '("tools") pr-menu-print-item)
-      (setq pr-menu-print-item nil
-           pr-menu-bar (vector 'menu-bar 'tools
-                               (pr-get-symbol "Printing")))))
-   ;; Emacs 21
-   (pr-menu-print-item
-    (easy-menu-change '("file") "Print" pr-menu-spec "print-buffer")
-    (let ((items '("print-buffer"          "print-region"
-                  "ps-print-buffer-faces" "ps-print-region-faces"
-                  "ps-print-buffer"       "ps-print-region")))
-      (while items
-       (easy-menu-remove-item nil '("file") (car items))
-       (setq items (cdr items)))
-      (setq pr-menu-print-item nil
-           pr-menu-bar (vector 'menu-bar 'file
-                               (pr-get-symbol "Print")))))
-   (t
-    (easy-menu-change '("file") "Print" pr-menu-spec)))))
+
+(defun pr-menu-bind ()
+  "Install `printing' menu in the menubar.
+
+On Emacs 20, it replaces the Tools/Print menu by Tools/Printing menu.
+
+On Emacs 21 and 22, it replaces the File/Print* menu entries by File/Print
+menu.
+
+Calls `pr-update-menus' to adjust menus."
+  (interactive)
+  (pr-global-menubar pr-menu-spec)
+  (pr-update-menus t))
 
 
 ;; Key binding
@@ -4168,7 +4742,7 @@ Interactively, you have the following situations:
    C-u 2 M-x pr-ps-fast-fire RET
       The command prompts the user for a N-UP value, then for a current
       PostScript printer and, finally, for a file name.  Then change the active
-      printer to that choosen by user and saves the PostScript image in
+      printer to that chosen by user and saves the PostScript image in
       that file instead of sending it to the printer.
 
 
@@ -4187,7 +4761,7 @@ zero and the argument SELECT is treated as follows:
 
    If it's an integer greater or equal to 2, the command prompts the user for a
    current PostScript printer and for a file name.  Then change the active
-   printer to that choosen by user and saves the PostScript image in that file
+   printer to that chosen by user and saves the PostScript image in that file
    instead of sending it to the printer.
 
    If it's a symbol which it's defined in `pr-ps-printer-alist', it's the new
@@ -4575,125 +5149,37 @@ Return only the dayname, if present, weekday, month, and year."
     )
   "Alist that associates menu part with number of items per part.
 
-It's used by `pr-menu-index'.
-
-Each element has the form:
-
-   (MENU-PART . NUMBER-OF-ITEMS)
-
-See `pr-visible-entry-alist'.")
-
-
-(defun pr-menu-index (entry index)
-  (let ((base-list
-        (cond ((eq entry 'text)
-               '(postscript))
-              ((eq entry 'postscript-options)
-               '(postscript text))
-              ((eq entry 'postscript-process)
-               '(postscript text postscript-options))
-              ((eq entry 'printing)
-               '(postscript text postscript-options postscript-process))
-              (t
-               nil)
-              ))
-       key)
-    (while base-list
-      (setq key       (car base-list)
-           base-list (cdr base-list))
-      (and (pr-visible-p key)
-          (setq index (+ index
-                         (cdr (assq key pr-menu-entry-alist)))))))
-  (+ index 2))
-
-
-(defvar pr-menu-position nil)
-(defvar pr-menu-state nil)
-
-
-(cond
- ((featurep 'xemacs)
-  ;; XEmacs
-  (defvar current-mouse-event nil)     ; to avoid compilation gripes
-  (defun pr-menu-position (entry index horizontal)
-    (pr-x-make-event
-     'button-release
-     (list 'button 1
-          'x (- (pr-x-event-x-pixel current-mouse-event) ; X
-                (* horizontal pr-menu-char-width))
-          'y (- (pr-x-event-y-pixel current-mouse-event) ; Y
-                (* (pr-menu-index entry index) pr-menu-char-height)))))
-  )
- (ps-windows-system
-  ;; GNU Emacs for Windows 9x/NT
-  (defun pr-menu-position (entry index horizontal)
-    (let ((pos (cdr (pr-e-mouse-pixel-position))))
-      (list
-       (list (or (car pos) 0)          ; X
-            (- (or (cdr pos) 0)        ; Y
-               (* (pr-menu-index entry index) pr-menu-char-height)))
-       (selected-frame))))             ; frame
-  )
- (t
-  ;; GNU Emacs
-  (defun pr-menu-position (entry index horizontal)
-    (let ((pos (cdr (pr-e-mouse-pixel-position))))
-      (list
-       (list (- (or (car pos) 0)       ; X
-               (* horizontal pr-menu-char-width))
-            (- (or (cdr pos) 0)        ; Y
-               (* (pr-menu-index entry index) pr-menu-char-height)))
-       (selected-frame))))             ; frame
-  ))
-
-(cond
- ((featurep 'xemacs)
-  ;; XEmacs
-  (defvar current-menubar nil)         ; to avoid compilation gripes
-  (defun pr-menu-lookup (path)
-    (car (pr-x-find-menu-item current-menubar (cons "Printing" path))))
-
-  ;; XEmacs
-  (defun pr-menu-lock (entry index horizontal state path)
-    (when pr-menu-lock
-      (or (and pr-menu-position (eq state pr-menu-state))
-         (setq pr-menu-position (pr-menu-position entry index horizontal)
-               pr-menu-state    state))
-      (let* ((menu   (pr-menu-lookup path))
-            (result (pr-x-get-popup-menu-response menu pr-menu-position)))
-       (and (pr-x-misc-user-event-p result)
-            (funcall (pr-x-event-function result)
-                     (pr-x-event-object result))))
-      (setq pr-menu-position nil))))
-
-
- (t
-  ;; GNU Emacs
-  (defun pr-menu-lookup (path)
-    (lookup-key global-map
-               (if path
-                   (vconcat pr-menu-bar
-                            (mapcar 'pr-get-symbol
-                                    (if (listp path)
-                                        path
-                                      (list path))))
-                 pr-menu-bar)))
-
-  ;; GNU Emacs
-  (defun pr-menu-lock (entry index horizontal state path)
-    (when pr-menu-lock
-      (or (and pr-menu-position (eq state pr-menu-state))
-         (setq pr-menu-position (pr-menu-position entry index horizontal)
-               pr-menu-state    state))
-      (let* ((menu   (pr-menu-lookup path))
-            (result (x-popup-menu pr-menu-position menu)))
-       (and result
-            (let ((command (lookup-key menu (vconcat result))))
-              (if (fboundp command)
-                  (funcall command)
-                (eval command)))))
-      (setq pr-menu-position nil)))))
-
+It's used by `pr-menu-index'.
+
+Each element has the form:
+
+   (MENU-PART . NUMBER-OF-ITEMS)
+
+See `pr-visible-entry-alist'.")
+
+
+(defun pr-menu-index (entry index)
+  (let ((base-list
+        (cond ((eq entry 'text)
+               '(postscript))
+              ((eq entry 'postscript-options)
+               '(postscript text))
+              ((eq entry 'postscript-process)
+               '(postscript text postscript-options))
+              ((eq entry 'printing)
+               '(postscript text postscript-options postscript-process))
+              (t
+               nil)
+              ))
+       key)
+    (while base-list
+      (setq key       (car base-list)
+           base-list (cdr base-list))
+      (and (pr-visible-p key)
+          (setq index (+ index
+                         (cdr (assq key pr-menu-entry-alist)))))))
+  (+ index 2))
+
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Printer & Utility Selection
@@ -4709,15 +5195,23 @@ See `pr-visible-entry-alist'.")
 
 If FORCE is non-nil, update menus doesn't matter if `pr-ps-printer-alist',
 `pr-txt-printer-alist' or `pr-ps-utility-alist' were modified or not;
-otherwise, update PostScript printer menu iff `pr-ps-printer-menu-modified' is
-non-nil, update text printer menu iff `pr-txt-printer-menu-modified' is
-non-nil, and update PostScript File menus iff `pr-ps-utility-menu-modified' is
-non-nil."
+otherwise, update PostScript printer menu if `pr-ps-printer-menu-modified' is
+non-nil, update text printer menu if `pr-txt-printer-menu-modified' is
+non-nil, and update PostScript File menus if `pr-ps-utility-menu-modified' is
+non-nil.
+
+If menu binding was not done, calls `pr-menu-bind'."
   (interactive "P")
-  (pr-update-var 'pr-ps-name pr-ps-printer-alist)
-  (pr-update-var 'pr-txt-name pr-txt-printer-alist)
-  (pr-update-var 'pr-ps-utility pr-ps-utility-alist)
-  (pr-do-update-menus force))
+  (if pr-menu-print-item               ; since v6.8.4
+      ;; There was no menu binding yet, so do it now!
+      ;; This is a hack to be compatible with old versions of printing.
+      ;; So, user does not need to change printing calling in init files.
+      (pr-menu-bind)
+    ;; Here menu binding is ok.
+    (pr-update-var 'pr-ps-name pr-ps-printer-alist)
+    (pr-update-var 'pr-txt-name pr-txt-printer-alist)
+    (pr-update-var 'pr-ps-utility pr-ps-utility-alist)
+    (pr-do-update-menus force)))
 
 
 (defvar pr-ps-printer-menu-modified  t
@@ -4749,237 +5243,6 @@ non-nil."
         alist)))
 
 
-(cond
- ((featurep 'xemacs)
-  ;; XEmacs
-  (defalias 'pr-update-mode-line 'set-menubar-dirty-flag)
-
-  ;; XEmacs
-  (defvar pr-ps-name-old     "PostScript Printers")
-  (defvar pr-txt-name-old    "Text Printers")
-  (defvar pr-ps-utility-old  "PostScript Utility")
-  (defvar pr-even-or-odd-old "Print All Pages")
-
-  ;; XEmacs
-  (defun pr-do-update-menus (&optional force)
-    (pr-menu-alist pr-ps-printer-alist
-                  'pr-ps-name
-                  'pr-menu-set-ps-title
-                  '("Printing")
-                  'pr-ps-printer-menu-modified
-                  force
-                  pr-ps-name-old
-                  'postscript 2)
-    (pr-menu-alist pr-txt-printer-alist
-                  'pr-txt-name
-                  'pr-menu-set-txt-title
-                  '("Printing")
-                  'pr-txt-printer-menu-modified
-                  force
-                  pr-txt-name-old
-                  'text 2)
-    (let ((save-var pr-ps-utility-menu-modified))
-      (pr-menu-alist pr-ps-utility-alist
-                    'pr-ps-utility
-                    'pr-menu-set-utility-title
-                    '("Printing" "PostScript Print"   "File")
-                    'save-var
-                    force
-                    pr-ps-utility-old
-                    nil 1))
-    (pr-menu-alist pr-ps-utility-alist
-                  'pr-ps-utility
-                  'pr-menu-set-utility-title
-                  '("Printing" "PostScript Preview" "File")
-                  'pr-ps-utility-menu-modified
-                  force
-                  pr-ps-utility-old
-                  nil 1)
-    (pr-even-or-odd-pages ps-even-or-odd-pages force))
-
-  ;; XEmacs
-  (defun pr-menu-alist (alist var-sym fun menu-path modified-sym force name
-                             entry index)
-    (when (and alist (or force (symbol-value modified-sym)))
-      (pr-xemacs-global-menubar
-       (pr-x-add-submenu menu-path
-                        (pr-menu-create name alist var-sym
-                                        fun entry index)))
-      (funcall fun (symbol-value var-sym))
-      (set modified-sym nil)))
-
-  ;; XEmacs
-  (defun pr-relabel-menu-item (newname var-sym)
-    (pr-xemacs-global-menubar
-     (pr-x-relabel-menu-item
-      (list "Printing" (symbol-value var-sym))
-      newname)
-     (set var-sym newname)))
-
-  ;; XEmacs
-  (defun pr-menu-set-ps-title (value &optional item entry index)
-    (pr-relabel-menu-item (format "PostScript Printer: %s" value)
-                         'pr-ps-name-old)
-    (pr-ps-set-printer value)
-    (and index
-        (pr-menu-lock entry index 12 'toggle nil)))
-
-  ;; XEmacs
-  (defun pr-menu-set-txt-title (value &optional item entry index)
-    (pr-relabel-menu-item (format "Text Printer: %s" value)
-                         'pr-txt-name-old)
-    (pr-txt-set-printer value)
-    (and index
-        (pr-menu-lock entry index 12 'toggle nil)))
-
-  ;; XEmacs
-  (defun pr-menu-set-utility-title (value &optional item entry index)
-    (pr-xemacs-global-menubar
-     (let ((newname (format "%s" value)))
-       (pr-x-relabel-menu-item
-       (list "Printing" "PostScript Print" "File" pr-ps-utility-old)
-       newname)
-       (pr-x-relabel-menu-item
-       (list "Printing" "PostScript Preview" "File" pr-ps-utility-old)
-       newname)
-       (setq pr-ps-utility-old newname)))
-    (pr-ps-set-utility value)
-    (and index
-        (pr-menu-lock entry index 5 nil '("PostScript Print" "File"))))
-
-  ;; XEmacs
-  (defun pr-even-or-odd-pages (value &optional no-lock)
-    (pr-relabel-menu-item (cdr (assq value pr-even-or-odd-alist))
-                         'pr-even-or-odd-old)
-    (setq ps-even-or-odd-pages value)
-    (or no-lock
-       (pr-menu-lock 'postscript-options 8 12 'toggle nil))))
-
-
- (t
-  ;; GNU Emacs
-  (defalias 'pr-update-mode-line 'force-mode-line-update)
-
-  ;; GNU Emacs
-  (defun pr-do-update-menus (&optional force)
-    (pr-menu-alist pr-ps-printer-alist
-                  'pr-ps-name
-                  'pr-menu-set-ps-title
-                  "PostScript Printers"
-                  'pr-ps-printer-menu-modified
-                  force
-                  "PostScript Printers"
-                  'postscript 2)
-    (pr-menu-alist pr-txt-printer-alist
-                  'pr-txt-name
-                  'pr-menu-set-txt-title
-                  "Text Printers"
-                  'pr-txt-printer-menu-modified
-                  force
-                  "Text Printers"
-                  'text 2)
-    (let ((save-var pr-ps-utility-menu-modified))
-      (pr-menu-alist pr-ps-utility-alist
-                    'pr-ps-utility
-                    'pr-menu-set-utility-title
-                    '("PostScript Print"   "File" "PostScript Utility")
-                    'save-var
-                    force
-                    "PostScript Utility"
-                    nil 1))
-    (pr-menu-alist pr-ps-utility-alist
-                  'pr-ps-utility
-                  'pr-menu-set-utility-title
-                  '("PostScript Preview" "File" "PostScript Utility")
-                  'pr-ps-utility-menu-modified
-                  force
-                  "PostScript Utility"
-                  nil 1)
-    (pr-even-or-odd-pages ps-even-or-odd-pages force))
-
-  ;; GNU Emacs
-  (defun pr-menu-get-item (name-list)
-    ;; NAME-LIST is a string or a list of strings.
-    (or (listp name-list)
-       (setq name-list (list name-list)))
-    (and name-list
-        (let* ((reversed (reverse name-list))
-               (name (pr-get-symbol (car reversed)))
-               (path (nreverse (cdr reversed)))
-               (menu (lookup-key
-                      global-map
-                      (vconcat pr-menu-bar
-                               (mapcar 'pr-get-symbol path)))))
-          (assq name (nthcdr 2 menu)))))
-
-  ;; GNU Emacs
-  (defvar pr-temp-menu nil)
-
-  ;; GNU Emacs
-  (defun pr-menu-alist (alist var-sym fun menu-path modified-sym force name
-                             entry index)
-    (when (and alist (or force (symbol-value modified-sym)))
-      (easy-menu-define pr-temp-menu nil ""
-       (pr-menu-create name alist var-sym fun entry index))
-      (let ((item (pr-menu-get-item menu-path)))
-       (and item
-            (let* ((binding     (nthcdr 3 item))
-                   (key-binding (cdr binding)))
-              (setcar binding pr-temp-menu)
-              (and key-binding (listp (car key-binding))
-                   (setcdr binding (cdr key-binding))) ; skip KEY-BINDING
-              (funcall fun (symbol-value var-sym) item))))
-      (set modified-sym nil)))
-
-  ;; GNU Emacs
-  (defun pr-menu-set-item-name (item name)
-    (and item
-        (setcar (nthcdr 2 item) name))) ; ITEM-NAME
-
-  ;; GNU Emacs
-  (defun pr-menu-set-ps-title (value &optional item entry index)
-    (pr-menu-set-item-name (or item
-                              (pr-menu-get-item "PostScript Printers"))
-                          (format "PostScript Printer: %s" value))
-    (pr-ps-set-printer value)
-    (and index
-        (pr-menu-lock entry index 12 'toggle nil)))
-
-  ;; GNU Emacs
-  (defun pr-menu-set-txt-title (value &optional item entry index)
-    (pr-menu-set-item-name (or item
-                              (pr-menu-get-item "Text Printers"))
-                          (format "Text Printer: %s" value))
-    (pr-txt-set-printer value)
-    (and index
-        (pr-menu-lock entry index 12 'toggle nil)))
-
-  ;; GNU Emacs
-  (defun pr-menu-set-utility-title (value &optional item entry index)
-    (let ((name (symbol-name value)))
-      (if item
-         (pr-menu-set-item-name item name)
-       (pr-menu-set-item-name
-        (pr-menu-get-item
-         '("PostScript Print"   "File" "PostScript Utility"))
-        name)
-       (pr-menu-set-item-name
-        (pr-menu-get-item
-         '("PostScript Preview" "File" "PostScript Utility"))
-        name)))
-    (pr-ps-set-utility value)
-    (and index
-        (pr-menu-lock entry index 5 nil '("PostScript Print" "File"))))
-
-  ;; GNU Emacs
-  (defun pr-even-or-odd-pages (value &optional no-lock)
-    (pr-menu-set-item-name (pr-menu-get-item "Print All Pages")
-                          (cdr (assq value pr-even-or-odd-alist)))
-    (setq ps-even-or-odd-pages value)
-    (or no-lock
-       (pr-menu-lock 'postscript-options 8 12 'toggle nil)))))
-
-
 (defun pr-ps-set-utility (value)
   (let ((item (cdr (assq value pr-ps-utility-alist))))
     (or item
@@ -5048,15 +5311,15 @@ non-nil."
 
 (defun pr-eval-local-alist (alist)
   (let (local-list)
-    (mapcar #'(lambda (option)
-               (let ((var-sym (car option))
-                     (value   (cdr option)))
-                 (setq local-list
-                       (if (eq var-sym 'inherits-from:)
-                           (nconc (pr-eval-setting-alist value) local-list)
-                         (set (make-local-variable var-sym) (eval value))
-                         (cons var-sym local-list)))))
-           alist)
+    (mapc #'(lambda (option)
+             (let ((var-sym (car option))
+                   (value   (cdr option)))
+               (setq local-list
+                     (if (eq var-sym 'inherits-from:)
+                         (nconc (pr-eval-setting-alist value) local-list)
+                       (set (make-local-variable var-sym) (eval value))
+                       (cons var-sym local-list)))))
+         alist)
     local-list))
 
 
@@ -5078,7 +5341,7 @@ non-nil."
                  (setq local-list
                        (pr-eval-setting-alist inherits global
                                               (cons inherits old)))))
-          (mapcar
+          (mapc
            (cond ((not local)          ; global settings
                   #'(lambda (option)
                       (let ((var-sym (car option)))
@@ -5461,7 +5724,7 @@ non-nil."
 (defun pr-interactive-n-up (mess)
   (or (stringp mess) (setq mess "*"))
   (save-match-data
-    (let* ((fmt-prompt "%s[%s] N-up printing: (default 1) ")
+    (let* ((fmt-prompt "%s[%s] N-up printing (default 1): ")
           (prompt "")
           (str (pr-f-read-string (format fmt-prompt prompt mess) "1" nil "1"))
           int)
@@ -5755,9 +6018,10 @@ COMMAND.exe, COMMAND.bat and COMMAND.com in this order."
 ;; Printing Interface (inspired on ps-print-interface.el)
 
 
-(require 'widget)
-(require 'wid-edit)
-(require 'cus-edit)
+(eval-when-compile
+  (require 'cus-edit)
+  (require 'wid-edit)
+  (require 'widget))
 
 
 (defvar pr-i-window-configuration nil)
@@ -5814,6 +6078,8 @@ COMMAND.exe, COMMAND.bat and COMMAND.com in this order."
   ;; header
   (let ((versions (concat "printing v" pr-version
                          "    ps-print v" ps-print-version)))
+    ;; to keep compatibility with Emacs 20 & 21:
+    ;; DO NOT REPLACE `?\ ' BY `?\s'
     (widget-insert (make-string (- 79 (length versions)) ?\ ) versions))
   (pr-insert-italic "\nCurrent Directory : " 1)
   (pr-insert-italic default-directory)
@@ -6181,7 +6447,7 @@ COMMAND.exe, COMMAND.bat and COMMAND.com in this order."
     ;; handlers
     ((quit error)
      (ding)
-     (message (error-message-string data)))))
+     (message "%s" (error-message-string data)))))
 
 
 (defun pr-interface-printify (&rest ignore)
@@ -6206,7 +6472,7 @@ COMMAND.exe, COMMAND.bat and COMMAND.com in this order."
     ;; handlers
     ((quit error)
      (ding)
-     (message (error-message-string data)))))
+     (message "%s" (error-message-string data)))))
 
 
 (defun pr-interface-ps-print (&rest ignore)
@@ -6272,7 +6538,7 @@ COMMAND.exe, COMMAND.bat and COMMAND.com in this order."
     ;; handlers
     ((quit error)
      (ding)
-     (message (error-message-string data)))))
+     (message "%s" (error-message-string data)))))
 
 
 (defun pr-i-ps-send ()
@@ -6434,9 +6700,6 @@ COMMAND.exe, COMMAND.bat and COMMAND.com in this order."
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 
-(pr-update-menus t)
-
-
 (provide 'printing)