(diary-face, holiday-face): Add dark-background variants.
[bpt/emacs.git] / lisp / ps-print.el
index 0ceb66f..8d46574 100644 (file)
@@ -1,6 +1,6 @@
 ;;; ps-print.el --- Print text from the buffer as PostScript
 
-;; Copyright (C) 1993, 94, 95, 96, 97, 98, 1999 Free Software Foundation, Inc.
+;; Copyright (C) 1993, 2000 Free Software Foundation, Inc.
 
 ;; Author:     Jim Thompson (was <thompson@wg2.waii.com>)
 ;; Author:     Jacques Duthen (was <duthen@cegelec-red.fr>)
@@ -9,16 +9,16 @@
 ;; Maintainer: Kenichi Handa <handa@etl.go.jp> (multi-byte characters)
 ;; Maintainer: Vinicius Jose Latorre <vinicius@cpqd.com.br>
 ;; Keywords:   wp, print, PostScript
-;; Time-stamp: <99/12/18 13:21:51 vinicius>
-;; Version:    5.0.3
+;; Time-stamp: <2000/10/28 23:38:44 Vinicius>
+;; Version:    6.3
+;; X-URL:      http://www.cpqd.com.br/~vinicius/emacs/
 
-(defconst ps-print-version "5.0.3"
-  "ps-print.el, v 5.0.3 <99/12/18 vinicius>
+(defconst ps-print-version "6.3"
+  "ps-print.el, v 6.3 <2000/10/28 vinicius>
 
 Vinicius's last change version -- this file may have been edited as part of
-Emacs without changes to the version number.  When reporting bugs,
-please also report the version of Emacs, if any, that ps-print was
-distributed with.
+Emacs without changes to the version number.  When reporting bugs, please also
+report the version of Emacs, if any, that ps-print was distributed with.
 
 Please send all bug fixes and enhancements to
        Vinicius Jose Latorre <vinicius@cpqd.com.br>.
@@ -183,19 +183,36 @@ Please send all bug fixes and enhancements to
 ;; The variable `ps-printer-name' determines the name of a local printer for
 ;; printing PostScript files.
 ;;
+;; The variable `ps-printer-name-option' determines the option used by some
+;; utilities to indicate the printer name, it's used only when
+;; `ps-printer-name' is a non-empty string.  If you're using lpr utility to
+;; print, for example, `ps-printer-name-option' should be set to "-P".
+;;
 ;; NOTE: `ps-lpr-command' and `ps-lpr-switches' take their initial values
 ;;       from the variables `lpr-command' and `lpr-switches'.  If you have
 ;;       `lpr-command' set to invoke a pretty-printer such as `enscript',
 ;;       then ps-print won't work properly.  `ps-lpr-command' must name
 ;;       a program that does not format the files it prints.
 ;;       `ps-printer-name' takes its initial value from the variable
-;;       `printer-name'.
+;;       `printer-name'.  `ps-printer-name-option' tries to guess which system
+;;       Emacs is running and takes its initial value in accordance with this
+;;       guess.
 ;;
 ;; The variable `ps-print-region-function' specifies a function to print the
 ;; region on a PostScript printer.
 ;; See definition of `call-process-region' for calling conventions.  The fourth
 ;; and the sixth arguments are both nil.
 ;;
+;; The variable `ps-manual-feed' indicates if the printer will manually feed
+;; paper.  If it's nil, automatic feeding takes place.  If it's non-nil, manual
+;; feeding takes place.  The default is nil (automatic feeding).
+;;
+;; If you're using Emacs for Windows 95/98/NT or MS-DOS, don't forget to
+;; customize the following variables: `ps-printer-name',
+;; `ps-printer-name-option', `ps-lpr-command', `ps-lpr-switches' and
+;; `ps-spool-config'.  See these variables documentation in the code or by
+;; typing, for example, C-h v ps-printer-name RET.
+;;
 ;;
 ;; The Page Layout
 ;; ---------------
@@ -204,30 +221,65 @@ Please send all bug fixes and enhancements to
 ;; 1 inch  ==       2.54  cm    ==     72       points
 ;; 1 cm    ==  (/ 1 2.54) inch  ==  (/ 72 2.54) points
 ;;
-;; The variable `ps-paper-type' determines the size of paper ps-print
-;; formats for; it should contain one of the symbols:
-;; `a4' `a3' `letter' `legal' `letter-small' `tabloid'
-;; `ledger' `statement' `executive' `a4small' `b4' `b5'
-;;
-;; The variable `ps-landscape-mode' determines the orientation
-;; of the printing on the page:
-;; nil means `portrait' mode, non-nil means `landscape' mode.
+;; The variable `ps-paper-type' determines the size of paper ps-print formats
+;; for; it should contain one of the symbols: `a4' `a3' `letter' `legal'
+;; `letter-small' `tabloid' `ledger' `statement' `executive' `a4small' `b4'
+;; `b5'.
+;;
+;; If variable `ps-warn-paper-type' is nil, it's *not* given an error if
+;; PostScript printer doesn't have a paper with the size indicated by
+;; `ps-paper-type', instead it uses the default paper size.  If variable
+;; `ps-warn-paper-type' is non-nil, it's given an error if PostScript printer
+;; doesn't have a paper with the size indicated by `ps-paper-type'.  It's used
+;; when `ps-spool-config' is set to `setpagedevice' (see section Duplex
+;; Printers).  The default value is non-nil (it gives an error).
+;;
+;; The variable `ps-landscape-mode' determines the orientation of the printing
+;; on the page: nil means `portrait' mode, non-nil means `landscape' mode.
 ;; There is no oblique mode yet, though this is easy to do in ps.
 ;;
-;; In landscape mode, the text is NOT scaled: you may print 70 lines
-;; in portrait mode and only 50 lignes in landscape mode.
-;; The margins represent margins in the printed paper:
-;; the top margin is the margin between the top of the page
+;; In landscape mode, the text is NOT scaled: you may print 70 lines in portrait
+;; mode and only 50 lines in landscape mode.  The margins represent margins in
+;; the printed paper: the top margin is the margin between the top of the page
 ;; and the printed header, whatever the orientation is.
 ;;
-;; The variable `ps-number-of-columns' determines the number of columns
-;; both in landscape and portrait mode.
+;; The variable `ps-number-of-columns' determines the number of columns both in
+;; landscape and portrait mode.
 ;; You can use:
-;; - (the standard) one column portrait mode
-;; - (my favorite) two columns landscape mode (which spares trees)
-;; but also
+;; - (the standard) one column portrait mode.
+;; - (my favorite) two columns landscape mode (which spares trees).
+;; but also:
 ;; - one column landscape mode for files with very long lines.
-;; - multi-column portrait or landscape mode
+;; - multi-column portrait or landscape mode.
+;;
+;; The variable `ps-print-upside-down' determines other orientation for printing
+;; page: nil means `normal' printing, non-nil means `upside-down' printing.  The
+;; default value is nil (`normal' printing).
+;;
+;; The `upside-down' orientation can be used in portrait or landscape mode.
+;;
+;; The variable `ps-selected-pages' specifies which pages to print.  If it's
+;; nil, all pages are printed.  If it's a list, the list element may be an
+;; integer or a cons cell (FROM . TO) designating FROM page to TO page; any
+;; invalid element is ignored, that is, an integer lesser than one or if FROM
+;; is greater than TO.  Otherwise, it's treated as nil.  The default value is
+;; nil (print all pages).  After ps-print processing `ps-selected-pages' is set
+;; to nil.  But the latest `ps-selected-pages' is saved in
+;; `ps-last-selected-pages' (see it for documentation).  So you can restore the
+;; latest selected pages by using `ps-last-selected-pages' or by calling
+;; `ps-restore-selected-pages' command (see it for documentation).
+;;
+;; The variable `ps-even-or-odd-pages' specifies if it prints even/odd pages.
+;;
+;; Valid values are:
+;;
+;; nil         print all pages.
+;;
+;; even                print only even pages.
+;;
+;; odd         print only odd pages.
+;;
+;; Any other value is treated as nil.  The default value is nil.
 ;;
 ;;
 ;; Horizontal layout
@@ -298,6 +350,17 @@ Please send all bug fixes and enhancements to
 ;; To print only one header at the top of each page,
 ;; set `ps-print-only-one-header' to t.
 ;;
+;; To switch headers, set `ps-switch-header' to:
+;;
+;;    nil      Never switch headers.
+;;
+;;    t                Always switch headers.
+;;
+;;    duplex   Switch headers only when duplexing is on, that is, when
+;;             `ps-spool-duplex' is non-nil (see Duplex Printers).
+;;
+;; Any other value is treated as t.  The default value is `duplex'.
+;;
 ;; The font family and size of text in the header are determined
 ;; by the variables `ps-header-font-family', `ps-header-font-size' and
 ;; `ps-header-title-font-size' (see below).
@@ -306,7 +369,7 @@ Please send all bug fixes and enhancements to
 ;; title line height to insert between the header frame and the text
 ;; it contains, both in the vertical and horizontal directions:
 ;; .5 means half a line.
-
+;;
 ;; Page numbers are printed in `n/m' format, indicating page n of m pages;
 ;; to omit the total page count and just print the page number,
 ;; set `ps-show-n-of-n' to nil.
@@ -394,6 +457,63 @@ Please send all bug fixes and enhancements to
 ;;    Adobe Systems Incorporated
 ;;    Appendix G: Document Structuring Conventions -- Version 3.0
 ;;
+;; It is also possible to add an user defined PostScript prologue code before
+;; all generated prologue code by setting the variable
+;; `ps-user-defined-prologue'.
+;;
+;; `ps-user-defined-prologue' may be a string or a symbol function which returns
+;; a string.  Note that this string is inserted after `ps-adobe-tag' and
+;; PostScript prologue comments, and before ps-print PostScript prologue code
+;; section.  That is, this string is inserted after error handler initialization
+;; and before ps-print settings.
+;;
+;; By default `ps-user-defined-prologue' is nil.
+;;
+;; It's strongly recommended only insert PostScript code and/or comments
+;; specific for your printing system particularities.  For example, some special
+;; initialization that only your printing system needs.
+;;
+;; Do not insert code for duplex printing, n-up printing or error handler,
+;; ps-print handles this in a suitable way.
+;;
+;; For more information about PostScript, see:
+;;    PostScript Language Reference Manual (2nd edition)
+;;    Adobe Systems Incorporated
+;;
+;; As an example for `ps-user-defined-prologue' setting:
+;;
+;;   ;; Setting for HP PostScript printer
+;;   (setq ps-user-defined-prologue
+;;        (concat "<</DeferredMediaSelection true /PageSize [612 792] "
+;;                "/MediaPosition 2 /MediaType (Plain)>> setpagedevice"))
+;;
+;;
+;; PostScript Error Handler
+;; ------------------------
+;;
+;; ps-print instruments generated PostScript code with an error handler.
+;;
+;; The variable `ps-error-handler-message' specifies where the error handler
+;; message should be sent.
+;;
+;; Valid values are:
+;;
+;; none                        catch the error and *DON'T* send any message.
+;;
+;; paper               catch the error and print on paper the error message.
+;;                     This is the default value.
+;;
+;; system              catch the error and send back the error message to
+;;                     printing system.  This is useful only if printing system
+;;                     send back an email reporting the error, or if there is
+;;                     some other alternative way to report back the error from
+;;                     the system to you.
+;;
+;; paper-and-system    catch the error, print on paper the error message and
+;;                     send back the error message to printing system.
+;;
+;; Any other value is treated as `paper'.
+;;
 ;;
 ;; Duplex Printers
 ;; ---------------
@@ -535,6 +655,58 @@ Please send all bug fixes and enhancements to
 ;; The variable `ps-line-number' specifies whether to number each line;
 ;; non-nil means do so.  The default is nil (don't number each line).
 ;;
+;; The variable `ps-line-number-step' specifies the interval that line number is
+;; printed.  For example, if `ps-line-number-step' is set to 2, the printing
+;; will look like:
+;;
+;;    1 one line
+;;      one line
+;;    3 one line
+;;      one line
+;;    5 one line
+;;      one line
+;;      ...
+;;
+;; Valid values are:
+;;
+;; integer     an integer that specifies the interval that line number is
+;;             printed.  If it's lesser than or equal to zero, it's used the
+;;             value 1.
+;;
+;; `zebra'     specifies that only the line number of the first line in a zebra
+;;             stripe is to be printed.
+;;
+;; Any other value is treated as `zebra'.
+;; The default value is 1, so each line number is printed.
+;;
+;; The variable `ps-line-number-start' specifies the starting point in the
+;; interval given by `ps-line-number-step'.  For example, if
+;; `ps-line-number-step' is set to 3 and `ps-line-number-start' is set to 3, the
+;; printing will look like:
+;;
+;;      one line
+;;      one line
+;;    3 one line
+;;      one line
+;;      one line
+;;    6 one line
+;;      one line
+;;      one line
+;;    9 one line
+;;      one line
+;;      ...
+;;
+;; The values for `ps-line-number-start':
+;;
+;;    * If `ps-line-number-step' is an integer, must be between 1 and the value
+;;     of `ps-line-number-step' inclusive.
+;;
+;;    * If `ps-line-number-step' is set to `zebra', must be between 1 and the
+;;     value of `ps-zebra-stripe-height' inclusive.
+;;
+;; The default value is 1, so the line number of the first line of each interval
+;; is printed.
+;;
 ;;
 ;; Zebra Stripes
 ;; -------------
@@ -562,9 +734,39 @@ Please send all bug fixes and enhancements to
 ;; The variable `ps-zebra-stripes' controls whether to print zebra stripes.
 ;; Non-nil means yes, nil means no.  The default is nil.
 ;;
-;; The variable `ps-zebra-gray' controls the zebra stripes gray scale.
-;; It should be a float number between 0.0 (black color) and 1.0 (white color).
-;; The default is 0.95.
+;; The variable `ps-zebra-color' controls the zebra stripes gray scale or RGB
+;; color.  It should be a float number between 0.0 (black color) and 1.0 (white
+;; color), a string which is a color name, or a list of 3 numbers which
+;; corresponds to the Red Green Blue color scale.
+;; The default is 0.95 (or "gray95", or '(0.95 0.95 0.95)).
+;;
+;; The variable `ps-zebra-stripe-follow' specifies if zebra stripe should
+;; continue on next page or restart on each page.  If `ps-zebra-stripe-follow'
+;; is nil, zebra stripe is restarted on each page.  If `ps-zebra-stripe-follow'
+;; is non-nil, zebra stripe continues on next page.  Visually, we have:
+;;
+;;             `ps-zebra-stripe-follow'        `ps-zebra-stripe-follow'
+;;                is nil                          is non-nil
+;; Current Page ------------------------       ------------------------
+;;             1  XXXXXXXXXXXXXXXXXXXXX        1  XXXXXXXXXXXXXXXXXXXXX
+;;             2  XXXXXXXXXXXXXXXXXXXXX        2  XXXXXXXXXXXXXXXXXXXXX
+;;             3  XXXXXXXXXXXXXXXXXXXXX        3  XXXXXXXXXXXXXXXXXXXXX
+;;             4                               4
+;;             5                               5
+;;             6                               6
+;;             7  XXXXXXXXXXXXXXXXXXXXX        7  XXXXXXXXXXXXXXXXXXXXX
+;;             8  XXXXXXXXXXXXXXXXXXXXX        8  XXXXXXXXXXXXXXXXXXXXX
+;;             ------------------------        ------------------------
+;;    Next Page ------------------------       ------------------------
+;;             9  XXXXXXXXXXXXXXXXXXXXX        9  XXXXXXXXXXXXXXXXXXXXX
+;;             10 XXXXXXXXXXXXXXXXXXXXX        10
+;;             11 XXXXXXXXXXXXXXXXXXXXX        11
+;;             12                              12
+;;             13                              13 XXXXXXXXXXXXXXXXXXXXX
+;;             14                              14 XXXXXXXXXXXXXXXXXXXXX
+;;             15 XXXXXXXXXXXXXXXXXXXXX        15 XXXXXXXXXXXXXXXXXXXXX
+;;             16 XXXXXXXXXXXXXXXXXXXXX        16
+;;             ------------------------        ------------------------
 ;;
 ;; See also section How Ps-Print Has A Text And/Or Image On Background.
 ;;
@@ -638,11 +840,11 @@ Please send all bug fixes and enhancements to
 ;; - create a new buffer
 ;; - generate the PostScript image to a file (C-u M-x ps-print-buffer)
 ;; - open this file and find the line:
-;;     `% 3 cm 20 cm moveto  10 /Courier ReportFontInfo  showpage'
+;;     `% 3 cm 20 cm moveto  10/Courier ReportFontInfo  showpage'
 ;; - delete the leading `%' (which is the PostScript comment character)
 ;; - replace in this line `Courier' by the new font (say `Helvetica')
 ;;   to get the line:
-;;     `3 cm 20 cm moveto  10 /Helvetica ReportFontInfo  showpage'
+;;     `3 cm 20 cm moveto  10/Helvetica ReportFontInfo  showpage'
 ;; - send this file to the printer (or to ghostscript).
 ;;   You should read the following on the output page:
 ;;
@@ -720,8 +922,10 @@ Please send all bug fixes and enhancements to
 ;; The PostScript file should be sent to YOUR PostScript printer.
 ;; If you send it to ghostscript or to another PostScript printer,
 ;; you may get slightly different results.
-;; Anyway, as ghostscript fonts are autoload, you won't get
-;; much font info.
+;; Anyway, as ghostscript fonts are autoload, you won't get much font info.
+;;
+;; Note also that ps-print DOESN'T download any font to your printer, instead
+;; it uses the fonts resident in your printer.
 ;;
 ;;
 ;; How Ps-Print Deals With Faces
@@ -759,6 +963,17 @@ Please send all bug fixes and enhancements to
 ;; rebuilt when ps-print is invoked, set the variable
 ;; `ps-always-build-face-reference' to t.
 ;;
+;; If you need to print without worrying about face background color, set the
+;; variable `ps-use-face-background' which specifies if face background should
+;; be used.  Valid values are:
+;;
+;;    t                always use face background color.
+;;    nil      never use face background color.
+;;    (face...)        list of faces whose background color will be used.
+;;
+;; Any other value will be treated as t.
+;; The default value is t.
+;;
 ;;
 ;; How Ps-Print Deals With Color
 ;; -----------------------------
@@ -767,7 +982,7 @@ Please send all bug fixes and enhancements to
 ;; defined and embeds color information in the PostScript image.
 ;; The default foreground and background colors are defined by the
 ;; variables `ps-default-fg' and `ps-default-bg'.
-;; On black-and-white printers, colors are displayed in grayscale.
+;; On black-and-white printers, colors are displayed in gray scale.
 ;; To turn off color output, set `ps-print-color-p' to nil.
 ;;
 ;;
@@ -840,13 +1055,14 @@ Please send all bug fixes and enhancements to
 ;;
 ;; The printing order is:
 ;;
-;;    1. Print zebra stripes
-;;    2. Print background texts that it should be on all pages
-;;    3. Print background images that it should be on all pages
-;;    4. Print background texts only for current page (if any)
-;;    5. Print background images only for current page (if any)
-;;    6. Print header
-;;    7. Print buffer text (with faces, if specified) and line number
+;;    1. Print background color
+;;    2. Print zebra stripes
+;;    3. Print background texts that it should be on all pages
+;;    4. Print background images that it should be on all pages
+;;    5. Print background texts only for current page (if any)
+;;    6. Print background images only for current page (if any)
+;;    7. Print header
+;;    8. Print buffer text (with faces, if specified) and line number
 ;;
 ;;
 ;; Utilities
@@ -890,60 +1106,72 @@ Please send all bug fixes and enhancements to
 ;; New since version 2.8
 ;; ---------------------
 ;;
-;; [vinicius] 991211 Vinicius Jose Latorre <vinicius@cpqd.com.br>
+;; [vinicius] Vinicius Jose Latorre <vinicius@cpqd.com.br>
 ;;
-;; `ps-print-customize'.
+;;    20000821
+;;      `ps-even-or-odd-pages'
 ;;
-;; [vinicius] 990703 Vinicius Jose Latorre <vinicius@cpqd.com.br>
+;;    20000617
+;;      `ps-manual-feed', `ps-warn-paper-type', `ps-print-upside-down',
+;;      `ps-selected-pages', `ps-last-selected-pages',
+;;      `ps-restore-selected-pages', `ps-switch-header',
+;;      `ps-line-number-step', `ps-line-number-start',
+;;      `ps-zebra-stripe-follow' and `ps-use-face-background'.
 ;;
-;; Better customization.
-;; `ps-banner-page-when-duplexing' and `ps-zebra-gray'.
+;;    20000310
+;;      PostScript error handler.
+;;      `ps-user-defined-prologue' and `ps-error-handler-message'.
 ;;
-;; [vinicius] 990513 Vinicius Jose Latorre <vinicius@cpqd.com.br>
+;;    19991211
+;;      `ps-print-customize'.
 ;;
-;; N-up printing.
-;; Hook: `ps-print-begin-sheet-hook'.
+;;    19990703
+;;      Better customization.
+;;      `ps-banner-page-when-duplexing' and `ps-zebra-color'.
 ;;
-;; [keinichi] 990509 Kein'ichi Handa <handa@etl.go.jp>
+;;    19990513
+;;      N-up printing.
+;;      Hook: `ps-print-begin-sheet-hook'.
 ;;
-;; `ps-print-region-function'
+;; [keinichi] 19990509 Kein'ichi Handa <handa@etl.go.jp>
 ;;
-;; [vinicius] 990301 Vinicius Jose Latorre <vinicius@cpqd.com.br>
+;; `ps-print-region-function'
 ;;
-;; PostScript tumble and setpagedevice.
+;; [vinicius] Vinicius Jose Latorre <vinicius@cpqd.com.br>
 ;;
-;; [vinicius] 980922 Vinicius Jose Latorre <vinicius@cpqd.com.br>
+;;    19990301
+;;      PostScript tumble and setpagedevice.
 ;;
-;; PostScript prologue header comment insertion.
-;; Skip invisible text better.
+;;    19980922
+;;      PostScript prologue header comment insertion.
+;;      Skip invisible text better.
 ;;
-;; [keinichi] 980819 Kein'ichi Handa <handa@etl.go.jp>
+;; [keinichi] 19980819 Kein'ichi Handa <handa@etl.go.jp>
 ;;
 ;; Multi-byte buffer handling.
 ;;
-;; [vinicius] 980306 Vinicius Jose Latorre <vinicius@cpqd.com.br>
-;;
-;; Skip invisible text.
+;; [vinicius] Vinicius Jose Latorre <vinicius@cpqd.com.br>
 ;;
-;; [vinicius] 971130 Vinicius Jose Latorre <vinicius@cpqd.com.br>
+;;    19980306
+;;      Skip invisible text.
 ;;
-;; Hooks: `ps-print-hook', `ps-print-begin-page-hook' and
-;; `ps-print-begin-column-hook'.
-;; Put one header per page over the columns.
-;; Better database font management.
-;; Better control characters handling.
+;;    19971130
+;;      Hooks: `ps-print-hook', `ps-print-begin-page-hook' and
+;;      `ps-print-begin-column-hook'.
+;;      Put one header per page over the columns.
+;;      Better database font management.
+;;      Better control characters handling.
 ;;
-;; [vinicius] 971121 Vinicius Jose Latorre <vinicius@cpqd.com.br>
+;;    19971121
+;;      Dynamic evaluation at print time of `ps-lpr-switches'.
+;;      Handle control characters.
+;;      Face remapping.
+;;      New face attributes.
+;;      Line number.
+;;      Zebra stripes.
+;;      Text and/or image on background.
 ;;
-;; Dynamic evaluation at print time of `ps-lpr-switches'.
-;; Handle control characters.
-;; Face remapping.
-;; New face attributes.
-;; Line number.
-;; Zebra stripes.
-;; Text and/or image on background.
-;;
-;; [jack] 960517 Jacques Duthen <duthen@cegelec-red.fr>
+;; [jack] 19960517 Jacques Duthen <duthen@cegelec-red.fr>
 ;;
 ;; Font family and float size for text and header.
 ;; Landscape mode.
@@ -997,6 +1225,22 @@ Please send all bug fixes and enhancements to
 ;; Acknowledgements
 ;; ----------------
 ;;
+;; Thanks to Gord Wait <Gord_Wait@spectrumsignal.com> for
+;; `ps-user-defined-prologue' example setting for HP PostScript printer.
+;;
+;; Thanks to Paul Furnanz <pfurnanz@synopsys.com> for XEmacs compatibility
+;; suggestion for `ps-postscript-code-directory' variable.
+;;
+;; Thanks to David X Callaway <dxc@xprt.net> for helping debugging PostScript
+;; level 1 compatibility.
+;;
+;; Thanks to Colin Marquardt <colin.marquardt@usa.alcatel.com> for upside-down,
+;; line number step, line number start and zebra stripe follow suggestions, and
+;; for XEmacs beta-tests.
+;;
+;; Thanks to Klaus Berndl <klaus.berndl@sdm.de> for user defined PostScript
+;; prologue code suggestion and for odd/even printing suggestion.
+;;
 ;; Thanks to Kein'ichi Handa <handa@etl.go.jp> for multi-byte buffer handling.
 ;;
 ;; Thanks to Matthew O Persico <Matthew.Persico@lazard.com> for line number on
@@ -1057,25 +1301,71 @@ Please send all bug fixes and enhancements to
 
 ;;; Code:
 
-(unless (featurep 'lisp-float-type)
-  (error "`ps-print' requires floating point support"))
+(eval-and-compile
+  (unless (featurep 'lisp-float-type)
+    (error "`ps-print' requires floating point support"))
+
 
+  ;; For Emacs 20.2 and the earlier version.
 
-;; For Emacs 20.2 and the earlier version.
+  (or (fboundp 'set-buffer-multibyte)
+      (defun set-buffer-multibyte (arg)
+       (setq enable-multibyte-characters arg)))
 
-(or (fboundp 'set-buffer-multibyte)
-    (defun set-buffer-multibyte (arg)
-      (setq enable-multibyte-characters arg)))
+  (or (fboundp 'string-as-unibyte)
+      (defun string-as-unibyte (arg) arg))
 
-(or (fboundp 'string-as-unibyte)
-    (defun string-as-unibyte (arg) arg))
+  (or (fboundp 'string-as-multibyte)
+      (defun string-as-multibyte (arg) arg))
 
-(or (fboundp 'string-as-multibyte)
-    (defun string-as-multibyte (arg) arg))
+  (or (fboundp 'char-charset)
+      (defun char-charset (arg) 'ascii))
 
-(or (fboundp 'charset-after)
-    (defun charset-after (&optional arg)
-      (char-charset (char-after arg))))
+  (or (fboundp 'charset-after)
+      (defun charset-after (&optional arg)
+       (char-charset (char-after arg))))
+
+
+  ;; GNU Emacs
+  (or (fboundp 'line-beginning-position)
+      (defun line-beginning-position (&optional n)
+       (save-excursion
+         (and n (/= n 1) (forward-line (1- n)))
+         (beginning-of-line)
+         (point))))
+
+
+  ;; to avoid compilation gripes
+
+  ;; XEmacs
+  (defalias 'ps-x-color-instance-p              'color-instance-p)
+  (defalias 'ps-x-color-instance-rgb-components 'color-instance-rgb-components)
+  (defalias 'ps-x-color-name                    'color-name)
+  (defalias 'ps-x-color-specifier-p             'color-specifier-p)
+  (defalias 'ps-x-copy-coding-system            'copy-coding-system)
+  (defalias 'ps-x-device-class                  'device-class)
+  (defalias 'ps-x-extent-end-position           'extent-end-position)
+  (defalias 'ps-x-extent-face                   'extent-face)
+  (defalias 'ps-x-extent-priority               'extent-priority)
+  (defalias 'ps-x-extent-start-position         'extent-start-position)
+  (defalias 'ps-x-face-font-instance            'face-font-instance)
+  (defalias 'ps-x-find-coding-system            'find-coding-system)
+  (defalias 'ps-x-font-instance-properties      'font-instance-properties)
+  (defalias 'ps-x-make-color-instance           'make-color-instance)
+  (defalias 'ps-x-map-extents                   'map-extents)
+
+  ;; GNU Emacs
+  (defalias 'ps-e-x-color-values 'x-color-values)
+  (defalias 'ps-e-color-values   'color-values)
+  (if (fboundp 'find-composition)
+      (defalias 'ps-e-find-composition 'find-composition)
+    (defalias 'ps-e-find-composition 'ignore))
+
+
+  (defconst ps-windows-system
+    (memq system-type '(emx win32 w32 mswindows ms-dos windows-nt)))
+  (defconst ps-lp-system
+    (memq system-type '(usq-unix-v dgux hpux irix))))
 
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -1090,7 +1380,8 @@ Please send all bug fixes and enhancements to
   :group 'emacs)
 
 (defgroup ps-print nil
-  "PostScript generator for Emacs 19"
+  "PostScript generator for Emacs"
+  :link '(emacs-library-link :tag "Source Lisp File" "ps-print.el")
   :prefix "ps-"
   :group 'wp
   :group 'postscript)
@@ -1107,7 +1398,7 @@ Please send all bug fixes and enhancements to
   :tag "Vertical"
   :group 'ps-print)
 
-(defgroup ps-print-header nil
+(defgroup ps-print-headers nil
   "Headers layout"
   :prefix "ps-"
   :tag "Header"
@@ -1162,6 +1453,69 @@ Please send all bug fixes and enhancements to
   :tag "Page"
   :group 'ps-print)
 
+(defgroup ps-print-miscellany nil
+  "Miscellany customization"
+  :prefix "ps-"
+  :tag "Miscellany"
+  :group 'ps-print)
+
+
+(defcustom ps-error-handler-message 'paper
+  "*Specify where the error handler message should be sent.
+
+Valid values are:
+
+   `none'              catch the error and *DON'T* send any message.
+
+   `paper'             catch the error and print on paper the error message.
+
+   `system'            catch the error and send back the error message to
+                       printing system.  This is useful only if printing system
+                       send back an email reporting the error, or if there is
+                       some other alternative way to report back the error from
+                       the system to you.
+
+   `paper-and-system'  catch the error, print on paper the error message and
+                       send back the error message to printing system.
+
+Any other value is treated as `paper'."
+  :type '(choice :menu-tag "Error Handler Message"
+                :tag "Error Handler Message"
+                (const none)   (const paper)
+                (const system) (const paper-and-system))
+  :group 'ps-print-miscellany)
+
+(defcustom ps-user-defined-prologue nil
+  "*User defined PostScript prologue code inserted before all prologue code.
+
+`ps-user-defined-prologue' may be a string or a symbol function which returns a
+string.  Note that this string is inserted after `ps-adobe-tag' and PostScript
+prologue comments, and before ps-print PostScript prologue code section.  That
+is, this string is inserted after error handler initialization and before
+ps-print settings.
+
+It's strongly recommended only insert PostScript code and/or comments specific
+for your printing system particularities.  For example, some special
+initialization that only your printing system needs.
+
+Do not insert code for duplex printing, n-up printing or error handler, ps-print
+handles this in a suitable way.
+
+For more information about PostScript, see:
+   PostScript Language Reference Manual (2nd edition)
+   Adobe Systems Incorporated
+
+As an example for `ps-user-defined-prologue' setting:
+
+   ;; Setting for HP PostScript printer
+   (setq ps-user-defined-prologue
+        (concat \"<</DeferredMediaSelection true /PageSize [612 792] \"
+                \"/MediaPosition 2 /MediaType (Plain)>> setpagedevice\"))
+"
+  :type '(choice :menu-tag "User Defined Prologue"
+                :tag "User Defined Prologue"
+                (const :tag "none" nil) string symbol)
+  :group 'ps-print-miscellany)
 
 (defcustom ps-print-prologue-header nil
   "*PostScript prologue header comments besides that ps-print generates.
@@ -1187,49 +1541,87 @@ For more information about PostScript document comments, see:
    PostScript Language Reference Manual (2nd edition)
    Adobe Systems Incorporated
    Appendix G: Document Structuring Conventions -- Version 3.0"
-  :type '(choice :tag "Prologue Header"
-                string symbol (other :tag "nil" nil))
-  :group 'ps-print)
+  :type '(choice :menu-tag "Prologue Header"
+                :tag "Prologue Header"
+                (const :tag "none" nil) string symbol)
+  :group 'ps-print-miscellany)
 
 (defcustom ps-printer-name (and (boundp 'printer-name)
                                printer-name)
   "*The name of a local printer for printing PostScript files.
 
-On Unix-like systems, a string value should be a name understood by
-lpr's -P option; a value of nil means use the value of `printer-name'
-instead.  Any other value will be ignored.
-
-On MS-DOS and MS-Windows systems, a string value is taken as the name of
-the printer device or port to which PostScript files are written,
-provided `ps-lpr-command' is \"\".  By default it is the same as
-`printer-name'; typical non-default settings would be \"LPT1\" to
-\"LPT3\" for parallel printers, or \"COM1\" to \"COM4\" or \"AUX\" for
-serial printers, or \"//hostname/printer\" for a shared network printer.
-You can also set it to a name of a file, in which case the output gets
-appended to that file.  \(Note that `ps-print' package already has
-facilities for printing to a file, so you might as well use them instead
-of changing the setting of this variable.\)  If you want to silently
-discard the printed output, set this to \"NUL\"."
-  :type '(choice :tag "Printer Name"
-                file (other :tag "Pipe to ps-lpr-command" pipe))
+On Unix-like systems, a string value should be a name understood by lpr's -P
+option; a value of nil means use the value of `printer-name' instead.
+
+On MS-DOS and MS-Windows systems, a string value is taken as the name of the
+printer device or port to which PostScript files are written, provided
+`ps-lpr-command' is \"\".  By default it is the same as `printer-name'; typical
+non-default settings would be \"LPT1\" to \"LPT3\" for parallel printers, or
+\"COM1\" to \"COM4\" or \"AUX\" for serial printers, or \"//hostname/printer\"
+for a shared network printer.  You can also set it to a name of a file, in
+which case the output gets appended to that file.  \(Note that `ps-print'
+package already has facilities for printing to a file, so you might as well use
+them instead of changing the setting of this variable.\)  If you want to
+silently discard the printed output, set this to \"NUL\".
+
+Set to t, if the utility given by `ps-lpr-command' needs an empty printer name.
+
+Any other value is treated as t, that is, an empty printer name.
+
+See also `ps-printer-name-option' for documentation."
+  :type '(choice :menu-tag "Printer Name"
+                :tag "Printer Name"
+                (const :tag "Same as printer-name" nil)
+                (const :tag "No Printer Name" t)
+                (file :tag "Print to file")
+                (string :tag "Pipe to ps-lpr-command"))
+  :group 'ps-print-printer)
+
+(defcustom ps-printer-name-option
+  (cond (ps-windows-system
+        "/D:")
+       (ps-lp-system
+        "-d")
+       (t
+        "-P" ))
+  "*Option for `ps-printer-name' variable (see it).
+
+On Unix-like systems, if it's been used lpr utility, it should be the string
+\"-P\"; if it's been used lp utility, it should be the string \"-d\".
+
+On MS-DOS and MS-Windows systems, if it's been used print utility, it should be
+the string \"/D:\".
+
+For any other printing utility, see the proper manual or documentation.
+
+Set to \"\" or nil, if the utility given by `ps-lpr-command' needs an empty
+option printer name option.
+
+Any other value is treated as nil, that is, an empty printer name option.
+
+This variable is used only when `ps-printer-name' is a non-empty string."
+  :type '(choice :menu-tag "Printer Name Option"
+                :tag "Printer Name Option"
+                (const :tag "None" nil)
+                (string :tag "Option"))
   :group 'ps-print-printer)
 
 (defcustom ps-lpr-command lpr-command
   "*Name of program for printing a PostScript file.
 
-On MS-DOS and MS-Windows systems, if the value is an empty string then
-Emacs will write directly to the printer port named by `ps-printer-name'.
-The programs `print' and `nprint' (the standard print programs on Windows
-NT and Novell Netware respectively) are handled specially, using
-`ps-printer-name' as the destination for output; any other program is
-treated like `lpr' except that an explicit filename is given as the last
-argument."
+On MS-DOS and MS-Windows systems, if the value is an empty string then Emacs
+will write directly to the printer port named by `ps-printer-name'.  The
+programs `print' and `nprint' (the standard print programs on Windows NT and
+Novell Netware respectively) are handled specially, using `ps-printer-name' as
+the destination for output; any other program is treated like `lpr' except that
+an explicit filename is given as the last argument."
   :type 'string
   :group 'ps-print-printer)
 
 (defcustom ps-lpr-switches lpr-switches
   "*A list of extra switches to pass to `ps-lpr-command'."
-  :type '(repeat string)
+  :type '(repeat :tag "PostScript lpr Switches"
+                (choice string symbol (repeat sexp)))
   :group 'ps-print-printer)
 
 (defcustom ps-print-region-function nil
@@ -1239,6 +1631,13 @@ the sixth arguments are both nil."
   :type 'function
   :group 'ps-print-printer)
 
+(defcustom ps-manual-feed nil
+  "*Non-nil means the printer will manually feed paper.
+
+If it's nil, automatic feeding takes place."
+  :type 'boolean
+  :group 'ps-print-printer)
+
 ;;; Page layout
 
 ;; All page dimensions are in PostScript points.
@@ -1294,11 +1693,81 @@ example `letter', `legal' or `a4'."
                               wid)))
   :group 'ps-print-page)
 
+(defcustom ps-warn-paper-type t
+  "*Non-nil means give an error if paper size is not equal to `ps-paper-type'.
+
+It's used when `ps-spool-config' is set to `setpagedevice'."
+  :type 'boolean
+  :group 'ps-print-page)
+
 (defcustom ps-landscape-mode nil
   "*Non-nil means print in landscape mode."
   :type 'boolean
   :group 'ps-print-page)
 
+(defcustom ps-print-upside-down nil
+  "*Non-nil means print upside-down."
+  :type 'boolean
+  :group 'ps-print-page)
+
+(defcustom ps-selected-pages nil
+  "*Specify which pages to print.
+
+If it's nil, all pages are printed.
+
+If it's a list, the list element may be an integer or a cons cell (FROM . TO)
+designating FROM page to TO page; any invalid element is ignored, that is, an
+integer lesser than one or if FROM is greater than TO.
+
+Otherwise, it's treated as nil.
+
+After ps-print processing `ps-selected-pages' is set to nil.  But the latest
+`ps-selected-pages' is saved in `ps-last-selected-pages' (see it for
+documentation).  So you can restore the latest selected pages by using
+`ps-last-selected-pages' or by calling `ps-restore-selected-pages' command (see
+it for documentation).
+
+See also `ps-even-or-odd-pages'."
+  :type '(repeat :tag "Selected Pages"
+                (radio :tag "Page"
+                       (integer :tag "Number")
+                       (cons :tag "Range"
+                             (integer :tag "From")
+                             (integer :tag "To"))))
+  :group 'ps-print-page)
+
+(defcustom ps-even-or-odd-pages nil
+  "*Specify if it prints even/odd pages.
+
+Valid values are:
+
+   nil         print all pages.
+
+   `even'      print only even pages.
+
+   `odd'       print only odd pages.
+
+Any other value is treated as nil.
+
+If you set `ps-selected-pages' (see it for documentation), first the pages are
+filtered by `ps-selected-pages' and then by `ps-even-or-odd-pages'.  For
+example, if we have:
+
+   (setq ps-selected-pages '(1 4 (6 . 10) 12))
+
+We have the following results:
+
+   `ps-even-or-odd-pages'      PAGES PRINTED
+       nil                     1, 4, 6, 7, 8, 9, 10, 12
+       even                    4, 6, 8, 10, 12
+       odd                     1, 7, 9"
+  :type '(choice :menu-tag "Print Even/Odd Pages"
+                :tag "Print Even/Odd Pages"
+                (const :tag "All Pages" nil)
+                (const :tag "Only Even Pages" even)
+                (const :tag "Only Odd Pages" odd))
+  :group 'ps-print-page)
+
 (defcustom ps-print-control-characters 'control-8-bit
   "*Specify the printable form for control and 8-bit characters.
 That is, instead of sending, for example, a ^D (\\004) to printer,
@@ -1324,10 +1793,11 @@ Valid values are:
                  current font.
 
 Any other value is treated as nil."
-  :type '(choice :tag "Control Char"
+  :type '(choice :menu-tag "Control Char"
+                :tag "Control Char"
                 (const 8-bit)   (const control-8-bit)
-                (const control) (other :tag "nil" nil))
-  :group 'ps-print)
+                (const control) (const :tag "nil" nil))
+  :group 'ps-print-miscellany)
 
 (defcustom ps-n-up-printing 1
   "*Specify the number of pages per sheet paper."
@@ -1377,7 +1847,8 @@ using a 3x4 page matrix:
                12 9  6  3                          10 7  4  1
 
 Any other value is treated as `left-top'."
-  :type '(choice :tag "N-Up Filling"
+  :type '(choice :menu-tag "N-Up Filling"
+                :tag "N-Up Filling"
                 (const left-top)  (const left-bottom)
                 (const right-top) (const right-bottom)
                 (const top-left)  (const bottom-left)
@@ -1387,30 +1858,128 @@ Any other value is treated as `left-top'."
 (defcustom ps-number-of-columns (if ps-landscape-mode 2 1)
   "*Specify the number of columns"
   :type 'number
-  :group 'ps-print)
+  :group 'ps-print-miscellany)
 
 (defcustom ps-zebra-stripes nil
   "*Non-nil means print zebra stripes.
-See also documentation for `ps-zebra-stripe-height' and `ps-zebra-gray'."
+See also documentation for `ps-zebra-stripe-height' and `ps-zebra-color'."
   :type 'boolean
   :group 'ps-print-zebra)
 
 (defcustom ps-zebra-stripe-height 3
   "*Number of zebra stripe lines.
-See also documentation for `ps-zebra-stripes' and `ps-zebra-gray'."
+See also documentation for `ps-zebra-stripes' and `ps-zebra-color'."
   :type 'number
   :group 'ps-print-zebra)
 
-(defcustom ps-zebra-gray 0.95
-  "*Zebra stripe gray scale.
+(defcustom ps-zebra-color 0.95
+  "*Zebra stripe gray scale or RGB color.
 See also documentation for `ps-zebra-stripes' and `ps-zebra-stripe-height'."
-  :type 'number
+  :type '(choice :menu-tag "Zebra Gray/Color"
+                :tag "Zebra Gray/Color"
+                (number :tag "Gray Scale" :value 0.95)
+                (string :tag "Color Name" :value "gray95")
+                (list :tag "RGB Color" :value (0.95 0.95 0.95)
+                      (number :tag "Red")
+                      (number :tag "Green")
+                      (number :tag "Blue")))
+  :group 'ps-print-zebra)
+
+(defcustom ps-zebra-stripe-follow nil
+  "*Non-nil means zebra stripe continues on next page.
+
+If `ps-zebra-stripe-follow' is nil, zebra stripe is restarted on each page.
+If `ps-zebra-stripe-follow' is non-nil, zebra stripe continues on next page.
+
+Visually, we have:
+
+               `ps-zebra-stripe-follow'        `ps-zebra-stripe-follow'
+                  is nil                          is non-nil
+   Current Page ------------------------       ------------------------
+               1  XXXXXXXXXXXXXXXXXXXXX        1  XXXXXXXXXXXXXXXXXXXXX
+               2  XXXXXXXXXXXXXXXXXXXXX        2  XXXXXXXXXXXXXXXXXXXXX
+               3  XXXXXXXXXXXXXXXXXXXXX        3  XXXXXXXXXXXXXXXXXXXXX
+               4                               4
+               5                               5
+               6                               6
+               7  XXXXXXXXXXXXXXXXXXXXX        7  XXXXXXXXXXXXXXXXXXXXX
+               8  XXXXXXXXXXXXXXXXXXXXX        8  XXXXXXXXXXXXXXXXXXXXX
+               ------------------------        ------------------------
+      Next Page ------------------------       ------------------------
+               9  XXXXXXXXXXXXXXXXXXXXX        9  XXXXXXXXXXXXXXXXXXXXX
+               10 XXXXXXXXXXXXXXXXXXXXX        10
+               11 XXXXXXXXXXXXXXXXXXXXX        11
+               12                              12
+               13                              13 XXXXXXXXXXXXXXXXXXXXX
+               14                              14 XXXXXXXXXXXXXXXXXXXXX
+               15 XXXXXXXXXXXXXXXXXXXXX        15 XXXXXXXXXXXXXXXXXXXXX
+               16 XXXXXXXXXXXXXXXXXXXXX        16
+               ------------------------        ------------------------"
+  :type 'boolean
   :group 'ps-print-zebra)
 
 (defcustom ps-line-number nil
   "*Non-nil means print line number."
   :type 'boolean
-  :group 'ps-print)
+  :group 'ps-print-miscellany)
+
+(defcustom ps-line-number-step 1
+  "*Specify the interval that line number is printed.
+
+For example, `ps-line-number-step' is set to 2, the printing will look like:
+
+   1 one line
+     one line
+   3 one line
+     one line
+   5 one line
+     one line
+     ...
+
+Valid values are:
+
+   integer     an integer that specifies the interval that line number is
+               printed.  If it's lesser than or equal to zero, it's used the
+               value 1.
+
+   `zebra'     specifies that only the line number of the first line in a zebra
+               stripe is to be printed.
+
+Any other value is treated as `zebra'."
+  :type '(choice :menu-tag "Line Number Step"
+                :tag "Line Number Step"
+                (integer :tag "Step Interval")
+                (const :tag "Synchronize Zebra" zebra))
+  :group 'ps-print-miscellany)
+
+(defcustom ps-line-number-start 1
+  "*Specify the starting point in the interval given by `ps-line-number-step'.
+
+For example, if `ps-line-number-step' is set to 3 and `ps-line-number-start' is
+set to 3, the printing will look like:
+
+      one line
+      one line
+    3 one line
+      one line
+      one line
+    6 one line
+      one line
+      one line
+    9 one line
+      one line
+      ...
+
+The values for `ps-line-number-start':
+
+   * If `ps-line-number-step' is an integer, must be between 1 and the value
+     of `ps-line-number-step' inclusive.
+
+   * If `ps-line-number-step' is set to `zebra', must be between 1 and the
+     value of `ps-zebra-strip-height' inclusive.  Use this combination if you
+     wish that line number be relative to zebra stripes."
+  :type '(integer :tag "Start Step Interval")
+  :group 'ps-print-miscellany)
 
 (defcustom ps-print-background-image nil
   "*EPS image list to be printed on background.
@@ -1443,17 +2012,19 @@ PostScript programming that returns a float or integer value.
 For example, if you wish to print an EPS image on all pages do:
 
    '((\"~/images/EPS-image.ps\"))"
-  :type '(repeat (list (file   :tag "EPS File")
-                      (choice :tag "X" number string (const nil))
-                      (choice :tag "Y" number string (const nil))
-                      (choice :tag "X Scale" number string (const nil))
-                      (choice :tag "Y Scale" number string (const nil))
-                      (choice :tag "Rotation" number string (const nil))
-                      (repeat :tag "Pages" :inline t
-                              (radio (integer :tag "Page")
-                                     (cons :tag "Range"
-                                           (integer :tag "From")
-                                           (integer :tag "To"))))))
+  :type '(repeat
+         (list
+          (file   :tag "EPS File")
+          (choice :tag "X" (const :tag "default" nil) number string)
+          (choice :tag "Y" (const :tag "default" nil) number string)
+          (choice :tag "X Scale" (const :tag "default" nil) number string)
+          (choice :tag "Y Scale" (const :tag "default" nil) number string)
+          (choice :tag "Rotation" (const :tag "default" nil) number string)
+          (repeat :tag "Pages" :inline t
+                  (radio (integer :tag "Page")
+                         (cons :tag "Range"
+                               (integer :tag "From")
+                               (integer :tag "To"))))))
   :group 'ps-print-background)
 
 (defcustom ps-print-background-text nil
@@ -1491,18 +2062,20 @@ PostScript programming that returns a float or integer value.
 For example, if you wish to print text \"Preliminary\" on all pages do:
 
    '((\"Preliminary\"))"
-  :type '(repeat (list (string :tag "Text")
-                      (choice :tag "X" number string (const nil))
-                      (choice :tag "Y" number string (const nil))
-                      (choice :tag "Font" string (const nil))
-                      (choice :tag "Fontsize" number string (const nil))
-                      (choice :tag "Gray" number string (const nil))
-                      (choice :tag "Rotation" number string (const nil))
-                      (repeat :tag "Pages" :inline t
-                              (radio (integer :tag "Page")
-                                     (cons :tag "Range"
-                                           (integer :tag "From")
-                                           (integer :tag "To"))))))
+  :type '(repeat
+         (list
+          (string :tag "Text")
+          (choice :tag "X" (const :tag "default" nil) number string)
+          (choice :tag "Y" (const :tag "default" nil) number string)
+          (choice :tag "Font" (const :tag "default" nil) string)
+          (choice :tag "Fontsize" (const :tag "default" nil) number string)
+          (choice :tag "Gray" (const :tag "default" nil) number string)
+          (choice :tag "Rotation" (const :tag "default" nil) number string)
+          (repeat :tag "Pages" :inline t
+                  (radio (integer :tag "Page")
+                         (cons :tag "Range"
+                               (integer :tag "From")
+                               (integer :tag "To"))))))
   :group 'ps-print-background)
 
 ;;; Horizontal layout
@@ -1572,7 +2145,7 @@ the buffer is visiting a file, the file's directory.  Headers are
 customizable by changing variables `ps-left-header' and
 `ps-right-header'."
   :type 'boolean
-  :group 'ps-print-header)
+  :group 'ps-print-headers)
 
 (defcustom ps-print-only-one-header nil
   "*Non-nil means print only one header at the top of each page.
@@ -1580,29 +2153,49 @@ This is useful when printing more than one column, so it is possible
 to have only one header over all columns or one header per column.
 See also `ps-print-header'."
   :type 'boolean
-  :group 'ps-print-header)
+  :group 'ps-print-headers)
 
 (defcustom ps-print-header-frame t
   "*Non-nil means draw a gaudy frame around the header."
   :type 'boolean
-  :group 'ps-print-header)
+  :group 'ps-print-headers)
 
 (defcustom ps-header-lines 2
   "*Number of lines to display in page header, when generating PostScript."
   :type 'integer
-  :group 'ps-print-header)
+  :group 'ps-print-headers)
+
+(defcustom ps-switch-header 'duplex
+  "*Specify if headers are switched or not.
+
+Valid values are:
+
+nil    Never switch headers.
+
+t      Always switch headers.
+
+duplex Switch headers only when duplexing is on, that is, when
+       `ps-spool-duplex' is non-nil.
+
+Any other value is treated as t."
+  :type '(choice :menu-tag "Switch Header"
+                :tag "Switch Header"
+                (const :tag "Never Switch" nil)
+                (const :tag "Always Switch" t)
+                (const :tag "Switch When Duplexing" duplex))
+  :group 'ps-print-headers)
 
 (defcustom ps-show-n-of-n t
   "*Non-nil means show page numbers as N/M, meaning page N of M.
 NOTE: page numbers are displayed as part of headers,
-      see variable `ps-print-headers'."
+      see variable `ps-print-header'."
   :type 'boolean
-  :group 'ps-print-header)
+  :group 'ps-print-headers)
 
-(defcustom ps-spool-config (if (memq system-type
-                                    '(win32 w32 mswindows ms-dos windows-nt))
-                              nil
-                            'lpr-switches)
+(defcustom ps-spool-config
+  (if ps-windows-system
+      nil
+    'lpr-switches)
   "*Specify who is responsable for setting duplex and page size switches.
 
 Valid values are:
@@ -1628,10 +2221,11 @@ WARNING: The setpagedevice PostScript operator affects ghostview utility when
         So, if you need to use setpagedevice, set `ps-spool-config' to
         `setpagedevice', generate a test file and send it to your printer; if
         the printed file isn't ok, set `ps-spool-config' to nil."
-  :type '(choice :tag "Spool Config"
+  :type '(choice :menu-tag "Spool Config"
+                :tag "Spool Config"
                 (const lpr-switches) (const setpagedevice)
-                (other :tag "nil" nil))
-  :group 'ps-print-header)
+                (const :tag "nil" nil))
+  :group 'ps-print-headers)
 
 (defcustom ps-spool-duplex nil         ; Not many people have duplex printers,
                                        ; so default to nil.
@@ -1644,7 +2238,7 @@ even-numbered pages.
 
 See also `ps-spool-tumble'."
   :type 'boolean
-  :group 'ps-print-header)
+  :group 'ps-print-headers)
 
 (defcustom ps-spool-tumble nil
   "*Specify how the page images on opposite sides of a sheet are oriented.
@@ -1654,7 +2248,7 @@ the top or bottom.
 
 It has effect only when `ps-spool-duplex' is non-nil."
   :type 'boolean
-  :group 'ps-print-header)
+  :group 'ps-print-headers)
 
 ;;; Fonts
 
@@ -1769,11 +2363,14 @@ To get the info for another specific font (say Helvetica), do the following:
 - generate the PostScript image to a file (C-u M-x ps-print-buffer)
 - open this file and delete the leading `%' (which is the PostScript
   comment character) from the line
-          `% 3 cm 20 cm moveto  10 /Courier ReportFontInfo  showpage'
+          `% 3 cm 20 cm moveto  10/Courier ReportFontInfo  showpage'
   to get the line
-          `3 cm 20 cm moveto  10 /Helvetica ReportFontInfo  showpage'
+          `3 cm 20 cm moveto  10/Helvetica ReportFontInfo  showpage'
 - add the values to `ps-font-info-database'.
-You can get all the fonts of YOUR printer using `ReportAllFontInfo'."
+You can get all the fonts of YOUR printer using `ReportAllFontInfo'.
+
+Note also that ps-print DOESN'T download any font to your printer, instead
+it uses the fonts resident in your printer."
   :type '(repeat (list :tag "Font Definition"
                       (symbol :tag "Font Family")
                       (cons :format "%v"
@@ -1836,8 +2433,11 @@ You can get all the fonts of YOUR printer using `ReportAllFontInfo'."
 ;;; Colors
 
 ;; Printing color requires x-color-values.
-(defcustom ps-print-color-p (or (fboundp 'x-color-values) ; Emacs
-                               (fboundp 'color-instance-rgb-components))
+(defcustom ps-print-color-p
+  (or (and (fboundp 'color-values)     ; Emacs
+          (ps-e-color-values "Green"))
+      (fboundp 'x-color-values)                ; Emacs
+      (fboundp 'color-instance-rgb-components))
                                        ; XEmacs
   "*Non-nil means print the buffer's text in color."
   :type 'boolean
@@ -1845,16 +2445,30 @@ You can get all the fonts of YOUR printer using `ReportAllFontInfo'."
 
 (defcustom ps-default-fg '(0.0 0.0 0.0)
   "*RGB values of the default foreground color.  Defaults to black."
-  :type '(list (number :tag "Red") (number :tag "Green") (number :tag "Blue"))
+  :type '(choice :menu-tag "Default Foreground Gray/Color"
+                :tag "Default Foreground Gray/Color"
+                (number :tag "Gray Scale" :value 0.0)
+                (string :tag "Color Name" :value "black")
+                (list :tag "RGB Color" :value (0.0 0.0 0.0)
+                      (number :tag "Red")
+                      (number :tag "Green")
+                      (number :tag "Blue")))
   :group 'ps-print-color)
 
 (defcustom ps-default-bg '(1.0 1.0 1.0)
   "*RGB values of the default background color.  Defaults to white."
-  :type '(list (number :tag "Red") (number :tag "Green") (number :tag "Blue"))
+  :type '(choice :menu-tag "Default Background Gray/Color"
+                :tag "Default Background Gray/Color"
+                (number :tag "Gray Scale" :value 1.0)
+                (string :tag "Color Name" :value "white")
+                (list :tag "RGB Color" :value (1.0 1.0 1.0)
+                      (number :tag "Red")
+                      (number :tag "Green")
+                      (number :tag "Blue")))
   :group 'ps-print-color)
 
 (defcustom ps-auto-font-detect t
-  "*Non-nil means automatically detect bold/italic face attributes.
+  "*Non-nil means automatically detect bold/italic/underline face attributes.
 If nil, we rely solely on the lists `ps-bold-faces', `ps-italic-faces',
 and `ps-underlined-faces'."
   :type 'boolean
@@ -1894,6 +2508,25 @@ This applies to generating PostScript."
   :type '(repeat face)
   :group 'ps-print-face)
 
+(defcustom ps-use-face-background nil
+  "*Specify if face background should be used.
+
+Valid values are:
+
+   t           always use face background color.
+   nil         never use face background color.
+   (face...)   list of faces whose background color will be used.
+
+Any other value will be treated as t."
+  :type '(choice :menu-tag "Use Face Background"
+                :tag "Use Face Background"
+                (const :tag "Always Use Face Background" t)
+                (const :tag "Never Use Face Background" nil)
+                (repeat :menu-tag "Face Background List"
+                        :tag "Face Background List"
+                        face))
+  :group 'ps-print-face)
+
 (defcustom ps-left-header
   (list 'ps-get-buffer-name 'ps-header-dirpart)
   "*The items to display (each on a line) on the left part of the page header.
@@ -1912,7 +2545,7 @@ values, the value should be a string to be inserted into the array.
 In either case, function or variable, the string value has PostScript
 string delimiters added to it."
   :type '(repeat (choice string symbol))
-  :group 'ps-print-header)
+  :group 'ps-print-headers)
 
 (defcustom ps-right-header
   (list "/pagenumberstring load" 'time-stamp-mon-dd-yyyy 'time-stamp-hh:mm:ss)
@@ -1922,19 +2555,19 @@ This applies to generating PostScript.
 See the variable `ps-left-header' for a description of the format of
 this variable."
   :type '(repeat (choice string symbol))
-  :group 'ps-print-header)
+  :group 'ps-print-headers)
 
 (defcustom ps-razzle-dazzle t
   "*Non-nil means report progress while formatting buffer."
   :type 'boolean
-  :group 'ps-print)
+  :group 'ps-print-miscellany)
 
 (defcustom ps-adobe-tag "%!PS-Adobe-3.0\n"
   "*Contains the header line identifying the output as PostScript.
 By default, `ps-adobe-tag' contains the standard identifier.  Some
 printers require slightly different versions of this line."
   :type 'string
-  :group 'ps-print)
+  :group 'ps-print-miscellany)
 
 (defcustom ps-build-face-reference t
   "*Non-nil means build the reference face lists.
@@ -1964,13 +2597,30 @@ variable."
   "*Non-nil means the very first page is skipped.
 It's like the very first character of buffer (or region) is ^L (\\014)."
   :type 'boolean
-  :group 'ps-print-header)
+  :group 'ps-print-headers)
 
-(defcustom ps-postscript-code-directory data-directory
+(defcustom ps-postscript-code-directory
+  (or (and (fboundp 'locate-data-directory) ; xemacs
+          (locate-data-directory "ps-print"))
+      data-directory)                  ; emacs
   "*Directory where it's located the PostScript prologue file used by ps-print.
 By default, this directory is the same as in the variable `data-directory'."
   :type 'directory
-  :group 'ps-print)
+  :group 'ps-print-miscellany)
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Selected Pages
+
+
+(defvar ps-last-selected-pages nil
+  "Latest `ps-selected-pages' value.")
+
+
+(defun ps-restore-selected-pages ()
+  "Restore latest `ps-selected-pages' value."
+  (interactive)
+  (setq ps-selected-pages ps-last-selected-pages))
 
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -2116,20 +2766,34 @@ The table depends on the current ps-print setup."
   "Return the current PostScript-generation setup."
   (format
    "
+;;; ps-print version %s
+
 \(setq ps-print-color-p         %s
       ps-lpr-command           %S
       ps-lpr-switches          %s
-      ps-printer-name          %S
+      ps-printer-name          %s
+      ps-printer-name-option   %s
       ps-print-region-function %s
+      ps-manual-feed           %S
 
       ps-paper-type          %s
+      ps-warn-paper-type     %s
       ps-landscape-mode      %s
+      ps-print-upside-down   %s
       ps-number-of-columns   %s
 
       ps-zebra-stripes       %s
       ps-zebra-stripe-height %s
-      ps-zebra-gray          %s
+      ps-zebra-stripe-follow %S
+      ps-zebra-color         %s
       ps-line-number         %s
+      ps-line-number-step    %s
+      ps-line-number-start   %S
+
+      ps-default-fg %s
+      ps-default-bg %s
+
+      ps-use-face-background %s
 
       ps-print-control-characters %s
 
@@ -2137,6 +2801,8 @@ The table depends on the current ps-print setup."
 
       ps-print-background-text %s
 
+      ps-error-handler-message %s
+      ps-user-defined-prologue %s
       ps-print-prologue-header %s
 
       ps-left-margin                %s
@@ -2149,6 +2815,7 @@ The table depends on the current ps-print setup."
       ps-print-header               %s
       ps-print-only-one-header      %s
       ps-print-header-frame         %s
+      ps-switch-header              %s
       ps-header-lines               %s
       ps-show-n-of-n                %s
       ps-spool-config               %s
@@ -2156,33 +2823,52 @@ The table depends on the current ps-print setup."
       ps-spool-tumble               %s
       ps-banner-page-when-duplexing %s
 
-      ps-n-up-printing         %s
-      ps-n-up-margin           %s
-      ps-n-up-border-p         %s
-      ps-n-up-filling          %s
+      ps-n-up-printing %s
+      ps-n-up-margin   %s
+      ps-n-up-border-p %s
+      ps-n-up-filling  %s
 
       ps-multibyte-buffer       %s
       ps-font-family            %s
       ps-font-size              %s
       ps-header-font-family     %s
       ps-header-font-size       %s
-      ps-header-title-font-size %s)
+      ps-header-title-font-size %s
+
+      ps-even-or-odd-pages   %s
+      ps-selected-pages      %s
+      ps-last-selected-pages %s)
+
+;;; ps-print - end of settings
 "
+   ps-print-version
    ps-print-color-p
    ps-lpr-command
    (ps-print-quote ps-lpr-switches)
-   ps-printer-name
+   (ps-print-quote ps-printer-name)
+   (ps-print-quote ps-printer-name-option)
    (ps-print-quote ps-print-region-function)
+   ps-manual-feed
    (ps-print-quote ps-paper-type)
+   ps-warn-paper-type
    ps-landscape-mode
+   ps-print-upside-down
    ps-number-of-columns
    ps-zebra-stripes
    ps-zebra-stripe-height
-   ps-zebra-gray
+   ps-zebra-stripe-follow
+   (ps-print-quote ps-zebra-color)
    ps-line-number
+   (ps-print-quote ps-line-number-step)
+   ps-line-number-start
+   (ps-print-quote ps-default-fg)
+   (ps-print-quote ps-default-bg)
+   (ps-print-quote ps-use-face-background)
    (ps-print-quote ps-print-control-characters)
    (ps-print-quote ps-print-background-image)
    (ps-print-quote ps-print-background-text)
+   (ps-print-quote ps-error-handler-message)
+   (ps-print-quote ps-user-defined-prologue)
    (ps-print-quote ps-print-prologue-header)
    ps-left-margin
    ps-right-margin
@@ -2194,6 +2880,7 @@ The table depends on the current ps-print setup."
    ps-print-header
    ps-print-only-one-header
    ps-print-header-frame
+   (ps-print-quote ps-switch-header)
    ps-header-lines
    ps-show-n-of-n
    (ps-print-quote ps-spool-config)
@@ -2209,7 +2896,10 @@ The table depends on the current ps-print setup."
    (ps-print-quote ps-font-size)
    (ps-print-quote ps-header-font-family)
    (ps-print-quote ps-header-font-size)
-   (ps-print-quote ps-header-title-font-size)))
+   (ps-print-quote ps-header-title-font-size)
+   (ps-print-quote ps-even-or-odd-pages)
+   (ps-print-quote ps-selected-pages)
+   (ps-print-quote ps-last-selected-pages)))
 
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -2226,32 +2916,131 @@ The table depends on the current ps-print setup."
        (t
         sym)))
 
-(defvar ps-print-emacs-type
-  (cond ((string-match "XEmacs" emacs-version) 'xemacs)
-       ((string-match "Lucid" emacs-version) 'lucid)
-       ((string-match "Epoch" emacs-version) 'epoch)
-       (t 'emacs)))
-
-(if (or (eq ps-print-emacs-type 'lucid)
-       (eq ps-print-emacs-type 'xemacs))
-    (if (< emacs-minor-version 12)
-       (setq ps-print-color-p nil))
-  (require 'faces))                    ; face-font, face-underline-p,
+
+(eval-and-compile
+  (defvar ps-print-emacs-type
+    (cond ((string-match "XEmacs" emacs-version) 'xemacs)
+         ((string-match "Lucid" emacs-version) 'lucid)
+         ((string-match "Epoch" emacs-version) 'epoch)
+         (t 'emacs)))
+
+  (if (memq ps-print-emacs-type '(lucid xemacs))
+      (if (< emacs-minor-version 12)
+         (setq ps-print-color-p nil))
+    (require 'faces))                  ; face-font, face-underline-p,
                                        ; x-font-regexp
 
-;; Return t if the device (which can be changed during an emacs session)
-;; can handle colors.
-;; This is function is not yet implemented for GNU emacs.
-(cond ((and (eq ps-print-emacs-type 'xemacs)
-           (>= emacs-minor-version 12)) ; xemacs
-       (defun ps-color-device ()
-        (eq (device-class) 'color))
-       )
+  ;; Return t if the device (which can be changed during an emacs session)
+  ;; can handle colors.
+  ;; This function is not yet implemented for GNU emacs.
+  (cond ((and (eq ps-print-emacs-type 'xemacs)
+             (>= emacs-minor-version 12)) ; xemacs
+        (defun ps-color-device ()
+          (eq (ps-x-device-class) 'color)))
+
+       (t                              ; emacs
+        (defun ps-color-device ()
+          (if (fboundp 'color-values)
+              (ps-e-color-values "Green")
+            t))))
+
+
+  (defun ps-mapper (extent list)
+    (nconc list
+          (list (list (ps-x-extent-start-position extent) 'push extent)
+                (list (ps-x-extent-end-position extent) 'pull extent)))
+    nil)
+
+  (defun ps-extent-sorter (a b)
+    (< (ps-x-extent-priority a) (ps-x-extent-priority b)))
+
+  (defun ps-xemacs-face-kind-p (face kind kind-regex)
+    (let* ((frame-font (or (ps-x-face-font-instance face)
+                          (ps-x-face-font-instance 'default)))
+          (kind-cons
+           (and frame-font
+                (assq kind
+                      (ps-x-font-instance-properties frame-font))))
+          (kind-spec (cdr-safe kind-cons))
+          (case-fold-search t))
+      (and kind-spec (string-match kind-regex kind-spec))))
+
+  (defun ps-xemacs-color-name (color)
+    (if (ps-x-color-specifier-p color)
+       (ps-x-color-name color)
+      color))
+
+  (cond ((eq ps-print-emacs-type 'emacs) ; emacs
+
+        (defun ps-color-values (x-color)
+          (cond
+           ((fboundp 'color-values)
+            (ps-e-color-values x-color))
+           ((fboundp 'x-color-values)
+            (ps-e-x-color-values x-color))
+           (t
+            (error "No available function to determine X color values."))))
+
+        (defalias 'ps-face-foreground-name 'face-foreground)
+        (defalias 'ps-face-background-name 'face-background)
+
+        (defun ps-face-bold-p (face)
+          (or (face-bold-p face)
+              (memq face ps-bold-faces)))
+
+        (defun ps-face-italic-p (face)
+          (or (face-italic-p face)
+              (memq face ps-italic-faces)))
+        )
+                                       ; xemacs
+                                       ; lucid
+       (t                              ; epoch
+
+        (or (ps-x-find-coding-system 'raw-text-unix)
+            (ps-x-copy-coding-system 'no-conversion-unix 'raw-text-unix))
+
+        (defun ps-color-values (x-color)
+          (let ((color (ps-xemacs-color-name x-color)))
+            (cond
+             ((fboundp 'x-color-values)
+              (ps-e-x-color-values color))
+             ((and (fboundp 'color-instance-rgb-components)
+                   (ps-color-device))
+              (ps-x-color-instance-rgb-components
+               (if (ps-x-color-instance-p x-color)
+                   x-color
+                 (ps-x-make-color-instance color))))
+             (t
+              (error "No available function to determine X color values.")))))
 
-      (t                               ; emacs
-       (defun ps-color-device ()
-        t)
-       ))
+        (defun ps-face-foreground-name (face)
+          (ps-xemacs-color-name (face-foreground face)))
+
+        (defun ps-face-background-name (face)
+          (ps-xemacs-color-name (face-background face)))
+
+        (defun ps-face-bold-p (face)
+          (or (ps-xemacs-face-kind-p face 'WEIGHT_NAME "bold\\|demibold")
+              (memq face ps-bold-faces))) ; Kludge-compatible
+
+        (defun ps-face-italic-p (face)
+          (or (ps-xemacs-face-kind-p face 'ANGLE_NAME "i\\|o")
+              (ps-xemacs-face-kind-p face 'SLANT "i\\|o")
+              (memq face ps-italic-faces))) ; Kludge-compatible
+        )))
+
+
+(defvar ps-print-color-scale 1.0)
+
+(defun ps-color-scale (color)
+  ;; Scale 16-bit X-COLOR-VALUE to PostScript color value in [0, 1] interval.
+  (mapcar #'(lambda (value) (/ value ps-print-color-scale))
+         (ps-color-values color)))
+
+
+(defun ps-face-underlined-p (face)
+  (or (face-underline-p face)
+      (memq face ps-underlined-faces)))
 
 
 (require 'time-stamp)
@@ -2259,13 +3048,12 @@ The table depends on the current ps-print setup."
 
 (defun ps-prologue-file (filenumber)
   (save-excursion
-    (let ((buffer
-          (or (find-file-noselect
-               (format "%sps-prin%d.ps"
-                       ps-postscript-code-directory filenumber)
-               'no-warn 'rawfile)
-              (error "ps-print PostScript prologue %d file was not found."
-                     filenumber))))
+    (let* ((filename (format "%sps-prin%d.ps"
+                            ps-postscript-code-directory filenumber))
+          (buffer
+           (or (find-file-noselect filename 'no-warn 'rawfile)
+               (error "ps-print PostScript prologue `%s' file was not found."
+                      filename))))
       (set-buffer buffer)
       (prog1
          (buffer-string)
@@ -2274,15 +3062,15 @@ The table depends on the current ps-print setup."
 
 (defvar ps-mark-code-directory nil)
 
+(defvar ps-print-prologue-0 ""
+  "ps-print PostScript error handler.")
+
 (defvar ps-print-prologue-1 ""
   "ps-print PostScript prologue begin.")
 
 (defvar ps-print-prologue-2 ""
   "ps-print PostScript prologue end.")
 
-(defvar ps-print-duplex-feature ""
-  "ps-print PostScript duplex feature.")
-
 ;; Start Editing Here:
 
 (defvar ps-source-buffer nil)
@@ -2295,9 +3083,14 @@ The table depends on the current ps-print setup."
 (defvar ps-page-postscript 0)
 (defvar ps-page-order 0)
 (defvar ps-page-count 0)
+(defvar ps-page-n-up 0)
 (defvar ps-showline-count 1)
+(defvar ps-first-page nil)
+(defvar ps-last-page nil)
+(defvar ps-print-page-p t)
 
 (defvar ps-control-or-escape-regexp nil)
+(defvar ps-n-up-on nil)
 
 (defvar ps-background-pages nil)
 (defvar ps-background-all-pages nil)
@@ -2305,8 +3098,9 @@ The table depends on the current ps-print setup."
 (defvar ps-background-image-count 0)
 
 (defvar ps-current-font 0)
-(defvar ps-default-color (and ps-print-color-p ps-default-fg)) ; black
-(defvar ps-current-color ps-default-color)
+(defvar ps-default-foreground nil)
+(defvar ps-default-color nil)
+(defvar ps-current-color nil)
 (defvar ps-current-bg nil)
 
 (defvar ps-razchunk 0)
@@ -2345,8 +3139,6 @@ This is in units of points (1/72 inch).")
 (defvar ps-height-remaining nil)
 (defvar ps-width-remaining nil)
 
-(defvar ps-print-color-scale nil)
-
 (defvar ps-font-size-internal nil)
 (defvar ps-header-font-size-internal nil)
 (defvar ps-header-title-font-size-internal nil)
@@ -2485,7 +3277,7 @@ If EXTENSION is any other symbol, it is ignored."
 (defun ps-font-lock-face-attributes ()
   (and (boundp 'font-lock-mode) (symbol-value 'font-lock-mode)
        (boundp 'font-lock-face-attributes)
-       (let ((face-attributes font-lock-face-attributes))
+       (let ((face-attributes (symbol-value 'font-lock-face-attributes)))
         (while face-attributes
           (let* ((face-attribute
                   (car (prog1 face-attributes
@@ -2520,10 +3312,10 @@ If EXTENSION is any other symbol, it is ignored."
 ;; Internal functions and variables
 
 
-(make-local-hook 'ps-print-hook)
-(make-local-hook 'ps-print-begin-sheet-hook)
-(make-local-hook 'ps-print-begin-page-hook)
-(make-local-hook 'ps-print-begin-column-hook)
+(defvar ps-print-hook nil)
+(defvar ps-print-begin-sheet-hook nil)
+(defvar ps-print-begin-page-hook nil)
+(defvar ps-print-begin-column-hook nil)
 
 
 (defun ps-print-without-faces (from to &optional filename region-p)
@@ -2533,7 +3325,7 @@ If EXTENSION is any other symbol, it is ignored."
 
 (defun ps-spool-without-faces (from to &optional region-p)
   (run-hooks 'ps-print-hook)
-  (ps-printing-region region-p)
+  (ps-printing-region region-p from)
   (ps-generate (current-buffer) from to 'ps-generate-postscript))
 
 
@@ -2544,7 +3336,7 @@ If EXTENSION is any other symbol, it is ignored."
 
 (defun ps-spool-with-faces (from to &optional region-p)
   (run-hooks 'ps-print-hook)
-  (ps-printing-region region-p)
+  (ps-printing-region region-p from)
   (ps-generate (current-buffer) from to 'ps-generate-postscript-with-faces))
 
 
@@ -2568,11 +3360,11 @@ file.")
   "Non-nil means ps-print is printing a region.")
 
 
-(defun ps-printing-region (region-p)
+(defun ps-printing-region (region-p from)
   (setq ps-printing-region-p region-p
        ps-printing-region
        (cons (if region-p
-                 (ps-count-lines (point-min) (region-beginning))
+                 (ps-count-lines (point-min) from)
                1)
              (ps-count-lines (point-min) (point-max)))))
 
@@ -2631,22 +3423,31 @@ which long lines wrap around."
   "Display the correspondence between a line length and a font size,
 using the current ps-print setup.
 Try: pr -t file | awk '{printf \"%3d %s\n\", length($0), $0}' | sort -r | head"
-  (let ((buf (get-buffer-create "*Line-lengths*"))
-       (ifs ps-font-size-internal)     ; initial font size
-       (icw (ps-avg-char-width 'ps-font-for-text)) ; initial character width
-       (print-width (progn (ps-get-page-dimensions)
-                           ps-print-width))
-       (ps-setup (ps-setup))           ; setup for the current buffer
-       (fs-min 5)                      ; minimum font size
-       cw-min                          ; minimum character width
-       nb-cpl-max                      ; maximum nb of characters per line
-       (fs-max 14)                     ; maximum font size
-       cw-max                          ; maximum character width
-       nb-cpl-min                      ; minimum nb of characters per line
-       fs                              ; current font size
-       cw                              ; current character width
-       nb-cpl                          ; current nb of characters per line
-       )
+  (let* ((ps-font-size-internal
+         (or ps-font-size-internal
+             (ps-get-font-size 'ps-font-size)))
+        (ps-header-font-size-internal
+         (or ps-header-font-size-internal
+             (ps-get-font-size 'ps-header-font-size)))
+        (ps-header-title-font-size-internal
+         (or ps-header-title-font-size-internal
+             (ps-get-font-size 'ps-header-title-font-size)))
+        (buf (get-buffer-create "*Line-lengths*"))
+        (ifs ps-font-size-internal)    ; initial font size
+        (icw (ps-avg-char-width 'ps-font-for-text)) ; initial character width
+        (print-width (progn (ps-get-page-dimensions)
+                            ps-print-width))
+        (ps-setup (ps-setup))          ; setup for the current buffer
+        (fs-min 5)                     ; minimum font size
+        cw-min                         ; minimum character width
+        nb-cpl-max                     ; maximum nb of characters per line
+        (fs-max 14)                    ; maximum font size
+        cw-max                         ; maximum character width
+        nb-cpl-min                     ; minimum nb of characters per line
+        fs                             ; current font size
+        cw                             ; current character width
+        nb-cpl                         ; current nb of characters per line
+        )
     (setq cw-min     (/ (* icw fs-min) ifs)
          nb-cpl-max (floor (/ print-width cw-min))
          cw-max     (/ (* icw fs-max) ifs)
@@ -2654,13 +3455,13 @@ Try: pr -t file | awk '{printf \"%3d %s\n\", length($0), $0}' | sort -r | head"
          nb-cpl     nb-cpl-min)
     (set-buffer buf)
     (goto-char (point-max))
-    (or (bolp) (insert "\n"))
+    (or (bobp) (insert "\n" (make-string 75 ?\;) "\n"))
     (insert ps-setup
-           "nb char per line / font size\n")
+           "\nnb char per line / font size\n")
     (while (<= nb-cpl nb-cpl-max)
       (setq cw (/ print-width (float nb-cpl))
            fs (/ (* ifs cw) icw))
-      (insert (format "%3s %s\n" nb-cpl fs))
+      (insert (format "%16d   %s\n" nb-cpl fs))
       (setq nb-cpl (1+ nb-cpl)))
     (insert "\n")
     (display-buffer buf 'not-this-window)))
@@ -2669,25 +3470,34 @@ Try: pr -t file | awk '{printf \"%3d %s\n\", length($0), $0}' | sort -r | head"
   "Display correspondence between font size and the number of pages.
 The correspondence is based on having NB-LINES lines of text,
 and on the current ps-print setup."
-  (let ((buf (get-buffer-create "*Nb-Pages*"))
-       (ifs ps-font-size-internal)     ; initial font size
-       (ilh (ps-line-height 'ps-font-for-text)) ; initial line height
-       (page-height (progn (ps-get-page-dimensions)
-                           ps-print-height))
-       (ps-setup (ps-setup))           ; setup for the current buffer
-       (fs-min 4)                      ; minimum font size
-       lh-min                          ; minimum line height
-       nb-lpp-max                      ; maximum nb of lines per page
-       nb-page-min                     ; minimum nb of pages
-       (fs-max 14)                     ; maximum font size
-       lh-max                          ; maximum line height
-       nb-lpp-min                      ; minimum nb of lines per page
-       nb-page-max                     ; maximum nb of pages
-       fs                              ; current font size
-       lh                              ; current line height
-       nb-lpp                          ; current nb of lines per page
-       nb-page                         ; current nb of pages
-       )
+  (let* ((ps-font-size-internal
+         (or ps-font-size-internal
+             (ps-get-font-size 'ps-font-size)))
+        (ps-header-font-size-internal
+         (or ps-header-font-size-internal
+             (ps-get-font-size 'ps-header-font-size)))
+        (ps-header-title-font-size-internal
+         (or ps-header-title-font-size-internal
+             (ps-get-font-size 'ps-header-title-font-size)))
+        (buf (get-buffer-create "*Nb-Pages*"))
+        (ifs ps-font-size-internal)    ; initial font size
+        (ilh (ps-line-height 'ps-font-for-text)) ; initial line height
+        (page-height (progn (ps-get-page-dimensions)
+                            ps-print-height))
+        (ps-setup (ps-setup))          ; setup for the current buffer
+        (fs-min 4)                     ; minimum font size
+        lh-min                         ; minimum line height
+        nb-lpp-max                     ; maximum nb of lines per page
+        nb-page-min                    ; minimum nb of pages
+        (fs-max 14)                    ; maximum font size
+        lh-max                         ; maximum line height
+        nb-lpp-min                     ; minimum nb of lines per page
+        nb-page-max                    ; maximum nb of pages
+        fs                             ; current font size
+        lh                             ; current line height
+        nb-lpp                         ; current nb of lines per page
+        nb-page                        ; current nb of pages
+        )
     (setq lh-min      (/ (* ilh fs-min) ifs)
          nb-lpp-max  (floor (/ page-height lh-min))
          nb-page-min (ceiling (/ (float nb-lines) nb-lpp-max))
@@ -2697,15 +3507,15 @@ and on the current ps-print setup."
          nb-page     nb-page-min)
     (set-buffer buf)
     (goto-char (point-max))
-    (or (bolp) (insert "\n"))
+    (or (bobp) (insert "\n" (make-string 75 ?\;) "\n"))
     (insert ps-setup
-           (format "%d lines\n" nb-lines)
+           (format "\nThere are %d lines.\n\n" nb-lines)
            "nb page / font size\n")
     (while (<= nb-page nb-page-max)
       (setq nb-lpp (ceiling (/ nb-lines (float nb-page)))
            lh     (/ page-height nb-lpp)
            fs     (/ (* ifs lh) ilh))
-      (insert (format "%s %s\n" nb-page fs))
+      (insert (format "%7d   %s\n" nb-page fs))
       (setq nb-page (1+ nb-page)))
     (insert "\n")
     (display-buffer buf 'not-this-window)))
@@ -2823,25 +3633,28 @@ page-height == bm + print-height + tm - ho - hh
                  ps-header-pad)
               ps-print-height))))
 
-(defun ps-print-preprint (&optional filename)
-  (and filename
-       (or (numberp filename)
-          (listp filename))
+(defun ps-print-preprint (prefix-arg)
+  (and prefix-arg
+       (or (numberp prefix-arg)
+          (listp prefix-arg))
        (let* ((name   (concat (file-name-nondirectory (or (buffer-file-name)
                                                          (buffer-name)))
                              ".ps"))
              (prompt (format "Save PostScript to file: (default %s) " name))
              (res    (read-file-name prompt default-directory name nil)))
-        (while (cond ((not (file-writable-p res))
+        (while (cond ((file-directory-p res)
+                      (ding)
+                      (setq prompt "It's a directory"))
+                     ((not (file-writable-p res))
                       (ding)
-                      (setq prompt "is unwritable"))
+                      (setq prompt "File is unwritable"))
                      ((file-exists-p res)
-                      (setq prompt "exists")
+                      (setq prompt "File exists")
                       (not (y-or-n-p (format "File `%s' exists; overwrite? "
                                              res))))
                      (t nil))
           (setq res (read-file-name
-                     (format "File %s; save PostScript to file: " prompt)
+                     (format "%s; save PostScript to file: " prompt)
                      (file-name-directory res) nil nil
                      (file-name-nondirectory res))))
         (if (file-directory-p res)
@@ -2896,13 +3709,43 @@ page-height == bm + print-height + tm - ho - hh
   (insert ")"))                                ;insert end-string delimiter
 
 (defun ps-init-output-queue ()
-  (setq ps-output-head '("")
+  (setq ps-output-head (list "")
        ps-output-tail ps-output-head))
 
+
+(defun ps-selected-pages ()
+  (while (progn
+          (setq ps-first-page     (car (car ps-selected-pages))
+                ps-last-page      (cdr (car ps-selected-pages))
+                ps-selected-pages (cdr ps-selected-pages))
+          (and ps-selected-pages
+               (< ps-last-page ps-page-postscript)))))
+
+
+(defun ps-print-page-p ()
+  (setq ps-print-page-p
+       (and (cond ((null ps-first-page))
+                  ((<= ps-page-postscript ps-last-page)
+                   (<= ps-first-page ps-page-postscript))
+                  (ps-selected-pages
+                   (ps-selected-pages)
+                   (and (<= ps-first-page ps-page-postscript)
+                        (<= ps-page-postscript ps-last-page)))
+                  (t
+                   nil))
+            (cond ((eq ps-even-or-odd-pages 'even)
+                   (= (logand ps-page-postscript 1) 0))
+                  ((eq ps-even-or-odd-pages 'odd)
+                   (= (logand ps-page-postscript 1) 1))
+                  (t)
+                  ))))
+
+
 (defun ps-output (&rest args)
-  (setcdr ps-output-tail args)
-  (while (cdr ps-output-tail)
-    (setq ps-output-tail (cdr ps-output-tail))))
+  (when ps-print-page-p
+    (setcdr ps-output-tail args)
+    (while (cdr ps-output-tail)
+      (setq ps-output-tail (cdr ps-output-tail)))))
 
 (defun ps-output-string (string)
   (ps-output t string))
@@ -2937,10 +3780,6 @@ page-height == bm + print-height + tm - ho - hh
 
 (defun ps-insert-file (fname)
   (ps-flush-output)
-  ;; Check to see that the file exists and is readable; if not, throw
-  ;; an error.
-  (or (file-readable-p fname)
-      (error "Could not read file `%s'" fname))
   (save-excursion
     (set-buffer ps-spool-buffer)
     (goto-char (point-max))
@@ -2984,9 +3823,8 @@ page-height == bm + print-height + tm - ho - hh
        (ps-output "] def\n"))))
 
 
-(defun ps-output-boolean (name bool &optional no-def)
-  (ps-output (format "/%s %s%s"
-                    name (if bool "true" "false") (if no-def "\n" " def\n"))))
+(defun ps-output-boolean (name bool)
+  (ps-output (format "/%s %s def\n" name (if bool "true" "false"))))
 
 
 (defun ps-background-pages (page-list func)
@@ -3045,7 +3883,7 @@ page-height == bm + print-height + tm - ho - hh
   (mapcar
    #'(lambda (text)
        (setq ps-background-text-count (1+ ps-background-text-count))
-       (ps-output (format "/ShowBackText-%d {\n" ps-background-text-count))
+       (ps-output (format "/ShowBackText-%d{\n" ps-background-text-count))
        (ps-output-string (nth 0 text)) ; text
        (ps-output
        "\n"
@@ -3055,8 +3893,8 @@ page-height == bm + print-height + tm - ho - hh
                         "PrintHeight PrintPageWidth atan") ; rotation
        (ps-float-format (nth 5 text) 0.85) ; gray
        (ps-float-format (nth 1 text) "0") ; x position
-       (ps-float-format (nth 2 text) "BottomMargin") ; y position
-       "\nShowBackText} def\n")
+       (ps-float-format (nth 2 text) "0") ; y position
+       "\nShowBackText}def\n")
        (ps-background-pages (nthcdr 7 text) ; page list
                            (format "ShowBackText-%d\n"
                                    ps-background-text-count)))
@@ -3070,7 +3908,7 @@ page-height == bm + print-height + tm - ho - hh
         (when (file-readable-p image-file)
           (setq ps-background-image-count (1+ ps-background-image-count))
           (ps-output
-           (format "/ShowBackImage-%d {\n--back-- "
+           (format "/ShowBackImage-%d{\n--back-- "
                    ps-background-image-count)
            (ps-float-format (nth 5 image) 0.0) ; rotation
            (ps-float-format (nth 3 image) 1.0) ; x scale
@@ -3097,7 +3935,7 @@ page-height == bm + print-height + tm - ho - hh
                               (- (+ (/ (- (aref box 3) (aref box 1)) 2.0)
                                     (aref box 1)))))
                      t)))))
-          (ps-output "\nEndBackImage} def\n")
+          (ps-output "\nEndBackImage}def\n")
           (ps-background-pages (nthcdr 6 image) ; page list
                                (format "ShowBackImage-%d\n"
                                        ps-background-image-count)))))
@@ -3112,10 +3950,10 @@ page-height == bm + print-height + tm - ho - hh
                     (if has-local-background
                         (ps-output (aref range 2))
                       (setq has-local-background t)
-                      (ps-output "/printLocalBackground {\n"
+                      (ps-output "/printLocalBackground{\n"
                                  (aref range 2)))))
            ps-background-pages)
-    (and has-local-background (ps-output "} def\n"))))
+    (and has-local-background (ps-output "}def\n"))))
 
 
 ;; Return a list of the distinct elements of LIST.
@@ -3193,6 +4031,7 @@ page-height == bm + print-height + tm - ho - hh
      (100 nil 10 10 0))
     (letter
      (1   nil 1  1  0)
+     (2   t   1  2  0)                 ; adjusted by PostScript code
      (4   nil 2  2  0)
      (6   t   2  3  0)
      (9   nil 3  3  0)
@@ -3235,6 +4074,7 @@ page-height == bm + print-height + tm - ho - hh
      (100 nil 10 10 0))
     (letter-small
      (1   nil 1  1  0)
+     (2   t   1  2  0)                 ; adjusted by PostScript code
      (4   nil 2  2  0)
      (6   t   2  3  0)
      (9   nil 3  3  0)
@@ -3330,6 +4170,7 @@ page-height == bm + print-height + tm - ho - hh
      (100 nil 10 10 0))
     (executive
      (1   nil 1  1  0)
+     (2   t   1  2  0)                 ; adjusted by PostScript code
      (4   nil 2  2  0)
      (6   t   2  3  0)
      (9   nil 3  3  0)
@@ -3567,10 +4408,20 @@ XSTART YSTART are the relative position for the first page in a sheet.")
 (defmacro ps-n-up-ystart  (init) `(nth 7 ,init))
 
 
+(defconst ps-error-handler-alist
+  '((none             . 0)
+    (paper            . 1)
+    (system           . 2)
+    (paper-and-system . 3))
+  "Alist for error handler message")
+
+
 (defun ps-begin-file ()
   (ps-get-page-dimensions)
   (setq ps-page-postscript 0
        ps-page-order 0
+       ps-page-n-up 0
+       ps-print-page-p t
        ps-background-text-count 0
        ps-background-image-count 0
        ps-background-pages nil
@@ -3580,7 +4431,7 @@ XSTART YSTART are the relative position for the first page in a sheet.")
        (tumble (if ps-landscape-mode (not ps-spool-tumble) ps-spool-tumble))
        (n-up (ps-n-up-printing))
        (n-up-filling (ps-n-up-filling)))
-    (and (> ps-n-up-printing 1) (setq tumble (not tumble)))
+    (and ps-n-up-on (setq tumble (not tumble)))
     (ps-output
      ps-adobe-tag
      "%%Title: " (buffer-name)         ; Take job name from name of
@@ -3603,23 +4454,30 @@ XSTART YSTART are the relative position for the first page in a sheet.")
      (format " %d" (round (ps-page-dimensions-get-height dimensions)))
      " 0 () ()\n%%PageOrder: Ascend\n%%Pages: (atend)\n%%Requirements:"
      (if ps-spool-duplex
-        (format " duplex%s" (if tumble "(tumble)\n" "\n"))
+        (if tumble " duplex(tumble)\n" " duplex\n")
        "\n"))
 
-    (let ((comments (if (functionp ps-print-prologue-header)
-                       (funcall ps-print-prologue-header)
-                     ps-print-prologue-header)))
-      (and (stringp comments)
-          (ps-output comments)))
+    (ps-insert-string ps-print-prologue-header)
 
-    (ps-output "%%EndComments\n\n%%BeginPrologue\n\n"
-              "/gs_languagelevel /languagelevel where "
-              "{pop languagelevel}{1}ifelse def\n\n")
+    (ps-output "%%EndComments\n%%BeginDefaults\n%%PageMedia: "
+              (ps-page-dimensions-get-media dimensions)
+              "\n%%EndDefaults\n\n%%BeginPrologue\n\n"
+              "/languagelevel where{pop}{/languagelevel 1 def}ifelse\n"
+              (format "/ErrorMessage  %s def\n\n"
+                      (or (cdr (assoc ps-error-handler-message
+                                      ps-error-handler-alist))
+                          1))          ; send to paper
+              ps-print-prologue-0
+              "\n%%BeginProcSet: UserDefinedPrologue\n\n")
+
+    (ps-insert-string ps-user-defined-prologue)
+
+    (ps-output "\n%%EndProcSet\n\n")
 
-    (ps-output-boolean "SkipFirstPage      " ps-banner-page-when-duplexing)
     (ps-output-boolean "LandscapeMode      "
                       (or ps-landscape-mode
                           (eq (ps-n-up-landscape n-up) 'pag)))
+    (ps-output-boolean "UpsideDown         " ps-print-upside-down)
     (ps-output (format "/NumberOfColumns     %d def\n" ps-number-of-columns)
 
               (format "/LandscapePageHeight %s def\n" ps-landscape-page-height)
@@ -3642,9 +4500,10 @@ XSTART YSTART are the relative position for the first page in a sheet.")
     (ps-output-boolean "PrintHeader       " ps-print-header)
     (ps-output-boolean "PrintOnlyOneHeader" ps-print-only-one-header)
     (ps-output-boolean "PrintHeaderFrame  " ps-print-header-frame)
+    (ps-output-boolean "SwitchHeader      " (if (eq ps-switch-header 'duplex)
+                                               ps-spool-duplex
+                                             ps-switch-header))
     (ps-output-boolean "ShowNofN          " ps-show-n-of-n)
-    (ps-output-boolean "DuplexValue       " ps-spool-duplex)
-    (ps-output-boolean "TumbleValue       " tumble)
 
     (let ((line-height (ps-line-height 'ps-font-for-text)))
       (ps-output (format "/LineHeight     %s def\n" line-height)
@@ -3653,15 +4512,26 @@ XSTART YSTART are the relative position for the first page in a sheet.")
                                      (* line-height 0.45))
                                   line-height)))))
 
+    (ps-output-boolean "WarnPaperSize   " ps-warn-paper-type)
     (ps-output-boolean "Zebra           " ps-zebra-stripes)
+    (ps-output-boolean "ZebraFollow     " ps-zebra-stripe-follow)
     (ps-output-boolean "PrintLineNumber " ps-line-number)
-    (ps-output (format "/ZebraHeight      %d def\n" ps-zebra-stripe-height)
-              (format "/ZebraGray        %s def\n" ps-zebra-gray)
-              "/UseSetpagedevice "
+    (ps-output-boolean "SyncLineZebra   " (not (integerp ps-line-number-step)))
+    (ps-output (format "/PrintLineStep    %d def\n"
+                      (if (integerp ps-line-number-step)
+                          ps-line-number-step
+                        ps-zebra-stripe-height))
+              (format "/PrintLineStart   %d def\n" ps-line-number-start)
+              (format "/ZebraHeight      %d def\n" ps-zebra-stripe-height)
+              "/ZebraColor       "
+              (ps-format-color ps-zebra-color 0.95)
+              "def\n/BackgroundColor  "
+              (ps-format-color ps-default-bg 1.0)
+              "def\n/UseSetpagedevice "
               (if (eq ps-spool-config 'setpagedevice)
-                  "/setpagedevice where {pop true}{false}ifelse def\n"
-                "false def\n")
-              "\n/PageWidth "
+                  "/setpagedevice where{pop languagelevel 2 eq}{false}ifelse"
+                "false")
+              " def\n\n/PageWidth "
               "PrintPageWidth LeftMargin add RightMargin add def\n\n"
               (format "/N-Up           %d def\n" ps-n-up-printing))
     (ps-output-boolean "N-Up-Landscape" (eq (ps-n-up-landscape n-up) t))
@@ -3669,8 +4539,8 @@ XSTART YSTART are the relative position for the first page in a sheet.")
     (ps-output (format "/N-Up-Lines     %d def\n" (ps-n-up-lines n-up))
               (format "/N-Up-Columns   %d def\n" (ps-n-up-columns n-up))
               (format "/N-Up-Missing   %d def\n" (ps-n-up-missing n-up))
-              (format "/N-Up-Margin    %s" ps-n-up-margin)
-              " def\n/N-Up-Repeat    "
+              (format "/N-Up-Margin    %s def\n" ps-n-up-margin)
+              "/N-Up-Repeat    "
               (if ps-landscape-mode
                   (ps-n-up-end     n-up-filling)
                 (ps-n-up-repeat  n-up-filling))
@@ -3692,15 +4562,15 @@ XSTART YSTART are the relative position for the first page in a sheet.")
 
     (ps-output "\n" ps-print-prologue-1)
 
-    (ps-output "\n/printGlobalBackground {\n")
+    (ps-output "\n/printGlobalBackground{\n")
     (ps-output-list ps-background-all-pages)
-    (ps-output "} def\n/printLocalBackground {\n} def\n")
+    (ps-output "}def\n/printLocalBackground{\n}def\n")
 
     ;; Header fonts
-    (ps-output (format "/h0 %s (%s) cvn DefFont\n" ; /h0 14 /Helvetica-Bold DefFont
+    (ps-output (format "/h0 %s(%s)cvn DefFont\n" ; /h0 14 /Helvetica-Bold DefFont
                       ps-header-title-font-size-internal
                       (ps-font 'ps-font-for-header 'bold))
-              (format "/h1 %s (%s) cvn DefFont\n" ; /h1 12 /Helvetica DefFont
+              (format "/h1 %s(%s)cvn DefFont\n" ; /h1 12 /Helvetica DefFont
                       ps-header-font-size-internal
                       (ps-font 'ps-font-for-header 'normal)))
 
@@ -3710,7 +4580,7 @@ XSTART YSTART are the relative position for the first page in a sheet.")
     (let ((font (ps-font-alist 'ps-font-for-text))
          (i 0))
       (while font
-       (ps-output (format "/f%d %s (%s) cvn DefFont\n"
+       (ps-output (format "/f%d %s(%s)cvn DefFont\n"
                           i
                           ps-font-size-internal
                           (ps-font 'ps-font-for-text (car (car font)))))
@@ -3727,16 +4597,55 @@ XSTART YSTART are the relative position for the first page in a sheet.")
                 (ps-boolean-capitalized ps-spool-duplex)
                 " *Tumble "
                 (ps-boolean-capitalized tumble)
-                "\n\n"
-                ps-print-duplex-feature
-                "\n%%EndFeature\n")))
-  (ps-output "\n/Lines 0 def\n/PageCount 0 def\n\nBeginDoc\n%%EndSetup\n"))
+                "\nUseSetpagedevice\n{BMark/Duplex "
+                (ps-boolean-constant ps-spool-duplex)
+                "/Tumble "
+                (ps-boolean-constant tumble)
+                " EMark setpagedevice}\n{statusdict begin "
+                (ps-boolean-constant ps-spool-duplex)
+                " setduplexmode "
+                (ps-boolean-constant tumble)
+                " settumble end}ifelse\n%%EndFeature\n")))
+  (ps-output "\n%%BeginFeature: *ManualFeed "
+            (ps-boolean-capitalized ps-manual-feed)
+            "\nBMark /ManualFeed "
+            (ps-boolean-constant ps-manual-feed)
+            " EMark setpagedevice\n%%EndFeature\n"
+            "\n/Lines 0 def\n/PageCount 0 def\n\nBeginDoc\n%%EndSetup\n")
+  (and ps-banner-page-when-duplexing
+       (ps-output "\n%%Page: banner 0\nsave showpage restore\n")))
+
+
+(defun ps-format-color (color &optional default)
+  (let ((the-color (if (stringp color)
+                      (ps-color-scale color)
+                    color)))
+    (if (and the-color (listp the-color))
+       (concat "["
+               (format ps-color-format
+                       (nth 0 the-color)
+                       (nth 1 the-color)
+                       (nth 2 the-color))
+               "] ")
+      (ps-float-format (if (numberp the-color) the-color default)))))
+
+
+(defun ps-insert-string (prologue)
+  (let ((str (if (functionp prologue)
+                (funcall prologue)
+              prologue)))
+    (and (stringp str)
+        (ps-output str))))
 
 
 (defun ps-boolean-capitalized (bool)
   (if bool "True" "False"))
 
 
+(defun ps-boolean-constant (bool)
+  (if bool "true" "false"))
+
+
 (defun ps-header-dirpart ()
   (let ((fname (buffer-file-name)))
     (if fname
@@ -3775,16 +4684,55 @@ XSTART YSTART are the relative position for the first page in a sheet.")
 
 
 (defun ps-begin-job ()
+  ;; prologue files
+  (let ((last-char (aref ps-postscript-code-directory
+                        (1- (length ps-postscript-code-directory)))))
+    (or (eq last-char ?/)
+       (and ps-windows-system (eq last-char ?\\))
+       (setq ps-postscript-code-directory
+             (concat ps-postscript-code-directory "/"))))
   (or (equal ps-mark-code-directory ps-postscript-code-directory)
-      (setq ps-print-prologue-1     (ps-prologue-file 1)
-           ps-print-prologue-2     (ps-prologue-file 2)
-           ps-print-duplex-feature (ps-prologue-file 3)
-           ps-mark-code-directory  ps-postscript-code-directory))
+      (setq ps-print-prologue-0    (ps-prologue-file 0)
+           ps-print-prologue-1    (ps-prologue-file 1)
+           ps-print-prologue-2    (ps-prologue-file 2)
+           ps-mark-code-directory ps-postscript-code-directory))
+  ;; selected pages
+  (let (new page)
+    (while ps-selected-pages
+      (setq page              (car ps-selected-pages)
+           ps-selected-pages (cdr ps-selected-pages))
+      (cond ((integerp page)
+            (and (> page 0)
+                 (setq new (cons (cons page page) new))))
+           ((consp page)
+            (and (integerp (car page)) (integerp (cdr page))
+                 (> (car page) 0)
+                 (<= (car page) (cdr page))
+                 (setq new (cons page new))))))
+    (setq ps-selected-pages      (sort new #'(lambda (one other)
+                                              (< (car one) (car other))))
+         ps-last-selected-pages ps-selected-pages
+         ps-first-page          nil
+         ps-last-page           nil))
+  ;; face background
+  (or (listp ps-use-face-background)
+      (setq ps-use-face-background t))
+  ;; line number
+  (and (integerp ps-line-number-step)
+       (<= ps-line-number-step 0)
+       (setq ps-line-number-step 1))
+  (setq ps-n-up-on           (> ps-n-up-printing 1)
+       ps-line-number-start (max 1 (min ps-line-number-start
+                                        (if (integerp ps-line-number-step)
+                                            ps-line-number-step
+                                          ps-zebra-stripe-height))))
+  ;; spooling buffer
   (save-excursion
     (set-buffer ps-spool-buffer)
     (goto-char (point-max))
     (and (re-search-backward "^%%Trailer$" nil t)
         (delete-region (match-beginning 0) (point-max))))
+  ;; miscellaneous
   (setq ps-showline-count (car ps-printing-region)
        ps-page-count 0
        ps-font-size-internal        (ps-get-font-size 'ps-font-size)
@@ -3798,28 +4746,31 @@ XSTART YSTART are the relative position for the first page in a sheet.")
               (string-as-unibyte "[\000-\037\177-\237]"))
              ((eq ps-print-control-characters 'control)
               "[\000-\037\177]")
-             (t "[\t\n\f]"))))
+             (t "[\t\n\f]"))
+       ps-default-foreground (ps-rgb-color ps-default-fg 0.0)
+       ps-default-color (and ps-print-color-p ps-default-foreground)
+       ps-current-color ps-default-color
+       ;; Set the color scale.  We do it here instead of in the defvar so
+       ;; that ps-print can be dumped into emacs.  This expression can't be
+       ;; evaluated at dump-time because X isn't initialized.
+       ps-color-p           (and ps-print-color-p (ps-color-device))
+       ps-print-color-scale (if ps-color-p
+                                (float (car (ps-color-values "white")))
+                              1.0)))
 
-(defmacro ps-page-number ()
-  `(1+ (/ (1- ps-page-count) ps-number-of-columns)))
 
-(defun ps-end-file ()
-  ;; Back to the PS output buffer to set the last page n-up printing
-  (save-excursion
-    (let ((pages-per-sheet (mod ps-page-postscript ps-n-up-printing))
-         case-fold-search)
-      (set-buffer ps-spool-buffer)
-      (goto-char (point-max))
-      (and (> pages-per-sheet 0)
-          (re-search-backward "^[0-9]+ BeginSheet$" nil t)
-          (replace-match (format "%d BeginSheet" pages-per-sheet) t))))
-  ;; Set dummy page
-  (and ps-spool-duplex (= (mod ps-page-order 2) 1)
-       (ps-dummy-page))
-  ;; Set end of PostScript file
-  (ps-output "EndSheet\n\n%%Trailer\n%%Pages: "
-            (format "%d" ps-page-order)
-            "\n\nEndDoc\n\n%%EOF\n"))
+(defun ps-rgb-color (color default)
+  (cond ((and color (listp color)) color)
+       ((stringp color) (ps-color-scale color))
+       ((numberp color) (list color color color))
+       (t (list default default default))
+       ))
+
+
+(defun ps-page-number ()
+  (if ps-print-only-one-header
+      (1+ (/ (1- ps-page-count) ps-number-of-columns))
+    ps-page-count))
 
 
 (defun ps-next-page ()
@@ -3830,36 +4781,39 @@ XSTART YSTART are the relative position for the first page in a sheet.")
 
 (defun ps-header-sheet ()
   ;; Print only when a new sheet begins.
-  (setq ps-page-postscript (1+ ps-page-postscript)
-       ps-page-order (1+ ps-page-order))
+  (setq ps-page-order (1+ ps-page-order))
   (and (> ps-page-order 1)
        (ps-output "EndSheet\n"))
-  (ps-output (format "\n%%%%Page: %d %d\n"
-                    ps-page-postscript ps-page-order))
-  (ps-output (format "%d BeginSheet\nBeginDSCPage\n" ps-n-up-printing)))
+  (ps-output (if ps-n-up-on
+                (format "\n%%%%Page: (%d \\(%d\\)) %d\n"
+                        ps-page-order ps-page-postscript ps-page-order)
+              (format "\n%%%%Page: %d %d\n"
+                      ps-page-postscript ps-page-order))
+            (format "%d BeginSheet\nBeginDSCPage\n"
+                    ps-n-up-printing)))
 
 
-(defsubst ps-header-page ()
+(defun ps-header-page ()
   ;; set total line and page number when printing has finished
   ;; (see `ps-generate')
-  (run-hooks
-   (if (prog1
-          (zerop (mod ps-page-count ps-number-of-columns))
-        (setq ps-page-count (1+ ps-page-count)))
-       (prog1
-          (if (zerop (mod ps-page-postscript ps-n-up-printing))
-              ;; Print only when a new sheet begins.
-              (progn
-                (ps-header-sheet)
-                'ps-print-begin-sheet-hook)
-            ;; Print only when a new page begins.
-            (setq ps-page-postscript (1+ ps-page-postscript))
-            (ps-output "BeginDSCPage\n")
-            'ps-print-begin-page-hook)
-        (ps-background ps-page-postscript))
-     ;; Print only when a new column begins.
-     (ps-output "BeginDSCPage\n")
-     'ps-print-begin-column-hook)))
+  (if (zerop (mod ps-page-count ps-number-of-columns))
+      (progn
+       (setq ps-page-postscript (1+ ps-page-postscript))
+       (when (ps-print-page-p)
+         (if (zerop (mod ps-page-n-up ps-n-up-printing))
+             ;; Print only when a new sheet begins.
+             (progn
+               (ps-header-sheet)
+               (run-hooks 'ps-print-begin-sheet-hook))
+           ;; Print only when a new page begins.
+           (ps-output "BeginDSCPage\n")
+           (run-hooks 'ps-print-begin-page-hook))
+         (ps-background ps-page-postscript)
+         (setq ps-page-n-up (1+ ps-page-n-up))))
+    ;; Print only when a new column begins.
+    (ps-output "BeginDSCPage\n")
+    (run-hooks 'ps-print-begin-column-hook))
+  (setq ps-page-count (1+ ps-page-count)))
 
 (defun ps-begin-page ()
   (ps-get-page-dimensions)
@@ -3869,9 +4823,7 @@ XSTART YSTART are the relative position for the first page in a sheet.")
   (ps-header-page)
 
   (ps-output (format "/LineNumber %d def\n" ps-showline-count)
-            (format "/PageNumber %d def\n" (if ps-print-only-one-header
-                                               (ps-page-number)
-                                             ps-page-count)))
+            (format "/PageNumber %d def\n" (ps-page-number)))
 
   (when ps-print-header
     (ps-generate-header "HeaderLinesLeft"    ps-left-header)
@@ -3887,17 +4839,6 @@ XSTART YSTART are the relative position for the first page in a sheet.")
 (defun ps-end-page ()
   (ps-output "EndPage\nEndDSCPage\n"))
 
-(defun ps-dummy-page ()
-  (let ((ps-n-up-printing 0))
-    (ps-header-sheet))
-  (ps-output "/PrintHeader false def
-/ColumnIndex 0 def
-/PrintLineNumber false def
-BeginPage
-EndPage
-EndDSCPage\n")
-  (setq ps-page-postscript ps-n-up-printing))
-
 (defun ps-next-line ()
   (setq ps-showline-count (1+ ps-showline-count))
   (let ((lh (ps-line-height 'ps-font-for-text)))
@@ -3976,7 +4917,7 @@ EndDSCPage\n")
     (ps-output "false BG\n")))
 
 (defun ps-set-color (color)
-  (setq ps-current-color (or color ps-default-fg))
+  (setq ps-current-color (or color ps-default-foreground))
   (ps-output (format ps-color-format
                     (nth 0 ps-current-color)
                     (nth 1 ps-current-color) (nth 2 ps-current-color))
@@ -4017,8 +4958,8 @@ EndDSCPage\n")
       (if (re-search-forward ps-control-or-escape-regexp to t)
          ;; region with some control characters or some multi-byte characters
          (let* ((match-point (match-beginning 0))
-                (match (char-after match-point))
-                (composition (find-composition from (1+ match-point))))
+                (match       (char-after match-point))
+                (composition (ps-e-find-composition from (1+ match-point))))
            (if composition
                (if (and (nth 2 composition)
                         (<= (car composition) match-point))
@@ -4047,23 +4988,22 @@ EndDSCPage\n")
             ((= match ?\f)             ; form feed
              ;; do not skip page if previous character is NEWLINE and
              ;; it is a beginning of page.
-             (or (and (= (char-after (1- match-point)) ?\n)
+             (or (and (equal (char-after (1- match-point)) ?\n)
                       (= ps-height-remaining ps-print-height))
                  (ps-next-page)))
 
             (composition               ; a composite sequence
              (ps-plot 'ps-mule-plot-composition match-point (point) bg-color))
 
-                                       ; characters from ^@ to ^_ and
             ((> match 255)             ; a multi-byte character
              (let* ((charset (char-charset match))
-                    (composition (find-composition match-point to))
+                    (composition (ps-e-find-composition match-point to))
                     (stop (if (nth 2 composition) (car composition) to)))
                (or (eq charset 'composition)
                    (while (and (< (point) stop) (eq (charset-after) charset))
                      (forward-char 1)))
                (ps-plot 'ps-mule-plot-string match-point (point) bg-color)))
-
+                                       ; characters from ^@ to ^_ and
             (t                         ; characters from 127 to 255
              (ps-control-character match)))
            (setq from (point)))
@@ -4105,37 +5045,6 @@ EndDSCPage\n")
     (ps-output-string str)
     (ps-output " S\n")))
 
-(defun ps-color-value (x-color-value)
-  ;; Scale 16-bit X-COLOR-VALUE to PostScript color value in [0, 1] interval.
-  (/ x-color-value ps-print-color-scale))
-
-
-(cond ((eq ps-print-emacs-type 'emacs)  ; emacs
-
-       (defun ps-color-values (x-color)
-        (if (fboundp 'x-color-values)
-            (x-color-values x-color)
-          (error "No available function to determine X color values.")))
-       )
-                                       ; xemacs
-                                       ; lucid
-      (t                               ; epoch
-       (defun ps-color-values (x-color)
-        (cond ((fboundp 'x-color-values)
-               (x-color-values x-color))
-              ((and (fboundp 'color-instance-rgb-components)
-                    (ps-color-device))
-               (color-instance-rgb-components
-                (if (color-instance-p x-color)
-                    x-color
-                  (make-color-instance
-                   (if (color-specifier-p x-color)
-                       (color-name x-color)
-                     x-color)))))
-              (t
-               (error "No available function to determine X color values."))))
-       ))
-
 
 (defun ps-face-attributes (face)
   "Return face attribute vector.
@@ -4145,30 +5054,70 @@ If FACE is not in `ps-print-face-extension-alist' or in
 return the attribute vector.
 
 If FACE is not a valid face name, it is used default face."
-  (cdr (or (assq face ps-print-face-extension-alist)
-          (assq face ps-print-face-alist)
-          (let* ((the-face (if (facep face) face 'default))
-                 (new-face (ps-screen-to-bit-face the-face)))
-            (or (and (eq the-face 'default)
-                     (assq the-face ps-print-face-alist))
-                (setq ps-print-face-alist (cons new-face ps-print-face-alist)))
-            new-face))))
+  (cond
+   ((symbolp face)
+    (cdr (or (assq face ps-print-face-extension-alist)
+            (assq face ps-print-face-alist)
+            (let* ((the-face (if (facep face) face 'default))
+                   (new-face (ps-screen-to-bit-face the-face)))
+              (or (and (eq the-face 'default)
+                       (assq the-face ps-print-face-alist))
+                  (setq ps-print-face-alist
+                        (cons new-face ps-print-face-alist)))
+              new-face))))
+   ((eq (car face) 'foreground-color)
+    (vector 0 (cdr face) nil))
+   ((eq (car face) 'background-color)
+    (vector 0 nil (cdr face)))
+   (t
+    (vector 0 nil nil))))
+
+
+(defun ps-face-background (face background)
+  (and (or (eq ps-use-face-background t)
+          (cond ((symbolp face)
+                 (memq face ps-use-face-background))
+                ((listp face)
+                 (or (memq (car face) '(foreground-color background-color))
+                     (let (ok)
+                       (while face
+                         (if (or (memq (car face) ps-use-face-background)
+                                 (memq (car face)
+                                       '(foreground-color background-color)))
+                             (setq face nil
+                                   ok   t)
+                           (setq face (cdr face))))
+                       ok)))
+                (t
+                 nil)
+                ))
+       background))
 
 
 (defun ps-face-attribute-list (face-or-list)
-  (if (listp face-or-list)
-      ;; list of faces
-      (let ((effects 0)
-           foreground background face-attr)
-       (while face-or-list
-         (setq face-attr (ps-face-attributes (car face-or-list))
-               effects (logior effects (aref face-attr 0)))
-         (or foreground (setq foreground (aref face-attr 1)))
-         (or background (setq background (aref face-attr 2)))
-         (setq face-or-list (cdr face-or-list)))
-       (vector effects foreground background))
-    ;; simple face
-    (ps-face-attributes face-or-list)))
+  (cond
+   ;; simple face
+   ((not (listp face-or-list))
+    (ps-face-attributes face-or-list))
+   ;; only foreground color, not a `real' face
+   ((eq (car face-or-list) 'foreground-color)
+    (vector 0 (cdr face-or-list) nil))
+   ;; only background color, not a `real' face
+   ((eq (car face-or-list) 'background-color)
+    (vector 0 nil (cdr face-or-list)))
+   ;; list of faces
+   (t
+    (let ((effects 0)
+         foreground background face-attr face)
+      (while face-or-list
+       (setq face         (car face-or-list)
+             face-or-list (cdr face-or-list)
+             face-attr    (ps-face-attributes face)
+             effects      (logior effects (aref face-attr 0)))
+       (or foreground (setq foreground (aref face-attr 1)))
+       (or background
+           (setq background (ps-face-background face (aref face-attr 2)))))
+      (vector effects foreground background)))))
 
 
 (defconst ps-font-type (vector nil 'bold 'italic 'bold-italic))
@@ -4183,14 +5132,12 @@ If FACE is not a valid face name, it is used default face."
     (let* ((face-bit   (ps-face-attribute-list face))
           (effect     (aref face-bit 0))
           (foreground (aref face-bit 1))
-          (background (aref face-bit 2))
+          (background (ps-face-background face (aref face-bit 2)))
           (fg-color (if (and ps-color-p foreground)
-                        (mapcar 'ps-color-value
-                                (ps-color-values foreground))
+                        (ps-color-scale foreground)
                       ps-default-color))
           (bg-color (and ps-color-p background
-                         (mapcar 'ps-color-value
-                                 (ps-color-values background)))))
+                         (ps-color-scale background))))
       (ps-plot-region
        from to
        (ps-font-number 'ps-font-for-text
@@ -4200,47 +5147,6 @@ If FACE is not a valid face name, it is used default face."
   (goto-char to))
 
 
-(defun ps-xemacs-face-kind-p (face kind kind-regex kind-list)
-  (let* ((frame-font (or (face-font-instance face)
-                        (face-font-instance 'default)))
-        (kind-cons (and frame-font
-                        (assq kind
-                              (font-instance-properties frame-font))))
-        (kind-spec (cdr-safe kind-cons))
-        (case-fold-search t))
-    (or (and kind-spec (string-match kind-regex kind-spec))
-       ;; Kludge-compatible:
-       (memq face kind-list))))
-
-
-(cond ((eq ps-print-emacs-type 'emacs)  ; emacs
-
-       (defun ps-face-bold-p (face)
-        (or (face-bold-p face)
-            (memq face ps-bold-faces)))
-
-       (defun ps-face-italic-p (face)
-        (or (face-italic-p face)
-            (memq face ps-italic-faces)))
-       )
-                                       ; xemacs
-                                       ; lucid
-      (t                               ; epoch
-       (defun ps-face-bold-p (face)
-        (ps-xemacs-face-kind-p face 'WEIGHT_NAME "bold\\|demibold"
-                               ps-bold-faces))
-
-       (defun ps-face-italic-p (face)
-        (or (ps-xemacs-face-kind-p face 'ANGLE_NAME "i\\|o" ps-italic-faces)
-            (ps-xemacs-face-kind-p face 'SLANT "i\\|o" ps-italic-faces)))
-       ))
-
-
-(defun ps-face-underlined-p (face)
-  (or (face-underline-p face)
-      (memq face ps-underlined-faces)))
-
-
 ;; Ensure that face-list is fbound.
 (or (fboundp 'face-list) (defalias 'face-list 'list-faces))
 
@@ -4293,45 +5199,30 @@ If FACE is not a valid face name, it is used default face."
        (vector (logior (if (ps-face-bold-p face) 1 0) ; bold
                        (if (ps-face-italic-p face) 2 0) ; italic
                        (if (ps-face-underlined-p face) 4 0)) ; underline
-               (face-foreground face)
-               (face-background face))))
-
-
-(cond ((not (eq ps-print-emacs-type 'emacs))
-                                       ; xemacs
-                                       ; lucid
-                                       ; epoch
-       (defun ps-mapper (extent list)
-        (nconc list (list (list (extent-start-position extent) 'push extent)
-                          (list (extent-end-position extent) 'pull extent)))
-        nil)
-
-       (defun ps-extent-sorter (a b)
-        (< (extent-priority a) (extent-priority b)))
-       ))
+               (ps-face-foreground-name face)
+               (ps-face-background-name face))))
 
 
+;; to avoid compilation gripes
 (defun ps-print-ensure-fontified (start end)
-  (and (boundp 'lazy-lock-mode) (symbol-value 'lazy-lock-mode)
-       (lazy-lock-fontify-region start end)))
+  (cond
+   ((and (boundp 'jit-lock-mode) (symbol-value 'jit-lock-mode))
+    (defalias 'ps-jitify 'jit-lock-fontify-now) ; avoid compilation gripes
+    (ps-jitify start end))
+   ((and (boundp 'lazy-lock-mode) (symbol-value 'lazy-lock-mode))
+    (defalias 'ps-lazify 'lazy-lock-fontify-region) ; avoid compilation gripes
+    (ps-lazify start end))))
+
 
 (defun ps-generate-postscript-with-faces (from to)
   ;; Some initialization...
   (setq ps-current-effect 0)
 
   ;; Build the reference lists of faces if necessary.
-  (if (or ps-always-build-face-reference
-         ps-build-face-reference)
-      (progn
-       (message "Collecting face information...")
-       (ps-build-reference-face-lists)))
-  ;; Set the color scale.  We do it here instead of in the defvar so
-  ;; that ps-print can be dumped into emacs.  This expression can't be
-  ;; evaluated at dump-time because X isn't initialized.
-  (setq ps-color-p           (and ps-print-color-p (ps-color-device))
-       ps-print-color-scale (if ps-color-p
-                                (float (car (ps-color-values "white")))
-                              1.0))
+  (when (or ps-always-build-face-reference
+           ps-build-face-reference)
+    (message "Collecting face information...")
+    (ps-build-reference-face-lists))
   ;; Generate some PostScript.
   (save-restriction
     (narrow-to-region from to)
@@ -4339,12 +5230,11 @@ If FACE is not a valid face name, it is used default face."
     (let ((face 'default)
          (position to))
       (cond
-       ((or (eq ps-print-emacs-type 'lucid)
-           (eq ps-print-emacs-type 'xemacs))
+       ((memq ps-print-emacs-type '(xemacs lucid))
        ;; Build the list of extents...
        (let ((a (cons 'dummy nil))
              record type extent extent-list)
-         (map-extents 'ps-mapper nil from to a)
+         (ps-x-map-extents 'ps-mapper nil from to a)
          (setq a (sort (cdr a) 'car-less-than-car)
                extent-list nil)
 
@@ -4364,15 +5254,14 @@ If FACE is not a valid face name, it is used default face."
            ;; XEmacs 19.12: for some reason, we're getting into a
            ;; situation in which some of the records have
            ;; positions less than 'from'.  Since we've narrowed
-           ;; the buffer, this'll generate errors.  This is a
-           ;; hack, but don't call ps-plot-with-face unless from >
-           ;; point-min.
-           (and (>= from (point-min)) (<= position (point-max))
-                (ps-plot-with-face from position face))
+           ;; the buffer, this'll generate errors.  This is a hack,
+           ;; but don't call ps-plot-with-face unless from > point-min.
+           (and (>= from (point-min))
+                (ps-plot-with-face from (min position (point-max)) face))
 
            (cond
             ((eq type 'push)
-             (and (extent-face extent)
+             (and (ps-x-extent-face extent)
                   (setq extent-list (sort (cons extent extent-list)
                                           'ps-extent-sorter))))
 
@@ -4381,7 +5270,7 @@ If FACE is not a valid face name, it is used default face."
                                      'ps-extent-sorter))))
 
            (setq face (if extent-list
-                          (extent-face (car extent-list))
+                          (ps-x-extent-face (car extent-list))
                         'default)
                  from position
                  a (cdr a)))))
@@ -4473,21 +5362,21 @@ If FACE is not a valid face name, it is used default face."
                (goto-char (point-min))
                (or (looking-at (regexp-quote ps-adobe-tag))
                    (setq needs-begin-file t))
-               (save-excursion
-                 (set-buffer ps-source-buffer)
-                 (ps-begin-job)
-                 (when needs-begin-file
-                   (ps-begin-file)
-                   (ps-mule-initialize))
-                 (ps-mule-begin-job from to)
-                 (ps-begin-page))
+
                (set-buffer ps-source-buffer)
+               (save-excursion
+                 (let ((ps-print-page-p t)
+                       ps-even-or-odd-pages)
+                   (ps-begin-job)
+                   (when needs-begin-file
+                     (ps-begin-file)
+                     (ps-mule-initialize))
+                   (ps-mule-begin-job from to)
+                   (ps-selected-pages)))
+               (ps-begin-page)
                (funcall genfunc from to)
                (ps-end-page)
-
-               (ps-end-file)
-               (ps-flush-output)
-               (ps-end-job)
+               (ps-end-job needs-begin-file)
 
                ;; Setting this variable tells the unwind form that the
                ;; the PostScript was generated without error.
@@ -4505,18 +5394,43 @@ If FACE is not a valid face name, it is used default face."
        (and ps-razzle-dazzle (message "Formatting...done"))))))
 
 
-(defun ps-end-job ()
-  (let ((total-lines (cdr ps-printing-region))
-       (total-pages (if ps-print-only-one-header
-                        (ps-page-number)
-                      ps-page-count))
-       case-fold-search)
-    (set-buffer ps-spool-buffer)
-    ;; Back to the PS output buffer to set the page count
-    (goto-char (point-min))
-    (and (re-search-forward "^/Lines 0 def\n/PageCount 0 def$" nil t)
-        (replace-match (format "/Lines %d def\n/PageCount %d def"
-                               total-lines total-pages) t))))
+(defun ps-end-job (needs-begin-file)
+  (let ((ps-print-page-p t))
+    (ps-flush-output)
+    (save-excursion
+      (let ((pages-per-sheet (mod ps-page-n-up ps-n-up-printing))
+           (total-lines (cdr ps-printing-region))
+           (total-pages (ps-page-number))
+           case-fold-search)
+       (set-buffer ps-spool-buffer)
+       ;; Back to the PS output buffer to set the last page n-up printing
+       (goto-char (point-max))
+       (and (> pages-per-sheet 0)
+            (re-search-backward "^[0-9]+ BeginSheet$" nil t)
+            (replace-match (format "%d BeginSheet" pages-per-sheet) t))
+       ;; Back to the PS output buffer to set the page count
+       (goto-char (point-min))
+       (and (re-search-forward "^/Lines 0 def\n/PageCount 0 def$" nil t)
+            (replace-match (format "/Lines %d def\n/PageCount %d def"
+                                   total-lines total-pages) t))))
+    ;; Set dummy page
+    (and ps-spool-duplex (= (mod ps-page-order 2) 1)
+        (let ((ps-n-up-printing 0))
+          (ps-header-sheet)
+          (ps-output "/PrintHeader false def\n/ColumnIndex 0 def\n"
+                     "/PrintLineNumber false def\nBeginPage\n")
+          (ps-end-page)))
+    ;; Set end of PostScript file
+    (ps-output "EndSheet\n\n%%Trailer\n%%Pages: "
+              (number-to-string
+               (if (and needs-begin-file
+                        ps-banner-page-when-duplexing)
+                   (1+ ps-page-order)
+                 ps-page-order))
+              "\n\nEndDoc\n\n%%EOF\n")
+    (ps-flush-output))
+  ;; disable selected pages
+  (setq ps-selected-pages nil))
 
 
 ;; Permit dynamic evaluation at print time of `ps-lpr-switches'.
@@ -4541,9 +5455,13 @@ If FACE is not a valid face name, it is used default face."
                                    (and (boundp 'printer-name)
                                         printer-name)))
               (ps-lpr-switches
-               (append (and (stringp ps-printer-name)
-                            (list (concat "-P" ps-printer-name)))
-                       ps-lpr-switches)))
+               (append ps-lpr-switches
+                       (and (stringp ps-printer-name)
+                            (string< "" ps-printer-name)
+                            (list (concat
+                                   (and (stringp ps-printer-name-option)
+                                        ps-printer-name-option)
+                                   ps-printer-name))))))
          (apply (or ps-print-region-function 'call-process-region)
                 (point-min) (point-max) ps-lpr-command nil
                 (and (fboundp 'start-process) 0)
@@ -4647,7 +5565,7 @@ If FACE is not a valid face name, it is used default face."
   (save-excursion
     (goto-char (point-min))
     (if (re-search-forward "^Subject:[ \t]+\\(.*\\)$" nil t)
-       (buffer-substring-no-properties (match-beginning 1) (match-end 1))
+       (buffer-substring (match-beginning 1) (match-end 1))
       "Subject ???")))
 
 ;; Look in an article or mail message for the From: line.  Sorta-kinda
@@ -4657,8 +5575,7 @@ If FACE is not a valid face name, it is used default face."
   (save-excursion
     (goto-char (point-min))
     (if (re-search-forward "^From:[ \t]+\\(.*\\)$" nil t)
-       (let ((fromstring (buffer-substring-no-properties (match-beginning 1)
-                                                         (match-end 1))))
+       (let ((fromstring (buffer-substring (match-beginning 1) (match-end 1))))
          (cond
 
           ;; Try first to match addresses that look like
@@ -4667,9 +5584,10 @@ If FACE is not a valid face name, it is used default face."
            (substring fromstring (match-beginning 1) (match-end 1)))
 
           ;; Next try to match addresses that look like
-          ;; Jim Thompson <thompson@wg2.waii.com>
-          ((string-match "\\(.*\\)[ \t]+<.*>" fromstring)
-           (substring fromstring (match-beginning 1) (match-end 1)))
+          ;; Jim Thompson <thompson@wg2.waii.com> or
+          ;; "Jim Thompson" <thompson@wg2.waii.com>
+          ((string-match "\\(\"?\\)\\(.*\\)\\1[ \t]+<.*>" fromstring)
+           (substring fromstring (match-beginning 2) (match-end 2)))
 
           ;; Couldn't find a real name -- show the address instead.
           (t fromstring)))
@@ -4725,7 +5643,7 @@ If FACE is not a valid face name, it is used default face."
   (save-excursion
     (goto-char (point-min))
     (if (re-search-forward "File:[ \t]+\\([^, \t\n]*\\)" nil t)
-       (buffer-substring-no-properties (match-beginning 1) (match-end 1))
+       (buffer-substring (match-beginning 1) (match-end 1))
       "File ???")))
 
 ;; Look in an article or mail message for the Subject: line.  To be
@@ -4734,7 +5652,7 @@ If FACE is not a valid face name, it is used default face."
   (save-excursion
     (goto-char (point-min))
     (if (re-search-forward "Node:[ \t]+\\([^,\t\n]*\\)" nil t)
-       (buffer-substring-no-properties (match-beginning 1) (match-end 1))
+       (buffer-substring (match-beginning 1) (match-end 1))
       "Node ???")))
 
 (defun ps-info-mode-hook ()