comparison lisp/ps-print.el @ 10492:a0f38717d82d

*** empty log message ***
author Richard M. Stallman <rms@gnu.org>
date Fri, 20 Jan 1995 06:09:03 +0000
parents 3759ad84023b
children ed52763e77d6
comparison
equal deleted inserted replaced
10491:dfc0d2c81c56 10492:a0f38717d82d
1 ;; Jim's Pretty-Good PostScript Generator for Emacs 19 (ps-print). 1 ;;; ps-print.el --- Jim's Pretty-Good PostScript Generator for Emacs 19.
2
2 ;; Copyright (C) 1993, 1994 Free Software Foundation, Inc. 3 ;; Copyright (C) 1993, 1994 Free Software Foundation, Inc.
3 4
4 ;; Author: James C. Thompson <thompson@wg2.waii.com> 5 ;; Author: Jim Thompson <thompson@wg2.waii.com>
5 ;; Keywords: faces, postscript, printing 6 ;; Version: 1.10
6 7 ;; Keywords: print, PostScript
7 ;; This file is part of GNU Emacs. 8
9 ;; This file is not yet part of GNU Emacs.
8 10
9 ;; GNU Emacs is free software; you can redistribute it and/or modify 11 ;; GNU Emacs is free software; you can redistribute it and/or modify
10 ;; it under the terms of the GNU General Public License as published by 12 ;; it under the terms of the GNU General Public License as published by
11 ;; the Free Software Foundation; either version 2, or (at your option) 13 ;; the Free Software Foundation; either version 2, or (at your option)
12 ;; any later version. 14 ;; any later version.
18 20
19 ;; You should have received a copy of the GNU General Public License 21 ;; You should have received a copy of the GNU General Public License
20 ;; along with GNU Emacs; see the file COPYING. If not, write to 22 ;; along with GNU Emacs; see the file COPYING. If not, write to
21 ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 23 ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
22 24
23 ;; Acknowledgements 25 ;; LCD Archive Entry:
24 ;; ---------------- 26 ;; ps-print|James C. Thompson|thompson@wg2.waii.com|
25 ;; Thanks to Avishai Yacobi, avishaiy@mcil.comm.mot.com, for writing 27 ;; Jim's Pretty-Good PostScript Generator for Emacs 19 (ps-print)|
26 ;; the Emacs 19 port. 28 ;; 26-Feb-1994|1.6|~/packages/ps-print.el|
27 ;; 29
28 ;; Thanks to Remi Houdaille and Michel Train, michel@metasoft.fdn.org, 30 ;;; Commentary:
29 ;; for adding underline support and title code. (Titling will appear
30 ;; in the next release.)
31 ;;
32 ;; Thanks to Heiko Muenkel, muenkel@tnt.uni-hannover.de, for showing
33 ;; me how to handle ISO-8859/1 characters.
34 ;;
35 ;; Code to handle ISO-8859/1 characters borrowed from the mp prologue
36 ;; file mp.pro.ps, used with permission of Rich Burridge of Sun
37 ;; Microsystems (Rich.Burridge@eng.sun.com).
38 31
39 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 32 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
40 ;; 33 ;;
41 ;; About ps-print: 34 ;; About ps-print
42 ;; -------------- 35 ;; --------------
43 ;; This package provides printing of Emacs buffers on PostScript 36 ;; This package provides printing of Emacs buffers on PostScript
44 ;; printers; the buffer's bold and italic text attributes are 37 ;; printers; the buffer's bold and italic text attributes are
45 ;; preserved in the printer output. Ps-print is intended for use with 38 ;; preserved in the printer output. Ps-print is intended for use with
46 ;; Emacs 19 (Lucid or FSF) and a fontifying package such as font-lock 39 ;; Emacs 19 (Lucid or FSF) and a fontifying package such as font-lock
47 ;; or hilit. 40 ;; or hilit.
48 ;; 41 ;;
49 ;; Installing ps-print: 42 ;; Installing ps-print
50 ;; ------------------- 43 ;; -------------------
51 ;; Place ps-print somewhere in your load-path and byte-compile it. 44 ;;
52 ;; Load ps-print with (require 'ps-print). 45 ;; 1. Place ps-print.el somewhere in your load-path and byte-compile
53 ;; 46 ;; it. You can ignore all byte-compiler warnings; they are the
54 ;; Using ps-print: 47 ;; result of multi-Emacs support. This step is necessary only if
48 ;; you're installing your own ps-print; if ps-print came with your
49 ;; copy of Emacs, this been done already.
50 ;;
51 ;; 2. Place in your .emacs file the line
52 ;;
53 ;; (require 'ps-print)
54 ;;
55 ;; to load ps-print. Or you may cause any of the ps-print commands
56 ;; to be autoloaded with an autoload command such as:
57 ;;
58 ;; (autoload 'ps-print-buffer "ps-print"
59 ;; "Generate and print a PostScript image of the buffer..." t)
60 ;;
61 ;; 3. Make sure that the variables ps-lpr-command and ps-lpr-switches
62 ;; contain appropriate values for your system; see the usage notes
63 ;; below and the documentation of these variables.
64 ;;
65 ;; Using ps-print
55 ;; -------------- 66 ;; --------------
56 ;; The variables ps-bold-faces and ps-italic-faces *must* contain 67 ;;
57 ;; lists of the faces that you wish to print in bold or italic font. 68 ;; The Commands
58 ;; These variables already contain some default values, but most users 69 ;;
59 ;; will probably have to add some of their own. To add a face to one 70 ;; Ps-print provides eight commands for generating PostScript images
60 ;; of these lists, put code something like the following into your 71 ;; of Emacs buffers:
61 ;; .emacs startup file: 72 ;;
62 ;; 73 ;; ps-print-buffer
63 ;; (setq ps-bold-faces (cons 'my-bold-face ps-bold-faces)) 74 ;; ps-print-buffer-with-faces
64 ;; 75 ;; ps-print-region
65 ;; Ps-print's printer interface is governed by the variables ps-lpr- 76 ;; ps-print-region-with-faces
66 ;; command and ps-lpr-switches; these are analogous to the variables 77 ;; ps-spool-buffer
67 ;; lpr-command and lpr-switches in the Emacs lpr package. 78 ;; ps-spool-buffer-with-faces
68 ;; 79 ;; ps-spool-region
69 ;; To use ps-print, invoke the command ps-print-buffer-with-faces. 80 ;; ps-spool-region-with-faces
70 ;; This will generate a PostScript image of the current buffer and 81 ;;
71 ;; send it to the printer. Precede this command with a numeric prefix 82 ;; These commands all perform essentially the same function: they
72 ;; (C-u), and the PostScript output will be saved in a file; you will 83 ;; generate PostScript images suitable for printing on a PostScript
73 ;; be prompted for a filename. Also see the functions ps-print- 84 ;; printer or displaying with GhostScript. These commands are
74 ;; buffer, ps-print-region, and ps-print-region-with-faces. 85 ;; collectively referred to as "ps-print- commands".
75 ;; 86 ;;
76 ;; I recommend binding ps-print-buffer-with-faces to a key sequence; 87 ;; The word "print" or "spool" in the command name determines when the
77 ;; on a Sun 4 keyboard, for example, you can bind to the PrSc key (aka 88 ;; PostScript image is sent to the printer:
78 ;; r22): 89 ;;
79 ;; 90 ;; print - The PostScript image is immediately sent to the
80 ;; (global-set-key 'f22 'ps-print-buffer-with-faces) 91 ;; printer;
81 ;; (global-set-key '(shift f22) 'ps-print-region-with-faces) 92 ;;
82 ;; 93 ;; spool - The PostScript image is saved temporarily in an
83 ;; Or, as I now prefer, you can also bind the ps-spool- functions to 94 ;; Emacs buffer. Many images may be spooled locally
84 ;; keys; here's my bindings: 95 ;; before printing them. To send the spooled images
85 ;; 96 ;; to the printer, use the command ps-despool.
86 ;; (global-set-key 'f22 'ps-spool-buffer-with-faces) 97 ;;
98 ;; The spooling mechanism was designed for printing lots of small
99 ;; files (mail messages or netnews articles) to save paper that would
100 ;; otherwise be wasted on banner pages, and to make it easier to find
101 ;; your output at the printer (it's easier to pick up one 50-page
102 ;; printout than to find 50 single-page printouts).
103 ;;
104 ;; Ps-print has a hook in the kill-emacs-hooks so that you won't
105 ;; accidently quit from Emacs while you have unprinted PostScript
106 ;; waiting in the spool buffer. If you do attempt to exit with
107 ;; spooled PostScript, you'll be asked if you want to print it, and if
108 ;; you decline, you'll be asked to confirm the exit; this is modeled
109 ;; on the confirmation that Emacs uses for modified buffers.
110 ;;
111 ;; The word "buffer" or "region" in the command name determines how
112 ;; much of the buffer is printed:
113 ;;
114 ;; buffer - Print the entire buffer.
115 ;;
116 ;; region - Print just the current region.
117 ;;
118 ;; The -with-faces suffix on the command name means that the command
119 ;; will include font, color, and underline information in the
120 ;; PostScript image, so the printed image can look as pretty as the
121 ;; buffer. The ps-print- commands without the -with-faces suffix
122 ;; don't include font, color, or underline information; images printed
123 ;; with these commands aren't as pretty, but are faster to generate.
124 ;;
125 ;; Two ps-print- command examples:
126 ;;
127 ;; ps-print-buffer - print the entire buffer,
128 ;; without font, color, or
129 ;; underline information, and
130 ;; send it immediately to the
131 ;; printer.
132 ;;
133 ;; ps-spool-region-with-faces - print just the current region;
134 ;; include font, color, and
135 ;; underline information, and
136 ;; spool the image in Emacs to
137 ;; send to the printer later.
138 ;;
139 ;;
140 ;; Invoking Ps-Print
141 ;;
142 ;; To print your buffer, type
143 ;;
144 ;; M-x ps-print-buffer
145 ;;
146 ;; or substitute one of the other seven ps-print- commands. The
147 ;; command will generate the PostScript image and print or spool it as
148 ;; specified. By giving the command a prefix argument
149 ;;
150 ;; C-u M-x ps-print-buffer
151 ;;
152 ;; it will save the PostScript image to a file instead of sending it
153 ;; to the printer; you will be prompted for the name of the file to
154 ;; save the image to. The prefix argument is ignored by the commands
155 ;; that spool their images, but you may save the spooled images to a
156 ;; file by giving a prefix argument to ps-despool:
157 ;;
158 ;; C-u M-x ps-despool
159 ;;
160 ;; When invoked this way, ps-despool will prompt you for the name of
161 ;; the file to save to.
162 ;;
163 ;; Any of the ps-print- commands can be bound to keys; I recommend
164 ;; binding ps-spool-buffer-with-faces, ps-spool-region-with-faces, and
165 ;; ps-despool. Here are the bindings I use on my Sun 4 keyboard:
166 ;;
167 ;; (global-set-key 'f22 'ps-spool-buffer-with-faces) ;f22 is prsc
87 ;; (global-set-key '(shift f22) 'ps-spool-region-with-faces) 168 ;; (global-set-key '(shift f22) 'ps-spool-region-with-faces)
88 ;; (global-set-key '(control f22) 'ps-despool) 169 ;; (global-set-key '(control f22) 'ps-despool)
89 ;; 170 ;;
90 ;; Using ps-print with other Emacses: 171 ;;
91 ;; --------------------------------- 172 ;; The Printer Interface
92 ;; Although it was intended for use with Emacs 19, ps-print will also work 173 ;;
93 ;; with Emacs version 18; you won't get fancy fontified output, but it 174 ;; The variables ps-lpr-command and ps-lpr-switches determine what
94 ;; should work. 175 ;; command is used to send the PostScript images to the printer, and
176 ;; what arguments to give the command. These are analogous to lpr-
177 ;; command and lpr-switches.
178 ;;
179 ;; NOTE: ps-lpr-command and ps-lpr-switches take their initial values
180 ;; from the variables lpr-command and lpr-switches. If you have
181 ;; lpr-command set to invoke a pretty-printer such as enscript,
182 ;; then ps-print won't work properly. Ps-lpr-command must name
183 ;; a program that does not format the files it prints.
184 ;;
185 ;;
186 ;; How Ps-Print Deals With Fonts
187 ;;
188 ;; The ps-print-*-with-faces commands attempt to determine which faces
189 ;; should be printed in bold or italic, but their guesses aren't
190 ;; always right. For example, you might want to map colors into faces
191 ;; so that blue faces print in bold, and red faces in italic.
192 ;;
193 ;; It is possible to force ps-print to consider specific faces bold or
194 ;; italic, no matter what font they are displayed in, by setting the
195 ;; variables ps-bold-faces and ps-italic-faces. These variables
196 ;; contain lists of faces that ps-print should consider bold or
197 ;; italic; to set them, put code like the following into your .emacs
198 ;; file:
199 ;;
200 ;; (setq ps-bold-faces '(my-blue-face))
201 ;; (setq ps-red-faces '(my-red-face))
202 ;;
203 ;; Ps-print does not attempt to guess the sizes of fonts; all text is
204 ;; rendered using the Courier font family, in 10 point size. To
205 ;; change the font family, change the variables ps-font, ps-font-bold,
206 ;; ps-font-italic, and ps-font-bold-italic; fixed-pitch fonts work
207 ;; best, but are not required. To change the font size, change the
208 ;; variable ps-font-size.
209 ;;
210 ;; If you change the font family or size, you MUST also change the
211 ;; variables ps-line-height, ps-avg-char-width, and ps-space-width, or
212 ;; ps-print cannot correctly place line and page breaks.
213 ;;
214 ;; Ps-print keeps internal lists of which fonts are bold and which are
215 ;; italic; these lists are built the first time you invoke ps-print.
216 ;; For the sake of efficiency, the lists are built only once; the same
217 ;; lists are referred in later invokations of ps-print.
218 ;;
219 ;; Because these lists are built only once, it's possible for them to
220 ;; get out of sync, if a face changes, or if new faces are added. To
221 ;; get the lists back in sync, you can set the variable
222 ;; ps-build-face-reference to t, and the lists will be rebuilt the
223 ;; next time ps-print is invoked.
224 ;;
225 ;;
226 ;; How Ps-Print Deals With Color
227 ;;
228 ;; Ps-print detects faces with foreground and background colors
229 ;; defined and embeds color information in the PostScript image. The
230 ;; default foreground and background colors are defined by the
231 ;; variables ps-default-fg and ps-default-bg. On black-and-white
232 ;; printers, colors are displayed in grayscale. To turn off color
233 ;; output, set ps-print-color-p to nil.
234 ;;
235 ;;
236 ;; Headers
237 ;;
238 ;; Ps-print can print headers at the top of each page; the default
239 ;; headers contain the following four items: on the left, the name of
240 ;; the buffer and, if the buffer is visiting a file, the file's
241 ;; directory; on the right, the page number and date of printing. The
242 ;; default headers look something like this:
243 ;;
244 ;; ps-print.el 1/21
245 ;; /home/jct/emacs-lisp/ps/new 94/12/31
95 ;; 246 ;;
96 ;; A few words about support: 247 ;; When printing on duplex printers, left and right are reversed so
97 ;; ------------------------- 248 ;; that the page numbers are toward the outside.
98 ;; Despite its appearance, with comment blocks, usage instructions, and 249 ;;
99 ;; documentation strings, ps-print is not a supported package. That's all 250 ;; Headers are configurable. To turn them off completely, set
100 ;; a masquerade. Ps-print is something I threw together in my spare time-- 251 ;; ps-print-header to nil. To turn off the header's gaudy framing
101 ;; an evening here, a Saturday there--to make my printouts look like my 252 ;; box, set ps-print-header-frame to nil. Page numbers are printed in
102 ;; Emacs buffers. It works, but is not complete. 253 ;; "n/m" format, indicating page n of m pages; to omit the total page
103 ;; 254 ;; count and just print the page number, set ps-show-n-of-n to nil.
104 ;; Unfortunately, supporting elisp code is not my job and, now that I have 255 ;;
105 ;; what I need out of ps-print, additional support is going to be up to 256 ;; The amount of information in the header can be changed by changing
106 ;; you, the user. But that's the spirit of Emacs, isn't it? I call on 257 ;; the number of lines. To show less, set ps-header-lines to 1, and
107 ;; all who use this package to help in developing it further. If you 258 ;; the header will show only the buffer name and page number. To show
108 ;; notice a bug, fix it and send me the patches. If you add a feature, 259 ;; more, set ps-header-lines to 3, and the header will show the time of
109 ;; again, send me the patches. I will collect all such contributions and 260 ;; printing below the date.
110 ;; periodically post the updates to the appropriate places. 261 ;;
111 ;; 262 ;; To change the content of the headers, change the variables
112 ;; A few more words about support: 263 ;; ps-left-header and ps-right-header. These variables are lists,
113 ;; ------------------------------ 264 ;; specifying top-to-bottom the text to display on the left or right
114 ;; The response to my call for public support of ps-print has been 265 ;; side of the header. Each element of the list should be a string or
115 ;; terrific. With the exception of the spooling mechanism, all the new 266 ;; a symbol. Strings are inserted directly into the PostScript
116 ;; features in this version of ps-print were contributed by users. I have 267 ;; arrays, and should contain the PostScript string delimiters '(' and
117 ;; some contributed code for printing headers that I'll add to the next 268 ;; ')'.
118 ;; release of ps-print, but there are still other features that users can 269 ;;
119 ;; write. See the "Features to Add" list a little further on, and keep 270 ;; Symbols in the header format lists can either represent functions
120 ;; that elisp rolling in. 271 ;; or variables. Functions are called, and should return a string to
121 ;; 272 ;; show in the header. Variables should contain strings to display in
122 ;; Please send all bug fixes and enhancements to me, thompson@wg2.waii.com. 273 ;; the header. In either case, function or variable, the PostScript
123 ;; 274 ;; strings delimeters are added by ps-print, and should not be part of
124 ;; New in version 1.5 275 ;; the returned value.
276 ;;
277 ;; Here's an example: say we want the left header to display the text
278 ;;
279 ;; Moe
280 ;; Larry
281 ;; Curly
282 ;;
283 ;; where we have a function to return "Moe"
284 ;;
285 ;; (defun moe-func ()
286 ;; "Moe")
287 ;;
288 ;; a variable specifying "Larry"
289 ;;
290 ;; (setq larry-var "Larry")
291 ;;
292 ;; and a literal for "Curly". Here's how ps-left-header should be
293 ;; set:
294 ;;
295 ;; (setq ps-left-header (list 'moe-func 'larry-var "(Curly)"))
296 ;;
297 ;; Note that Curly has the PostScript string delimiters inside his
298 ;; quotes -- those aren't misplaced lisp delimiters! Without them,
299 ;; PostScript would attempt to call the undefined function Curly,
300 ;; which would result in a PostScript error. Since most printers
301 ;; don't report PostScript errors except by aborting the print job,
302 ;; this kind of error can be hard to track down. Consider yourself
303 ;; warned.
304 ;;
305 ;;
306 ;; Duplex Printers
307 ;;
308 ;; If you have a duplex-capable printer (one that prints both sides of
309 ;; the paper), set ps-spool-duplex to t. Ps-print will insert blank
310 ;; pages to make sure each buffer starts on the correct side of the
311 ;; paper. Don't forget to set ps-lpr-switches to select duplex
312 ;; printing for your printer.
313 ;;
314 ;;
315 ;; Paper Size
316 ;;
317 ;; The variable ps-paper-type determines the size of paper ps-print
318 ;; formats for; it should contain one of the symbols ps-letter,
319 ;; ps-legal, or ps-a4. The default is ps-letter.
320 ;;
321 ;;
322 ;; New in version 1.6
125 ;; ------------------ 323 ;; ------------------
126 ;; Support for Emacs 19. Works with both overlays and text 324 ;; Color output capability.
127 ;; properties. 325 ;;
128 ;; 326 ;; Automatic detection of font attributes (bold, italic).
129 ;; Underlining. 327 ;;
130 ;; 328 ;; Configurable headers with page numbers.
131 ;; Local spooling; see function ps-spool-buffer. 329 ;;
132 ;; 330 ;; Slightly faster.
133 ;; Support for ISO8859-1 character set. 331 ;;
134 ;; 332 ;; Support for different paper sizes.
135 ;; Page breaks are now handled correctly. 333 ;;
136 ;; 334 ;; Better conformance to PostScript Document Structure Conventions.
137 ;; Percentages reported while formatting are now correct. 335 ;;
138 ;; 336 ;;
139 ;; Known bugs and limitations of ps-print: 337 ;; Known bugs and limitations of ps-print:
140 ;; -------------------------------------- 338 ;; --------------------------------------
141 ;; Slow. (Byte-compiling helps.) 339 ;; Color output doesn't yet work in XEmacs.
142 ;; 340 ;;
143 ;; The PostScript needs review/cleanup/enhancing by a PS expert. 341 ;; Slow. Because XEmacs implements certain functions, such as
144 ;; 342 ;; next-property-change, in lisp, printing with faces is several times
343 ;; slower in XEmacs. In Emacs, these functions are implemented in C,
344 ;; so Emacs is somewhat faster.
345 ;;
145 ;; ASCII Control characters other than tab, linefeed and pagefeed are 346 ;; ASCII Control characters other than tab, linefeed and pagefeed are
146 ;; not handled. 347 ;; not handled.
147 ;; 348 ;;
148 ;; The mechanism for determining whether a stretch of characters 349 ;; Default background color isn't working.
149 ;; should be printed bold, italic, or plain is crude and extremely
150 ;; limited.
151 ;; 350 ;;
152 ;; Faces are always treated as opaque. 351 ;; Faces are always treated as opaque.
153 ;; 352 ;;
154 ;; Font names are hardcoded. 353 ;; Epoch and Emacs 18 not supported. At all.
155 ;; 354 ;;
156 ;; Epoch not fully supported.
157 ;;
158 ;; Tested with only one PostScript printer.
159 ;; 355 ;;
160 ;; Features to add: 356 ;; Features to add:
161 ;; --------------- 357 ;; ---------------
358 ;; 2-up and 4-up capability.
359 ;;
162 ;; Line numbers. 360 ;; Line numbers.
163 ;; 361 ;;
164 ;; Simple headers with date, filename, and page numbers. 362 ;; Wide-print (landscape) capability.
165 ;; 363 ;;
166 ;; Gaudy headers a`la enscript and mp. 364 ;;
167 ;; 365 ;; Acknowledgements
168 ;; 2-up and 4-up capability. 366 ;; ----------------
169 ;; 367 ;; Thanks to Kevin Rodgers <kevinr@ihs.com> for adding support for
170 ;; Wide-print capability. 368 ;; color and the invisible property.
171 ;; 369 ;;
370 ;; Thanks to Avishai Yacobi, avishaiy@mcil.comm.mot.com, for writing
371 ;; the initial port to Emacs 19. His code is no longer part of
372 ;; ps-print, but his work is still appreciated.
373 ;;
374 ;; Thanks to Remi Houdaille and Michel Train, michel@metasoft.fdn.org,
375 ;; for adding underline support. Their code also is no longer part of
376 ;; ps-print, but their efforts are not forgotten.
377 ;;
378 ;; Thanks also to all of you who mailed code to add features to
379 ;; ps-print; although I didn't use your code, I still appreciate your
380 ;; sharing it with me.
381 ;;
382 ;; Thanks to all who mailed comments, encouragement, and criticism.
383 ;; Thanks also to all who responded to my survey; I had too many
384 ;; responses to reply to them all, but I greatly appreciate your
385 ;; interest.
386 ;;
387 ;; Jim
388 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
172 389
173 ;;; Code: 390 ;;; Code:
174 391
175 (defconst ps-print-version (substring "$Revision: 1.5 $" 11 -2) 392 (defconst ps-print-version "1.10"
176 "$Id: ps-print.el,v 1.5 1994/04/22 13:25:18 jct Exp $ 393 "ps-print.el,v 1.10 1995/01/09 14:45:03 jct Exp
177 394
178 Please send all bug fixes and enhancements to Jim Thompson, 395 Please send all bug fixes and enhancements to
179 thompson@wg2.waii.com.") 396 Jim Thompson <thompson@wg2.waii.com>.")
180 397
181 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 398 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
182 (defvar ps-lpr-command (if (memq system-type 399 ;; User Variables:
183 '(usg-unix-v hpux silicon-graphics-unix)) 400
184 "lp" "lpr") 401 (defvar ps-lpr-command lpr-command
185 "The shell command for printing a PostScript file.") 402 "*The shell command for printing a PostScript file.")
186 403
187 (defvar ps-lpr-switches nil 404 (defvar ps-lpr-switches lpr-switches
188 "A list of extra switches to pass to ps-lpr-command.") 405 "*A list of extra switches to pass to `ps-lpr-command'.")
189
190 (defvar ps-bold-faces
191 '(bold
192 bold-italic
193 font-lock-function-name-face
194 message-headers
195 )
196 "A list of the faces that should be printed italic.")
197
198 (defvar ps-italic-faces
199 '(italic
200 bold-italic
201 font-lock-function-name-face
202 font-lock-string-face
203 font-lock-comment-face
204 message-header-contents
205 message-highlighted-header-contents
206 message-cited-text
207 )
208 "A list of the faces that should be printed bold.")
209
210 (defvar ps-underline-faces
211 '(underline
212 font-lock-string-face)
213 "A list of the faces that should be printed underline.")
214
215 (defvar ps-razzle-dazzle t
216 "Non-nil means report progress while formatting buffer")
217
218 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
219
220 (defun ps-print-buffer (&optional filename)
221
222 "Generate and print a PostScript image of the buffer.
223
224 When called with a numeric prefix argument (C-u), prompt the user for
225 the name of a file to save the PostScript image in, instead of sending
226 it to the printer.
227
228 More specifically, the FILENAME argument is treated as follows: if it
229 is nil, send the image to the printer. If FILENAME is a string, save
230 the PostScript image in a file with that name. If FILENAME is a
231 number, prompt the user for the name of the file to save in.
232
233 The image is rendered using the PostScript font Courier.
234
235 See also: ps-print-buffer-with-faces
236 ps-spool-buffer
237 ps-spool-buffer-with-faces"
238
239 (interactive "P")
240 (setq filename (ps-preprint filename))
241 (ps-generate (current-buffer) (point-min) (point-max)
242 'ps-generate-postscript)
243 (ps-do-despool filename))
244
245
246 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
247
248 (defun ps-print-buffer-with-faces (&optional filename)
249
250 "Generate and print a PostScript image of the buffer.
251
252 This function works like ps-print-buffer, with the additional benefit
253 that any bold/italic formatting information present in the buffer
254 (contained in extents and faces) will be retained in the PostScript
255 image. In other words, WYSIAWYG -- What You See Is (Almost) What You
256 Get.
257
258 Ps-print uses three lists to determine which faces should be printed
259 bold, italic, and/or underlined; the lists are named ps-bold-faces, ps-
260 italic-faces, and ps-underline-faces. A given face should appear on as
261 many lists as are appropriate; for example, face bold-italic is in both
262 the lists ps-bold-faces and ps-italic-faces. The lists are pre-built
263 with the standard bold, italic, and bold-italic faces, with font-lock's
264 faces, and with the faces used by gnus and rmail.
265
266 The image is rendered using the PostScript fonts Courier, Courier-Bold,
267 Courier-Oblique, and Courier-BoldOblique.
268
269 See also: ps-print-buffer
270 ps-spool-buffer
271 ps-spool-buffer-with-faces."
272
273 (interactive "P")
274 (setq filename (ps-preprint filename))
275 (ps-generate (current-buffer) (point-min) (point-max)
276 'ps-generate-postscript-with-faces)
277 (ps-do-despool filename))
278
279 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
280
281 (defun ps-print-region (from to &optional filename)
282
283 "Generate and print a PostScript image of the region.
284
285 When called with a numeric prefix argument (C-u), prompt the user for
286 the name of a file to save the PostScript image in, instead of sending
287 it to the printer.
288
289 This function is essentially the same as ps-print-buffer except that it
290 prints just a region, and not the entire buffer. For more information,
291 see the function ps-print-buffer.
292
293 See also: ps-print-region-with-faces
294 ps-spool-region
295 ps-spool-region-with-faces"
296
297 (interactive "r\nP")
298 (setq filename (ps-preprint filename))
299 (ps-generate (current-buffer) from to
300 'ps-generate-postscript)
301 (ps-do-despool filename))
302
303 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
304
305 (defun ps-print-region-with-faces (from to &optional filename)
306
307 "Generate and print a PostScript image of the region.
308
309 This function is essentially the same as ps-print-buffer except that it
310 prints just a region, and not the entire buffer. See the functions
311 ps-print-region and ps-print-buffer-with-faces for
312 more information.
313
314 See also: ps-print-region
315 ps-spool-region
316 ps-spool-region-with-faces"
317
318 (interactive "r\nP")
319 (setq filename (ps-preprint filename))
320 (ps-generate (current-buffer) from to
321 'ps-generate-postscript-with-faces)
322 (ps-do-despool filename))
323
324 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
325
326 (defun ps-spool-buffer ()
327
328 "Generate and spool a PostScript image of the buffer.
329
330 This function is essentially the same as function ps-print-buffer
331 except that the PostScript image is saved in a local buffer to be sent
332 to the printer later.
333
334 Each time you call one of the ps-spool- functions, the generated
335 PostScript is appended to a buffer named *PostScript*; to send the
336 spooled PostScript to the printer, or save it to a file, use the command
337 ps-despool.
338
339 If the variable ps-spool-duplex is non-nil, then the spooled PostScript
340 is padded with blank pages, when needed, so that each printed buffer
341 will start on a front page when printed on a duplex printer (a printer
342 that prints on both sides on the paper). Users of non-duplex printers
343 will want to leave ps-spool-duplex nil.
344
345 The spooling mechanism was designed for printing lots of small files
346 (mail messages or netnews articles) to save paper that would otherwise
347 be wasted on banner pages, and to make it easier to find your output at
348 the printer (it's easier to pick up one 50-page printout than to find 50
349 single-page printouts).
350
351 Ps-print has a hook in the kill-emacs-hook list so that you won't
352 accidently quit from Emacs while you have unprinted PostScript waiting
353 in the spool buffer. If you do attempt to exit with spooled PostScript,
354 you'll be asked if you want to print it, and if you decline, you'll be
355 asked to confirm the exit; this is modeled on the confirmation that
356 Emacs uses for modified buffers.
357
358 See also: ps-despool
359 ps-print-buffer
360 ps-print-buffer-with-faces
361 ps-spool-buffer-with-faces"
362
363 (interactive)
364 (ps-generate (current-buffer) (point-min) (point-max)
365 'ps-generate-postscript))
366
367 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
368
369 (defun ps-spool-buffer-with-faces ()
370
371 "Generate and spool PostScript image of the buffer.
372
373 This function is essentially the same as function ps-print-buffer-with-
374 faces except that the PostScript image is saved in a local buffer to be
375 sent to the printer later.
376
377 Use the function ps-despool to send the spooled images to the printer.
378 See the function ps-spool-buffer for a description of the spooling
379 mechanism.
380
381 See also: ps-despool
382 ps-spool-buffer
383 ps-print-buffer
384 ps-print-buffer-with-faces"
385
386 (interactive)
387 (ps-generate (current-buffer) (point-min) (point-max)
388 'ps-generate-postscript-with-faces))
389
390 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
391
392 (defun ps-spool-region (from to)
393
394 "Generate PostScript image of the region and spool locally.
395
396 This function is essentially the same as function ps-print-region except
397 that the PostScript image is saved in a local buffer to be sent to the
398 printer later.
399
400 Use the function ps-despool to send the spooled images to the printer.
401 See the function ps-spool-buffer for a description of the spooling
402 mechanism.
403
404 See also: ps-despool
405 ps-spool-buffer
406 ps-print-buffer
407 ps-print-buffer-with-faces"
408
409 (interactive "r")
410 (ps-generate (current-buffer) from to
411 'ps-generate-postscript))
412
413 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
414
415 (defun ps-spool-region-with-faces (from to)
416
417 "Generate PostScript image of the region and spool locally.
418
419 This function is essentially the same as function ps-print-region-with-
420 faces except that the PostScript image is saved in a local buffer to be
421 sent to the printer later.
422
423 Use the function ps-despool to send the spooled images to the printer.
424 See the function ps-spool-buffer for a description of the spooling
425 mechanism.
426
427 See also: ps-despool
428 ps-spool-buffer
429 ps-print-buffer
430 ps-print-buffer-with-faces"
431
432 (interactive "r")
433 (ps-generate (current-buffer) from to
434 'ps-generate-postscript-with-faces))
435
436 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
437 406
438 (defvar ps-spool-duplex nil ; Not many people have duplex 407 (defvar ps-spool-duplex nil ; Not many people have duplex
439 ; printers, so default to nil. 408 ; printers, so default to nil.
440 "*Non-nil indicates spooling is for a two-sided printer. 409 "*Non-nil indicates spooling is for a two-sided printer.
441 For a duplex printer, the ps-spool functions will insert blank pages 410 For a duplex printer, the `ps-spool-*' commands will insert blank pages
442 as needed between print jobs so that the next buffer printed will 411 as needed between print jobs so that the next buffer printed will
443 start on the right page.") 412 start on the right page. Also, if headers are turned on, the headers
444 413 will be reversed on duplex printers so that the page numbers fall to
445 (defun ps-despool (&optional filename) 414 the left on even-numbered pages.")
446 "Send the spooled PostScript to the printer. 415
416 (defvar ps-paper-type 'ps-letter
417 "*Specifies the size of paper to format for. Should be one of
418 'ps-letter, 'ps-legal, or 'ps-a4.")
419
420 (defvar ps-print-header t
421 "*Non-nil means print a header at the top of each page. By default,
422 the header displays the buffer name, page number, and, if the buffer
423 is visiting a file, the file's directory. Headers are customizable by
424 changing variables `ps-header-left' and `ps-header-right'.")
425
426 (defvar ps-print-header-frame t
427 "*Non-nil means draw a gaudy frame around the header.")
428
429 (defvar ps-show-n-of-n t
430 "*Non-nil means show page numbers as \"n/m\", meaning page n of m.
431 Note: page numbers are displayed as part of headers, see variable `ps-
432 print-headers'.")
433
434 (defvar ps-print-color-p (and (fboundp 'x-color-values)
435 (fboundp 'float))
436 ; Printing color requires both floating point and x-color-values.
437 "*If non-nil, print the buffer's text in color.")
438
439 (defvar ps-default-fg '(0.0 0.0 0.0)
440 "*RGB values of the default foreground color. Defaults to black.")
441
442 (defvar ps-default-bg '(1.0 1.0 1.0)
443 "*RGB values of the default background color. Defaults to white.")
444
445 (defvar ps-font-size 10
446 "*Specifies the size, in points, of the font to print text in.")
447
448 (defvar ps-font "Courier"
449 "*Specifies the name of the font family to print text in.")
450
451 (defvar ps-font-bold "Courier-Bold"
452 "*Specifies the name of the font family to print bold text in.")
453
454 (defvar ps-font-italic "Courier-Oblique"
455 "*Specifies the name of the font family to print italic text in.")
456
457 (defvar ps-font-bold-italic "Courier-BoldOblique"
458 "*Specifies the name of the font family to print bold-italic text in.")
459
460 (defvar ps-avg-char-width (if (fboundp 'float) 5.6 6)
461 "*Specifies the average width, in points, of a character. This is the
462 value that ps-print uses to determine the length, x-dimension, of the
463 text it has printed, and thus affects the point at which long lines
464 wrap around. Note that if you change the font or font size, you will
465 probably have to adjust this value to match.")
466
467 (defvar ps-space-width (if (fboundp 'float) 5.6 6)
468 "*Specifies the width of a space character. This value is used in
469 expanding tab characters.")
470
471 (defvar ps-line-height (if (fboundp 'float) 11.29 11)
472 "*Specifies the height of a line. This is the value that ps-print
473 uses to determine the height, y-dimension, of the lines of text it has
474 printed, and thus affects the point at which page-breaks are placed.
475 Note that if you change the font or font size, you will probably have
476 to adjust this value to match. Note also that the line-height is
477 *not* the same as the point size of the font.")
478
479 (defvar ps-auto-font-detect t
480 "*Non-nil means automatically detect bold/italic face attributes.
481 Nil means rely solely on the lists `ps-bold-faces', `ps-italic-faces',
482 and `ps-underlined-faces'.")
483
484 (defvar ps-bold-faces '()
485 "*A list of the \(non-bold\) faces that should be printed in bold font.")
486
487 (defvar ps-italic-faces '()
488 "*A list of the \(non-italic\) faces that should be printed in italic font.")
489
490 (defvar ps-underlined-faces '()
491 "*A list of the \(non-underlined\) faces that should be printed underlined.")
492
493 (defvar ps-header-lines 2
494 "*The number of lines to display in the page header.")
495 (make-variable-buffer-local 'ps-header-lines)
496
497 (defvar ps-left-header
498 (list 'ps-get-buffer-name 'ps-header-dirpart)
499 "*The items to display on the right part of the page header.
500
501 Should contain a list of strings and symbols, each representing an
502 entry in the PostScript array HeaderLinesLeft.
503
504 Strings are inserted unchanged into the array; those representing
505 PostScript string literals should be delimited with PostScript string
506 delimiters '(' and ')'.
507
508 For symbols with bound functions, the function is called and should
509 return a string to be inserted into the array. For symbols with bound
510 values, the value should be a string to be inserted into the array.
511 In either case, function or variable, the string value has PostScript
512 string delimiters added to it.")
513 (make-variable-buffer-local 'ps-left-header)
514
515 (defvar ps-right-header
516 (list "/pagenumberstring load" 'time-stamp-yy/mm/dd 'time-stamp-hh:mm:ss)
517 "*The items to display on the left part of the page header.
518
519 See the variable ps-left-header for a description of the format of
520 this variable.")
521 (make-variable-buffer-local 'ps-right-header)
522
523 (defvar ps-razzle-dazzle t
524 "*Non-nil means report progress while formatting buffer.")
525
526 (defvar ps-adobe-tag "%!PS-Adobe-1.0\n"
527 "*Contains the header line identifying the output as PostScript.
528 By default, `ps-adobe-tag' contains the standard identifier. Some
529 printers require slightly different versions of this line.")
530
531 (defvar ps-build-face-reference t
532 "*Non-nil means build the reference face lists.
533
534 Ps-print sets this value to nil after it builds its internal reference
535 lists of bold and italic faces. By settings its value back to t, you
536 can force ps-print to rebuild the lists the next time you invoke one
537 of the -with-faces commands.
538
539 You should set this value back to t after you change the attributes of
540 any face, or create new faces. Most users shouldn't have to worry
541 about its setting, though.")
542
543 (defvar ps-always-build-face-reference nil
544 "*Non-nil means always rebuild the reference face lists.
545
546 If this variable is non-nil, ps-print will rebuild its internal
547 reference lists of bold and italic faces *every* time one of the
548 -with-faces commands is called. Most users shouldn't need to set this
549 variable.")
550
551 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
552 ;; User commands
553
554 (defun ps-print-buffer (&optional filename)
555 "Generate and print a PostScript image of the buffer.
447 556
448 When called with a numeric prefix argument (C-u), prompt the user for 557 When called with a numeric prefix argument (C-u), prompt the user for
449 the name of a file to save the spooled PostScript in, instead of sending 558 the name of a file to save the PostScript image in, instead of sending
450 it to the printer. 559 it to the printer.
451 560
452 More specifically, the FILENAME argument is treated as follows: if it 561 More specifically, the FILENAME argument is treated as follows: if it
453 is nil, send the image to the printer. If FILENAME is a string, save 562 is nil, send the image to the printer. If FILENAME is a string, save
454 the PostScript image in a file with that name. If FILENAME is a 563 the PostScript image in a file with that name. If FILENAME is a
455 number, prompt the user for the name of the file to save in." 564 number, prompt the user for the name of the file to save in."
456 565
457 (interactive "P") 566 (interactive "P")
458 567 (setq filename (ps-print-preprint filename))
459 ;; If argument FILENAME is nil, send the image to the printer; if 568 (ps-generate (current-buffer) (point-min) (point-max)
460 ;; FILENAME is a string, save the PostScript image in that filename; 569 'ps-generate-postscript)
461 ;; if FILENAME is a number, prompt the user for the name of the file
462 ;; to save in.
463
464 (setq filename (ps-preprint filename))
465 (ps-do-despool filename)) 570 (ps-do-despool filename))
466 571
467 ;; Here end the definitions that users need to know about; proceed 572
468 ;; further at your own risk! 573 (defun ps-print-buffer-with-faces (&optional filename)
574 "Generate and print a PostScript image of the buffer.
575
576 Like `ps-print-buffer', but includes font, color, and underline
577 information in the generated image."
578 (interactive "P")
579 (setq filename (ps-print-preprint filename))
580 (ps-generate (current-buffer) (point-min) (point-max)
581 'ps-generate-postscript-with-faces)
582 (ps-do-despool filename))
583
584
585 (defun ps-print-region (from to &optional filename)
586 "Generate and print a PostScript image of the region.
587
588 Like `ps-print-buffer', but prints just the current region."
589
590 (interactive "r\nP")
591 (setq filename (ps-print-preprint filename))
592 (ps-generate (current-buffer) from to
593 'ps-generate-postscript)
594 (ps-do-despool filename))
595
596
597 (defun ps-print-region-with-faces (from to &optional filename)
598 "Generate and print a PostScript image of the region.
599
600 Like `ps-print-region', but includes font, color, and underline
601 information in the generated image."
602
603 (interactive "r\nP")
604 (setq filename (ps-print-preprint filename))
605 (ps-generate (current-buffer) from to
606 'ps-generate-postscript-with-faces)
607 (ps-do-despool filename))
608
609
610 (defun ps-spool-buffer ()
611 "Generate and spool a PostScript image of the buffer.
612
613 Like `ps-print-buffer' except that the PostScript image is saved in a
614 local buffer to be sent to the printer later.
615
616 Use the command `ps-despool' to send the spooled images to the printer."
617 (interactive)
618 (ps-generate (current-buffer) (point-min) (point-max)
619 'ps-generate-postscript))
620
621
622 (defun ps-spool-buffer-with-faces ()
623 "Generate and spool a PostScript image of the buffer.
624
625 Like `ps-spool-buffer', but includes font, color, and underline
626 information in the generated image.
627
628 Use the command `ps-despool' to send the spooled images to the printer."
629
630 (interactive)
631 (ps-generate (current-buffer) (point-min) (point-max)
632 'ps-generate-postscript-with-faces))
633
634
635 (defun ps-spool-region (from to)
636 "Generate a PostScript image of the region and spool locally.
637
638 Like `ps-spool-buffer', but spools just the current region.
639
640 Use the command `ps-despool' to send the spooled images to the printer."
641 (interactive "r")
642 (ps-generate (current-buffer) from to
643 'ps-generate-postscript))
644
645
646 (defun ps-spool-region-with-faces (from to)
647 "Generate a PostScript image of the region and spool locally.
648
649 Like `ps-spool-region', but includes font, color, and underline
650 information in the generated image.
651
652 Use the command `ps-despool' to send the spooled images to the printer."
653 (interactive "r")
654 (ps-generate (current-buffer) from to
655 'ps-generate-postscript-with-faces))
656
657 (defun ps-despool (&optional filename)
658 "Send the spooled PostScript to the printer.
659
660 When called with a numeric prefix argument (C-u), prompt the user for
661 the name of a file to save the spooled PostScript in, instead of sending
662 it to the printer.
663
664 More specifically, the FILENAME argument is treated as follows: if it
665 is nil, send the image to the printer. If FILENAME is a string, save
666 the PostScript image in a file with that name. If FILENAME is a
667 number, prompt the user for the name of the file to save in."
668 (interactive "P")
669 (ps-do-despool (ps-print-preprint filename)))
670
469 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 671 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
470 672 ;; Utility functions and variables:
471 (defun ps-kill-emacs-check () 673
472 (if (and (setq ps-buffer (get-buffer ps-spool-buffer-name)) 674 (if (featurep 'emacs-vers)
473 (buffer-modified-p ps-buffer)) 675 nil
474 (if (y-or-n-p "Unprinted PostScript waiting... print now? ") 676 (defvar emacs-type (cond ((string-match "XEmacs" emacs-version) 'xemacs)
475 (ps-despool))) 677 ((string-match "Lucid" emacs-version) 'lucid)
476 678 ((string-match "Epoch" emacs-version) 'epoch)
477 (if (and (setq ps-buffer (get-buffer ps-spool-buffer-name)) 679 (t 'fsf))))
478 (buffer-modified-p ps-buffer)) 680
479 (if (yes-or-no-p "Unprinted PostScript waiting; exit anyway? ") 681 (if (or (eq emacs-type 'lucid)
480 nil 682 (eq emacs-type 'xemacs))
481 (error "Unprinted PostScript")))) 683 (setq ps-print-color-p nil)
482 684 (require 'faces)) ; face-font, face-underline-p,
483 (if (fboundp 'add-hook) 685 ; x-font-regexp
484 (add-hook 'kill-emacs-hook 'ps-kill-emacs-check) 686
485 (if kill-emacs-hook 687 (require 'time-stamp)
486 (message "Won't override existing kill-emacs-hook.") 688
487 (setq kill-emacs-hook 'ps-kill-emacs-check))) 689 (defvar ps-print-prologue "% ISOLatin1Encoding stolen from ps_init.ps in GhostScript 2.6.1.4:
488 690 % If the ISOLatin1Encoding vector isn't known, define it.
489 (defun ps-preprint (&optional filename) 691 /ISOLatin1Encoding where { pop } {
692 % Define the ISO Latin-1 encoding vector.
693 % The first half is the same as the standard encoding,
694 % except for minus instead of hyphen at code 055.
695 /ISOLatin1Encoding
696 StandardEncoding 0 45 getinterval aload pop
697 /minus
698 StandardEncoding 46 82 getinterval aload pop
699 %*** NOTE: the following are missing in the Adobe documentation,
700 %*** but appear in the displayed table:
701 %*** macron at 0225, dieresis at 0230, cedilla at 0233, space at 0240.
702 % \20x
703 /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
704 /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
705 /dotlessi /grave /acute /circumflex /tilde /macron /breve /dotaccent
706 /dieresis /.notdef /ring /cedilla /.notdef /hungarumlaut /ogonek /caron
707 % \24x
708 /space /exclamdown /cent /sterling
709 /currency /yen /brokenbar /section
710 /dieresis /copyright /ordfeminine /guillemotleft
711 /logicalnot /hyphen /registered /macron
712 /degree /plusminus /twosuperior /threesuperior
713 /acute /mu /paragraph /periodcentered
714 /cedilla /onesuperior /ordmasculine /guillemotright
715 /onequarter /onehalf /threequarters /questiondown
716 % \30x
717 /Agrave /Aacute /Acircumflex /Atilde
718 /Adieresis /Aring /AE /Ccedilla
719 /Egrave /Eacute /Ecircumflex /Edieresis
720 /Igrave /Iacute /Icircumflex /Idieresis
721 /Eth /Ntilde /Ograve /Oacute
722 /Ocircumflex /Otilde /Odieresis /multiply
723 /Oslash /Ugrave /Uacute /Ucircumflex
724 /Udieresis /Yacute /Thorn /germandbls
725 % \34x
726 /agrave /aacute /acircumflex /atilde
727 /adieresis /aring /ae /ccedilla
728 /egrave /eacute /ecircumflex /edieresis
729 /igrave /iacute /icircumflex /idieresis
730 /eth /ntilde /ograve /oacute
731 /ocircumflex /otilde /odieresis /divide
732 /oslash /ugrave /uacute /ucircumflex
733 /udieresis /yacute /thorn /ydieresis
734 256 packedarray def
735 } ifelse
736
737 /reencodeFontISO { %def
738 dup
739 length 5 add dict % Make a new font (a new dict
740 % the same size as the old
741 % one) with room for our new
742 % symbols.
743
744 begin % Make the new font the
745 % current dictionary.
746
747
748 { 1 index /FID ne
749 { def } { pop pop } ifelse
750 } forall % Copy each of the symbols
751 % from the old dictionary to
752 % the new except for the font
753 % ID.
754
755 /Encoding ISOLatin1Encoding def % Override the encoding with
756 % the ISOLatin1 encoding.
757
758 % Use the font's bounding box to determine the ascent, descent,
759 % and overall height; don't forget that these values have to be
760 % transformed using the font's matrix.
761 FontBBox
762 FontMatrix transform /Ascent exch def pop
763 FontMatrix transform /Descent exch def pop
764 /FontHeight Ascent Descent sub def
765
766 % Define these in case they're not in the FontInfo (also, here
767 % they're easier to get to.
768 /UnderlinePosition 1 def
769 /UnderlineThickness 1 def
770
771 % Get the underline position and thickness if they're defined.
772 currentdict /FontInfo known {
773 FontInfo
774
775 dup /UnderlinePosition known {
776 dup /UnderlinePosition get
777 0 exch FontMatrix transform exch pop
778 /UnderlinePosition exch def
779 } if
780
781 dup /UnderlineThickness known {
782 /UnderlineThickness get
783 0 exch FontMatrix transform exch pop
784 /UnderlineThickness exch def
785 } if
786
787 } if
788
789 currentdict % Leave the new font on the
790 % stack
791
792 end % Stop using the font as the
793 % current dictionary.
794
795 definefont % Put the font into the font
796 % dictionary
797
798 pop % Discard the returned font.
799 } bind def
800
801 /Font {
802 findfont exch scalefont reencodeFontISO
803 } def
804
805 /F { % Font select
806 findfont
807 dup /Ascent get /Ascent exch def
808 dup /Descent get /Descent exch def
809 dup /FontHeight get /LineHeight exch def
810 dup /UnderlinePosition get /UnderlinePosition exch def
811 dup /UnderlineThickness get /UnderlineThickness exch def
812 setfont
813 } def
814
815 /FG /setrgbcolor load def
816
817 /bg false def
818 /BG {
819 dup /bg exch def
820 { mark 4 1 roll ] /bgcolor exch def } if
821 } def
822
823 /dobackground { % width --
824 currentpoint
825 gsave
826 newpath
827 moveto
828 0 Ascent rmoveto
829 dup 0 rlineto
830 0 Descent Ascent sub rlineto
831 neg 0 rlineto
832 closepath
833 bgcolor aload pop setrgbcolor
834 fill
835 grestore
836 } def
837
838 /dobackgroundstring { % string --
839 stringwidth pop
840 dobackground
841 } def
842
843 /dounderline { % fromx fromy --
844 currentpoint
845 gsave
846 UnderlineThickness setlinewidth
847 4 2 roll
848 UnderlinePosition add moveto
849 UnderlinePosition add lineto
850 stroke
851 grestore
852 } def
853
854 /eolbg {
855 currentpoint pop
856 PrintWidth LeftMargin add exch sub dobackground
857 } def
858
859 /eolul {
860 currentpoint exch pop
861 PrintWidth LeftMargin add exch dounderline
862 } def
863
864 /SL { % Soft Linefeed
865 bg { eolbg } if
866 ul { eolul } if
867 currentpoint LineHeight sub LeftMargin exch moveto pop
868 } def
869
870 /HL /SL load def % Hard Linefeed
871
872 /sp1 { currentpoint 3 -1 roll } def
873
874 % Some debug
875 /dcp { currentpoint exch 40 string cvs print (, ) print = } def
876 /dp { print 2 copy
877 exch 40 string cvs print (, ) print = } def
878
879 /S {
880 bg { dup dobackgroundstring } if
881 ul { sp1 } if
882 show
883 ul { dounderline } if
884 } def
885
886 /W {
887 ul { sp1 } if
888 ( ) stringwidth % Get the width of a space
889 pop % Discard the Y component
890 mul % Multiply the width of a
891 % space by the number of
892 % spaces to plot
893 bg { dup dobackground } if
894 0 rmoveto
895 ul { dounderline } if
896 } def
897
898 /BeginDSCPage {
899 /vmstate save def
900 } def
901
902 /BeginPage {
903 PrintHeader {
904 PrintHeaderFrame { HeaderFrame } if
905 HeaderText
906 } if
907 LeftMargin
908 BottomMargin PrintHeight add
909 moveto % move to where printing will
910 % start.
911 } def
912
913 /EndPage {
914 bg { eolbg } if
915 ul { eolul } if
916 showpage % Spit out a page
917 } def
918
919 /EndDSCPage {
920 vmstate restore
921 } def
922
923 /ul false def
924
925 /UL { /ul exch def } def
926
927 /h0 14 /Helvetica-Bold Font
928 /h1 12 /Helvetica Font
929
930 /h1 F
931
932 /HeaderLineHeight LineHeight def
933 /HeaderDescent Descent def
934 /HeaderPad 2 def
935
936 /SetHeaderLines {
937 /HeaderOffset TopMargin 2 div def
938 /HeaderLines exch def
939 /HeaderHeight HeaderLines HeaderLineHeight mul HeaderPad 2 mul add def
940 /PrintHeight PrintHeight HeaderHeight sub def
941 } def
942
943 /HeaderFrameStart {
944 LeftMargin BottomMargin PrintHeight add HeaderOffset add
945 } def
946
947 /HeaderFramePath {
948 PrintWidth 0 rlineto
949 0 HeaderHeight rlineto
950 PrintWidth neg 0 rlineto
951 0 HeaderHeight neg rlineto
952 } def
953
954 /HeaderFrame {
955 gsave
956 0.4 setlinewidth
957 HeaderFrameStart moveto
958 1 -1 rmoveto
959 HeaderFramePath
960 0 setgray fill
961 HeaderFrameStart moveto
962 HeaderFramePath
963 gsave 0.9 setgray fill grestore
964 gsave 0 setgray stroke grestore
965 grestore
966 } def
967
968 /HeaderStart {
969 HeaderFrameStart
970 exch HeaderPad add exch
971 HeaderLineHeight HeaderLines 1 sub mul add HeaderDescent sub HeaderPad add
972 } def
973
974 /strcat {
975 dup length 3 -1 roll dup length dup 4 -1 roll add string dup
976 0 5 -1 roll putinterval
977 dup 4 2 roll exch putinterval
978 } def
979
980 /pagenumberstring {
981 PageNumber 32 string cvs
982 ShowNofN {
983 (/) strcat
984 PageCount 32 string cvs strcat
985 } if
986 } def
987
988 /HeaderText {
989 HeaderStart moveto
990
991 HeaderLinesRight HeaderLinesLeft
992 Duplex PageNumber 1 and 0 eq and { exch } if
993
994 {
995 aload pop
996 exch F
997 gsave
998 dup xcheck { exec } if
999 show
1000 grestore
1001 0 HeaderLineHeight neg rmoveto
1002 } forall
1003
1004 HeaderStart moveto
1005
1006 {
1007 aload pop
1008 exch F
1009 gsave
1010 dup xcheck { exec } if
1011 dup stringwidth pop
1012 PrintWidth exch sub HeaderPad 2 mul sub 0 rmoveto
1013 show
1014 grestore
1015 0 HeaderLineHeight neg rmoveto
1016 } forall
1017 } def
1018
1019 /ReportFontInfo {
1020 2 copy
1021 /t0 3 1 roll Font
1022 /t0 F
1023 /lh LineHeight def
1024 /sw ( ) stringwidth pop def
1025 /aw (01234567890abcdefghijklmnopqrstuvwxyz) dup length exch
1026 stringwidth pop exch div def
1027 /t1 12 /Helvetica-Oblique Font
1028 /t1 F
1029 72 72 moveto
1030 gsave
1031 (For ) show
1032 128 string cvs show
1033 ( ) show
1034 32 string cvs show
1035 ( point, the line height is ) show
1036 lh 32 string cvs show
1037 (, the space width is ) show
1038 sw 32 string cvs show
1039 (,) show
1040 grestore
1041 0 LineHeight neg rmoveto
1042 (and a crude estimate of average character width is ) show
1043 aw 32 string cvs show
1044 (.) show
1045 showpage
1046 } def
1047
1048 % 10 /Courier ReportFontInfo
1049 ")
1050
1051 ;; Start Editing Here:
1052
1053 (defvar ps-source-buffer nil)
1054 (defvar ps-spool-buffer-name "*PostScript*")
1055 (defvar ps-spool-buffer nil)
1056
1057 (defvar ps-output-head nil)
1058 (defvar ps-output-tail nil)
1059
1060 (defvar ps-page-count 0)
1061 (defvar ps-showpage-count 0)
1062
1063 (defvar ps-current-font 0)
1064 (defvar ps-current-underline-p nil)
1065 (defvar ps-default-color (if ps-print-color-p ps-default-fg)) ; black
1066 (defvar ps-current-color ps-default-color)
1067 (defvar ps-current-bg nil)
1068
1069 (defvar ps-razchunk 0)
1070
1071 (defvar ps-color-format (if (eq emacs-type 'fsf)
1072
1073 ;;Emacs understands the %f format; we'll
1074 ;;use it to limit color RGB values to
1075 ;;three decimals to cut down some on the
1076 ;;size of the PostScript output.
1077 "%0.3f %0.3f %0.3f"
1078
1079 ;; Lucid emacsen will have to make do with
1080 ;; %s (princ) for floats.
1081 "%s %s %s"))
1082
1083 ;; These values determine how much print-height to deduct when headers
1084 ;; are turned on. This is a pretty clumsy way of handling it, but
1085 ;; it'll do for now.
1086 (defvar ps-header-title-line-height (if (fboundp 'float) 16.0 16));Helvetica 14
1087 (defvar ps-header-line-height (if (fboundp 'float) 13.7 14));Helvetica 12
1088 (defvar ps-header-pad 2)
1089
1090 ;; LetterSmall 7.68 inch 10.16 inch
1091 ;; Tabloid 11.0 inch 17.0 inch
1092 ;; Ledger 17.0 inch 11.0 inch
1093 ;; Statement 5.5 inch 8.5 inch
1094 ;; Executive 7.5 inch 10.0 inch
1095 ;; A3 11.69 inch 16.5 inch
1096 ;; A4Small 7.47 inch 10.85 inch
1097 ;; B4 10.125 inch 14.33 inch
1098 ;; B5 7.16 inch 10.125 inch
1099
1100 ;; All page dimensions are in PostScript points.
1101
1102 (defvar ps-left-margin 72) ; 1 inch
1103 (defvar ps-right-margin 72) ; 1 inch
1104 (defvar ps-bottom-margin 36) ; 1/2 inch
1105 (defvar ps-top-margin 72) ; 1 inch
1106
1107 ;; Letter 8.5 inch x 11.0 inch
1108 (defvar ps-letter-page-height 792) ; 11 inches
1109 (defvar ps-letter-page-width 612) ; 8.5 inches
1110
1111 ;; Legal 8.5 inch x 14.0 inch
1112 (defvar ps-legal-page-height 1008) ; 14.0 inches
1113 (defvar ps-legal-page-width 612) ; 8.5 inches
1114
1115 ;; A4 8.26 inch x 11.69 inch
1116 (defvar ps-a4-page-height 842) ; 11.69 inches
1117 (defvar ps-a4-page-width 595) ; 8.26 inches
1118
1119 (defvar ps-pages-alist
1120 (list (list 'ps-letter ps-letter-page-width ps-letter-page-height)
1121 (list 'ps-legal ps-legal-page-width ps-legal-page-height)
1122 (list 'ps-a4 ps-a4-page-width ps-a4-page-height)))
1123
1124 ;; Define some constants to index into the page lists.
1125 (defvar ps-page-width-i 1)
1126 (defvar ps-page-height-i 2)
1127
1128 (defvar ps-page-dimensions nil)
1129 (defvar ps-print-width nil)
1130 (defvar ps-print-height nil)
1131
1132 (defvar ps-height-remaining)
1133 (defvar ps-width-remaining)
1134
1135 (defvar ps-ref-bold-faces nil)
1136 (defvar ps-ref-italic-faces nil)
1137 (defvar ps-ref-underlined-faces nil)
1138
1139 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1140 ;; Internal functions
1141
1142 (defun ps-get-page-dimensions ()
1143 (setq ps-page-dimensions (assq ps-paper-type ps-pages-alist))
1144 (let ((ps-page-width (nth ps-page-width-i ps-page-dimensions))
1145 (ps-page-height (nth ps-page-height-i ps-page-dimensions)))
1146 (setq ps-print-height (- ps-page-height ps-top-margin ps-bottom-margin))
1147 (setq ps-print-width (- ps-page-width ps-left-margin ps-right-margin))))
1148
1149 (defun ps-print-preprint (&optional filename)
490 (if (and filename 1150 (if (and filename
491 (or (numberp filename) 1151 (or (numberp filename)
492 (listp filename))) 1152 (listp filename)))
493 (setq filename 1153 (let* ((name (concat (buffer-name) ".ps"))
494 (let* ((name (concat (buffer-name) ".ps")) 1154 (prompt (format "Save PostScript to file: (default %s) "
495 (prompt (format "Save PostScript to file: (default %s) " 1155 name)))
496 name))) 1156 (read-file-name prompt default-directory
497 (read-file-name prompt default-directory 1157 name nil))))
498 name nil))))) 1158
499 1159 ;; The following functions implement a simple list-buffering scheme so
500 (defvar ps-spool-buffer-name "*PostScript*") 1160 ;; that ps-print doesn't have to repeatedly switch between buffers
501 1161 ;; while spooling. The functions ps-output and ps-output-string build
502 (defvar ps-col 0) 1162 ;; up the lists; the function ps-flush-output takes the lists and
503 (defvar ps-row 0) 1163 ;; insert its contents into the spool buffer (*PostScript*).
504 (defvar ps-xpos 0) 1164
505 (defvar ps-ypos 0) 1165 (defun ps-output-string-prim (string)
506 1166 (insert "(") ;insert start-string delimiter
507 (defvar ps-chars-per-line 80) 1167 (save-excursion ;insert string
508 (defvar ps-lines-per-page 66) 1168 (insert string))
509 1169
510 (defvar ps-page-start-ypos 745) 1170 ;; Find and quote special characters as necessary for PS
511 (defvar ps-line-start-xpos 40) 1171 (while (re-search-forward "[()\\]" nil t)
512 1172 (save-excursion
513 (defvar ps-char-xpos-inc 6) 1173 (forward-char -1)
514 (defvar ps-line-ypos-inc 11) 1174 (insert "\\")))
515 1175
516 (defvar ps-current-font 0) 1176 (goto-char (point-max))
517 1177 (insert ")")) ;insert end-string delimiter
518 (defvar ps-multiple nil) 1178
519 (defvar ps-virtual-page-number 0) 1179 (defun ps-init-output-queue ()
1180 (setq ps-output-head (list ""))
1181 (setq ps-output-tail ps-output-head))
1182
1183 (defun ps-output (&rest args)
1184 (setcdr ps-output-tail args)
1185 (while (cdr ps-output-tail)
1186 (setq ps-output-tail (cdr ps-output-tail))))
1187
1188 (defun ps-output-string (string)
1189 (ps-output t string))
1190
1191 (defun ps-flush-output ()
1192 (save-excursion
1193 (set-buffer ps-spool-buffer)
1194 (goto-char (point-max))
1195 (while ps-output-head
1196 (let ((it (car ps-output-head)))
1197 (if (not (eq t it))
1198 (insert it)
1199 (setq ps-output-head (cdr ps-output-head))
1200 (ps-output-string-prim (car ps-output-head))))
1201 (setq ps-output-head (cdr ps-output-head))))
1202 (ps-init-output-queue))
1203
1204 (defun ps-insert-file (fname)
1205 (ps-flush-output)
1206
1207 ;; Check to see that the file exists and is readable; if not, throw
1208 ;; and error.
1209 (if (not (file-readable-p fname))
1210 (error "Could not read file `%s'" fname))
1211
1212 (save-excursion
1213 (set-buffer ps-spool-buffer)
1214 (goto-char (point-max))
1215 (insert-file fname)))
1216
1217 ;; These functions insert the arrays that define the contents of the
1218 ;; headers.
1219
1220 (defun ps-generate-header-line (fonttag &optional content)
1221 (ps-output " [ " fonttag " ")
1222 (cond
1223 ;; Literal strings should be output as is -- the string must
1224 ;; contain its own PS string delimiters, '(' and ')', if necessary.
1225 ((stringp content)
1226 (ps-output content))
1227
1228 ;; Functions are called -- they should return strings; they will be
1229 ;; inserted as strings and the PS string delimiters added.
1230 ((and (symbolp content) (fboundp content))
1231 (ps-output-string (funcall content)))
1232
1233 ;; Variables will have their contents inserted. They should
1234 ;; contain strings, and will be inserted as strings.
1235 ((and (symbolp content) (boundp content))
1236 (ps-output-string (symbol-value content)))
1237
1238 ;; Anything else will get turned into an empty string.
1239 (t
1240 (ps-output-string "")))
1241 (ps-output " ]\n"))
1242
1243 (defun ps-generate-header (name contents)
1244 (ps-output "/" name " [\n")
1245 (if (> ps-header-lines 0)
1246 (let ((count 1))
1247 (ps-generate-header-line "/h0" (car contents))
1248 (while (and (< count ps-header-lines)
1249 (setq contents (cdr contents)))
1250 (ps-generate-header-line "/h1" (car contents))
1251 (setq count (+ count 1)))
1252 (ps-output "] def\n"))))
1253
1254 (defun ps-output-boolean (name bool)
1255 (ps-output (format "/%s %s def\n" name (if bool "true" "false"))))
520 1256
521 (defun ps-begin-file () 1257 (defun ps-begin-file ()
522 (save-excursion 1258 (setq ps-showpage-count 0)
523 (set-buffer ps-output-buffer) 1259
524 (goto-char (point-min)) 1260 (ps-output ps-adobe-tag)
525 (setq ps-real-page-number 1) 1261 (ps-output "%%Title: " (buffer-name) "\n") ;Take job name from name of
526 (insert 1262 ;first buffer printed
527 "%!PS-Adobe-1.0 1263 (ps-output "%%Creator: " (user-full-name) "\n")
528 1264 (ps-output "%%CreationDate: "
529 /S /show load def 1265 (time-stamp-hh:mm:ss) " " (time-stamp-mon-dd-yyyy) "\n")
530 /M /moveto load def 1266 (ps-output "%% DocumentFonts: Helvetica Helvetica-Bold "
531 /L { gsave newpath 3 1 roll 1 sub M 0 rlineto closepath stroke grestore } def 1267 ps-font " " ps-font-bold " " ps-font-italic " "
532 1268 ps-font-bold-italic "\n")
533 /F{$fd exch get setfont}def 1269 (ps-output "%%Pages: (atend)\n")
534 1270 (ps-output "%%EndComments\n\n")
535 /StartPage{/svpg save def}def 1271
536 /EndPage{svpg restore showpage}def 1272 (ps-output-boolean "Duplex" ps-spool-duplex)
537 1273 (ps-output-boolean "PrintHeader" ps-print-header)
538 /SetUpFonts 1274 (ps-output-boolean "PrintHeaderFrame" ps-print-header-frame)
539 {dup/$fd exch array def{findfont exch scalefont $fd 3 1 roll put}repeat}def 1275 (ps-output-boolean "ShowNofN" ps-show-n-of-n)
540 1276
541 % Define /ISOLatin1Encoding only if it's not already there. 1277 (ps-output (format "/LeftMargin %d def\n" ps-left-margin))
542 /ISOLatin1Encoding where { pop save true }{ false } ifelse 1278 (ps-output (format "/RightMargin %d def\n" ps-right-margin))
543 /ISOLatin1Encoding [ StandardEncoding 0 45 getinterval aload pop /minus 1279 (ps-output (format "/BottomMargin %d def\n" ps-bottom-margin))
544 StandardEncoding 46 98 getinterval aload pop /dotlessi /grave /acute 1280 (ps-output (format "/TopMargin %d def\n" ps-top-margin))
545 /circumflex /tilde /macron /breve /dotaccent /dieresis /.notdef /ring 1281
546 /cedilla /.notdef /hungarumlaut /ogonek /caron /space /exclamdown /cent 1282 (ps-get-page-dimensions)
547 /sterling /currency /yen /brokenbar /section /dieresis /copyright 1283 (ps-output (format "/PrintWidth %d def\n" ps-print-width))
548 /ordfeminine /guillemotleft /logicalnot /hyphen /registered /macron 1284 (ps-output (format "/PrintHeight %d def\n" ps-print-height))
549 /degree /plusminus /twosuperior /threesuperior /acute /mu /paragraph 1285
550 /periodcentered /cedilla /onesuperior /ordmasculine /guillemotright 1286 (ps-output ps-print-prologue)
551 /onequarter /onehalf /threequarters /questiondown /Agrave /Aacute 1287
552 /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla /Egrave /Eacute 1288 (ps-output (format "/f0 %d /%s Font\n" ps-font-size ps-font))
553 /Ecircumflex /Edieresis /Igrave /Iacute /Icircumflex /Idieresis /Eth 1289 (ps-output (format "/f1 %d /%s Font\n" ps-font-size ps-font-bold))
554 /Ntilde /Ograve /Oacute /Ocircumflex /Otilde /Odieresis /multiply 1290 (ps-output (format "/f2 %d /%s Font\n" ps-font-size ps-font-italic))
555 /Oslash /Ugrave /Uacute /Ucircumflex /Udieresis /Yacute /Thorn 1291 (ps-output (format "/f3 %d /%s Font\n" ps-font-size
556 /germandbls /agrave /aacute /acircumflex /atilde /adieresis /aring /ae 1292 ps-font-bold-italic))
557 /ccedilla /egrave /eacute /ecircumflex /edieresis /igrave /iacute 1293
558 /icircumflex /idieresis /eth /ntilde /ograve /oacute /ocircumflex 1294 (ps-output "%%EndPrologue\n"))
559 /otilde /odieresis /divide /oslash /ugrave /uacute /ucircumflex 1295
560 /udieresis /yacute /thorn /ydieresis ] def 1296 (defun ps-header-dirpart ()
561 { restore } if 1297 (let ((fname (buffer-file-name)))
562 1298 (if fname
563 /reencodeISO { %def 1299 (if (string-equal (buffer-name) (file-name-nondirectory fname))
564 findfont dup length dict begin 1300 (file-name-directory fname)
565 { 1 index /FID ne { def }{ pop pop } ifelse } forall 1301 fname)
566 /Encoding ISOLatin1Encoding def 1302 "")))
567 currentdict end definefont pop 1303
568 } bind def 1304 (defun ps-get-buffer-name ()
569 1305 ;; Indulge me this little easter egg:
570 /CourierISO /Courier reencodeISO 1306 (if (string= (buffer-name) "ps-print.el")
571 /Courier-ObliqueISO /Courier-Oblique reencodeISO 1307 "Hey, Cool! It's ps-print.el!!!"
572 /Courier-BoldISO /Courier-Bold reencodeISO 1308 (buffer-name)))
573 /Courier-BoldObliqueISO /Courier-BoldOblique reencodeISO 1309
574 1310 (defun ps-begin-job ()
575 3 10 /Courier-BoldObliqueISO 1311 (setq ps-page-count 0))
576 2 10 /Courier-ObliqueISO
577 1 10 /Courier-BoldISO
578 0 10 /CourierISO
579 4 SetUpFonts
580
581 .4 setlinewidth
582 ")))
583 1312
584 (defun ps-end-file () 1313 (defun ps-end-file ()
585 ) 1314 (ps-output "%%Trailer\n")
1315 (ps-output "%%Pages: " (format "%d\n" ps-showpage-count)))
586 1316
587 (defun ps-next-page () 1317 (defun ps-next-page ()
588 (ps-end-page) 1318 (ps-end-page)
589 (ps-begin-page) 1319 (ps-flush-output)
1320 (ps-begin-page))
1321
1322 (defun ps-begin-page (&optional dummypage)
1323 (ps-get-page-dimensions)
1324 (setq ps-width-remaining ps-print-width)
1325 (setq ps-height-remaining ps-print-height)
1326
1327 ;; If headers are turned on, deduct the height of the header from
1328 ;; the print height remaining. Clumsy clumsy clumsy.
1329 (if ps-print-header
1330 (setq ps-height-remaining
1331 (- ps-height-remaining
1332 ps-header-title-line-height
1333 (* ps-header-line-height (- ps-header-lines 1))
1334 (* 2 ps-header-pad))))
1335
1336 (setq ps-page-count (+ ps-page-count 1))
1337
1338 (ps-output "\n%%Page: "
1339 (format "%d %d\n" ps-page-count (+ 1 ps-showpage-count)))
1340 (ps-output "BeginDSCPage\n")
1341 (ps-output (format "/PageNumber %d def\n" ps-page-count))
1342 (ps-output "/PageCount 0 def\n")
1343
1344 (if ps-print-header
1345 (progn
1346 (ps-generate-header "HeaderLinesLeft" ps-left-header)
1347 (ps-generate-header "HeaderLinesRight" ps-right-header)
1348 (ps-output (format "%d SetHeaderLines\n" ps-header-lines))))
1349
1350 (ps-output "BeginPage\n")
590 (ps-set-font ps-current-font) 1351 (ps-set-font ps-current-font)
591 (ps-init-page)) 1352 (ps-set-bg ps-current-bg)
592 1353 (ps-set-color ps-current-color)
593 (defun ps-top-of-page () (ps-next-page)) 1354 (ps-set-underline ps-current-underline-p))
594
595 (defun ps-init-page ()
596 (setq ps-row 0)
597 (setq ps-col 0)
598 (setq ps-ypos ps-page-start-ypos)
599 (setq ps-xpos ps-line-start-xpos)
600 (ps-set-font))
601
602 (defun ps-begin-page ()
603 (save-excursion
604 (set-buffer ps-output-buffer)
605 (goto-char (point-max))
606 (insert (format "%%%%Page: ? %d\n" ps-real-page-number))
607 (setq ps-real-page-number (+ 1 ps-real-page-number))
608 (insert "StartPage\n0.4 setlinewidth\n")))
609 1355
610 (defun ps-end-page () 1356 (defun ps-end-page ()
611 (save-excursion 1357 (setq ps-showpage-count (+ 1 ps-showpage-count))
612 (set-buffer ps-output-buffer) 1358 (ps-output "EndPage\n")
613 (goto-char (point-max)) 1359 (ps-output "EndDSCPage\n"))
614 (insert "EndPage\n"))) 1360
615 1361 (defun ps-dummy-page ()
1362 (setq ps-showpage-count (+ 1 ps-showpage-count))
1363 (ps-output "%%Page: " (format "- %d\n" ps-showpage-count)
1364 "BeginDSCPage
1365 /PrintHeader false def
1366 BeginPage
1367 EndPage
1368 EndDSCPage\n"))
1369
616 (defun ps-next-line () 1370 (defun ps-next-line ()
617 (setq ps-row (+ ps-row 1)) 1371 (if (< ps-height-remaining ps-line-height)
618 (if (>= ps-row ps-lines-per-page)
619 (ps-next-page) 1372 (ps-next-page)
620 (setq ps-col 0) 1373 (setq ps-width-remaining ps-print-width)
621 (setq ps-xpos ps-line-start-xpos) 1374 (setq ps-height-remaining (- ps-height-remaining ps-line-height))
622 (setq ps-ypos (- ps-ypos ps-line-ypos-inc)))) 1375 (ps-hard-lf)))
623 1376
624 (defun ps-continue-line () 1377 (defun ps-continue-line ()
625 (ps-next-line)) 1378 (if (< ps-height-remaining ps-line-height)
626 1379 (ps-next-page)
627 (defvar ps-source-buffer nil) 1380 (setq ps-width-remaining ps-print-width)
628 (defvar ps-output-buffer nil) 1381 (setq ps-height-remaining (- ps-height-remaining ps-line-height))
629 1382 (ps-soft-lf)))
630 (defun ps-basic-plot-string (from to &optional underline-p) 1383
631 (setq text (buffer-substring from to)) 1384 (defun ps-hard-lf ()
632 (save-excursion 1385 (ps-output "HL\n"))
633 (set-buffer ps-output-buffer) 1386
634 (goto-char (point-max)) 1387 (defun ps-soft-lf ()
635 (setq count (- to from)) 1388 (ps-output "SL\n"))
636 1389
637 (if underline-p 1390 (defun ps-find-wrappoint (from to char-width)
638 (insert (format "%d %d %d L\n" ps-xpos ps-ypos 1391 (let ((avail (truncate (/ ps-width-remaining char-width)))
639 (* count ps-char-xpos-inc)))) 1392 (todo (- to from)))
640 1393 (if (< todo avail)
641 (insert (format "%d %d M (" ps-xpos ps-ypos)) 1394 (cons to (* todo char-width))
642 (save-excursion 1395 (cons (+ from avail) ps-width-remaining))))
643 (insert text)) 1396
644 1397 (defun ps-basic-plot-string (from to &optional bg-color)
645 (while (re-search-forward "[()\\]" nil t) 1398 (let* ((wrappoint (ps-find-wrappoint from to ps-avg-char-width))
646 (save-excursion 1399 (to (car wrappoint))
647 (forward-char -1) 1400 (string (buffer-substring from to)))
648 (insert "\\"))) 1401 (ps-output-string string)
649 1402 (ps-output " S\n") ;
650 (end-of-line) 1403 wrappoint))
651 (insert ") S\n") 1404
652 1405 (defun ps-basic-plot-whitespace (from to &optional bg-color)
653 (setq ps-xpos (+ ps-xpos (* count ps-char-xpos-inc))))) 1406 (let* ((wrappoint (ps-find-wrappoint from to ps-space-width))
654 1407 (to (car wrappoint)))
655 (defun ps-basic-plot-whitespace (from to underline-p) 1408
656 (setq count (- to from)) 1409 (ps-output (format "%d W\n" (- to from)))
657 (setq ps-xpos (+ ps-xpos (* count ps-char-xpos-inc)))) 1410 wrappoint))
658 1411
659 (defun ps-plot (plotfunc from to &optional underline-p) 1412 (defun ps-plot (plotfunc from to &optional bg-color)
660
661 (while (< from to) 1413 (while (< from to)
662 (setq count (- to from)) 1414 (let* ((wrappoint (funcall plotfunc from to bg-color))
663 ;; Test to see whether this region will fit on the current line 1415 (plotted-to (car wrappoint))
664 (if (<= (+ ps-col count) ps-chars-per-line) 1416 (plotted-width (cdr wrappoint)))
665 (progn 1417 (setq from plotted-to)
666 ;; It fits; plot it. 1418 (setq ps-width-remaining (- ps-width-remaining plotted-width))
667 (funcall plotfunc from to underline-p) 1419 (if (< from to)
668 (setq from to)) 1420 (ps-continue-line))))
669
670 ;; It needs to be wrapped; plot part of it, then loop
671 (setq chars-that-will-fit (- ps-chars-per-line ps-col))
672 (funcall plotfunc from (+ from chars-that-will-fit))
673
674 (ps-continue-line)
675
676 (setq from (+ from chars-that-will-fit))))
677
678 (if ps-razzle-dazzle 1421 (if ps-razzle-dazzle
679 (let* ((q-todo (- (point-max) (point-min))) 1422 (let* ((q-todo (- (point-max) (point-min)))
680 (q-done (- to (point-min))) 1423 (q-done (- (point) (point-min)))
681 (chunkfrac (/ q-todo 8)) 1424 (chunkfrac (/ q-todo 8))
682 (chunksize (if (> chunkfrac 10000) 10000 chunkfrac))) 1425 (chunksize (if (> chunkfrac 1000) 1000 chunkfrac)))
683 (if (> (- q-done ps-razchunk) chunksize) 1426 (if (> (- q-done ps-razchunk) chunksize)
684 (progn 1427 (progn
685 (setq ps-razchunk q-done) 1428 (setq ps-razchunk q-done)
686 (setq foo 1429 (setq foo
687 (if (< q-todo 100) 1430 (if (< q-todo 100)
688 (* (/ q-done q-todo) 100) 1431 (/ (* 100 q-done) q-todo)
689 (setq basis (/ q-todo 100)) 1432 (/ q-done (/ q-todo 100))))
690 (/ q-done basis))) 1433 (message "Formatting...%d%%" foo))))))
691 1434
692 (message "Formatting... %d%%" foo)))))) 1435 (defun ps-set-font (font)
693 1436 (setq ps-current-font font)
694 (defun ps-set-font (&optional font) 1437 (ps-output (format "/f%d F\n" ps-current-font)))
695 (save-excursion 1438
696 (set-buffer ps-output-buffer) 1439 (defvar ps-print-color-scale (if ps-print-color-p
697 (goto-char (point-max)) 1440 (float (car (x-color-values "white")))
698 (insert (format "%d F\n" (if font font ps-current-font)))) 1441 1.0))
699 (if font 1442
700 (setq ps-current-font font))) 1443 (defun ps-set-bg (color)
701 1444 (if (setq ps-current-bg color)
702 (defun ps-plot-region (from to font &optional underline-p) 1445 (ps-output (format ps-color-format (nth 0 color) (nth 1 color)
703 1446 (nth 2 color))
704 (ps-set-font font) 1447 " true BG\n")
705 1448 (ps-output "false BG\n")))
1449
1450 (defun ps-set-color (color)
1451 (if (setq ps-current-color color)
1452 (ps-output (format ps-color-format (nth 0 ps-current-color)
1453 (nth 1 ps-current-color) (nth 2 ps-current-color))
1454 " FG\n")))
1455
1456 (defun ps-set-underline (underline-p)
1457 (ps-output (if underline-p "true" "false") " UL\n")
1458 (setq ps-current-underline-p underline-p))
1459
1460 (defun ps-plot-region (from to font fg-color &optional bg-color underline-p)
1461
1462 (if (not (equal font ps-current-font))
1463 (ps-set-font font))
1464
1465 ;; Specify a foreground color only if one's specified and it's
1466 ;; different than the current.
1467 (if (not (equal fg-color ps-current-color))
1468 (ps-set-color fg-color))
1469
1470 (if (not (equal bg-color ps-current-bg))
1471 (ps-set-bg bg-color))
1472
1473 ;; Toggle underlining if different.
1474 (if (not (equal underline-p ps-current-underline-p))
1475 (ps-set-underline underline-p))
1476
1477 ;; Starting at the beginning of the specified region...
706 (save-excursion 1478 (save-excursion
707 (goto-char from) 1479 (goto-char from)
1480
1481 ;; ...break the region up into chunks separated by tabs, linefeeds,
1482 ;; and pagefeeds, and plot each chunk.
708 (while (< from to) 1483 (while (< from to)
709 (if (re-search-forward "[\t\n\014]" to t) 1484 (if (re-search-forward "[\t\n\f]" to t)
710 (let ((match (char-after (match-beginning 0)))) 1485 (let ((match (char-after (match-beginning 0))))
711 (cond 1486 (cond
712 ((= match ?\n) 1487 ((= match ?\t)
713 (ps-plot 'ps-basic-plot-string from (- (point) 1) underline-p) 1488 (let ((linestart
714 (ps-next-line)) 1489 (save-excursion (beginning-of-line) (point))))
715 1490 (ps-plot 'ps-basic-plot-string from (- (point) 1)
716 ((= match ?\t) 1491 bg-color)
717 (ps-plot 'ps-basic-plot-string from (- (point) 1) underline-p) 1492 (forward-char -1)
718 (setq linestart (save-excursion (beginning-of-line) (point))) 1493 (setq from (+ linestart (current-column)))
719 (forward-char -1) 1494 (if (re-search-forward "[ \t]+" to t)
720 (setq from (+ linestart (current-column))) 1495 (ps-plot 'ps-basic-plot-whitespace
721 (if (re-search-forward "[ \t]+" to t) 1496 from (+ linestart (current-column))
722 (ps-plot 'ps-basic-plot-whitespace from 1497 bg-color))))
723 (+ linestart (current-column))))) 1498
724 1499 ((= match ?\n)
725 ((= match ?\014) 1500 (ps-plot 'ps-basic-plot-string from (- (point) 1)
726 (ps-plot 'ps-basic-plot-string from (- (point) 1) underline-p) 1501 bg-color)
727 (ps-top-of-page))) 1502 (ps-next-line)
1503 )
1504
1505 ((= match ?\f)
1506 (ps-plot 'ps-basic-plot-string from (- (point) 1)
1507 bg-color)
1508 (ps-next-page)))
728 (setq from (point))) 1509 (setq from (point)))
729 1510 (ps-plot 'ps-basic-plot-string from to bg-color)
730 (ps-plot 'ps-basic-plot-string from to underline-p)
731 (setq from to))))) 1511 (setq from to)))))
732 1512
733 (defun ps-format-buffer () 1513 (defun ps-color-value (x-color-value)
734 (interactive) 1514 ;; Scale 16-bit X-COLOR-VALUE to PostScript color value in [0, 1] interval.
735 1515 (/ x-color-value ps-print-color-scale))
736 (setq ps-source-buffer (current-buffer)) 1516
737 (setq ps-output-buffer (get-buffer-create "%PostScript%")) 1517 (defun ps-plot-with-face (from to face)
738 1518 (if face
739 (save-excursion 1519 (let* ((bold-p (memq face ps-ref-bold-faces))
740 (set-buffer ps-output-buffer) 1520 (italic-p (memq face ps-ref-italic-faces))
741 (delete-region (point-max) (point-min))) 1521 (underline-p (memq face ps-ref-underlined-faces))
742 1522 (foreground (face-foreground face))
743 (ps-begin-file) 1523 (background (face-background face))
744 (ps-begin-page) 1524 (fg-color (if (and ps-print-color-p foreground)
745 (ps-init-page) 1525 (mapcar 'ps-color-value
746 1526 (x-color-values foreground))
747 (ps-plot-region (point-min) (point-max) 0) 1527 ps-default-color))
748 1528 (bg-color (if (and ps-print-color-p background)
749 (ps-end-page) 1529 (mapcar 'ps-color-value
750 (ps-end-file) 1530 (x-color-values background)))))
751 ) 1531 (ps-plot-region from to
1532 (cond ((and bold-p italic-p) 3)
1533 (italic-p 2)
1534 (bold-p 1)
1535 (t 0))
1536 ; (or fg-color '(0.0 0.0 0.0))
1537 fg-color
1538 bg-color underline-p))
1539 (goto-char to)))
1540
1541
1542 (defun ps-fsf-face-kind-p (face kind kind-regex kind-list)
1543 (let ((frame-font (face-font face))
1544 (face-defaults (face-font face t)))
1545 (or
1546 ;; Check FACE defaults:
1547 (and (listp face-defaults)
1548 (memq kind face-defaults))
1549
1550 ;; Check the user's preferences
1551 (memq face kind-list))))
1552
1553 (defun ps-xemacs-face-kind-p (face kind kind-regex kind-list)
1554 (let* ((frame-font (or (face-font face) (face-font 'default)))
1555 (kind-cons (assq kind (x-font-properties frame-font)))
1556 (kind-spec (cdr-safe kind-cons))
1557 (case-fold-search t))
1558
1559 (or (and kind-spec (string-match kind-regex kind-spec))
1560 ;; Kludge-compatible:
1561 (memq face kind-list))))
1562
1563 (defun ps-face-bold-p (face)
1564 (if (eq emacs-type 'fsf)
1565 (ps-fsf-face-kind-p face 'bold "-\\(bold\\|demibold\\)-"
1566 ps-bold-faces)
1567 (ps-xemacs-face-kind-p face 'WEIGHT_NAME "bold\\|demibold"
1568 ps-bold-faces)))
1569
1570 (defun ps-face-italic-p (face)
1571 (if (eq emacs-type 'fsf)
1572 (ps-fsf-face-kind-p face 'italic "-[io]-" ps-italic-faces)
1573 (ps-xemacs-face-kind-p face 'ANGLE_NAME "i\\|o" ps-italic-faces)))
1574
1575 (defun ps-face-underlined-p (face)
1576 (or (face-underline-p face)
1577 (memq face ps-underlined-faces)))
1578
1579 (defun ps-faces-list ()
1580 (if (or (eq emacs-type 'lucid) (eq emacs-type 'xemacs))
1581 (list-faces)
1582 (face-list)))
1583
1584 (defun ps-build-reference-face-lists ()
1585 (if ps-auto-font-detect
1586 (let ((faces (ps-faces-list))
1587 the-face)
1588 (setq ps-ref-bold-faces nil
1589 ps-ref-italic-faces nil
1590 ps-ref-underlined-faces nil)
1591 (while faces
1592 (setq the-face (car faces))
1593 (if (ps-face-italic-p the-face)
1594 (setq ps-ref-italic-faces
1595 (cons the-face ps-ref-italic-faces)))
1596 (if (ps-face-bold-p the-face)
1597 (setq ps-ref-bold-faces
1598 (cons the-face ps-ref-bold-faces)))
1599 (if (ps-face-underlined-p the-face)
1600 (setq ps-ref-underlined-faces
1601 (cons the-face ps-ref-underlined-faces)))
1602 (setq faces (cdr faces))))
1603 (setq ps-ref-bold-faces ps-bold-faces)
1604 (setq ps-ref-italic-faces ps-italic-faces)
1605 (setq ps-ref-underlined-faces ps-underlined-faces))
1606 (setq ps-build-face-reference nil))
752 1607
753 (defun ps-mapper (extent list) 1608 (defun ps-mapper (extent list)
754 (nconc list (list (list (extent-start-position extent) 'push extent) 1609 (nconc list (list (list (extent-start-position extent) 'push extent)
755 (list (extent-end-position extent) 'pull extent))) 1610 (list (extent-end-position extent) 'pull extent)))
756 nil) 1611 nil)
757 1612
758 (defun ps-sorter (a b) 1613 (defun ps-sorter (a b)
759 (< (car a) (car b))) 1614 (< (car a) (car b)))
760 1615
761 (defun ps-extent-sorter (a b)
762 (< (extent-priority a) (extent-priority b)))
763
764 (defun overlay-priority (p)
765 (if (setq priority (overlay-get p 'priority)) priority 0))
766
767 (defun ps-overlay-sorter (a b)
768 (> (overlay-priority a) (overlay-priority b)))
769
770 (defun ps-plot-with-face (from to face)
771
772 (setq bold-p (memq face ps-bold-faces))
773 (setq italic-p (memq face ps-italic-faces))
774 (setq underline-p (memq face ps-underline-faces))
775
776 (cond
777 ((and bold-p italic-p)
778 (ps-plot-region from to 3 underline-p))
779 (italic-p
780 (ps-plot-region from to 2 underline-p))
781 (bold-p
782 (ps-plot-region from to 1 underline-p))
783 (t
784 (ps-plot-region from to 0 underline-p))))
785
786
787 (defun ps-generate-postscript-with-faces (from to) 1616 (defun ps-generate-postscript-with-faces (from to)
788 1617 (if (or ps-always-build-face-reference
1618 ps-build-face-reference)
1619 (progn
1620 (message "Collecting face information...")
1621 (ps-build-reference-face-lists)))
789 (save-restriction 1622 (save-restriction
790 (narrow-to-region from to) 1623 (narrow-to-region from to)
791 (setq face 'default) 1624 (let ((face 'default)
792 1625 (position to))
793 (cond ((string-match "Lucid" emacs-version) 1626 (cond ((or (eq emacs-type 'lucid) (eq emacs-type 'xemacs))
794 ;; Build the list of extents... 1627 ;; Build the list of extents...
795 (let ((a (cons 'dummy nil))) 1628 (let ((a (cons 'dummy nil))
1629 record type extent extent-list)
796 (map-extents 'ps-mapper nil from to a) 1630 (map-extents 'ps-mapper nil from to a)
797 (setq a (cdr a)) 1631 (setq a (cdr a))
798 (setq a (sort a 'ps-sorter)) 1632 (setq a (sort a 'ps-sorter))
799 1633
800 (setq extent-list nil) 1634 (setq extent-list nil)
829 'default)) 1663 'default))
830 1664
831 (setq from position) 1665 (setq from position)
832 (setq a (cdr a))))) 1666 (setq a (cdr a)))))
833 1667
834 ((string-match "^19" emacs-version) 1668 ((eq emacs-type 'fsf)
835 1669 (let ((property-change from)
836 (while (< from to) 1670 (overlay-change from))
837 1671 (while (< from to)
838 (setq prop-position 1672 (if (< property-change to) ; Don't search for property change
839 (if (setq p (next-property-change from)) 1673 ; unless previous search succeeded.
840 (if (> p to) to p) 1674 (setq property-change
841 to)) 1675 (next-property-change from nil to)))
842 1676 (if (< overlay-change to) ; Don't search for overlay change
843 (setq over-position 1677 ; unless previous search succeeded.
844 (if (setq p (next-overlay-change from)) 1678 (setq overlay-change
845 (if (> p to) to p) 1679 (min (next-overlay-change from) to)))
846 to)) 1680 (setq position
847 1681 (min property-change overlay-change))
848 (setq position 1682 (setq face
849 (if (< prop-position over-position) 1683 (cond ((get-text-property from 'invisible) nil)
850 prop-position 1684 ((get-text-property from 'face))
851 over-position)) 1685 (t 'default)))
852 1686 (let ((overlays (overlays-at from))
853 (setq face 1687 (face-priority -1)) ; text-property
854 (if (setq f (get-text-property from 'face)) f 'default))
855
856 (if (setq overlays (overlays-at from))
857 (progn
858 (setq overlays (sort overlays 'ps-overlay-sorter))
859 (while overlays 1688 (while overlays
860 (if (setq face (overlay-get (car overlays) 'face)) 1689 (let* ((overlay (car overlays))
861 (setq overlays nil) 1690 (overlay-face (overlay-get overlay 'face))
862 (setq overlays (cdr overlays)))))) 1691 (overlay-invisible (overlay-get overlay 'invisible))
863 1692 (overlay-priority (or (overlay-get overlay
864 ;; Plot up to this record. 1693 'priority)
865 (ps-plot-with-face from position face) 1694 0)))
866 1695 (if (and (or overlay-invisible overlay-face)
867 (setq from position)))) 1696 (> overlay-priority face-priority))
868 1697 (setq face (cond (overlay-invisible nil)
869 (ps-plot-with-face from to face))) 1698 ((and face overlay-face)))
1699 face-priority overlay-priority)))
1700 (setq overlays (cdr overlays))))
1701 ;; Plot up to this record.
1702 (ps-plot-with-face from position face)
1703 (setq from position)))))
1704 (ps-plot-with-face from to face))))
870 1705
871 (defun ps-generate-postscript (from to) 1706 (defun ps-generate-postscript (from to)
872 (ps-plot-region from to 0)) 1707 (ps-plot-region from to 0 nil))
873 1708
874 (defun ps-generate (buffer from to genfunc) 1709 (defun ps-generate (buffer from to genfunc)
875
876 (save-restriction 1710 (save-restriction
877 (narrow-to-region from to) 1711 (narrow-to-region from to)
878 (if ps-razzle-dazzle 1712 (if ps-razzle-dazzle
879 (message "Formatting... %d%%" (setq ps-razchunk 0))) 1713 (message "Formatting...%d%%" (setq ps-razchunk 0)))
880
881 (set-buffer buffer) 1714 (set-buffer buffer)
882 (setq ps-source-buffer buffer) 1715 (setq ps-source-buffer buffer)
883 (setq ps-output-buffer (get-buffer-create ps-spool-buffer-name)) 1716 (setq ps-spool-buffer (get-buffer-create ps-spool-buffer-name))
884 1717 (ps-init-output-queue)
885 (unwind-protect 1718 (let (safe-marker completed-safely needs-begin-file)
886 (progn 1719 (unwind-protect
887 1720 (progn
888 (set-buffer ps-output-buffer) 1721 (set-buffer ps-spool-buffer)
889 (goto-char (point-min))
890 (if (looking-at (regexp-quote "%!PS-Adobe-1.0"))
891 (ps-set-font ps-current-font)
892 (ps-begin-file))
893 (ps-begin-page)
894 (ps-init-page)
895
896 (goto-char (point-max))
897 (if (and ps-spool-duplex
898 (re-search-backward "^%%Page")
899 (looking-at "^%%Page.*[24680]$"))
900 (ps-next-page))
901 1722
902 (set-buffer ps-source-buffer) 1723 ;; Get a marker and make it point to the current end of the
903 (funcall genfunc from to) 1724 ;; buffer, If an error occurs, we'll delete everything from
904 1725 ;; the end of this marker onwards.
905 (ps-end-page))) 1726 (setq safe-marker (make-marker))
1727 (set-marker safe-marker (point-max))
1728
1729 (goto-char (point-min))
1730 (if (looking-at (regexp-quote "%!PS-Adobe-1.0"))
1731 nil
1732 (setq needs-begin-file t))
1733 (save-excursion
1734 (set-buffer ps-source-buffer)
1735 (if needs-begin-file (ps-begin-file))
1736 (ps-begin-job)
1737 (ps-begin-page))
1738 (set-buffer ps-source-buffer)
1739 (funcall genfunc from to)
1740 (ps-end-page)
1741
1742 (if (and ps-spool-duplex
1743 (= (mod ps-page-count 2) 1))
1744 (ps-dummy-page))
1745 (ps-flush-output)
1746
1747 ;; Back to the PS output buffer to set the page count
1748 (set-buffer ps-spool-buffer)
1749 (goto-char (point-max))
1750 (while (re-search-backward "^/PageCount 0 def$" nil t)
1751 (replace-match (format "/PageCount %d def" ps-page-count) t))
1752
1753 ;; Setting this variable tells the unwind form that the
1754 ;; the postscript was generated without error.
1755 (setq completed-safely t))
1756
1757 ;; Unwind form: If some bad mojo ocurred while generating
1758 ;; postscript, delete all the postscript that was generated.
1759 ;; This protects the previously spooled files from getting
1760 ;; corrupted.
1761 (if (and (markerp safe-marker) (not completed-safely))
1762 (progn
1763 (set-buffer ps-spool-buffer)
1764 (delete-region (marker-position safe-marker) (point-max))))))
906 1765
907 (if ps-razzle-dazzle 1766 (if ps-razzle-dazzle
908 (message "Formatting... Done.")))) 1767 (message "Formatting...done"))))
909 1768
910 (defun ps-do-despool (filename) 1769 (defun ps-do-despool (filename)
911 1770 (if (or (not (boundp 'ps-spool-buffer))
912 (if (or (not (boundp 'ps-output-buffer)) 1771 (not ps-spool-buffer))
913 (not ps-output-buffer)) 1772 (message "No spooled PostScript to print")
914 (message "No spooled PostScript to print.")
915
916 (ps-end-file) 1773 (ps-end-file)
917 1774 (ps-flush-output)
918 (if filename 1775 (if filename
919 (save-excursion 1776 (save-excursion
920 (if ps-razzle-dazzle 1777 (if ps-razzle-dazzle
921 (message "Saving...")) 1778 (message "Saving..."))
922 1779 (set-buffer ps-spool-buffer)
923 (set-buffer ps-output-buffer)
924 (setq filename (expand-file-name filename)) 1780 (setq filename (expand-file-name filename))
925 (write-region (point-min) (point-max) filename) 1781 (write-region (point-min) (point-max) filename)
926
927 (if ps-razzle-dazzle 1782 (if ps-razzle-dazzle
928 (message "Wrote %s" filename))) 1783 (message "Wrote %s" filename)))
929
930 ;; Else, spool to the printer 1784 ;; Else, spool to the printer
931 (if ps-razzle-dazzle 1785 (if ps-razzle-dazzle
932 (message "Printing...")) 1786 (message "Printing..."))
933
934 (save-excursion 1787 (save-excursion
935 (set-buffer ps-output-buffer) 1788 (set-buffer ps-spool-buffer)
936 (apply 'call-process-region 1789 (apply 'call-process-region
937 (point-min) (point-max) ps-lpr-command nil 0 nil 1790 (point-min) (point-max) ps-lpr-command nil 0 nil
938 ps-lpr-switches)) 1791 ps-lpr-switches))
939
940 (if ps-razzle-dazzle 1792 (if ps-razzle-dazzle
941 (message "Printing... Done."))) 1793 (message "Printing...done")))
942 1794 (kill-buffer ps-spool-buffer)))
943 (kill-buffer ps-output-buffer))) 1795
944 1796 (defun ps-kill-emacs-check ()
945 (defun ps-testpattern () 1797 (let (ps-buffer)
946 (setq foo 1) 1798 (if (and (setq ps-buffer (get-buffer ps-spool-buffer-name))
947 (while (< foo 60) 1799 (buffer-modified-p ps-buffer))
948 (insert "|" (make-string foo ?\ ) (format "%d\n" foo)) 1800 (if (y-or-n-p "Unprinted PostScript waiting; print now? ")
949 (setq foo (+ 1 foo)))) 1801 (ps-despool)))
950 1802 (if (and (setq ps-buffer (get-buffer ps-spool-buffer-name))
951 (defun pts (stuff) 1803 (buffer-modified-p ps-buffer))
1804 (if (yes-or-no-p "Unprinted PostScript waiting; exit anyway? ")
1805 nil
1806 (error "Unprinted PostScript")))))
1807
1808 (if (fboundp 'add-hook)
1809 (add-hook 'kill-emacs-hook 'ps-kill-emacs-check)
1810 (if kill-emacs-hook
1811 (message "Won't override existing kill-emacs-hook")
1812 (setq kill-emacs-hook 'ps-kill-emacs-check)))
1813
1814 ;;; Sample Setup Code:
1815
1816 ;; This stuff is for anybody that's brave enough to look this far,
1817 ;; and able to figure out how to use it. It isn't really part of ps-
1818 ;; print, but I'll leave it here in hopes it might be useful:
1819
1820 ;; Look in an article or mail message for the Subject: line. To be
1821 ;; placed in ps-left-headers.
1822 (defun ps-article-subject ()
952 (save-excursion 1823 (save-excursion
953 (set-buffer "*scratch*") 1824 (goto-char (point-min))
954 (goto-char (point-max)) 1825 (if (re-search-forward "^Subject:[ \t]+\\(.*\\)$")
955 (insert "---------------------------------\n" 1826 (buffer-substring (match-beginning 1) (match-end 1))
956 (symbol-name stuff) ":\n" 1827 "Subject ???")))
957 (prin1-to-string (symbol-value stuff)) 1828
958 "\n"))) 1829 ;; Look in an article or mail message for the From: line. Sorta-kinda
1830 ;; understands RFC-822 addresses and can pull the real name out where
1831 ;; it's provided. To be placed in ps-left-headers.
1832 (defun ps-article-author ()
1833 (save-excursion
1834 (goto-char (point-min))
1835 (if (re-search-forward "^From:[ \t]+\\(.*\\)$")
1836 (let ((fromstring (buffer-substring (match-beginning 1) (match-end 1))))
1837 (cond
1838
1839 ;; Try first to match addresses that look like
1840 ;; thompson@wg2.waii.com (Jim Thompson)
1841 ((string-match ".*[ \t]+(\\(.*\\))" fromstring)
1842 (substring fromstring (match-beginning 1) (match-end 1)))
1843
1844 ;; Next try to match addresses that look like
1845 ;; Jim Thompson <thompson@wg2.waii.com>
1846 ((string-match "\\(.*\\)[ \t]+<.*>" fromstring)
1847 (substring fromstring (match-beginning 1) (match-end 1)))
1848
1849 ;; Couldn't find a real name -- show the address instead.
1850 (t fromstring)))
1851 "From ???")))
1852
1853 ;; A hook to bind to gnus-Article-prepare-hook. This will set the ps-
1854 ;; left-headers specially for gnus articles. Unfortunately, gnus-
1855 ;; article-mode-hook is called only once, the first time the *Article*
1856 ;; buffer enters that mode, so it would only work for the first time
1857 ;; we ran gnus. The second time, this hook wouldn't get set up. The
1858 ;; only alternative is gnus-article-prepare-hook.
1859 (defun ps-gnus-article-prepare-hook ()
1860 (setq ps-header-lines 3)
1861 (setq ps-left-header
1862 ;; The left headers will display the article's subject, its
1863 ;; author, and the newsgroup it was in.
1864 (list 'ps-article-subject 'ps-article-author 'gnus-newsgroup-name)))
1865
1866 ;; A hook to bind to vm-mode-hook to locally bind prsc and set the ps-
1867 ;; left-headers specially for mail messages. This header setup would
1868 ;; also work, I think, for RMAIL.
1869 (defun ps-vm-mode-hook ()
1870 (local-set-key 'f22 'ps-vm-print-message-from-summary)
1871 (setq ps-header-lines 3)
1872 (setq ps-left-header
1873 ;; The left headers will display the message's subject, its
1874 ;; author, and the name of the folder it was in.
1875 (list 'ps-article-subject 'ps-article-author 'buffer-name)))
1876
1877 ;; Every now and then I forget to switch from the *Summary* buffer to
1878 ;; the *Article* before hitting prsc, and a nicely formatted list of
1879 ;; article subjects shows up at the printer. This function, bound to
1880 ;; prsc for the gnus *Summary* buffer means I don't have to switch
1881 ;; buffers first.
1882 (defun ps-gnus-print-article-from-summary ()
1883 (interactive)
1884 (if (get-buffer "*Article*")
1885 (save-excursion
1886 (set-buffer "*Article*")
1887 (ps-spool-buffer-with-faces))))
1888
1889 ;; See ps-gnus-print-article-from-summary. This function does the
1890 ;; same thing for vm.
1891 (defun ps-vm-print-message-from-summary ()
1892 (interactive)
1893 (if vm-mail-buffer
1894 (save-excursion
1895 (set-buffer vm-mail-buffer)
1896 (ps-spool-buffer-with-faces))))
1897
1898 ;; A hook to bind to bind to gnus-summary-setup-buffer to locally bind
1899 ;; prsc.
1900 (defun ps-gnus-summary-setup ()
1901 (local-set-key 'f22 'ps-gnus-print-article-from-summary))
1902
1903 ;; File: lispref.info, Node: Standard Errors
1904
1905 ;; Look in an article or mail message for the Subject: line. To be
1906 ;; placed in ps-left-headers.
1907 (defun ps-info-file ()
1908 (save-excursion
1909 (goto-char (point-min))
1910 (if (re-search-forward "File:[ \t]+\\([^, \t\n]*\\)")
1911 (buffer-substring (match-beginning 1) (match-end 1))
1912 "File ???")))
1913
1914 ;; Look in an article or mail message for the Subject: line. To be
1915 ;; placed in ps-left-headers.
1916 (defun ps-info-node ()
1917 (save-excursion
1918 (goto-char (point-min))
1919 (if (re-search-forward "Node:[ \t]+\\([^,\t\n]*\\)")
1920 (buffer-substring (match-beginning 1) (match-end 1))
1921 "Node ???")))
1922
1923 (defun ps-info-mode-hook ()
1924 (setq ps-left-header
1925 ;; The left headers will display the node name and file name.
1926 (list 'ps-info-node 'ps-info-file)))
1927
1928 (defun ps-jts-ps-setup ()
1929 (global-set-key 'f22 'ps-spool-buffer-with-faces) ;f22 is prsc
1930 (global-set-key '(shift f22) 'ps-spool-region-with-faces)
1931 (global-set-key '(control f22) 'ps-despool)
1932 (add-hook 'gnus-article-prepare-hook 'ps-gnus-article-prepare-hook)
1933 (add-hook 'gnus-summary-mode-hook 'ps-gnus-summary-setup)
1934 (add-hook 'vm-mode-hook 'ps-vm-mode-hook)
1935 (add-hook 'Info-mode-hook 'ps-info-mode-hook)
1936 (setq ps-spool-duplex t)
1937 (setq ps-print-color-p nil)
1938 (setq ps-lpr-command "lpr")
1939 (setq ps-lpr-switches '("-Jjct,duplex_long")))
959 1940
960 (provide 'ps-print) 1941 (provide 'ps-print)
961 1942 ;;; ps-print.el ends here
962 ;; ps-print.el ends here