;; Copyright (C) 2000, 2001, 2002, 2003, 2004
;; Free Software Foundation, Inc.
-;; Author: Vinicius Jose Latorre <vinicius@cpqd.com.br>
-;; Maintainer: Vinicius Jose Latorre <vinicius@cpqd.com.br>
-;; Time-stamp: <2004/04/05 23:41:49 vinicius>
+;; Author: Vinicius Jose Latorre <viniciusjl@ig.com.br>
+;; Maintainer: Vinicius Jose Latorre <viniciusjl@ig.com.br>
+;; Time-stamp: <2004/09/21 22:51:58 vinicius>
;; Keywords: wp, print, PostScript
-;; Version: 6.7.4
+;; Version: 6.8
;; X-URL: http://www.cpqd.com.br/~vinicius/emacs/
-(defconst pr-version "6.7.4"
- "printing.el, v 6.7.4 <2004/03/31 vinicius>
+(defconst pr-version "6.8"
+ "printing.el, v 6.8 <2004/09/21 vinicius>
Please send all bug fixes and enhancements to
- Vinicius Jose Latorre <vinicius@cpqd.com.br>
+ Vinicius Jose Latorre <viniciusjl@ig.com.br>
")
;; This file is part of GNU Emacs.
;; Introduction
;; ------------
;;
-;; This package provides some printing utilities that includes
-;; previewing/printing a PostScript file, printing a text file and
-;; previewing/printing some major modes (like mh-folder-mode,
-;; rmail-summary-mode, gnus-summary-mode, etc).
+;; With `printing' you can preview or print a PostScript file. You can also
+;; print a text file using PostScript, and preview or print buffers that use
+;; certain special modes like mh-folder-mode, rmail-summary-mode,
+;; gnus-summary-mode, etc. This package also includes a PostScript/text
+;; printer database.
+;;
+;; There are two user interfaces:
+;;
+;; * Menu interface:
+;; The `printing' menu replaces the usual print options in the menu bar.
+;; This is the default user interface.
+;;
+;; * Buffer interface:
+;; You can use a buffer interface instead of menus. It looks like a
+;; customization buffer. Basically, it has the same options found in the
+;; menu and some extra options, all this on a buffer.
+;;
+;; `printing' is prepared to run on GNU, Unix and NT systems.
+;; On GNU or Unix system, `printing' depends on gs and gv utilities.
+;; On NT system, `printing' depends on gstools (gswin32.exe and gsview32.exe).
+;; To obtain ghostscript, ghostview and GSview see the URL
+;; `http://www.gnu.org/software/ghostscript/ghostscript.html'.
+;;
+;; `printing' depends on ps-print package to generate PostScript files, to
+;; spool and to despool PostScript buffer. So, `printing' provides an
+;; interface to ps-print package and it also provides some extra stuff.
+;;
+;; To download the latest ps-print package see
+;; `http://www.cpqd.com.br/~vinicius/emacs/ps-print.tar.gz'.
+;; Please, see README file for ps-print installation instructions.
;;
;; `printing' was inspired on:
;;
;; ps-print-interface.el Volker Franz <volker.franz@tuebingen.mpg.de>
;; Graphical front end for ps-print and previewing
;;
-;; `printing' is prepared to run on GNU, Unix and NT systems.
-;; On GNU or Unix system, `printing' depends on gs and gv utilities.
-;; On NT system, `printing' depends on gstools (gswin32.exe and gsview32.exe).
-;; To obtain ghostscript, ghostview and GSview see the URL
-;; `http://www.gnu.org/software/ghostscript/ghostscript.html'.
;;
-;; `printing' also depends on ps-print and lpr GNU Emacs packages.
-;; To download the latest ps-print package see
-;; `http://www.cpqd.com.br/~vinicius/emacs/ps-print.tar.gz'.
-;; Please, see README file for ps-print installation instructions.
+;; Log Messages
+;; ------------
+;;
+;; The buffer *Printing Command Output* is where the `printing' log messages
+;; are inserted. All program called by `printing' has a log entry in the
+;; buffer *Printing Command Output*. A log entry has the following form:
+;;
+;; PROGRAM (ARG...)
+;; MESSAGE
+;; Exit status: CODE
+;;
+;; Where
+;; PROGRAM is the program activated by `printing',
+;; ARG is an argument passed to PROGRAM (it can have more than one argument),
+;; MESSAGE is an error message returned by PROGRAM (it can have no message, if
+;; PROGRAM is successful),
+;; and CODE is a numeric exit status or a signal description string.
+;;
+;; For example, after previewing a PostScript file, *Printing Command Output*
+;; will have the following entry:
+;;
+;; /usr/X11R6/bin/gv ("/home/user/example/file.ps")
+;; Exit status: 0
+;;
+;; In the example above, the previewing was successful. If during previewing,
+;; you quit gv execution (by typing C-g during Emacs session), the log entry
+;; would be:
+;;
+;; /usr/X11R6/bin/gv ("/home/user/example/file.ps")
+;; Exit status: Quit
+;;
+;; So, if something goes wrong, a good place to take a look is the buffer
+;; *Printing Command Output*. Don't forget to see also the buffer *Messages*,
+;; it can help.
;;
;;
;; Novices (First Users)
;; Tips
;; ----
;;
-;; 1. If your have a local printer, that is, a printer which is connected
+;; 1. If you have a local printer, that is, a printer which is connected
;; directly to your computer, don't forget to connect the printer to your
;; computer before printing.
;;
;; another buffer and, then, print the file or the new static buffer.
;; An example of dynamic buffer is the *Messages* buffer.
;;
-;; 4. When running Emacs on Windows with cygwin, check if the
-;; `pr-shell-file-name' variable is set to the proper shell. This shell
-;; will execute the commands to preview/print the buffer, file or directory.
-;; Also check the setting of `pr-path-style' variable.
-;; Probably, you should use:
+;; 4. When running Emacs on Windows (with or without cygwin), check if your
+;; printer is a text printer or not by typing in a DOS window:
+;;
+;; print /D:\\host\printer somefile.txt
+;;
+;; Where, `host' is the machine where the printer is directly connected,
+;; `printer' is the printer name and `somefile.txt' is a text file.
+;;
+;; If the printer `\\host\printer' doesn't print the content of
+;; `somefile.txt' or, instead, it returns the following message:
+;;
+;; PostScript Error Handler
+;; Offending Command = CCC
+;; Stack =
+;;
+;; Where `CCC' is whatever is at the beginning of the text to be printed.
+;;
+;; Therefore, the printer `\\host\printer' is not a text printer, but a
+;; PostScript printer. So, please, don't include this printer in
+;; `pr-txt-printer-alist' (which see).
+;;
+;; 5. Use gsprint instead of ghostscript to print monochrome PostScript files
+;; in Windows. The gsprint utility is faster than ghostscript to print
+;; monochrome PostScript.
+;;
+;; The efficiency is similar to print non-monochrome PostScript file.
;;
-;; (setq pr-shell-file-name "bash")
-;; (setq pr-path-style 'unix)
+;; Also the gsprint utility comes together with gsview distribution.
;;
-;; And use / instead of \ when specifying a directory.
+;; For more information about gsprint see
+;; `http://www.cs.wisc.edu/~ghost/gsview/gsprint.htm'.
;;
;;
;; Using `printing'
;; `pr-buffer-verbose' Non-nil means to be verbose when editing a
;; field in interface buffer.
;;
-;; `pr-shell-file-name' Specify file name to load inferior shells
-;; from.
-;;
;; To set the above options you may:
;;
;; a) insert the code in your ~/.emacs, like:
;;
;; gswin32, gsview32
;; `http://www.gnu.org/software/ghostscript/ghostscript.html'
+;; gsprint `http://www.cs.wisc.edu/~ghost/gsview/gsprint.htm'.
;; enscript `http://people.ssh.fi/mtr/genscript/'
;; psnup `http://www.dcs.ed.ac.uk/home/ajcd/psutils/index.html'
;; redmon `http://www.cs.wisc.edu/~ghost/redmon/'
;; Acknowledgments
;; ---------------
;;
-;; Thanks to Drew Adams <drew.adams@oracle.com> for directory processing and
-;; `pr-path-alist' suggestions.
+;; Thanks to Lennart Borgman <lennart.borgman.073@student.lu.se> for gsprint
+;; suggestion (see tip 5 in section Tips).
+;;
+;; Thanks to Drew Adams <drew.adams@oracle.com> for suggestions:
+;; - directory processing.
+;; - `pr-path-alist' variable.
+;; - doc fix.
+;; - a lot of tests on Windows.
;;
;; Thanks to Fred Labrosse <f.labrosse@maths.bath.ac.uk> for XEmacs tests.
;;
(require 'ps-print)
-(and (string< ps-print-version "6.5.7")
- (error "`printing' requires `ps-print' package version 6.5.7 or later."))
+(and (string< ps-print-version "6.6.4")
+ (error "`printing' requires `ps-print' package version 6.6.4 or later"))
(eval-and-compile
;; Internal Functions (I)
-(defun pr-dosify-path (path)
+(defun pr-dosify-file-name (path)
"Replace unix-style directory separator character with dos/windows one."
(interactive "sPath: ")
(if (eq pr-path-style 'windows)
path))
-(defun pr-unixify-path (path)
+(defun pr-unixify-file-name (path)
"Replace dos/windows-style directory separator character with unix one."
(interactive "sPath: ")
(if (eq pr-path-style 'windows)
path))
+(defun pr-standard-file-name (path)
+ "Ensure the proper directory separator depending on the OS.
+That is, if Emacs is running on DOS/Windows, ensure dos/windows-style directory
+separator; otherwise, ensure unix-style directory separator."
+ (if (or pr-cygwin-system ps-windows-system)
+ (subst-char-in-string ?/ ?\\ path)
+ (subst-char-in-string ?\\ ?/ path)))
+
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; User Interface (II)
(defcustom pr-temp-dir
- (pr-dosify-path
+ (pr-dosify-file-name
(if (boundp 'temporary-file-directory)
(symbol-value 'temporary-file-directory)
;; hacked from `temporary-file-directory' variable in files.el
:group 'printing)
-(defcustom pr-shell-file-name
- (if (and (not pr-cygwin-system)
- ps-windows-system)
- "cmdproxy.exe"
- shell-file-name)
- "*Specify file name to load inferior shells from."
- :type 'string
- :group 'printing)
-
-
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Internal Variables
(and pr-auto-region transient-mark-mode mark-active)))
((eq ps-print-emacs-type 'xemacs) ; XEmacs
+ (defvar zmacs-region-stays nil) ; to avoid compilation gripes
(defsubst pr-region-active-p ()
(and pr-auto-region (not zmacs-region-stays) (ps-mark-active-p)))))
"Preview PostScript file FILENAME."
(interactive (list (pr-ps-infile-preprint "Preview ")))
(and (stringp filename) (file-exists-p filename)
- (let ((shell-file-name pr-shell-file-name))
- (start-process-shell-command "PREVIEW" "*Messages*"
- (pr-command pr-gv-command) filename))))
+ (pr-call-process pr-gv-command filename)))
;;;###autoload
(interactive (list (pr-ps-infile-preprint "Print preview ")))
(and (stringp filename) (file-exists-p filename)
(let* ((file (pr-expand-file-name filename))
- (tempfile (pr-dosify-path (make-temp-name file))))
+ (tempfile (pr-dosify-file-name (make-temp-name file))))
;; gs use
- (pr-shell-command
- (concat (pr-command pr-gs-command)
- " -sDEVICE=" pr-gs-device
- " -r" (int-to-string pr-gs-resolution)
- " " (pr-switches-string pr-gs-switches "pr-gs-switches")
- " -sOutputFile=" tempfile " " file " -c quit"))
+ (pr-call-process pr-gs-command
+ (format "-sDEVICE=%s" pr-gs-device)
+ (format "-r%d" pr-gs-resolution)
+ (pr-switches-string pr-gs-switches "pr-gs-switches")
+ (format "-sOutputFile=\"%s\"" tempfile)
+ file
+ "-c quit")
;; printing
(pr-ps-file-print tempfile)
;; deleting
(erase-buffer)
(insert-file-contents-literally file))
(pr-despool-print))
- (pr-shell-command
- (concat (pr-command pr-ps-command) " "
- (pr-switches-string pr-ps-switches "pr-gs-switches") " "
- (if (string-match "cp" pr-ps-command)
- ;; for "cp" (cmd in out)
- (concat "\"" file "\" "
- pr-ps-printer-switch pr-ps-printer)
- ;; else, for others (cmd out in)
- (concat pr-ps-printer-switch pr-ps-printer
- " \"" file "\""))))))))
+ (apply 'pr-call-process
+ pr-ps-command
+ (pr-switches-string pr-ps-switches "pr-gs-switches")
+ (if (string-match "cp" pr-ps-command)
+ ;; for "cp" (cmd in out)
+ (list file
+ (concat pr-ps-printer-switch pr-ps-printer))
+ ;; else, for others (cmd out in)
+ (list (concat pr-ps-printer-switch pr-ps-printer)
+ file)))))))
;;;###autoload
(pr-ps-buffer-ps-print
(if (integerp n-up)
(min (max n-up 1) 100)
- (error "n-up must be an integer greater than zero."))
+ (error "n-up must be an integer greater than zero"))
filename)))
#'ps-print-quote
(list
(concat "\n;;; printing.el version " pr-version "\n")
- '(19 . pr-shell-file-name)
- '(19 . pr-path-style)
- '(19 . pr-path-alist)
+ ";; internal vars"
+ (ps-comment-string "pr-txt-command " pr-txt-command)
+ (ps-comment-string "pr-txt-switches "
+ (pr-switches-string pr-txt-switches "pr-txt-switches"))
+ (ps-comment-string "pr-txt-printer " pr-txt-printer)
+ (ps-comment-string "pr-ps-command " pr-ps-command)
+ (ps-comment-string "pr-ps-switches "
+ (pr-switches-string pr-ps-switches "pr-ps-switches"))
+ (ps-comment-string "pr-ps-printer-switch" pr-ps-printer-switch)
+ (ps-comment-string "pr-ps-printer " pr-ps-printer)
+ (ps-comment-string "pr-cygwin-system " pr-cygwin-system)
+ (ps-comment-string "ps-windows-system " ps-windows-system)
+ (ps-comment-string "ps-lp-system " ps-lp-system)
+ nil
+ '(14 . pr-path-style)
+ '(14 . pr-path-alist)
nil
'(21 . pr-txt-name)
'(21 . pr-txt-printer-alist)
(cond
((eq ps-print-emacs-type 'xemacs)
;; XEmacs
+ (defvar current-mouse-event nil) ; to avoid compilation gripes
(defun pr-menu-position (entry index horizontal)
(pr-x-make-event
'button-release
((eq ps-print-emacs-type 'xemacs)
;; XEmacs
+ (defvar current-menubar nil) ; to avoid compilation gripes
(defun pr-menu-lookup (path)
(car (pr-x-find-menu-item current-menubar (cons "Printing" path))))
(let ((item (cdr (assq value pr-ps-utility-alist))))
(or item
(error
- "Invalid PostScript utility name `%s' for variable `pr-ps-utility'."
+ "Invalid PostScript utility name `%s' for variable `pr-ps-utility'"
value))
(setq pr-ps-utility value)
(pr-eval-alist (nthcdr 9 item)))
(let ((ps (cdr (assq value pr-ps-printer-alist))))
(or ps
(error
- "Invalid PostScript printer name `%s' for variable `pr-ps-name'."
+ "Invalid PostScript printer name `%s' for variable `pr-ps-name'"
value))
(setq pr-ps-name value
- pr-ps-command (pr-dosify-path (nth 0 ps))
+ pr-ps-command (pr-dosify-file-name (nth 0 ps))
pr-ps-switches (nth 1 ps)
pr-ps-printer-switch (nth 2 ps)
- pr-ps-printer (pr-dosify-path (nth 3 ps)))
+ pr-ps-printer (nth 3 ps))
(or (stringp pr-ps-command)
(setq pr-ps-command
(cond (ps-windows-system "print")
(defun pr-txt-set-printer (value)
(let ((txt (cdr (assq value pr-txt-printer-alist))))
(or txt
- (error "Invalid text printer name `%s' for variable `pr-txt-name'."
+ (error "Invalid text printer name `%s' for variable `pr-txt-name'"
value))
(setq pr-txt-name value
- pr-txt-command (pr-dosify-path (nth 0 txt))
+ pr-txt-command (pr-dosify-file-name (nth 0 txt))
pr-txt-switches (nth 1 txt)
- pr-txt-printer (pr-dosify-path (nth 2 txt))))
+ pr-txt-printer (nth 2 txt)))
(or (stringp pr-txt-command)
(setq pr-txt-command
(cond (ps-windows-system "print")
(setq global nil)))
(and inherits
(if (memq inherits old)
- (error "Circular inheritance for `%S'." inherits)
+ (error "Circular inheritance for `%S'" inherits)
(setq local-list
(pr-eval-setting-alist inherits global
(cons inherits old)))))
(defun pr-expand-file-name (filename)
- (pr-dosify-path (expand-file-name filename)))
+ (pr-dosify-file-name (expand-file-name filename)))
(defun pr-ps-outfile-preprint (&optional mess)
;; input file
(or (symbol-value infile-sym)
(error "%s: input PostScript file name is missing" prompt))
- (set infile-sym (pr-dosify-path (symbol-value infile-sym)))
+ (set infile-sym (pr-dosify-file-name (symbol-value infile-sym)))
;; output file
(and (eq (symbol-value outfile-sym) t)
(set outfile-sym (and (not (interactive-p))
current-prefix-arg
(pr-ps-outfile-preprint prompt))))
(and (symbol-value outfile-sym)
- (set outfile-sym (pr-dosify-path (symbol-value outfile-sym))))
+ (set outfile-sym (pr-dosify-file-name (symbol-value outfile-sym))))
(pr-ps-file (symbol-value outfile-sym)))
(let (item)
(and (stringp infile) (file-exists-p infile)
(setq item (cdr (assq pr-ps-utility pr-ps-utility-alist)))
- (pr-shell-command
- (concat (pr-command (nth 0 item)) " "
- (pr-switches-string (nth 1 item)
- "pr-ps-utility-alist entry")
- " "
- (pr-switches-string (nth 8 item)
- "pr-ps-utility-alist entry")
- " "
- (and (nth 2 item)
- (format (nth 2 item) ps-paper-type))
- " " (format (nth 3 item) n-up) " "
- (and pr-file-landscape (nth 4 item)) " "
- (and pr-file-duplex (nth 5 item)) " "
- (and pr-file-tumble (nth 6 item))
- " \"" (pr-expand-file-name infile) "\" "
- (nth 7 item)
- " \"" (pr-expand-file-name outfile) "\"")))))
-
-
-(defun pr-shell-command (command)
- (let ((shell-file-name pr-shell-file-name))
- (shell-command command)))
+ (pr-call-process (nth 0 item)
+ (pr-switches-string (nth 1 item)
+ "pr-ps-utility-alist entry")
+ (pr-switches-string (nth 8 item)
+ "pr-ps-utility-alist entry")
+ (and (nth 2 item)
+ (format (nth 2 item) ps-paper-type))
+ (format (nth 3 item) n-up)
+ (and pr-file-landscape (nth 4 item))
+ (and pr-file-duplex (nth 5 item))
+ (and pr-file-tumble (nth 6 item))
+ (pr-expand-file-name infile)
+ (nth 7 item)
+ (pr-expand-file-name outfile)))))
+
+
+(defun pr-remove-nil-from-list (lst)
+ (while (and lst (null (car lst)))
+ (setq lst (cdr lst)))
+ (let ((b lst)
+ (l (cdr lst)))
+ (while l
+ (if (car l)
+ (setq b l
+ l (cdr l))
+ (setq l (cdr l))
+ (setcdr b l))))
+ lst)
+
+
+(defun pr-call-process (command &rest args)
+ (let ((buffer (get-buffer-create "*Printing Command Output*"))
+ (cmd (pr-command command))
+ status)
+ (setq args (pr-remove-nil-from-list args))
+ (save-excursion
+ (set-buffer buffer)
+ (goto-char (point-max))
+ (insert (format "%s %S\n" cmd args)))
+ (setq status
+ (condition-case data
+ (apply 'call-process cmd nil buffer nil args)
+ ((quit error)
+ (error-message-string data))))
+ (save-excursion
+ (set-buffer buffer)
+ (goto-char (point-max))
+ (insert (format "Exit status: %s\n" status)))))
(defun pr-txt-print (from to)
- (let ((lpr-command (pr-command pr-txt-command))
+ (let ((lpr-command (pr-standard-file-name (pr-command pr-txt-command)))
(lpr-switches (pr-switches pr-txt-switches "pr-txt-switches"))
(printer-name pr-txt-printer))
(lpr-region from to)))
(defun pr-switches (switches mess)
(or (listp switches)
- (error "%S should have a list of strings." mess))
+ (error "%S should have a list of strings" mess))
(ps-flatten-list ; dynamic evaluation
(mapcar 'ps-eval-switch switches)))
(defun pr-ps-file (&optional filename)
- (pr-dosify-path (or filename
- (convert-standard-filename
- (expand-file-name pr-ps-temp-file pr-temp-dir)))))
+ (pr-dosify-file-name (or filename
+ (convert-standard-filename
+ (expand-file-name pr-ps-temp-file pr-temp-dir)))))
(defun pr-interactive-n-up (mess)
current-prefix-arg
(ps-print-preprint current-prefix-arg))))
(and (symbol-value filename-sym)
- (set filename-sym (pr-dosify-path (symbol-value filename-sym)))))
+ (set filename-sym (pr-dosify-file-name (symbol-value filename-sym)))))
(defun pr-set-n-up-and-filename (n-up-sym filename-sym mess)
COMMAND.exe, COMMAND.bat and COMMAND.com in this order."
(if (string= command "")
command
- (pr-dosify-path
+ (pr-dosify-file-name
(or (pr-find-command command)
(pr-path-command (cond (pr-cygwin-system 'cygwin)
(ps-windows-system 'windows)