]> code.delx.au - gnu-emacs/blob - lisp/ps-print.el
(fast_install): Bring commands up-to-date, and fix typo.
[gnu-emacs] / lisp / ps-print.el
1 ;;; ps-print.el --- Print text from the buffer as PostScript
2
3 ;; Copyright (C) 1993, 94, 95, 96, 97, 98, 1999 Free Software Foundation, Inc.
4
5 ;; Author: Jim Thompson (was <thompson@wg2.waii.com>)
6 ;; Author: Jacques Duthen (was <duthen@cegelec-red.fr>)
7 ;; Author: Vinicius Jose Latorre <vinicius@cpqd.com.br>
8 ;; Author: Kenichi Handa <handa@etl.go.jp> (multi-byte characters)
9 ;; Maintainer: Kenichi Handa <handa@etl.go.jp> (multi-byte characters)
10 ;; Maintainer: Vinicius Jose Latorre <vinicius@cpqd.com.br>
11 ;; Keywords: wp, print, PostScript
12 ;; Time-stamp: <99/07/03 20:16:48 vinicius>
13 ;; Version: 5.0
14
15 (defconst ps-print-version "5.0"
16 "ps-print.el, v 5.0 <99/07/03 vinicius>
17
18 Vinicius's last change version -- this file may have been edited as part of
19 Emacs without changes to the version number. When reporting bugs,
20 please also report the version of Emacs, if any, that ps-print was
21 distributed with.
22
23 Please send all bug fixes and enhancements to
24 Vinicius Jose Latorre <vinicius@cpqd.com.br>.
25 ")
26
27 ;; This file is part of GNU Emacs.
28
29 ;; GNU Emacs is free software; you can redistribute it and/or modify
30 ;; it under the terms of the GNU General Public License as published by
31 ;; the Free Software Foundation; either version 2, or (at your option)
32 ;; any later version.
33
34 ;; GNU Emacs is distributed in the hope that it will be useful,
35 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
36 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
37 ;; GNU General Public License for more details.
38
39 ;; You should have received a copy of the GNU General Public License
40 ;; along with GNU Emacs; see the file COPYING. If not, write to the
41 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
42 ;; Boston, MA 02111-1307, USA.
43
44 ;;; Commentary:
45
46 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
47 ;;
48 ;; About ps-print
49 ;; --------------
50 ;;
51 ;; This package provides printing of Emacs buffers on PostScript
52 ;; printers; the buffer's bold and italic text attributes are
53 ;; preserved in the printer output. ps-print is intended for use with
54 ;; Emacs 19 or Lucid Emacs, together with a fontifying package such as
55 ;; font-lock or hilit.
56 ;;
57 ;; ps-print uses the same face attributes defined through font-lock or hilit
58 ;; to print a PostScript file, but some faces are better seeing on the screen
59 ;; than on paper, specially when you have a black/white PostScript printer.
60 ;;
61 ;; ps-print allows a remap of face to another one that it is better to print,
62 ;; for example, the face font-lock-comment-face (if you are using font-lock)
63 ;; could have bold or italic attribute when printing, besides foreground color.
64 ;; This remap improves printing look (see How Ps-Print Maps Faces).
65 ;;
66 ;;
67 ;; Using ps-print
68 ;; --------------
69 ;;
70 ;; ps-print provides eight commands for generating PostScript images
71 ;; of Emacs buffers:
72 ;;
73 ;; ps-print-buffer
74 ;; ps-print-buffer-with-faces
75 ;; ps-print-region
76 ;; ps-print-region-with-faces
77 ;; ps-spool-buffer
78 ;; ps-spool-buffer-with-faces
79 ;; ps-spool-region
80 ;; ps-spool-region-with-faces
81 ;;
82 ;; These commands all perform essentially the same function: they
83 ;; generate PostScript images suitable for printing on a PostScript
84 ;; printer or displaying with GhostScript. These commands are
85 ;; collectively referred to as "ps-print- commands".
86 ;;
87 ;; The word "print" or "spool" in the command name determines when the
88 ;; PostScript image is sent to the printer:
89 ;;
90 ;; print - The PostScript image is immediately sent to the
91 ;; printer;
92 ;;
93 ;; spool - The PostScript image is saved temporarily in an
94 ;; Emacs buffer. Many images may be spooled locally
95 ;; before printing them. To send the spooled images
96 ;; to the printer, use the command `ps-despool'.
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-hook' so that you won't
105 ;; accidentally 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 ;;
143 ;; To print your buffer, type
144 ;;
145 ;; M-x ps-print-buffer
146 ;;
147 ;; or substitute one of the other seven ps-print- commands. The
148 ;; command will generate the PostScript image and print or spool it as
149 ;; specified. By giving the command a prefix argument
150 ;;
151 ;; C-u M-x ps-print-buffer
152 ;;
153 ;; it will save the PostScript image to a file instead of sending it
154 ;; to the printer; you will be prompted for the name of the file to
155 ;; save the image to. The prefix argument is ignored by the commands
156 ;; that spool their images, but you may save the spooled images to a
157 ;; file by giving a prefix argument to `ps-despool':
158 ;;
159 ;; C-u M-x ps-despool
160 ;;
161 ;; When invoked this way, `ps-despool' will prompt you for the name of
162 ;; the file to save to.
163 ;;
164 ;; Any of the `ps-print-' commands can be bound to keys; I recommend
165 ;; binding `ps-spool-buffer-with-faces', `ps-spool-region-with-faces',
166 ;; and `ps-despool'. Here are the bindings I use on my Sun 4 keyboard:
167 ;;
168 ;; (global-set-key 'f22 'ps-spool-buffer-with-faces) ;f22 is prsc
169 ;; (global-set-key '(shift f22) 'ps-spool-region-with-faces)
170 ;; (global-set-key '(control f22) 'ps-despool)
171 ;;
172 ;;
173 ;; The Printer Interface
174 ;; ---------------------
175 ;;
176 ;; The variables `ps-lpr-command' and `ps-lpr-switches' determine what
177 ;; command is used to send the PostScript images to the printer, and
178 ;; what arguments to give the command. These are analogous to
179 ;; `lpr-command' and `lpr-switches'.
180 ;;
181 ;; Make sure that they contain appropriate values for your system;
182 ;; see the usage notes below and the documentation of these variables.
183 ;;
184 ;; The variable `ps-printer-name' determines the name of a local printer for
185 ;; printing PostScript files.
186 ;;
187 ;; NOTE: `ps-lpr-command' and `ps-lpr-switches' take their initial values
188 ;; from the variables `lpr-command' and `lpr-switches'. If you have
189 ;; `lpr-command' set to invoke a pretty-printer such as `enscript',
190 ;; then ps-print won't work properly. `ps-lpr-command' must name
191 ;; a program that does not format the files it prints.
192 ;; `ps-printer-name' takes its initial value from the variable
193 ;; `printer-name'.
194 ;;
195 ;; The variable `ps-print-region-function' specifies a function to print the
196 ;; region on a PostScript printer.
197 ;; See definition of `call-process-region' for calling conventions. The fourth
198 ;; and the sixth arguments are both nil.
199 ;;
200 ;;
201 ;; The Page Layout
202 ;; ---------------
203 ;;
204 ;; All dimensions are floats in PostScript points.
205 ;; 1 inch == 2.54 cm == 72 points
206 ;; 1 cm == (/ 1 2.54) inch == (/ 72 2.54) points
207 ;;
208 ;; The variable `ps-paper-type' determines the size of paper ps-print
209 ;; formats for; it should contain one of the symbols:
210 ;; `a4' `a3' `letter' `legal' `letter-small' `tabloid'
211 ;; `ledger' `statement' `executive' `a4small' `b4' `b5'
212 ;;
213 ;; The variable `ps-landscape-mode' determines the orientation
214 ;; of the printing on the page:
215 ;; nil means `portrait' mode, non-nil means `landscape' mode.
216 ;; There is no oblique mode yet, though this is easy to do in ps.
217 ;;
218 ;; In landscape mode, the text is NOT scaled: you may print 70 lines
219 ;; in portrait mode and only 50 lignes in landscape mode.
220 ;; The margins represent margins in the printed paper:
221 ;; the top margin is the margin between the top of the page
222 ;; and the printed header, whatever the orientation is.
223 ;;
224 ;; The variable `ps-number-of-columns' determines the number of columns
225 ;; both in landscape and portrait mode.
226 ;; You can use:
227 ;; - (the standard) one column portrait mode
228 ;; - (my favorite) two columns landscape mode (which spares trees)
229 ;; but also
230 ;; - one column landscape mode for files with very long lines.
231 ;; - multi-column portrait or landscape mode
232 ;;
233 ;;
234 ;; Horizontal layout
235 ;; -----------------
236 ;;
237 ;; The horizontal layout is determined by the variables
238 ;; `ps-left-margin' `ps-inter-column' `ps-right-margin'
239 ;; as follows:
240 ;;
241 ;; ------------------------------------------
242 ;; | | | | | | | |
243 ;; | lm | text | ic | text | ic | text | rm |
244 ;; | | | | | | | |
245 ;; ------------------------------------------
246 ;;
247 ;; If `ps-number-of-columns' is 1, `ps-inter-column' is not relevant.
248 ;; Usually, lm = rm > 0 and ic = lm
249 ;; If (ic < 0), the text of adjacent columns can overlap.
250 ;;
251 ;;
252 ;; Vertical layout
253 ;; ---------------
254 ;;
255 ;; The vertical layout is determined by the variables
256 ;; `ps-bottom-margin' `ps-top-margin' `ps-header-offset'
257 ;; as follows:
258 ;;
259 ;; |--------| |--------|
260 ;; | tm | | tm |
261 ;; |--------| |--------|
262 ;; | header | | |
263 ;; |--------| | |
264 ;; | ho | | |
265 ;; |--------| or | text |
266 ;; | | | |
267 ;; | text | | |
268 ;; | | | |
269 ;; |--------| |--------|
270 ;; | bm | | bm |
271 ;; |--------| |--------|
272 ;;
273 ;; If `ps-print-header' is nil, `ps-header-offset' is not relevant.
274 ;; The margins represent margins in the printed paper:
275 ;; the top margin is the margin between the top of the page
276 ;; and the printed header, whatever the orientation is.
277 ;;
278 ;;
279 ;; Headers
280 ;; -------
281 ;;
282 ;; ps-print can print headers at the top of each column or at the top
283 ;; of each page; the default headers contain the following four items:
284 ;; on the left, the name of the buffer and, if the buffer is visiting
285 ;; a file, the file's directory; on the right, the page number and
286 ;; date of printing. The default headers look something like this:
287 ;;
288 ;; ps-print.el 1/21
289 ;; /home/jct/emacs-lisp/ps/new 94/12/31
290 ;;
291 ;; When printing on duplex printers, left and right are reversed so
292 ;; that the page numbers are toward the outside (cf. `ps-spool-duplex').
293 ;;
294 ;; Headers are configurable:
295 ;; To turn them off completely, set `ps-print-header' to nil.
296 ;; To turn off the header's gaudy framing box,
297 ;; set `ps-print-header-frame' to nil.
298 ;;
299 ;; To print only one header at the top of each page,
300 ;; set `ps-print-only-one-header' to t.
301 ;;
302 ;; The font family and size of text in the header are determined
303 ;; by the variables `ps-header-font-family', `ps-header-font-size' and
304 ;; `ps-header-title-font-size' (see below).
305 ;;
306 ;; The variable `ps-header-line-pad' determines the portion of a header
307 ;; title line height to insert between the header frame and the text
308 ;; it contains, both in the vertical and horizontal directions:
309 ;; .5 means half a line.
310
311 ;; Page numbers are printed in `n/m' format, indicating page n of m pages;
312 ;; to omit the total page count and just print the page number,
313 ;; set `ps-show-n-of-n' to nil.
314 ;;
315 ;; The amount of information in the header can be changed by changing
316 ;; the number of lines. To show less, set `ps-header-lines' to 1, and
317 ;; the header will show only the buffer name and page number. To show
318 ;; more, set `ps-header-lines' to 3, and the header will show the time of
319 ;; printing below the date.
320 ;;
321 ;; To change the content of the headers, change the variables
322 ;; `ps-left-header' and `ps-right-header'.
323 ;; These variables are lists, specifying top-to-bottom the text
324 ;; to display on the left or right side of the header.
325 ;; Each element of the list should be a string or a symbol.
326 ;; Strings are inserted directly into the PostScript arrays,
327 ;; and should contain the PostScript string delimiters '(' and ')'.
328 ;;
329 ;; Symbols in the header format lists can either represent functions
330 ;; or variables. Functions are called, and should return a string to
331 ;; show in the header. Variables should contain strings to display in
332 ;; the header. In either case, function or variable, the PostScript
333 ;; string delimiters are added by ps-print, and should not be part of
334 ;; the returned value.
335 ;;
336 ;; Here's an example: say we want the left header to display the text
337 ;;
338 ;; Moe
339 ;; Larry
340 ;; Curly
341 ;;
342 ;; where we have a function to return "Moe"
343 ;;
344 ;; (defun moe-func ()
345 ;; "Moe")
346 ;;
347 ;; a variable specifying "Larry"
348 ;;
349 ;; (setq larry-var "Larry")
350 ;;
351 ;; and a literal for "Curly". Here's how `ps-left-header' should be
352 ;; set:
353 ;;
354 ;; (setq ps-left-header (list 'moe-func 'larry-var "(Curly)"))
355 ;;
356 ;; Note that Curly has the PostScript string delimiters inside his
357 ;; quotes -- those aren't misplaced lisp delimiters!
358 ;;
359 ;; Without them, PostScript would attempt to call the undefined
360 ;; function Curly, which would result in a PostScript error.
361 ;;
362 ;; Since most printers don't report PostScript errors except by
363 ;; aborting the print job, this kind of error can be hard to track down.
364 ;;
365 ;; Consider yourself warned!
366 ;;
367 ;;
368 ;; PostScript Prologue Header
369 ;; --------------------------
370 ;;
371 ;; It is possible to add PostScript prologue header comments besides that
372 ;; ps-print generates by setting the variable `ps-print-prologue-header'.
373 ;;
374 ;; `ps-print-prologue-header' may be a string or a symbol function which returns
375 ;; a string. Note that this string is inserted on PostScript prologue header
376 ;; section which is used to define some document characteristic through
377 ;; PostScript special comments, like "%%Requirements: jog\n".
378 ;;
379 ;; By default `ps-print-prologue-header' is nil.
380 ;;
381 ;; ps-print always inserts the %%Requirements: comment, so if you need to insert
382 ;; more requirements put them first in `ps-print-prologue-header' using the
383 ;; "%%+" comment. For example, if you need to set numcopies to 3 and jog on
384 ;; requirements and set %%LanguageLevel: to 2, do:
385 ;;
386 ;; (setq ps-print-prologue-header
387 ;; "%%+ numcopies(3) jog\n%%LanguageLevel: 2\n")
388 ;;
389 ;; The duplex requirement is inserted by ps-print (see section Duplex Printers).
390 ;;
391 ;; Do not forget to terminate the string with "\n".
392 ;;
393 ;; For more information about PostScript document comments, see:
394 ;; PostScript Language Reference Manual (2nd edition)
395 ;; Adobe Systems Incorporated
396 ;; Appendix G: Document Structuring Conventions -- Version 3.0
397 ;;
398 ;;
399 ;; Duplex Printers
400 ;; ---------------
401 ;;
402 ;; If you have a duplex-capable printer (one that prints both sides of the
403 ;; paper), set `ps-spool-duplex' to t.
404 ;; ps-print will insert blank pages to make sure each buffer starts on the
405 ;; correct side of the paper.
406 ;;
407 ;; The variable `ps-spool-config' specifies who is the responsable for setting
408 ;; duplex and page size switches. Valid values are:
409 ;;
410 ;; lpr-switches duplex and page size are configured by `ps-lpr-switches'.
411 ;; Don't forget to set `ps-lpr-switches' to select duplex
412 ;; printing for your printer.
413 ;;
414 ;; setpagedevice duplex and page size are configured by ps-print using the
415 ;; setpagedevice PostScript operator.
416 ;;
417 ;; nil duplex and page size are configured by ps-print *not* using
418 ;; the setpagedevice PostScript operator.
419 ;;
420 ;; Any other value is treated as nil.
421 ;;
422 ;; The default value is `lpr-switches'.
423 ;;
424 ;; WARNING: The setpagedevice PostScript operator affects ghostview utility when
425 ;; viewing file generated using landscape. Also on some printers,
426 ;; setpagedevice affects zebra stripes; on other printers,
427 ;; setpagedevice affects the left margin.
428 ;; Besides all that, if your printer does not have the paper size
429 ;; specified by setpagedevice, your printing will be aborted.
430 ;; So, if you need to use setpagedevice, set `ps-spool-config' to
431 ;; `setpagedevice', generate a test file and send it to your printer;
432 ;; if the printed file isn't ok, set `ps-spool-config' to nil.
433 ;;
434 ;; The variable `ps-spool-tumble' specifies how the page images on opposite
435 ;; sides of a sheet are oriented with respect to each other. If
436 ;; `ps-spool-tumble' is nil, produces output suitable for binding on the left or
437 ;; right. If `ps-spool-tumble' is non-nil, produces output suitable for binding
438 ;; at the top or bottom. It has effect only when `ps-spool-duplex' is non-nil.
439 ;; The default value is nil.
440 ;;
441 ;; Some printer system prints a header page and forces the first page be printed
442 ;; on header page back, when using duplex. If your printer system has this
443 ;; behavior, set variable `ps-banner-page-when-duplexing' to t.
444 ;;
445 ;; When `ps-banner-page-when-duplexing' is non-nil means the very first page is
446 ;; skipped. It's like the very first character of buffer (or region) is ^L
447 ;; (\014).
448 ;;
449 ;; The default for `ps-banner-page-when-duplexing' is nil (*don't* skip the very
450 ;; first page).
451 ;;
452 ;;
453 ;; N-up Printing
454 ;; -------------
455 ;;
456 ;; The variable `ps-n-up-printing' specifies the number of pages per sheet of
457 ;; paper. The value specified must be between 1 and 100. The default is 1.
458 ;;
459 ;; NOTE: some PostScript printer may crash printing if `ps-n-up-printing' is set
460 ;; to a high value (for example, 23). If this happens, set a lower value.
461 ;;
462 ;; The variable `ps-n-up-margin' specifies the margin in points between the
463 ;; sheet border and the n-up printing. The default is 1 cm (or 0.3937 inches,
464 ;; or 28.35 points).
465 ;;
466 ;; If variable `ps-n-up-border-p' is non-nil a border is drawn around each page.
467 ;; The default is t.
468 ;;
469 ;; The variable `ps-n-up-filling' specifies how page matrix is filled on each
470 ;; sheet of paper. Following are the valid values for `ps-n-up-filling' with a
471 ;; filling example using a 3x4 page matrix:
472 ;;
473 ;; left-top 1 2 3 4 left-bottom 9 10 11 12
474 ;; 5 6 7 8 5 6 7 8
475 ;; 9 10 11 12 1 2 3 4
476 ;;
477 ;; right-top 4 3 2 1 right-bottom 12 11 10 9
478 ;; 8 7 6 5 8 7 6 5
479 ;; 12 11 10 9 4 3 2 1
480 ;;
481 ;; top-left 1 4 7 10 bottom-left 3 6 9 12
482 ;; 2 5 8 11 2 5 8 11
483 ;; 3 6 9 12 1 4 7 10
484 ;;
485 ;; top-right 10 7 4 1 bottom-right 12 9 6 3
486 ;; 11 8 5 2 11 8 5 2
487 ;; 12 9 6 3 10 7 4 1
488 ;;
489 ;; Any other value is treated as left-top.
490 ;;
491 ;; The default value is left-top.
492 ;;
493 ;;
494 ;; Control And 8-bit Characters
495 ;; ----------------------------
496 ;;
497 ;; The variable `ps-print-control-characters' specifies whether you want to see
498 ;; a printable form for control and 8-bit characters, that is, instead of
499 ;; sending, for example, a ^D (\004) to printer, it is sent the string "^D".
500 ;;
501 ;; Valid values for `ps-print-control-characters' are:
502 ;;
503 ;; 8-bit This is the value to use when you want an ASCII encoding of
504 ;; any control or non-ASCII character. Control characters are
505 ;; encoded as "^D", and non-ASCII characters have an
506 ;; octal encoding.
507 ;;
508 ;; control-8-bit This is the value to use when you want an ASCII encoding of
509 ;; any control character, whether it is 7 or 8-bit.
510 ;; European 8-bits accented characters are printed according
511 ;; the current font.
512 ;;
513 ;; control Only ASCII control characters have an ASCII encoding.
514 ;; European 8-bits accented characters are printed according
515 ;; the current font.
516 ;;
517 ;; nil No ASCII encoding. Any character is printed according the
518 ;; current font.
519 ;;
520 ;; Any other value is treated as nil.
521 ;;
522 ;; The default is `control-8-bit'.
523 ;;
524 ;; Characters TAB, NEWLINE and FORMFEED are always treated by ps-print engine.
525 ;;
526 ;;
527 ;; Printing Multi-byte Buffer
528 ;; --------------------------
529 ;;
530 ;; See ps-mule.el for documentation.
531 ;;
532 ;; See ps-print-def.el for definition.
533 ;;
534 ;;
535 ;; Line Number
536 ;; -----------
537 ;;
538 ;; The variable `ps-line-number' specifies whether to number each line;
539 ;; non-nil means do so. The default is nil (don't number each line).
540 ;;
541 ;;
542 ;; Zebra Stripes
543 ;; -------------
544 ;;
545 ;; Zebra stripes are a kind of background that appear "underneath" the text
546 ;; and can make the text easier to read. They look like this:
547 ;;
548 ;; XXXXXXXXXXXXXXXXXXXXXXXX
549 ;; XXXXXXXXXXXXXXXXXXXXXXXX
550 ;; XXXXXXXXXXXXXXXXXXXXXXXX
551 ;;
552 ;;
553 ;;
554 ;; XXXXXXXXXXXXXXXXXXXXXXXX
555 ;; XXXXXXXXXXXXXXXXXXXXXXXX
556 ;; XXXXXXXXXXXXXXXXXXXXXXXX
557 ;;
558 ;; The blocks of X's represent rectangles filled with a light gray color.
559 ;; Each rectangle extends all the way across the page.
560 ;;
561 ;; The height, in lines, of each rectangle is controlled by
562 ;; the variable `ps-zebra-stripe-height', which is 3 by default.
563 ;; The distance between stripes equals the height of a stripe.
564 ;;
565 ;; The variable `ps-zebra-stripes' controls whether to print zebra stripes.
566 ;; Non-nil means yes, nil means no. The default is nil.
567 ;;
568 ;; The variable `ps-zebra-gray' controls the zebra stripes gray scale.
569 ;; It should be a float number between 0.0 (black color) and 1.0 (white color).
570 ;; The default is 0.95.
571 ;;
572 ;; See also section How Ps-Print Has A Text And/Or Image On Background.
573 ;;
574 ;;
575 ;; Hooks
576 ;; -----
577 ;;
578 ;; ps-print has the following hook variables:
579 ;;
580 ;; `ps-print-hook'
581 ;; It is evaluated once before any printing process. This is the right
582 ;; place to initialize ps-print global data.
583 ;; For an example, see section Adding a New Font Family.
584 ;;
585 ;; `ps-print-begin-sheet-hook'
586 ;; It is evaluated on each beginning of sheet of paper.
587 ;; If `ps-n-up-printing' is equal to 1, `ps-print-begin-page-hook' is never
588 ;; evaluated.
589 ;;
590 ;; `ps-print-begin-page-hook'
591 ;; It is evaluated on each beginning of page, except in the beginning
592 ;; of page that `ps-print-begin-sheet-hook' is evaluated.
593 ;;
594 ;; `ps-print-begin-column-hook'
595 ;; It is evaluated on each beginning of column, except in the beginning
596 ;; of column that `ps-print-begin-page-hook' is evaluated or that
597 ;; `ps-print-begin-sheet-hook' is evaluated.
598 ;;
599 ;;
600 ;; Font Managing
601 ;; -------------
602 ;;
603 ;; ps-print now knows rather precisely some fonts: the variable
604 ;; `ps-font-info-database' contains information for a list of font families
605 ;; (currently mainly `Courier' `Helvetica' `Times' `Palatino' `Helvetica-Narrow'
606 ;; `NewCenturySchlbk'). Each font family contains the font names for standard,
607 ;; bold, italic and bold-italic characters, a reference size (usually 10) and
608 ;; the corresponding line height, width of a space and average character width.
609 ;;
610 ;; The variable `ps-font-family' determines which font family is to be used for
611 ;; ordinary text. If its value does not correspond to a known font family, an
612 ;; error message is printed into the `*Messages*' buffer, which lists the
613 ;; currently available font families.
614 ;;
615 ;; The variable `ps-font-size' determines the size (in points) of the font for
616 ;; ordinary text, when generating PostScript. Its value is a float or a cons of
617 ;; floats which has the following form:
618 ;;
619 ;; (LANDSCAPE-SIZE . PORTRAIT-SIZE)
620 ;;
621 ;; Similarly, the variable `ps-header-font-family' determines which font family
622 ;; is to be used for text in the header.
623 ;;
624 ;; The variable `ps-header-font-size' determines the font size, in points, for
625 ;; text in the header (similar to `ps-font-size').
626 ;;
627 ;; The variable `ps-header-title-font-size' determines the font size, in points,
628 ;; for the top line of text in the header (similar to `ps-font-size').
629 ;;
630 ;;
631 ;; Adding a New Font Family
632 ;; ------------------------
633 ;;
634 ;; To use a new font family, you MUST first teach ps-print
635 ;; this font, i.e., add its information to `ps-font-info-database',
636 ;; otherwise ps-print cannot correctly place line and page breaks.
637 ;;
638 ;; For example, assuming `Helvetica' is unknown,
639 ;; you first need to do the following ONLY ONCE:
640 ;;
641 ;; - create a new buffer
642 ;; - generate the PostScript image to a file (C-u M-x ps-print-buffer)
643 ;; - open this file and find the line:
644 ;; `% 3 cm 20 cm moveto 10 /Courier ReportFontInfo showpage'
645 ;; - delete the leading `%' (which is the PostScript comment character)
646 ;; - replace in this line `Courier' by the new font (say `Helvetica')
647 ;; to get the line:
648 ;; `3 cm 20 cm moveto 10 /Helvetica ReportFontInfo showpage'
649 ;; - send this file to the printer (or to ghostscript).
650 ;; You should read the following on the output page:
651 ;;
652 ;; For Helvetica 10 point, the line height is 11.56, the space width is 2.78
653 ;; and a crude estimate of average character width is 5.09243
654 ;;
655 ;; - Add these values to the `ps-font-info-database':
656 ;; (setq ps-font-info-database
657 ;; (append
658 ;; '((Helvetica ; the family key
659 ;; (fonts (normal . "Helvetica")
660 ;; (bold . "Helvetica-Bold")
661 ;; (italic . "Helvetica-Oblique")
662 ;; (bold-italic . "Helvetica-BoldOblique"))
663 ;; (size . 10.0)
664 ;; (line-height . 11.56)
665 ;; (space-width . 2.78)
666 ;; (avg-char-width . 5.09243)))
667 ;; ps-font-info-database))
668 ;; - Now you can use this font family with any size:
669 ;; (setq ps-font-family 'Helvetica)
670 ;; - if you want to use this family in another emacs session, you must
671 ;; put into your `~/.emacs':
672 ;; (require 'ps-print)
673 ;; (setq ps-font-info-database (append ...)))
674 ;; if you don't want to load ps-print, you have to copy the whole value:
675 ;; (setq ps-font-info-database '(<your stuff> <the standard stuff>))
676 ;; or, use `ps-print-hook' (see section Hooks):
677 ;; (add-hook 'ps-print-hook
678 ;; '(lambda ()
679 ;; (or (assq 'Helvetica ps-font-info-database)
680 ;; (setq ps-font-info-database (append ...)))))
681 ;;
682 ;; You can create new `mixed' font families like:
683 ;; (my-mixed-family
684 ;; (fonts (normal . "Courier-Bold")
685 ;; (bold . "Helvetica")
686 ;; (italic . "Zapf-Chancery-MediumItalic")
687 ;; (bold-italic . "NewCenturySchlbk-BoldItalic")
688 ;; (w3-table-hack-x-face . "LineDrawNormal"))
689 ;; (size . 10.0)
690 ;; (line-height . 10.55)
691 ;; (space-width . 6.0)
692 ;; (avg-char-width . 6.0))
693 ;;
694 ;; Now you can use your new font family with any size:
695 ;; (setq ps-font-family 'my-mixed-family)
696 ;;
697 ;; Note that on above example the `w3-table-hack-x-face' entry refers to
698 ;; a face symbol, so when printing this face it'll be used the font
699 ;; `LineDrawNormal'. If the face `w3-table-hack-x-face' is remapped to
700 ;; use bold and/or italic attribute, the corresponding entry (bold, italic
701 ;; or bold-italic) will be used instead of `w3-table-hack-x-face' entry.
702 ;;
703 ;; Note also that the font family entry order is irrelevant, so the above
704 ;; example could also be written:
705 ;; (my-mixed-family
706 ;; (size . 10.0)
707 ;; (fonts (w3-table-hack-x-face . "LineDrawNormal")
708 ;; (bold . "Helvetica")
709 ;; (bold-italic . "NewCenturySchlbk-BoldItalic")
710 ;; (italic . "Zapf-Chancery-MediumItalic")
711 ;; (normal . "Courier-Bold"))
712 ;; (avg-char-width . 6.0)
713 ;; (space-width . 6.0)
714 ;; (line-height . 10.55))
715 ;;
716 ;; Despite the note above, it is recommended that some convention about
717 ;; entry order be used.
718 ;;
719 ;; You can get information on all the fonts resident in YOUR printer
720 ;; by uncommenting the line:
721 ;; % 3 cm 20 cm moveto ReportAllFontInfo showpage
722 ;;
723 ;; The PostScript file should be sent to YOUR PostScript printer.
724 ;; If you send it to ghostscript or to another PostScript printer,
725 ;; you may get slightly different results.
726 ;; Anyway, as ghostscript fonts are autoload, you won't get
727 ;; much font info.
728 ;;
729 ;;
730 ;; How Ps-Print Deals With Faces
731 ;; -----------------------------
732 ;;
733 ;; The ps-print-*-with-faces commands attempt to determine which faces
734 ;; should be printed in bold or italic, but their guesses aren't
735 ;; always right. For example, you might want to map colors into faces
736 ;; so that blue faces print in bold, and red faces in italic.
737 ;;
738 ;; It is possible to force ps-print to consider specific faces bold,
739 ;; italic or underline, no matter what font they are displayed in, by setting
740 ;; the variables `ps-bold-faces', `ps-italic-faces' and `ps-underlined-faces'.
741 ;; These variables contain lists of faces that ps-print should consider bold,
742 ;; italic or underline; to set them, put code like the following into your
743 ;; .emacs file:
744 ;;
745 ;; (setq ps-bold-faces '(my-blue-face))
746 ;; (setq ps-italic-faces '(my-red-face))
747 ;; (setq ps-underlined-faces '(my-green-face))
748 ;;
749 ;; Faces like bold-italic that are both bold and italic should go in
750 ;; *both* lists.
751 ;;
752 ;; ps-print keeps internal lists of which fonts are bold and which are
753 ;; italic; these lists are built the first time you invoke ps-print.
754 ;; For the sake of efficiency, the lists are built only once; the same
755 ;; lists are referred in later invocations of ps-print.
756 ;;
757 ;; Because these lists are built only once, it's possible for them to
758 ;; get out of sync, if a face changes, or if new faces are added. To
759 ;; get the lists back in sync, you can set the variable
760 ;; `ps-build-face-reference' to t, and the lists will be rebuilt the
761 ;; next time ps-print is invoked. If you need that the lists always be
762 ;; rebuilt when ps-print is invoked, set the variable
763 ;; `ps-always-build-face-reference' to t.
764 ;;
765 ;;
766 ;; How Ps-Print Deals With Color
767 ;; -----------------------------
768 ;;
769 ;; ps-print detects faces with foreground and background colors
770 ;; defined and embeds color information in the PostScript image.
771 ;; The default foreground and background colors are defined by the
772 ;; variables `ps-default-fg' and `ps-default-bg'.
773 ;; On black-and-white printers, colors are displayed in grayscale.
774 ;; To turn off color output, set `ps-print-color-p' to nil.
775 ;;
776 ;;
777 ;; How Ps-Print Maps Faces
778 ;; -----------------------
779 ;;
780 ;; As ps-print uses PostScript to print buffers, it is possible to have
781 ;; other attributes associated with faces. So the new attributes used
782 ;; by ps-print are:
783 ;;
784 ;; strikeout - like underline, but the line is in middle of text.
785 ;; overline - like underline, but the line is over the text.
786 ;; shadow - text will have a shadow.
787 ;; box - text will be surrounded by a box.
788 ;; outline - print characters as hollow outlines.
789 ;;
790 ;; See the documentation for `ps-extend-face'.
791 ;;
792 ;; Let's, for example, remap `font-lock-keyword-face' to another foreground
793 ;; color and bold attribute:
794 ;;
795 ;; (ps-extend-face '(font-lock-keyword-face "RoyalBlue" nil bold) 'MERGE)
796 ;;
797 ;; If you want to use a new face, define it first with `defface',
798 ;; and then call `ps-extend-face' to specify how to print it.
799 ;;
800 ;;
801 ;; How Ps-Print Has A Text And/Or Image On Background
802 ;; --------------------------------------------------
803 ;;
804 ;; ps-print can print texts and/or EPS PostScript images on background; it is
805 ;; possible to define the following text attributes: font name, font size,
806 ;; initial position, angle, gray scale and pages to print.
807 ;;
808 ;; It has the following EPS PostScript images attributes: file name containing
809 ;; the image, initial position, X and Y scales, angle and pages to print.
810 ;;
811 ;; See documentation for `ps-print-background-text' and
812 ;; `ps-print-background-image'.
813 ;;
814 ;; For example, if we wish to print text "preliminary" on all pages and text
815 ;; "special" on page 5 and from page 11 to page 17, we could specify:
816 ;;
817 ;; (setq ps-print-background-text
818 ;; '(("preliminary")
819 ;; ("special"
820 ;; "LeftMargin" "BottomMargin PrintHeight add" ; X and Y position
821 ;; ; (upper left corner)
822 ;; nil nil nil
823 ;; "PrintHeight neg PrintPageWidth atan" ; angle
824 ;; 5 (11 . 17)) ; page list
825 ;; ))
826 ;;
827 ;; Similarly, we could print image "~/images/EPS-image1.ps" on all pages and
828 ;; image "~/images/EPS-image2.ps" on page 5 and from page 11 to page 17, we
829 ;; specify:
830 ;;
831 ;; (setq ps-print-background-image
832 ;; '(("~/images/EPS-image1.ps"
833 ;; "LeftMargin" "BottomMargin") ; X and Y position (lower left corner)
834 ;; ("~/images/EPS-image2.ps"
835 ;; "LeftMargin" "BottomMargin PrintHeight 2 div add" ; X and Y position
836 ;; ; (upper left corner)
837 ;; nil nil nil
838 ;; 5 (11 . 17)) ; page list
839 ;; ))
840 ;;
841 ;; If it is not possible to read (or does not exist) an image file, that file
842 ;; is ignored.
843 ;;
844 ;; The printing order is:
845 ;;
846 ;; 1. Print zebra stripes
847 ;; 2. Print background texts that it should be on all pages
848 ;; 3. Print background images that it should be on all pages
849 ;; 4. Print background texts only for current page (if any)
850 ;; 5. Print background images only for current page (if any)
851 ;; 6. Print header
852 ;; 7. Print buffer text (with faces, if specified) and line number
853 ;;
854 ;;
855 ;; Utilities
856 ;; ---------
857 ;;
858 ;; Some tools are provided to help you customize your font setup.
859 ;;
860 ;; `ps-setup' returns (some part of) the current setup.
861 ;;
862 ;; To avoid wrapping too many lines, you may want to adjust the
863 ;; left and right margins and the font size. On UN*X systems, do:
864 ;; pr -t file | awk '{printf "%3d %s\n", length($0), $0}' | sort -r | head
865 ;; to determine the longest lines of your file.
866 ;; Then, the command `ps-line-lengths' will give you the correspondence
867 ;; between a line length (number of characters) and the maximum font
868 ;; size which doesn't wrap such a line with the current ps-print setup.
869 ;;
870 ;; The commands `ps-nb-pages-buffer' and `ps-nb-pages-region' display
871 ;; the correspondence between a number of pages and the maximum font
872 ;; size which allow the number of lines of the current buffer or of
873 ;; its current region to fit in this number of pages.
874 ;;
875 ;; NOTE: line folding is not taken into account in this process and could
876 ;; change the results.
877 ;;
878 ;;
879 ;; New since version 1.5
880 ;; ---------------------
881 ;;
882 ;; Color output capability.
883 ;; Automatic detection of font attributes (bold, italic).
884 ;; Configurable headers with page numbers.
885 ;; Slightly faster.
886 ;; Support for different paper sizes.
887 ;; Better conformance to PostScript Document Structure Conventions.
888 ;;
889 ;;
890 ;; New since version 2.8
891 ;; ---------------------
892 ;;
893 ;; [vinicius] 990703 Vinicius Jose Latorre <vinicius@cpqd.com.br>
894 ;;
895 ;; Better customization.
896 ;; `ps-banner-page-when-duplexing' and `ps-zebra-gray'.
897 ;;
898 ;; [vinicius] 990513 Vinicius Jose Latorre <vinicius@cpqd.com.br>
899 ;;
900 ;; N-up printing.
901 ;; Hook: `ps-print-begin-sheet-hook'.
902 ;;
903 ;; [keinichi] 990509 Kein'ichi Handa <handa@etl.go.jp>
904 ;;
905 ;; `ps-print-region-function'
906 ;;
907 ;; [vinicius] 990301 Vinicius Jose Latorre <vinicius@cpqd.com.br>
908 ;;
909 ;; PostScript tumble and setpagedevice.
910 ;;
911 ;; [vinicius] 980922 Vinicius Jose Latorre <vinicius@cpqd.com.br>
912 ;;
913 ;; PostScript prologue header comment insertion.
914 ;; Skip invisible text better.
915 ;;
916 ;; [keinichi] 980819 Kein'ichi Handa <handa@etl.go.jp>
917 ;;
918 ;; Multi-byte buffer handling.
919 ;;
920 ;; [vinicius] 980306 Vinicius Jose Latorre <vinicius@cpqd.com.br>
921 ;;
922 ;; Skip invisible text.
923 ;;
924 ;; [vinicius] 971130 Vinicius Jose Latorre <vinicius@cpqd.com.br>
925 ;;
926 ;; Hooks: `ps-print-hook', `ps-print-begin-page-hook' and
927 ;; `ps-print-begin-column-hook'.
928 ;; Put one header per page over the columns.
929 ;; Better database font management.
930 ;; Better control characters handling.
931 ;;
932 ;; [vinicius] 971121 Vinicius Jose Latorre <vinicius@cpqd.com.br>
933 ;;
934 ;; Dynamic evaluation at print time of `ps-lpr-switches'.
935 ;; Handle control characters.
936 ;; Face remapping.
937 ;; New face attributes.
938 ;; Line number.
939 ;; Zebra stripes.
940 ;; Text and/or image on background.
941 ;;
942 ;; [jack] 960517 Jacques Duthen <duthen@cegelec-red.fr>
943 ;;
944 ;; Font family and float size for text and header.
945 ;; Landscape mode.
946 ;; Multiple columns.
947 ;; Tools for page setup.
948 ;;
949 ;;
950 ;; Known bugs and limitations of ps-print
951 ;; --------------------------------------
952 ;;
953 ;; Although color printing will work in XEmacs 19.12, it doesn't work
954 ;; well; in particular, bold or italic fonts don't print in the right
955 ;; background color.
956 ;;
957 ;; Invisible properties aren't correctly ignored in XEmacs 19.12.
958 ;;
959 ;; Automatic font-attribute detection doesn't work well, especially
960 ;; with hilit19 and older versions of get-create-face. Users having
961 ;; problems with auto-font detection should use the lists
962 ;; `ps-italic-faces', `ps-bold-faces' and `ps-underlined-faces' and/or
963 ;; turn off automatic detection by setting `ps-auto-font-detect' to nil.
964 ;;
965 ;; Automatic font-attribute detection doesn't work with XEmacs 19.12
966 ;; in tty mode; use the lists `ps-italic-faces', `ps-bold-faces' and
967 ;; `ps-underlined-faces' instead.
968 ;;
969 ;; Still too slow; could use some hand-optimization.
970 ;;
971 ;; Default background color isn't working.
972 ;;
973 ;; Faces are always treated as opaque.
974 ;;
975 ;; Epoch and Emacs 18 not supported. At all.
976 ;;
977 ;; Fixed-pitch fonts work better for line folding, but are not required.
978 ;;
979 ;; `ps-nb-pages-buffer' and `ps-nb-pages-region' don't take care
980 ;; of folding lines.
981 ;;
982 ;;
983 ;; Things to change
984 ;; ----------------
985 ;;
986 ;; Avoid page break inside a paragraph.
987 ;; Add `ps-non-bold-faces' and `ps-non-italic-faces' (should be easy).
988 ;; Improve the memory management for big files (hard?).
989 ;; `ps-nb-pages-buffer' and `ps-nb-pages-region' should take care
990 ;; of folding lines.
991 ;;
992 ;;
993 ;; Acknowledgements
994 ;; ----------------
995 ;;
996 ;; Thanks to Kein'ichi Handa <handa@etl.go.jp> for multi-byte buffer handling.
997 ;;
998 ;; Thanks to Matthew O Persico <Matthew.Persico@lazard.com> for line number on
999 ;; empty columns.
1000 ;;
1001 ;; Thanks to Theodore Jump <tjump@cais.com> for adjust PostScript code order on
1002 ;; last page.
1003 ;;
1004 ;; Thanks to Roland Ducournau <ducour@lirmm.fr> for
1005 ;; `ps-print-control-characters' variable documentation.
1006 ;;
1007 ;; Thanks to Marcus G Daniels <marcus@cathcart.sysc.pdx.edu> for a better
1008 ;; database font management.
1009 ;;
1010 ;; Thanks to Martin Boyer <gamin@videotron.ca> for some ideas on putting one
1011 ;; header per page over the columns and correct line numbers when printing a
1012 ;; region.
1013 ;;
1014 ;; Thanks to Steven L Baur <steve@miranova.com> for dynamic evaluation at
1015 ;; print time of `ps-lpr-switches'.
1016 ;;
1017 ;; Thanks to Kevin Rodgers <kevinr@ihs.com> for handling control characters
1018 ;; (his code was severely modified, but the main idea was kept).
1019 ;;
1020 ;; Thanks to some suggestions on:
1021 ;; * Face color map: Marco Melgazzi <marco@techie.com>
1022 ;; * XEmacs compatibility: William J. Henney <will@astrosmo.unam.mx>
1023 ;; * Check `ps-paper-type': Sudhakar Frederick <sfrederi@asc.corp.mot.com>
1024 ;;
1025 ;; Thanks to Jacques Duthen <duthen@cegelec-red.fr> (Jack) for the 3.4 version
1026 ;; I started from. [vinicius]
1027 ;;
1028 ;; Thanks to Jim Thompson <?@?> for the 2.8 version I started from.
1029 ;; [jack]
1030 ;;
1031 ;; Thanks to Kevin Rodgers <kevinr@ihs.com> for adding support for
1032 ;; color and the invisible property.
1033 ;;
1034 ;; Thanks to Avishai Yacobi, avishaiy@mcil.comm.mot.com, for writing
1035 ;; the initial port to Emacs 19. His code is no longer part of
1036 ;; ps-print, but his work is still appreciated.
1037 ;;
1038 ;; Thanks to Remi Houdaille and Michel Train, michel@metasoft.fdn.org,
1039 ;; for adding underline support. Their code also is no longer part of
1040 ;; ps-print, but their efforts are not forgotten.
1041 ;;
1042 ;; Thanks also to all of you who mailed code to add features to
1043 ;; ps-print; although I didn't use your code, I still appreciate your
1044 ;; sharing it with me.
1045 ;;
1046 ;; Thanks to all who mailed comments, encouragement, and criticism.
1047 ;; Thanks also to all who responded to my survey; I had too many
1048 ;; responses to reply to them all, but I greatly appreciate your
1049 ;; interest.
1050 ;;
1051 ;; Jim
1052 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1053
1054 ;;; Code:
1055
1056 (unless (featurep 'lisp-float-type)
1057 (error "`ps-print' requires floating point support"))
1058
1059 ;; For Emacs 20.2 and the earlier version.
1060 (eval-and-compile
1061 (and (boundp 'mule-version) ; only if mule package is loaded
1062 (string< mule-version "4.0")
1063 (progn
1064 (defun set-buffer-multibyte (arg)
1065 (setq enable-multibyte-characters arg))
1066 (defun string-as-unibyte (arg) arg)
1067 (defun string-as-multibyte (arg) arg)
1068 (defun charset-after (&optional arg)
1069 (char-charset (char-after arg))))))
1070
1071 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1072 ;; User Variables:
1073
1074 ;;; Interface to the command system
1075
1076 (defgroup postscript nil
1077 "PostScript Group"
1078 :tag "PostScript"
1079 :group 'emacs)
1080
1081 (defgroup ps-print nil
1082 "PostScript generator for Emacs 19"
1083 :prefix "ps-"
1084 :group 'wp
1085 :group 'postscript)
1086
1087 (defgroup ps-print-horizontal nil
1088 "Horizontal page layout"
1089 :prefix "ps-"
1090 :tag "Horizontal"
1091 :group 'ps-print)
1092
1093 (defgroup ps-print-vertical nil
1094 "Vertical page layout"
1095 :prefix "ps-"
1096 :tag "Vertical"
1097 :group 'ps-print)
1098
1099 (defgroup ps-print-header nil
1100 "Headers layout"
1101 :prefix "ps-"
1102 :tag "Header"
1103 :group 'ps-print)
1104
1105 (defgroup ps-print-font nil
1106 "Fonts customization"
1107 :prefix "ps-"
1108 :tag "Font"
1109 :group 'ps-print)
1110
1111 (defgroup ps-print-color nil
1112 "Color customization"
1113 :prefix "ps-"
1114 :tag "Color"
1115 :group 'ps-print)
1116
1117 (defgroup ps-print-face nil
1118 "Faces customization"
1119 :prefix "ps-"
1120 :tag "PS Faces"
1121 :group 'ps-print
1122 :group 'faces)
1123
1124 (defgroup ps-print-n-up nil
1125 "N-up customization"
1126 :prefix "ps-"
1127 :tag "N-Up"
1128 :group 'ps-print)
1129
1130 (defgroup ps-print-zebra nil
1131 "Zebra customization"
1132 :prefix "ps-"
1133 :tag "Zebra"
1134 :group 'ps-print)
1135
1136 (defgroup ps-print-background nil
1137 "Background customization"
1138 :prefix "ps-"
1139 :tag "Background"
1140 :group 'ps-print)
1141
1142 (defgroup ps-print-printer nil
1143 "Printer customization"
1144 :prefix "ps-"
1145 :tag "Printer"
1146 :group 'ps-print)
1147
1148 (defgroup ps-print-page nil
1149 "Page customization"
1150 :prefix "ps-"
1151 :tag "Page"
1152 :group 'ps-print)
1153
1154
1155 (require 'ps-vars) ; Common definitions
1156
1157
1158 (defcustom ps-print-prologue-header nil
1159 "*PostScript prologue header comments besides that ps-print generates.
1160
1161 `ps-print-prologue-header' may be a string or a symbol function which
1162 returns a string. Note that this string is inserted on PostScript prologue
1163 header section which is used to define some document characteristic through
1164 PostScript special comments, like \"%%Requirements: jog\\n\".
1165
1166 ps-print always inserts the %%Requirements: comment, so if you need to insert
1167 more requirements put them first in `ps-print-prologue-header' using the
1168 \"%%+\" comment. For example, if you need to set numcopies to 3 and jog on
1169 requirements and set %%LanguageLevel: to 2, do:
1170
1171 (setq ps-print-prologue-header
1172 \"%%+ numcopies(3) jog\\n%%LanguageLevel: 2\\n\")
1173
1174 The duplex requirement is inserted by ps-print (see `ps-spool-duplex').
1175
1176 Do not forget to terminate the string with \"\\n\".
1177
1178 For more information about PostScript document comments, see:
1179 PostScript Language Reference Manual (2nd edition)
1180 Adobe Systems Incorporated
1181 Appendix G: Document Structuring Conventions -- Version 3.0"
1182 :type '(choice :tag "Prologue Header"
1183 string symbol (other :tag "nil" nil))
1184 :group 'ps-print)
1185
1186 (defcustom ps-printer-name (and (boundp 'printer-name)
1187 printer-name)
1188 "*The name of a local printer for printing PostScript files.
1189
1190 On Unix-like systems, a string value should be a name understood by
1191 lpr's -P option; a value of nil means use the value of `printer-name'
1192 instead. Any other value will be ignored.
1193
1194 On MS-DOS and MS-Windows systems, a string value is taken as the name of
1195 the printer device or port to which PostScript files are written,
1196 provided `ps-lpr-command' is \"\". By default it is the same as
1197 `printer-name'; typical non-default settings would be \"LPT1\" to
1198 \"LPT3\" for parallel printers, or \"COM1\" to \"COM4\" or \"AUX\" for
1199 serial printers, or \"//hostname/printer\" for a shared network printer.
1200 You can also set it to a name of a file, in which case the output gets
1201 appended to that file. \(Note that `ps-print' package already has
1202 facilities for printing to a file, so you might as well use them instead
1203 of changing the setting of this variable.\) If you want to silently
1204 discard the printed output, set this to \"NUL\"."
1205 :type '(choice :tag "Printer Name"
1206 file (other :tag "Pipe to ps-lpr-command" pipe))
1207 :group 'ps-print-printer)
1208
1209 (defcustom ps-lpr-command lpr-command
1210 "*Name of program for printing a PostScript file.
1211
1212 On MS-DOS and MS-Windows systems, if the value is an empty string then
1213 Emacs will write directly to the printer port named by `ps-printer-name'.
1214 The programs `print' and `nprint' (the standard print programs on Windows
1215 NT and Novell Netware respectively) are handled specially, using
1216 `ps-printer-name' as the destination for output; any other program is
1217 treated like `lpr' except that an explicit filename is given as the last
1218 argument."
1219 :type 'string
1220 :group 'ps-print-printer)
1221
1222 (defcustom ps-lpr-switches lpr-switches
1223 "*A list of extra switches to pass to `ps-lpr-command'."
1224 :type '(repeat string)
1225 :group 'ps-print-printer)
1226
1227 (defcustom ps-print-region-function nil
1228 "*Specify a function to print the region on a PostScript printer.
1229 See definition of `call-process-region' for calling conventions. The fourth and
1230 the sixth arguments are both nil."
1231 :type 'function
1232 :group 'ps-print-printer)
1233
1234 ;;; Page layout
1235
1236 ;; All page dimensions are in PostScript points.
1237 ;; 1 inch == 2.54 cm == 72 points
1238 ;; 1 cm == (/ 1 2.54) inch == (/ 72 2.54) points
1239
1240 ;; Letter 8.5 inch x 11.0 inch
1241 ;; Legal 8.5 inch x 14.0 inch
1242 ;; A4 8.26 inch x 11.69 inch = 21.0 cm x 29.7 cm
1243
1244 ;; LetterSmall 7.68 inch x 10.16 inch
1245 ;; Tabloid 11.0 inch x 17.0 inch
1246 ;; Ledger 17.0 inch x 11.0 inch
1247 ;; Statement 5.5 inch x 8.5 inch
1248 ;; Executive 7.5 inch x 10.0 inch
1249 ;; A3 11.69 inch x 16.5 inch = 29.7 cm x 42.0 cm
1250 ;; A4Small 7.47 inch x 10.85 inch
1251 ;; B4 10.125 inch x 14.33 inch
1252 ;; B5 7.16 inch x 10.125 inch
1253
1254 (defcustom ps-page-dimensions-database
1255 (list (list 'a4 (/ (* 72 21.0) 2.54) (/ (* 72 29.7) 2.54) "A4")
1256 (list 'a3 (/ (* 72 29.7) 2.54) (/ (* 72 42.0) 2.54) "A3")
1257 (list 'letter (* 72 8.5) (* 72 11.0) "Letter")
1258 (list 'legal (* 72 8.5) (* 72 14.0) "Legal")
1259 (list 'letter-small (* 72 7.68) (* 72 10.16) "LetterSmall")
1260 (list 'tabloid (* 72 11.0) (* 72 17.0) "Tabloid")
1261 (list 'ledger (* 72 17.0) (* 72 11.0) "Ledger")
1262 (list 'statement (* 72 5.5) (* 72 8.5) "Statement")
1263 (list 'executive (* 72 7.5) (* 72 10.0) "Executive")
1264 (list 'a4small (* 72 7.47) (* 72 10.85) "A4Small")
1265 (list 'b4 (* 72 10.125) (* 72 14.33) "B4")
1266 (list 'b5 (* 72 7.16) (* 72 10.125) "B5"))
1267 "*List associating a symbolic paper type to its width, height and doc media.
1268 See `ps-paper-type'."
1269 :type '(repeat (list :tag "Paper Type"
1270 (symbol :tag "Name")
1271 (number :tag "Width")
1272 (number :tag "Height")
1273 (string :tag "Media")))
1274 :group 'ps-print-page)
1275
1276 ;;;###autoload
1277 (defcustom ps-paper-type 'letter
1278 "*Specify the size of paper to format for.
1279 Should be one of the paper types defined in `ps-page-dimensions-database', for
1280 example `letter', `legal' or `a4'."
1281 :type '(symbol :validate (lambda (wid)
1282 (if (assq (widget-value wid)
1283 ps-page-dimensions-database)
1284 nil
1285 (widget-put wid :error "Unknown paper size")
1286 wid)))
1287 :group 'ps-print-page)
1288
1289 (defcustom ps-landscape-mode nil
1290 "*Non-nil means print in landscape mode."
1291 :type 'boolean
1292 :group 'ps-print-page)
1293
1294 (defcustom ps-print-control-characters 'control-8-bit
1295 "*Specify the printable form for control and 8-bit characters.
1296 That is, instead of sending, for example, a ^D (\\004) to printer,
1297 it is sent the string \"^D\".
1298
1299 Valid values are:
1300
1301 `8-bit' This is the value to use when you want an ASCII encoding of
1302 any control or non-ASCII character. Control characters are
1303 encoded as \"^D\", and non-ASCII characters have an
1304 octal encoding.
1305
1306 `control-8-bit' This is the value to use when you want an ASCII encoding of
1307 any control character, whether it is 7 or 8-bit.
1308 European 8-bits accented characters are printed according
1309 the current font.
1310
1311 `control' Only ASCII control characters have an ASCII encoding.
1312 European 8-bits accented characters are printed according
1313 the current font.
1314
1315 nil No ASCII encoding. Any character is printed according the
1316 current font.
1317
1318 Any other value is treated as nil."
1319 :type '(choice :tag "Control Char"
1320 (const 8-bit) (const control-8-bit)
1321 (const control) (other :tag "nil" nil))
1322 :group 'ps-print)
1323
1324 (defcustom ps-n-up-printing 1
1325 "*Specify the number of pages per sheet paper."
1326 :type '(integer
1327 :tag "N Up Printing"
1328 :validate
1329 (lambda (wid)
1330 (if (and (< 0 (widget-value wid))
1331 (<= (widget-value wid) 100))
1332 nil
1333 (widget-put
1334 wid :error
1335 "Number of pages per sheet paper must be between 1 and 100.")
1336 wid)))
1337 :group 'ps-print-n-up)
1338
1339 (defcustom ps-n-up-margin (/ (* 72 1.0) 2.54) ; 1 cm
1340 "*Specify the margin in points between the sheet border and n-up printing."
1341 :type 'number
1342 :group 'ps-print-n-up)
1343
1344 (defcustom ps-n-up-border-p t
1345 "*Non-nil means a border is drawn around each page."
1346 :type 'boolean
1347 :group 'ps-print-n-up)
1348
1349 (defcustom ps-n-up-filling 'left-top
1350 "*Specify how page matrix is filled on each sheet of paper.
1351
1352 Following are the valid values for `ps-n-up-filling' with a filling example
1353 using a 3x4 page matrix:
1354
1355 `left-top' 1 2 3 4 `left-bottom' 9 10 11 12
1356 5 6 7 8 5 6 7 8
1357 9 10 11 12 1 2 3 4
1358
1359 `right-top' 4 3 2 1 `right-bottom' 12 11 10 9
1360 8 7 6 5 8 7 6 5
1361 12 11 10 9 4 3 2 1
1362
1363 `top-left' 1 4 7 10 `bottom-left' 3 6 9 12
1364 2 5 8 11 2 5 8 11
1365 3 6 9 12 1 4 7 10
1366
1367 `top-right' 10 7 4 1 `bottom-right' 12 9 6 3
1368 11 8 5 2 11 8 5 2
1369 12 9 6 3 10 7 4 1
1370
1371 Any other value is treated as `left-top'."
1372 :type '(choice :tag "N-Up Filling"
1373 (const left-top) (const left-bottom)
1374 (const right-top) (const right-bottom)
1375 (const top-left) (const bottom-left)
1376 (const top-right) (const bottom-right))
1377 :group 'ps-print-n-up)
1378
1379 (defcustom ps-number-of-columns (if ps-landscape-mode 2 1)
1380 "*Specify the number of columns"
1381 :type 'number
1382 :group 'ps-print)
1383
1384 (defcustom ps-zebra-stripes nil
1385 "*Non-nil means print zebra stripes.
1386 See also documentation for `ps-zebra-stripe-height' and `ps-zebra-gray'."
1387 :type 'boolean
1388 :group 'ps-print-zebra)
1389
1390 (defcustom ps-zebra-stripe-height 3
1391 "*Number of zebra stripe lines.
1392 See also documentation for `ps-zebra-stripes' and `ps-zebra-gray'."
1393 :type 'number
1394 :group 'ps-print-zebra)
1395
1396 (defcustom ps-zebra-gray 0.95
1397 "*Zebra stripe gray scale.
1398 See also documentation for `ps-zebra-stripes' and `ps-zebra-stripe-height'."
1399 :type 'number
1400 :group 'ps-print-zebra)
1401
1402 (defcustom ps-line-number nil
1403 "*Non-nil means print line number."
1404 :type 'boolean
1405 :group 'ps-print)
1406
1407 (defcustom ps-print-background-image nil
1408 "*EPS image list to be printed on background.
1409
1410 The elements are:
1411
1412 (FILENAME X Y XSCALE YSCALE ROTATION PAGES...)
1413
1414 FILENAME is a file name which contains an EPS image or some PostScript
1415 programming like EPS.
1416 FILENAME is ignored, if it doesn't exist or is read protected.
1417
1418 X and Y are relative positions on paper to put the image.
1419 If X and Y are nil, the image is centralized on paper.
1420
1421 XSCALE and YSCALE are scale factor to be applied to image before printing.
1422 If XSCALE and YSCALE are nil, the original size is used.
1423
1424 ROTATION is the image rotation angle; if nil, the default is 0.
1425
1426 PAGES designates the page to print background image.
1427 PAGES may be a number or a cons cell (FROM . TO) designating FROM page
1428 to TO page.
1429 If PAGES is nil, print background image on all pages.
1430
1431 X, Y, XSCALE, YSCALE and ROTATION may be a floating point number,
1432 an integer number or a string. If it is a string, the string should contain
1433 PostScript programming that returns a float or integer value.
1434
1435 For example, if you wish to print an EPS image on all pages do:
1436
1437 '((\"~/images/EPS-image.ps\"))"
1438 :type '(repeat (list (file :tag "EPS File")
1439 (choice :tag "X" number string (const nil))
1440 (choice :tag "Y" number string (const nil))
1441 (choice :tag "X Scale" number string (const nil))
1442 (choice :tag "Y Scale" number string (const nil))
1443 (choice :tag "Rotation" number string (const nil))
1444 (repeat :tag "Pages" :inline t
1445 (radio (integer :tag "Page")
1446 (cons :tag "Range"
1447 (integer :tag "From")
1448 (integer :tag "To"))))))
1449 :group 'ps-print-background)
1450
1451 (defcustom ps-print-background-text nil
1452 "*Text list to be printed on background.
1453
1454 The elements are:
1455
1456 (STRING X Y FONT FONTSIZE GRAY ROTATION PAGES...)
1457
1458 STRING is the text to be printed on background.
1459
1460 X and Y are positions on paper to put the text.
1461 If X and Y are nil, the text is positioned at lower left corner.
1462
1463 FONT is a font name to be used on printing the text.
1464 If nil, \"Times-Roman\" is used.
1465
1466 FONTSIZE is font size to be used, if nil, 200 is used.
1467
1468 GRAY is the text gray factor (should be very light like 0.8).
1469 If nil, the default is 0.85.
1470
1471 ROTATION is the text rotation angle; if nil, the angle is given by
1472 the diagonal from lower left corner to upper right corner.
1473
1474 PAGES designates the page to print background text.
1475 PAGES may be a number or a cons cell (FROM . TO) designating FROM page
1476 to TO page.
1477 If PAGES is nil, print background text on all pages.
1478
1479 X, Y, FONTSIZE, GRAY and ROTATION may be a floating point number,
1480 an integer number or a string. If it is a string, the string should contain
1481 PostScript programming that returns a float or integer value.
1482
1483 For example, if you wish to print text \"Preliminary\" on all pages do:
1484
1485 '((\"Preliminary\"))"
1486 :type '(repeat (list (string :tag "Text")
1487 (choice :tag "X" number string (const nil))
1488 (choice :tag "Y" number string (const nil))
1489 (choice :tag "Font" string (const nil))
1490 (choice :tag "Fontsize" number string (const nil))
1491 (choice :tag "Gray" number string (const nil))
1492 (choice :tag "Rotation" number string (const nil))
1493 (repeat :tag "Pages" :inline t
1494 (radio (integer :tag "Page")
1495 (cons :tag "Range"
1496 (integer :tag "From")
1497 (integer :tag "To"))))))
1498 :group 'ps-print-background)
1499
1500 ;;; Horizontal layout
1501
1502 ;; ------------------------------------------
1503 ;; | | | | | | | |
1504 ;; | lm | text | ic | text | ic | text | rm |
1505 ;; | | | | | | | |
1506 ;; ------------------------------------------
1507
1508 (defcustom ps-left-margin (/ (* 72 2.0) 2.54) ; 2 cm
1509 "*Left margin in points (1/72 inch)."
1510 :type 'number
1511 :group 'ps-print-horizontal)
1512
1513 (defcustom ps-right-margin (/ (* 72 2.0) 2.54) ; 2 cm
1514 "*Right margin in points (1/72 inch)."
1515 :type 'number
1516 :group 'ps-print-horizontal)
1517
1518 (defcustom ps-inter-column (/ (* 72 2.0) 2.54) ; 2 cm
1519 "*Horizontal space between columns in points (1/72 inch)."
1520 :type 'number
1521 :group 'ps-print-horizontal)
1522
1523 ;;; Vertical layout
1524
1525 ;; |--------|
1526 ;; | tm |
1527 ;; |--------|
1528 ;; | header |
1529 ;; |--------|
1530 ;; | ho |
1531 ;; |--------|
1532 ;; | text |
1533 ;; |--------|
1534 ;; | bm |
1535 ;; |--------|
1536
1537 (defcustom ps-bottom-margin (/ (* 72 1.5) 2.54) ; 1.5 cm
1538 "*Bottom margin in points (1/72 inch)."
1539 :type 'number
1540 :group 'ps-print-vertical)
1541
1542 (defcustom ps-top-margin (/ (* 72 1.5) 2.54) ; 1.5 cm
1543 "*Top margin in points (1/72 inch)."
1544 :type 'number
1545 :group 'ps-print-vertical)
1546
1547 (defcustom ps-header-offset (/ (* 72 1.0) 2.54) ; 1.0 cm
1548 "*Vertical space in points (1/72 inch) between the main text and the header."
1549 :type 'number
1550 :group 'ps-print-vertical)
1551
1552 (defcustom ps-header-line-pad 0.15
1553 "*Portion of a header title line height to insert between the header frame
1554 and the text it contains, both in the vertical and horizontal directions."
1555 :type 'number
1556 :group 'ps-print-vertical)
1557
1558 ;;; Header setup
1559
1560 (defcustom ps-print-header t
1561 "*Non-nil means print a header at the top of each page.
1562 By default, the header displays the buffer name, page number, and, if
1563 the buffer is visiting a file, the file's directory. Headers are
1564 customizable by changing variables `ps-left-header' and
1565 `ps-right-header'."
1566 :type 'boolean
1567 :group 'ps-print-header)
1568
1569 (defcustom ps-print-only-one-header nil
1570 "*Non-nil means print only one header at the top of each page.
1571 This is useful when printing more than one column, so it is possible
1572 to have only one header over all columns or one header per column.
1573 See also `ps-print-header'."
1574 :type 'boolean
1575 :group 'ps-print-header)
1576
1577 (defcustom ps-print-header-frame t
1578 "*Non-nil means draw a gaudy frame around the header."
1579 :type 'boolean
1580 :group 'ps-print-header)
1581
1582 (defcustom ps-header-lines 2
1583 "*Number of lines to display in page header, when generating PostScript."
1584 :type 'integer
1585 :group 'ps-print-header)
1586 (make-variable-buffer-local 'ps-header-lines)
1587
1588 (defcustom ps-show-n-of-n t
1589 "*Non-nil means show page numbers as N/M, meaning page N of M.
1590 NOTE: page numbers are displayed as part of headers,
1591 see variable `ps-print-headers'."
1592 :type 'boolean
1593 :group 'ps-print-header)
1594
1595 (defcustom ps-spool-config 'lpr-switches
1596 "*Specify who is responsable for setting duplex and page size switches.
1597
1598 Valid values are:
1599
1600 `lpr-switches' duplex and page size are configured by `ps-lpr-switches'.
1601 Don't forget to set `ps-lpr-switches' to select duplex
1602 printing for your printer.
1603
1604 `setpagedevice' duplex and page size are configured by ps-print using the
1605 setpagedevice PostScript operator.
1606
1607 nil duplex and page size are configured by ps-print *not* using
1608 the setpagedevice PostScript operator.
1609
1610 Any other value is treated as nil.
1611
1612 WARNING: The setpagedevice PostScript operator affects ghostview utility when
1613 viewing file generated using landscape. Also on some printers,
1614 setpagedevice affects zebra stripes; on other printers, setpagedevice
1615 affects the left margin.
1616 Besides all that, if your printer does not have the paper size
1617 specified by setpagedevice, your printing will be aborted.
1618 So, if you need to use setpagedevice, set `ps-spool-config' to
1619 `setpagedevice', generate a test file and send it to your printer; if
1620 the printed file isn't ok, set `ps-spool-config' to nil."
1621 :type '(choice :tag "Spool Config"
1622 (const lpr-switches) (const setpagedevice)
1623 (other :tag "nil" nil))
1624 :group 'ps-print-header)
1625
1626 (defcustom ps-spool-duplex nil ; Not many people have duplex printers,
1627 ; so default to nil.
1628 "*Non-nil generates PostScript for a two-sided printer.
1629 For a duplex printer, the `ps-spool-*' and `ps-print-*' commands will insert
1630 blank pages as needed between print jobs so that the next buffer printed will
1631 start on the right page. Also, if headers are turned on, the headers will be
1632 reversed on duplex printers so that the page numbers fall to the left on
1633 even-numbered pages."
1634 :type 'boolean
1635 :group 'ps-print-header)
1636
1637 (defcustom ps-spool-tumble nil
1638 "*Specify how the page images on opposite sides of a sheet are oriented.
1639 If `ps-spool-tumble' is nil, produces output suitable for binding on the left or
1640 right. If `ps-spool-tumble' is non-nil, produces output suitable for binding at
1641 the top or bottom.
1642
1643 It has effect only when `ps-spool-duplex' is non-nil."
1644 :type 'boolean
1645 :group 'ps-print-header)
1646
1647 ;;; Fonts
1648
1649 (defcustom ps-font-info-database
1650 '((Courier ; the family key
1651 (fonts (normal . "Courier")
1652 (bold . "Courier-Bold")
1653 (italic . "Courier-Oblique")
1654 (bold-italic . "Courier-BoldOblique"))
1655 (size . 10.0)
1656 (line-height . 10.55)
1657 (space-width . 6.0)
1658 (avg-char-width . 6.0))
1659 (Helvetica ; the family key
1660 (fonts (normal . "Helvetica")
1661 (bold . "Helvetica-Bold")
1662 (italic . "Helvetica-Oblique")
1663 (bold-italic . "Helvetica-BoldOblique"))
1664 (size . 10.0)
1665 (line-height . 11.56)
1666 (space-width . 2.78)
1667 (avg-char-width . 5.09243))
1668 (Times
1669 (fonts (normal . "Times-Roman")
1670 (bold . "Times-Bold")
1671 (italic . "Times-Italic")
1672 (bold-italic . "Times-BoldItalic"))
1673 (size . 10.0)
1674 (line-height . 11.0)
1675 (space-width . 2.5)
1676 (avg-char-width . 4.71432))
1677 (Palatino
1678 (fonts (normal . "Palatino-Roman")
1679 (bold . "Palatino-Bold")
1680 (italic . "Palatino-Italic")
1681 (bold-italic . "Palatino-BoldItalic"))
1682 (size . 10.0)
1683 (line-height . 12.1)
1684 (space-width . 2.5)
1685 (avg-char-width . 5.08676))
1686 (Helvetica-Narrow
1687 (fonts (normal . "Helvetica-Narrow")
1688 (bold . "Helvetica-Narrow-Bold")
1689 (italic . "Helvetica-Narrow-Oblique")
1690 (bold-italic . "Helvetica-Narrow-BoldOblique"))
1691 (size . 10.0)
1692 (line-height . 11.56)
1693 (space-width . 2.2796)
1694 (avg-char-width . 4.17579))
1695 (NewCenturySchlbk
1696 (fonts (normal . "NewCenturySchlbk-Roman")
1697 (bold . "NewCenturySchlbk-Bold")
1698 (italic . "NewCenturySchlbk-Italic")
1699 (bold-italic . "NewCenturySchlbk-BoldItalic"))
1700 (size . 10.0)
1701 (line-height . 12.15)
1702 (space-width . 2.78)
1703 (avg-char-width . 5.31162))
1704 ;; got no bold for the next ones
1705 (AvantGarde-Book
1706 (fonts (normal . "AvantGarde-Book")
1707 (italic . "AvantGarde-BookOblique"))
1708 (size . 10.0)
1709 (line-height . 11.77)
1710 (space-width . 2.77)
1711 (avg-char-width . 5.45189))
1712 (AvantGarde-Demi
1713 (fonts (normal . "AvantGarde-Demi")
1714 (italic . "AvantGarde-DemiOblique"))
1715 (size . 10.0)
1716 (line-height . 12.72)
1717 (space-width . 2.8)
1718 (avg-char-width . 5.51351))
1719 (Bookman-Demi
1720 (fonts (normal . "Bookman-Demi")
1721 (italic . "Bookman-DemiItalic"))
1722 (size . 10.0)
1723 (line-height . 11.77)
1724 (space-width . 3.4)
1725 (avg-char-width . 6.05946))
1726 (Bookman-Light
1727 (fonts (normal . "Bookman-Light")
1728 (italic . "Bookman-LightItalic"))
1729 (size . 10.0)
1730 (line-height . 11.79)
1731 (space-width . 3.2)
1732 (avg-char-width . 5.67027))
1733 ;; got no bold and no italic for the next ones
1734 (Symbol
1735 (fonts (normal . "Symbol"))
1736 (size . 10.0)
1737 (line-height . 13.03)
1738 (space-width . 2.5)
1739 (avg-char-width . 3.24324))
1740 (Zapf-Dingbats
1741 (fonts (normal . "Zapf-Dingbats"))
1742 (size . 10.0)
1743 (line-height . 9.63)
1744 (space-width . 2.78)
1745 (avg-char-width . 2.78))
1746 (Zapf-Chancery-MediumItalic
1747 (fonts (normal . "Zapf-Chancery-MediumItalic"))
1748 (size . 10.0)
1749 (line-height . 11.45)
1750 (space-width . 2.2)
1751 (avg-char-width . 4.10811))
1752 )
1753 "*Font info database: font family (the key), name, bold, italic, bold-italic,
1754 reference size, line height, space width, average character width.
1755 To get the info for another specific font (say Helvetica), do the following:
1756 - create a new buffer
1757 - generate the PostScript image to a file (C-u M-x ps-print-buffer)
1758 - open this file and delete the leading `%' (which is the PostScript
1759 comment character) from the line
1760 `% 3 cm 20 cm moveto 10 /Courier ReportFontInfo showpage'
1761 to get the line
1762 `3 cm 20 cm moveto 10 /Helvetica ReportFontInfo showpage'
1763 - add the values to `ps-font-info-database'.
1764 You can get all the fonts of YOUR printer using `ReportAllFontInfo'."
1765 :type '(repeat (list :tag "Font Definition"
1766 (symbol :tag "Font Family")
1767 (cons :format "%v"
1768 (const :format "" fonts)
1769 (repeat :tag "Faces"
1770 (cons (choice (const normal)
1771 (const bold)
1772 (const italic)
1773 (const bold-italic)
1774 (symbol :tag "Face"))
1775 (string :tag "Font Name"))))
1776 (cons :format "%v"
1777 (const :format "" size)
1778 (number :tag "Reference Size"))
1779 (cons :format "%v"
1780 (const :format "" line-height)
1781 (number :tag "Line Height"))
1782 (cons :format "%v"
1783 (const :format "" space-width)
1784 (number :tag "Space Width"))
1785 (cons :format "%v"
1786 (const :format "" avg-char-width)
1787 (number :tag "Average Character Width"))))
1788 :group 'ps-print-font)
1789
1790 (defcustom ps-font-family 'Courier
1791 "*Font family name for ordinary text, when generating PostScript."
1792 :type 'symbol
1793 :group 'ps-print-font)
1794
1795 (defcustom ps-font-size '(7 . 8.5)
1796 "*Font size, in points, for ordinary text, when generating PostScript."
1797 :type '(choice (number :tag "Text Size")
1798 (cons :tag "Landscape/Portrait"
1799 (number :tag "Landscape Text Size")
1800 (number :tag "Portrait Text Size")))
1801 :group 'ps-print-font)
1802
1803 (defcustom ps-header-font-family 'Helvetica
1804 "*Font family name for text in the header, when generating PostScript."
1805 :type 'symbol
1806 :group 'ps-print-font)
1807
1808 (defcustom ps-header-font-size '(10 . 12)
1809 "*Font size, in points, for text in the header, when generating PostScript."
1810 :type '(choice (number :tag "Header Size")
1811 (cons :tag "Landscape/Portrait"
1812 (number :tag "Landscape Header Size")
1813 (number :tag "Portrait Header Size")))
1814 :group 'ps-print-font)
1815
1816 (defcustom ps-header-title-font-size '(12 . 14)
1817 "*Font size, in points, for the top line of text in header, in PostScript."
1818 :type '(choice (number :tag "Header Title Size")
1819 (cons :tag "Landscape/Portrait"
1820 (number :tag "Landscape Header Title Size")
1821 (number :tag "Portrait Header Title Size")))
1822 :group 'ps-print-font)
1823
1824 ;;; Colors
1825
1826 ;; Printing color requires x-color-values.
1827 (defcustom ps-print-color-p (or (fboundp 'x-color-values) ; Emacs
1828 (fboundp 'color-instance-rgb-components))
1829 ; XEmacs
1830 "*Non-nil means print the buffer's text in color."
1831 :type 'boolean
1832 :group 'ps-print-color)
1833
1834 (defcustom ps-default-fg '(0.0 0.0 0.0)
1835 "*RGB values of the default foreground color. Defaults to black."
1836 :type '(list (number :tag "Red") (number :tag "Green") (number :tag "Blue"))
1837 :group 'ps-print-color)
1838
1839 (defcustom ps-default-bg '(1.0 1.0 1.0)
1840 "*RGB values of the default background color. Defaults to white."
1841 :type '(list (number :tag "Red") (number :tag "Green") (number :tag "Blue"))
1842 :group 'ps-print-color)
1843
1844 (defcustom ps-auto-font-detect t
1845 "*Non-nil means automatically detect bold/italic face attributes.
1846 If nil, we rely solely on the lists `ps-bold-faces', `ps-italic-faces',
1847 and `ps-underlined-faces'."
1848 :type 'boolean
1849 :group 'ps-print-font)
1850
1851 (defcustom ps-bold-faces
1852 (unless ps-print-color-p
1853 '(font-lock-function-name-face
1854 font-lock-builtin-face
1855 font-lock-variable-name-face
1856 font-lock-keyword-face
1857 font-lock-warning-face))
1858 "*A list of the \(non-bold\) faces that should be printed in bold font.
1859 This applies to generating PostScript."
1860 :type '(repeat face)
1861 :group 'ps-print-face)
1862
1863 (defcustom ps-italic-faces
1864 (unless ps-print-color-p
1865 '(font-lock-variable-name-face
1866 font-lock-type-face
1867 font-lock-string-face
1868 font-lock-comment-face
1869 font-lock-warning-face))
1870 "*A list of the \(non-italic\) faces that should be printed in italic font.
1871 This applies to generating PostScript."
1872 :type '(repeat face)
1873 :group 'ps-print-face)
1874
1875 (defcustom ps-underlined-faces
1876 (unless ps-print-color-p
1877 '(font-lock-function-name-face
1878 font-lock-constant-face
1879 font-lock-warning-face))
1880 "*A list of the \(non-underlined\) faces that should be printed underlined.
1881 This applies to generating PostScript."
1882 :type '(repeat face)
1883 :group 'ps-print-face)
1884
1885 (defcustom ps-left-header
1886 (list 'ps-get-buffer-name 'ps-header-dirpart)
1887 "*The items to display (each on a line) on the left part of the page header.
1888 This applies to generating PostScript.
1889
1890 The value should be a list of strings and symbols, each representing an
1891 entry in the PostScript array HeaderLinesLeft.
1892
1893 Strings are inserted unchanged into the array; those representing
1894 PostScript string literals should be delimited with PostScript string
1895 delimiters '(' and ')'.
1896
1897 For symbols with bound functions, the function is called and should
1898 return a string to be inserted into the array. For symbols with bound
1899 values, the value should be a string to be inserted into the array.
1900 In either case, function or variable, the string value has PostScript
1901 string delimiters added to it."
1902 :type '(repeat (choice string symbol))
1903 :group 'ps-print-header)
1904 (make-variable-buffer-local 'ps-left-header)
1905
1906 (defcustom ps-right-header
1907 (list "/pagenumberstring load" 'time-stamp-mon-dd-yyyy 'time-stamp-hh:mm:ss)
1908 "*The items to display (each on a line) on the right part of the page header.
1909 This applies to generating PostScript.
1910
1911 See the variable `ps-left-header' for a description of the format of
1912 this variable."
1913 :type '(repeat (choice string symbol))
1914 :group 'ps-print-header)
1915 (make-variable-buffer-local 'ps-right-header)
1916
1917 (defcustom ps-razzle-dazzle t
1918 "*Non-nil means report progress while formatting buffer."
1919 :type 'boolean
1920 :group 'ps-print)
1921
1922 (defcustom ps-adobe-tag "%!PS-Adobe-3.0\n"
1923 "*Contains the header line identifying the output as PostScript.
1924 By default, `ps-adobe-tag' contains the standard identifier. Some
1925 printers require slightly different versions of this line."
1926 :type 'string
1927 :group 'ps-print)
1928
1929 (defcustom ps-build-face-reference t
1930 "*Non-nil means build the reference face lists.
1931
1932 ps-print sets this value to nil after it builds its internal reference
1933 lists of bold and italic faces. By settings its value back to t, you
1934 can force ps-print to rebuild the lists the next time you invoke one
1935 of the ...-with-faces commands.
1936
1937 You should set this value back to t after you change the attributes of
1938 any face, or create new faces. Most users shouldn't have to worry
1939 about its setting, though."
1940 :type 'boolean
1941 :group 'ps-print-face)
1942
1943 (defcustom ps-always-build-face-reference nil
1944 "*Non-nil means always rebuild the reference face lists.
1945
1946 If this variable is non-nil, ps-print will rebuild its internal
1947 reference lists of bold and italic faces *every* time one of the
1948 ...-with-faces commands is called. Most users shouldn't need to set this
1949 variable."
1950 :type 'boolean
1951 :group 'ps-print-face)
1952
1953 (defcustom ps-banner-page-when-duplexing nil
1954 "*Non-nil means the very first page is skipped.
1955 It's like the very first character of buffer (or region) is ^L (\\014)."
1956 :type 'boolean
1957 :group 'ps-print-header)
1958
1959 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1960 ;; User commands
1961
1962 ;;;###autoload
1963 (defun ps-print-buffer (&optional filename)
1964 "Generate and print a PostScript image of the buffer.
1965
1966 Interactively, when you use a prefix argument (C-u), the command
1967 prompts the user for a file name, and saves the PostScript image
1968 in that file instead of sending it to the printer.
1969
1970 Noninteractively, the argument FILENAME is treated as follows: if it
1971 is nil, send the image to the printer. If FILENAME is a string, save
1972 the PostScript image in a file with that name."
1973 (interactive (list (ps-print-preprint current-prefix-arg)))
1974 (ps-print-without-faces (point-min) (point-max) filename))
1975
1976
1977 ;;;###autoload
1978 (defun ps-print-buffer-with-faces (&optional filename)
1979 "Generate and print a PostScript image of the buffer.
1980 Like `ps-print-buffer', but includes font, color, and underline
1981 information in the generated image. This command works only if you
1982 are using a window system, so it has a way to determine color values."
1983 (interactive (list (ps-print-preprint current-prefix-arg)))
1984 (ps-print-with-faces (point-min) (point-max) filename))
1985
1986
1987 ;;;###autoload
1988 (defun ps-print-region (from to &optional filename)
1989 "Generate and print a PostScript image of the region.
1990 Like `ps-print-buffer', but prints just the current region."
1991 (interactive (list (point) (mark) (ps-print-preprint current-prefix-arg)))
1992 (ps-print-without-faces from to filename t))
1993
1994
1995 ;;;###autoload
1996 (defun ps-print-region-with-faces (from to &optional filename)
1997 "Generate and print a PostScript image of the region.
1998 Like `ps-print-region', but includes font, color, and underline
1999 information in the generated image. This command works only if you
2000 are using a window system, so it has a way to determine color values."
2001 (interactive (list (point) (mark) (ps-print-preprint current-prefix-arg)))
2002 (ps-print-with-faces from to filename t))
2003
2004
2005 ;;;###autoload
2006 (defun ps-spool-buffer ()
2007 "Generate and spool a PostScript image of the buffer.
2008 Like `ps-print-buffer' except that the PostScript image is saved in a
2009 local buffer to be sent to the printer later.
2010
2011 Use the command `ps-despool' to send the spooled images to the printer."
2012 (interactive)
2013 (ps-spool-without-faces (point-min) (point-max)))
2014
2015
2016 ;;;###autoload
2017 (defun ps-spool-buffer-with-faces ()
2018 "Generate and spool a PostScript image of the buffer.
2019 Like `ps-spool-buffer', but includes font, color, and underline
2020 information in the generated image. This command works only if you
2021 are using a window system, so it has a way to determine color values.
2022
2023 Use the command `ps-despool' to send the spooled images to the printer."
2024 (interactive)
2025 (ps-spool-with-faces (point-min) (point-max)))
2026
2027
2028 ;;;###autoload
2029 (defun ps-spool-region (from to)
2030 "Generate a PostScript image of the region and spool locally.
2031 Like `ps-spool-buffer', but spools just the current region.
2032
2033 Use the command `ps-despool' to send the spooled images to the printer."
2034 (interactive "r")
2035 (ps-spool-without-faces from to t))
2036
2037
2038 ;;;###autoload
2039 (defun ps-spool-region-with-faces (from to)
2040 "Generate a PostScript image of the region and spool locally.
2041 Like `ps-spool-region', but includes font, color, and underline
2042 information in the generated image. This command works only if you
2043 are using a window system, so it has a way to determine color values.
2044
2045 Use the command `ps-despool' to send the spooled images to the printer."
2046 (interactive "r")
2047 (ps-spool-with-faces from to t))
2048
2049 ;;;###autoload
2050 (defun ps-despool (&optional filename)
2051 "Send the spooled PostScript to the printer.
2052
2053 Interactively, when you use a prefix argument (C-u), the command
2054 prompts the user for a file name, and saves the spooled PostScript
2055 image in that file instead of sending it to the printer.
2056
2057 Noninteractively, the argument FILENAME is treated as follows: if it
2058 is nil, send the image to the printer. If FILENAME is a string, save
2059 the PostScript image in a file with that name."
2060 (interactive (list (ps-print-preprint current-prefix-arg)))
2061 (ps-do-despool filename))
2062
2063 ;;;###autoload
2064 (defun ps-line-lengths ()
2065 "Display the correspondence between a line length and a font size,
2066 using the current ps-print setup.
2067 Try: pr -t file | awk '{printf \"%3d %s\n\", length($0), $0}' | sort -r | head"
2068 (interactive)
2069 (ps-line-lengths-internal))
2070
2071 ;;;###autoload
2072 (defun ps-nb-pages-buffer (nb-lines)
2073 "Display number of pages to print this buffer, for various font heights.
2074 The table depends on the current ps-print setup."
2075 (interactive (list (count-lines (point-min) (point-max))))
2076 (ps-nb-pages nb-lines))
2077
2078 ;;;###autoload
2079 (defun ps-nb-pages-region (nb-lines)
2080 "Display number of pages to print the region, for various font heights.
2081 The table depends on the current ps-print setup."
2082 (interactive (list (count-lines (mark) (point))))
2083 (ps-nb-pages nb-lines))
2084
2085 ;;;###autoload
2086 (defun ps-setup ()
2087 "Return the current PostScript-generation setup."
2088 (format
2089 "
2090 \(setq ps-print-color-p %s
2091 ps-lpr-command %S
2092 ps-lpr-switches %s
2093 ps-printer-name %S
2094 ps-print-region-function %s
2095
2096 ps-paper-type %s
2097 ps-landscape-mode %s
2098 ps-number-of-columns %s
2099
2100 ps-zebra-stripes %s
2101 ps-zebra-stripe-height %s
2102 ps-zebra-gray %s
2103 ps-line-number %s
2104
2105 ps-print-control-characters %s
2106
2107 ps-print-background-image %s
2108
2109 ps-print-background-text %s
2110
2111 ps-print-prologue-header %s
2112
2113 ps-left-margin %s
2114 ps-right-margin %s
2115 ps-inter-column %s
2116 ps-bottom-margin %s
2117 ps-top-margin %s
2118 ps-header-offset %s
2119 ps-header-line-pad %s
2120 ps-print-header %s
2121 ps-print-only-one-header %s
2122 ps-print-header-frame %s
2123 ps-header-lines %s
2124 ps-show-n-of-n %s
2125 ps-spool-config %s
2126 ps-spool-duplex %s
2127 ps-spool-tumble %s
2128 ps-banner-page-when-duplexing %s
2129
2130 ps-n-up-printing %s
2131 ps-n-up-margin %s
2132 ps-n-up-border-p %s
2133 ps-n-up-filling %s
2134
2135 ps-multibyte-buffer %s
2136 ps-font-family %s
2137 ps-font-size %s
2138 ps-header-font-family %s
2139 ps-header-font-size %s
2140 ps-header-title-font-size %s)
2141 "
2142 ps-print-color-p
2143 ps-lpr-command
2144 (ps-print-quote ps-lpr-switches)
2145 ps-printer-name
2146 (ps-print-quote ps-print-region-function)
2147 (ps-print-quote ps-paper-type)
2148 ps-landscape-mode
2149 ps-number-of-columns
2150 ps-zebra-stripes
2151 ps-zebra-stripe-height
2152 ps-zebra-gray
2153 ps-line-number
2154 (ps-print-quote ps-print-control-characters)
2155 (ps-print-quote ps-print-background-image)
2156 (ps-print-quote ps-print-background-text)
2157 (ps-print-quote ps-print-prologue-header)
2158 ps-left-margin
2159 ps-right-margin
2160 ps-inter-column
2161 ps-bottom-margin
2162 ps-top-margin
2163 ps-header-offset
2164 ps-header-line-pad
2165 ps-print-header
2166 ps-print-only-one-header
2167 ps-print-header-frame
2168 ps-header-lines
2169 ps-show-n-of-n
2170 (ps-print-quote ps-spool-config)
2171 ps-spool-duplex
2172 ps-spool-tumble
2173 ps-banner-page-when-duplexing
2174 ps-n-up-printing
2175 ps-n-up-margin
2176 ps-n-up-border-p
2177 (ps-print-quote ps-n-up-filling)
2178 (ps-print-quote ps-multibyte-buffer) ; see `ps-mule.el' and `ps-print-def.el'
2179 (ps-print-quote ps-font-family)
2180 (ps-print-quote ps-font-size)
2181 (ps-print-quote ps-header-font-family)
2182 (ps-print-quote ps-header-font-size)
2183 (ps-print-quote ps-header-title-font-size)))
2184
2185 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2186 ;; Utility functions and variables:
2187
2188 (defun ps-print-quote (sym)
2189 (cond ((null sym)
2190 nil)
2191 ((or (symbolp sym) (listp sym))
2192 (format "'%S" sym))
2193 ((stringp sym)
2194 (format "%S" sym))
2195 (t
2196 sym)))
2197
2198 (defvar ps-print-emacs-type
2199 (cond ((string-match "XEmacs" emacs-version) 'xemacs)
2200 ((string-match "Lucid" emacs-version) 'lucid)
2201 ((string-match "Epoch" emacs-version) 'epoch)
2202 (t 'emacs)))
2203
2204 (if (or (eq ps-print-emacs-type 'lucid)
2205 (eq ps-print-emacs-type 'xemacs))
2206 (if (< emacs-minor-version 12)
2207 (setq ps-print-color-p nil))
2208 (require 'faces)) ; face-font, face-underline-p,
2209 ; x-font-regexp
2210
2211 ;; Return t if the device (which can be changed during an emacs session)
2212 ;; can handle colors.
2213 ;; This is function is not yet implemented for GNU emacs.
2214 (cond ((and (eq ps-print-emacs-type 'xemacs)
2215 (>= emacs-minor-version 12)) ; xemacs
2216 (defun ps-color-device ()
2217 (eq (device-class) 'color))
2218 )
2219
2220 (t ; emacs
2221 (defun ps-color-device ()
2222 t)
2223 ))
2224
2225
2226 (require 'time-stamp)
2227
2228 (defconst ps-print-prologue-1
2229 "
2230 % ISOLatin1Encoding stolen from ps_init.ps in GhostScript 2.6.1.4:
2231 /ISOLatin1Encoding where { pop } {
2232 % -- The ISO Latin-1 encoding vector isn't known, so define it.
2233 % -- The first half is the same as the standard encoding,
2234 % -- except for minus instead of hyphen at code 055.
2235 /ISOLatin1Encoding
2236 StandardEncoding 0 45 getinterval aload pop
2237 /minus
2238 StandardEncoding 46 82 getinterval aload pop
2239 %*** NOTE: the following are missing in the Adobe documentation,
2240 %*** but appear in the displayed table:
2241 %*** macron at 0225, dieresis at 0230, cedilla at 0233, space at 0240.
2242 % 0200 (128)
2243 /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
2244 /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
2245 /dotlessi /grave /acute /circumflex /tilde /macron /breve /dotaccent
2246 /dieresis /.notdef /ring /cedilla /.notdef /hungarumlaut /ogonek /caron
2247 % 0240 (160)
2248 /space /exclamdown /cent /sterling
2249 /currency /yen /brokenbar /section
2250 /dieresis /copyright /ordfeminine /guillemotleft
2251 /logicalnot /hyphen /registered /macron
2252 /degree /plusminus /twosuperior /threesuperior
2253 /acute /mu /paragraph /periodcentered
2254 /cedilla /onesuperior /ordmasculine /guillemotright
2255 /onequarter /onehalf /threequarters /questiondown
2256 % 0300 (192)
2257 /Agrave /Aacute /Acircumflex /Atilde
2258 /Adieresis /Aring /AE /Ccedilla
2259 /Egrave /Eacute /Ecircumflex /Edieresis
2260 /Igrave /Iacute /Icircumflex /Idieresis
2261 /Eth /Ntilde /Ograve /Oacute
2262 /Ocircumflex /Otilde /Odieresis /multiply
2263 /Oslash /Ugrave /Uacute /Ucircumflex
2264 /Udieresis /Yacute /Thorn /germandbls
2265 % 0340 (224)
2266 /agrave /aacute /acircumflex /atilde
2267 /adieresis /aring /ae /ccedilla
2268 /egrave /eacute /ecircumflex /edieresis
2269 /igrave /iacute /icircumflex /idieresis
2270 /eth /ntilde /ograve /oacute
2271 /ocircumflex /otilde /odieresis /divide
2272 /oslash /ugrave /uacute /ucircumflex
2273 /udieresis /yacute /thorn /ydieresis
2274 256 packedarray def
2275 } ifelse
2276
2277 /reencodeFontISO { %def
2278 dup
2279 length 12 add dict % Make a new font (a new dict the same size
2280 % as the old one) with room for our new symbols.
2281
2282 begin % Make the new font the current dictionary.
2283
2284
2285 { 1 index /FID ne
2286 { def } { pop pop } ifelse
2287 } forall % Copy each of the symbols from the old dictionary
2288 % to the new one except for the font ID.
2289
2290 currentdict /FontType get 0 ne {
2291 /Encoding ISOLatin1Encoding def % Override the encoding with
2292 % the ISOLatin1 encoding.
2293 } if
2294
2295 % Use the font's bounding box to determine the ascent, descent,
2296 % and overall height; don't forget that these values have to be
2297 % transformed using the font's matrix.
2298
2299 % ^ (x2 y2)
2300 % | |
2301 % | v
2302 % | +----+ - -
2303 % | | | ^
2304 % | | | | Ascent (usually > 0)
2305 % | | | |
2306 % (0 0) -> +--+----+-------->
2307 % | | |
2308 % | | v Descent (usually < 0)
2309 % (x1 y1) --> +----+ - -
2310
2311 currentdict /FontType get 0 ne {
2312 /FontBBox load aload pop % -- x1 y1 x2 y2
2313 FontMatrix transform /Ascent exch def pop
2314 FontMatrix transform /Descent exch def pop
2315 } {
2316 /PrimaryFont FDepVector 0 get def
2317 PrimaryFont /FontBBox get aload pop
2318 PrimaryFont /FontMatrix get transform /Ascent exch def pop
2319 PrimaryFont /FontMatrix get transform /Descent exch def pop
2320 } ifelse
2321
2322 /FontHeight Ascent Descent sub def % use `sub' because descent < 0
2323
2324 % Define these in case they're not in the FontInfo
2325 % (also, here they're easier to get to).
2326 /UnderlinePosition Descent 0.70 mul def
2327 /OverlinePosition Descent UnderlinePosition sub Ascent add def
2328 /StrikeoutPosition Ascent 0.30 mul def
2329 /LineThickness FontHeight 0.05 mul def
2330 /Xshadow FontHeight 0.08 mul def
2331 /Yshadow FontHeight -0.09 mul def
2332 /SpaceBackground Descent neg UnderlinePosition add def
2333 /XBox Descent neg def
2334 /YBox LineThickness 0.7 mul def
2335
2336 currentdict % Leave the new font on the stack
2337 end % Stop using the font as the current dictionary.
2338 definefont % Put the font into the font dictionary
2339 pop % Discard the returned font.
2340 } bind def
2341
2342 /DefFont { % Font definition
2343 findfont exch scalefont reencodeFontISO
2344 } def
2345
2346 /F { % Font selection
2347 findfont
2348 dup /Ascent get /Ascent exch def
2349 dup /Descent get /Descent exch def
2350 dup /FontHeight get /FontHeight exch def
2351 dup /UnderlinePosition get /UnderlinePosition exch def
2352 dup /OverlinePosition get /OverlinePosition exch def
2353 dup /StrikeoutPosition get /StrikeoutPosition exch def
2354 dup /LineThickness get /LineThickness exch def
2355 dup /Xshadow get /Xshadow exch def
2356 dup /Yshadow get /Yshadow exch def
2357 dup /SpaceBackground get /SpaceBackground exch def
2358 dup /XBox get /XBox exch def
2359 dup /YBox get /YBox exch def
2360 setfont
2361 } def
2362
2363 /FG /setrgbcolor load def
2364
2365 /bg false def
2366 /BG {
2367 dup /bg exch def
2368 {mark 4 1 roll ]}
2369 {[ 1.0 1.0 1.0 ]}
2370 ifelse
2371 /bgcolor exch def
2372 } def
2373
2374 % B width C
2375 % +-----------+
2376 % | Ascent (usually > 0)
2377 % A + +
2378 % | Descent (usually < 0)
2379 % +-----------+
2380 % E width D
2381
2382 /dobackground { % width --
2383 currentpoint % -- width x y
2384 gsave
2385 newpath
2386 moveto % A (x y)
2387 0 Ascent rmoveto % B
2388 dup 0 rlineto % C
2389 0 Descent Ascent sub rlineto % D
2390 neg 0 rlineto % E
2391 closepath
2392 bgcolor aload pop setrgbcolor
2393 fill
2394 grestore
2395 } def
2396
2397 /eolbg { % dobackground until right margin
2398 PrintWidth % -- x-eol
2399 currentpoint pop % -- cur-x
2400 sub % -- width until eol
2401 dobackground
2402 } def
2403
2404 /PLN {PrintLineNumber {doLineNumber}if} def
2405
2406 /SL { % Soft Linefeed
2407 bg { eolbg } if
2408 0 currentpoint exch pop LineHeight sub moveto
2409 } def
2410
2411 /HL {SL PLN} def % Hard Linefeed
2412
2413 % Some debug
2414 /dcp { currentpoint exch 40 string cvs print (, ) print = } def
2415 /dp { print 2 copy exch 40 string cvs print (, ) print = } def
2416
2417 /W {
2418 ( ) stringwidth % Get the width of a space in the current font.
2419 pop % Discard the Y component.
2420 mul % Multiply the width of a space
2421 % by the number of spaces to plot
2422 bg { dup dobackground } if
2423 0 rmoveto
2424 } def
2425
2426 /Effect 0 def
2427 /EF {/Effect exch def} def
2428
2429 % stack: string |- --
2430 % effect: 1 - underline 2 - strikeout 4 - overline
2431 % 8 - shadow 16 - box 32 - outline
2432 /S {
2433 /xx currentpoint dup Descent add /yy exch def
2434 Ascent add /YY exch def def
2435 dup stringwidth pop xx add /XX exch def
2436 Effect 8 and 0 ne {
2437 /yy yy Yshadow add def
2438 /XX XX Xshadow add def
2439 } if
2440 bg {
2441 true
2442 Effect 16 and 0 ne
2443 {SpaceBackground doBox}
2444 {xx yy XX YY doRect}
2445 ifelse
2446 } if % background
2447 Effect 16 and 0 ne {false 0 doBox}if % box
2448 Effect 8 and 0 ne {dup doShadow}if % shadow
2449 Effect 32 and 0 ne
2450 {true doOutline} % outline
2451 {show} % normal text
2452 ifelse
2453 Effect 1 and 0 ne {UnderlinePosition Hline}if % underline
2454 Effect 2 and 0 ne {StrikeoutPosition Hline}if % strikeout
2455 Effect 4 and 0 ne {OverlinePosition Hline}if % overline
2456 } bind def
2457
2458 % stack: position |- --
2459 /Hline {
2460 currentpoint exch pop add dup
2461 gsave
2462 newpath
2463 xx exch moveto
2464 XX exch lineto
2465 closepath
2466 LineThickness setlinewidth stroke
2467 grestore
2468 } bind def
2469
2470 % stack: fill-or-not delta |- --
2471 /doBox {
2472 /dd exch def
2473 xx XBox sub dd sub yy YBox sub dd sub
2474 XX XBox add dd add YY YBox add dd add
2475 doRect
2476 } bind def
2477
2478 % stack: fill-or-not lower-x lower-y upper-x upper-y |- --
2479 /doRect {
2480 /rYY exch def
2481 /rXX exch def
2482 /ryy exch def
2483 /rxx exch def
2484 gsave
2485 newpath
2486 rXX rYY moveto
2487 rxx rYY lineto
2488 rxx ryy lineto
2489 rXX ryy lineto
2490 closepath
2491 % top of stack: fill-or-not
2492 {FillBgColor}
2493 {LineThickness setlinewidth stroke}
2494 ifelse
2495 grestore
2496 } bind def
2497
2498 % stack: string |- --
2499 /doShadow {
2500 gsave
2501 Xshadow Yshadow rmoveto
2502 false doOutline
2503 grestore
2504 } bind def
2505
2506 /st 1 string def
2507
2508 % stack: string fill-or-not |- --
2509 /doOutline {
2510 /-fillp- exch def
2511 /-ox- currentpoint /-oy- exch def def
2512 gsave
2513 LineThickness setlinewidth
2514 {
2515 st 0 3 -1 roll put
2516 st dup true charpath
2517 -fillp- {gsave FillBgColor grestore}if
2518 stroke stringwidth
2519 -oy- add /-oy- exch def
2520 -ox- add /-ox- exch def
2521 -ox- -oy- moveto
2522 } forall
2523 grestore
2524 -ox- -oy- moveto
2525 } bind def
2526
2527 % stack: --
2528 /FillBgColor {bgcolor aload pop setrgbcolor fill} bind def
2529
2530 /L0 6 /Times-Italic DefFont
2531
2532 % stack: --
2533 /doLineNumber {
2534 /LineNumber where
2535 {
2536 pop
2537 currentfont
2538 gsave
2539 0.0 0.0 0.0 setrgbcolor
2540 /L0 findfont setfont
2541 LineNumber Lines ge
2542 {(end )}
2543 {LineNumber 6 string cvs ( ) strcat}
2544 ifelse
2545 dup stringwidth pop neg 0 rmoveto
2546 show
2547 grestore
2548 setfont
2549 /LineNumber LineNumber 1 add def
2550 } if
2551 } def
2552
2553 % stack: --
2554 /printZebra {
2555 gsave
2556 ZebraGray setgray
2557 /double-zebra ZebraHeight ZebraHeight add def
2558 /yiter double-zebra LineHeight mul neg def
2559 /xiter PrintWidth InterColumn add def
2560 NumberOfColumns {LinesPerColumn doColumnZebra xiter 0 rmoveto}repeat
2561 grestore
2562 } def
2563
2564 % stack: lines-per-column |- --
2565 /doColumnZebra {
2566 gsave
2567 dup double-zebra idiv {ZebraHeight doZebra 0 yiter rmoveto}repeat
2568 double-zebra mod
2569 dup 0 le {pop}{dup ZebraHeight gt {pop ZebraHeight}if doZebra}ifelse
2570 grestore
2571 } def
2572
2573 % stack: zebra-height (in lines) |- --
2574 /doZebra {
2575 /zh exch 0.05 sub LineHeight mul def
2576 gsave
2577 0 LineHeight 0.65 mul rmoveto
2578 PrintWidth 0 rlineto
2579 0 zh neg rlineto
2580 PrintWidth neg 0 rlineto
2581 0 zh rlineto
2582 fill
2583 grestore
2584 } def
2585
2586 % tx ty rotation xscale yscale xpos ypos BeginBackImage
2587 /BeginBackImage {
2588 /-save-image- save def
2589 /showpage {}def
2590 translate
2591 scale
2592 rotate
2593 translate
2594 } def
2595
2596 /EndBackImage {
2597 -save-image- restore
2598 } def
2599
2600 % string fontsize fontname rotation gray xpos ypos ShowBackText
2601 /ShowBackText {
2602 gsave
2603 translate
2604 setgray
2605 rotate
2606 findfont exch dup /-offset- exch -0.25 mul def scalefont setfont
2607 0 -offset- moveto
2608 /-saveLineThickness- LineThickness def
2609 /LineThickness 1 def
2610 false doOutline
2611 /LineThickness -saveLineThickness- def
2612 grestore
2613 } def
2614
2615 /BeginDoc {
2616 % ---- Remember space width of the normal text font `f0'.
2617 /SpaceWidth /f0 findfont setfont ( ) stringwidth pop def
2618 % ---- save the state of the document (useful for ghostscript!)
2619 /docState save def
2620 % ---- [andrewi] set PageSize based on chosen dimensions
2621 UseSetpagedevice {
2622 0
2623 {<< /PageSize [PageWidth LandscapePageHeight] >> setpagedevice}
2624 CheckConfig
2625 }{
2626 LandscapeMode {
2627 % ---- translate to bottom-right corner of Portrait page
2628 LandscapePageHeight 0 translate
2629 90 rotate
2630 }if
2631 }ifelse
2632 % ---- [jack] Kludge: my ghostscript window is 21x27.7 instead of 21x29.7
2633 /JackGhostscript where {pop 1 27.7 29.7 div scale}if
2634 % ---- N-Up printing
2635 N-Up 1 gt {
2636 % ---- landscape
2637 N-Up-Landscape {
2638 PageWidth 0 translate
2639 90 rotate
2640 }if
2641 N-Up-Margin dup translate
2642 % ---- scale
2643 LandscapeMode{
2644 /HH PageWidth def
2645 /WW LandscapePageHeight def
2646 }{
2647 /HH LandscapePageHeight def
2648 /WW PageWidth def
2649 }ifelse
2650 WW N-Up-Margin sub N-Up-Margin sub
2651 N-Up-Landscape
2652 {N-Up-Lines div HH}{N-Up-Columns N-Up-Missing add div WW}ifelse
2653 div dup scale
2654 0 N-Up-Repeat 1 sub LandscapePageHeight mul translate
2655 % ---- go to start position in page matrix
2656 N-Up-XStart N-Up-Missing 0.5 mul
2657 LandscapeMode{
2658 LandscapePageHeight mul N-Up-YStart add
2659 }{
2660 PageWidth mul add N-Up-YStart
2661 }ifelse
2662 translate
2663 }if
2664 /ColumnWidth PrintWidth InterColumn add def
2665 % ---- translate to lower left corner of TEXT
2666 LeftMargin BottomMargin translate
2667 % ---- define where printing will start
2668 /f0 F % this installs Ascent
2669 /PrintStartY PrintHeight Ascent sub def
2670 /ColumnIndex 1 def
2671 /N-Up-Counter N-Up-End 1 sub def
2672 SkipFirstPage{save showpage restore}if
2673 }def
2674
2675 /EndDoc {
2676 % ---- restore the state of the document (useful for ghostscript!)
2677 docState restore
2678 }def
2679
2680 /BeginDSCPage {
2681 % ---- when 1st column, save the state of the page
2682 ColumnIndex 1 eq {
2683 /pageState save def
2684 }if
2685 % ---- save the state of the column
2686 /columnState save def
2687 }def
2688
2689 /PrintHeaderWidth PrintOnlyOneHeader{PrintPageWidth}{PrintWidth}ifelse def
2690
2691 /BeginPage {
2692 % ---- when 1st column, print all background effects
2693 ColumnIndex 1 eq {
2694 0 PrintStartY moveto % move to where printing will start
2695 Zebra {printZebra}if
2696 printGlobalBackground
2697 printLocalBackground
2698 }if
2699 PrintHeader {
2700 PrintOnlyOneHeader{ColumnIndex 1 eq}{true}ifelse {
2701 PrintHeaderFrame {HeaderFrame}if
2702 HeaderText
2703 }if
2704 }if
2705 0 PrintStartY moveto % move to where printing will start
2706 PLN
2707 }def
2708
2709 /EndPage {
2710 bg {eolbg}if
2711 }def
2712
2713 /EndDSCPage {
2714 ColumnIndex NumberOfColumns eq {
2715 % ---- restore the state of the page
2716 pageState restore
2717 /ColumnIndex 1 def
2718 % ---- N-up printing
2719 N-Up 1 gt {
2720 N-Up-Counter 0 gt {
2721 % ---- Next page on same row
2722 /N-Up-Counter N-Up-Counter 1 sub def
2723 N-Up-XColumn N-Up-YColumn
2724 }{
2725 % ---- Next page on next line
2726 /N-Up-Counter N-Up-End 1 sub def
2727 N-Up-XLine N-Up-YLine
2728 }ifelse
2729 translate
2730 }if
2731 }{ % else
2732 % ---- restore the state of the current column
2733 columnState restore
2734 % ---- and translate to the next column
2735 ColumnWidth 0 translate
2736 /ColumnIndex ColumnIndex 1 add def
2737 }ifelse
2738 }def
2739
2740 % stack: number-of-pages-per-sheet |- --
2741 /BeginSheet {
2742 /sheetState save def
2743 /pages-per-sheet exch def
2744 % ---- N-up printing
2745 N-Up 1 gt N-Up-Border and pages-per-sheet 0 gt and {
2746 % ---- page border
2747 gsave
2748 0 setgray
2749 LeftMargin neg BottomMargin neg moveto
2750 N-Up-Repeat
2751 {N-Up-End
2752 {gsave
2753 PageWidth 0 rlineto
2754 0 LandscapePageHeight rlineto
2755 PageWidth neg 0 rlineto
2756 closepath stroke
2757 grestore
2758 /pages-per-sheet pages-per-sheet 1 sub def
2759 pages-per-sheet 0 le{exit}if
2760 N-Up-XColumn N-Up-YColumn rmoveto
2761 }repeat
2762 pages-per-sheet 0 le{exit}if
2763 N-Up-XLine N-Up-XColumn sub N-Up-YLine rmoveto
2764 }repeat
2765 grestore
2766 }if
2767 }def
2768
2769 /EndSheet {
2770 showpage
2771 sheetState restore
2772 }def
2773
2774 /SetHeaderLines { % nb-lines --
2775 /HeaderLines exch def
2776 % ---- bottom up
2777 HeaderPad
2778 HeaderLines 1 sub HeaderLineHeight mul add
2779 HeaderTitleLineHeight add
2780 HeaderPad add
2781 /HeaderHeight exch def
2782 } def
2783
2784 % |---------|
2785 % | tm |
2786 % |---------|
2787 % | header |
2788 % |-+-------| <-- (x y)
2789 % | ho |
2790 % |---------|
2791 % | text |
2792 % |-+-------| <-- (0 0)
2793 % | bm |
2794 % |---------|
2795
2796 /HeaderFrameStart { % -- x y
2797 0 PrintHeight HeaderOffset add
2798 } def
2799
2800 /HeaderFramePath {
2801 PrintHeaderWidth 0 rlineto
2802 0 HeaderHeight rlineto
2803 PrintHeaderWidth neg 0 rlineto
2804 0 HeaderHeight neg rlineto
2805 } def
2806
2807 /HeaderFrame {
2808 gsave
2809 0.4 setlinewidth
2810 % ---- fill a black rectangle (the shadow of the next one)
2811 HeaderFrameStart moveto
2812 1 -1 rmoveto
2813 HeaderFramePath
2814 0 setgray fill
2815 % ---- do the next rectangle ...
2816 HeaderFrameStart moveto
2817 HeaderFramePath
2818 gsave 0.9 setgray fill grestore % filled with grey
2819 gsave 0 setgray stroke grestore % drawn with black
2820 grestore
2821 } def
2822
2823 /HeaderStart {
2824 HeaderFrameStart
2825 exch HeaderPad add exch % horizontal pad
2826 % ---- bottom up
2827 HeaderPad add % vertical pad
2828 HeaderDescent sub
2829 HeaderLineHeight HeaderLines 1 sub mul add
2830 } def
2831
2832 /strcat {
2833 dup length 3 -1 roll dup length dup 4 -1 roll add string dup
2834 0 5 -1 roll putinterval
2835 dup 4 2 roll exch putinterval
2836 } def
2837
2838 /pagenumberstring {
2839 PageNumber 32 string cvs
2840 ShowNofN {
2841 (/) strcat
2842 PageCount 32 string cvs strcat
2843 } if
2844 } def
2845
2846 /HeaderText {
2847 HeaderStart moveto
2848
2849 HeaderLinesRight HeaderLinesLeft % -- rightLines leftLines
2850
2851 % ---- hack: `PN 1 and' == `PN 2 modulo'
2852
2853 % ---- if even page number and duplex, then exchange left and right
2854 PageNumber 1 and 0 eq DuplexValue and { exch } if
2855
2856 { % ---- process the left lines
2857 aload pop
2858 exch F
2859 gsave
2860 dup xcheck { exec } if
2861 show
2862 grestore
2863 0 HeaderLineHeight neg rmoveto
2864 } forall
2865
2866 HeaderStart moveto
2867
2868 { % ---- process the right lines
2869 aload pop
2870 exch F
2871 gsave
2872 dup xcheck { exec } if
2873 dup stringwidth pop
2874 PrintHeaderWidth exch sub HeaderPad 2 mul sub 0 rmoveto
2875 show
2876 grestore
2877 0 HeaderLineHeight neg rmoveto
2878 } forall
2879 } def
2880
2881 /ReportFontInfo {
2882 2 copy
2883 /t0 3 1 roll DefFont
2884 /t0 F
2885 /lh FontHeight def
2886 /sw ( ) stringwidth pop def
2887 /aw (01234567890abcdefghijklmnopqrstuvwxyz) dup length exch
2888 stringwidth pop exch div def
2889 /t1 12 /Helvetica-Oblique DefFont
2890 /t1 F
2891 gsave
2892 (languagelevel = ) show
2893 gs_languagelevel 32 string cvs show
2894 grestore
2895 0 FontHeight neg rmoveto
2896 gsave
2897 (For ) show
2898 128 string cvs show
2899 ( ) show
2900 32 string cvs show
2901 ( point, the line height is ) show
2902 lh 32 string cvs show
2903 (, the space width is ) show
2904 sw 32 string cvs show
2905 (,) show
2906 grestore
2907 0 FontHeight neg rmoveto
2908 gsave
2909 (and a crude estimate of average character width is ) show
2910 aw 32 string cvs show
2911 (.) show
2912 grestore
2913 0 FontHeight neg rmoveto
2914 } def
2915
2916 /cm { % cm to point
2917 72 mul 2.54 div
2918 } def
2919
2920 /ReportAllFontInfo {
2921 FontDirectory
2922 { % key = font name value = font dictionary
2923 pop 10 exch ReportFontInfo
2924 } forall
2925 } def
2926
2927 % 3 cm 20 cm moveto 10 /Courier ReportFontInfo showpage
2928 % 3 cm 20 cm moveto ReportAllFontInfo showpage
2929
2930 /ErrorMessages
2931 [(This PostScript printer is not configured with this document page size.)
2932 (Duplex printing is not supported on this PostScript printer.)]def
2933
2934 % stack: error-index proc |- --
2935 /CheckConfig {
2936 stopped {
2937 1 cm LandscapePageHeight 0.5 mul moveto
2938 /Courier findfont 10 scalefont setfont
2939 gsave
2940 (ps-print error:) show
2941 grestore
2942 0 -10 rmoveto
2943 ErrorMessages exch get show
2944 showpage
2945 $error /newerror false put
2946 stop
2947 }if
2948 } bind def
2949
2950 ")
2951
2952 (defconst ps-print-prologue-2
2953 "
2954 % ---- These lines must be kept together because...
2955
2956 /h0 F
2957 /HeaderTitleLineHeight FontHeight def
2958
2959 /h1 F
2960 /HeaderLineHeight FontHeight def
2961 /HeaderDescent Descent def
2962
2963 % ---- ...because `F' has a side-effect on `FontHeight' and `Descent'
2964
2965 ")
2966
2967 (defconst ps-print-duplex-feature
2968 "
2969 % --- duplex feature verification
2970 1
2971 UseSetpagedevice {
2972 {<< /Duplex DuplexValue /Tumble TumbleValue >> setpagedevice}
2973 }{
2974 {statusdict begin
2975 DuplexValue setduplexmode TumbleValue settumble
2976 end}
2977 }ifelse
2978 CheckConfig
2979 ")
2980
2981 ;; Start Editing Here:
2982
2983 (defvar ps-source-buffer nil)
2984 (defvar ps-spool-buffer-name "*PostScript*")
2985 (defvar ps-spool-buffer nil)
2986
2987 (defvar ps-output-head nil)
2988 (defvar ps-output-tail nil)
2989
2990 (defvar ps-page-postscript 0)
2991 (defvar ps-page-order 0)
2992 (defvar ps-page-count 0)
2993 (defvar ps-showline-count 1)
2994
2995 (defvar ps-control-or-escape-regexp nil)
2996
2997 (defvar ps-background-pages nil)
2998 (defvar ps-background-all-pages nil)
2999 (defvar ps-background-text-count 0)
3000 (defvar ps-background-image-count 0)
3001
3002 (defvar ps-current-font 0)
3003 (defvar ps-default-color (and ps-print-color-p ps-default-fg)) ; black
3004 (defvar ps-current-color ps-default-color)
3005 (defvar ps-current-bg nil)
3006
3007 (defvar ps-razchunk 0)
3008
3009 (defvar ps-color-p nil)
3010 (defvar ps-color-format
3011 (if (eq ps-print-emacs-type 'emacs)
3012
3013 ;; Emacs understands the %f format; we'll use it to limit color RGB
3014 ;; values to three decimals to cut down some on the size of the
3015 ;; PostScript output.
3016 "%0.3f %0.3f %0.3f"
3017
3018 ;; Lucid emacsen will have to make do with %s (princ) for floats.
3019 "%s %s %s"))
3020
3021 ;; These values determine how much print-height to deduct when headers
3022 ;; are turned on. This is a pretty clumsy way of handling it, but
3023 ;; it'll do for now.
3024
3025 (defvar ps-header-pad 0
3026 "Vertical and horizontal space between the header frame and the text.
3027 This is in units of points (1/72 inch).")
3028
3029 ;; Define accessors to the dimensions list.
3030
3031 (defmacro ps-page-dimensions-get-width (dims) `(nth 0 ,dims))
3032 (defmacro ps-page-dimensions-get-height (dims) `(nth 1 ,dims))
3033 (defmacro ps-page-dimensions-get-media (dims) `(nth 2 ,dims))
3034
3035 (defvar ps-landscape-page-height nil)
3036
3037 (defvar ps-print-width nil)
3038 (defvar ps-print-height nil)
3039
3040 (defvar ps-height-remaining nil)
3041 (defvar ps-width-remaining nil)
3042
3043 (defvar ps-print-color-scale nil)
3044
3045 (defvar ps-font-size-internal nil)
3046 (defvar ps-header-font-size-internal nil)
3047 (defvar ps-header-title-font-size-internal nil)
3048
3049 \f
3050 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3051 ;; Internal Variables
3052
3053
3054 (defvar ps-print-face-extension-alist nil
3055 "Alist of symbolic faces *WITH* extension features (box, outline, etc).
3056 An element of this list has the following form:
3057
3058 (FACE . [BITS FG BG])
3059
3060 FACE is a symbol denoting a face name
3061 BITS is a bit vector, where each bit correspond
3062 to a feature (bold, underline, etc)
3063 (see documentation for `ps-print-face-map-alist')
3064 FG foreground color (string or nil)
3065 BG background color (string or nil)
3066
3067 Don't change this list directly; instead,
3068 use `ps-extend-face' and `ps-extend-face-list'.
3069 See documentation for `ps-extend-face' for valid extension symbol.")
3070
3071
3072 (defvar ps-print-face-alist nil
3073 "Alist of symbolic faces *WITHOUT* extension features (box, outline, etc).
3074
3075 An element of this list has the same form as an element of
3076 `ps-print-face-extension-alist'.
3077
3078 Don't change this list directly; this list is used by `ps-face-attributes',
3079 `ps-map-face' and `ps-build-reference-face-lists'.")
3080
3081
3082 (defconst ps-print-face-map-alist
3083 '((bold . 1)
3084 (italic . 2)
3085 (underline . 4)
3086 (strikeout . 8)
3087 (overline . 16)
3088 (shadow . 32)
3089 (box . 64)
3090 (outline . 128))
3091 "Alist of all features and the corresponding bit mask.
3092 Each symbol correspond to one bit in a bit vector.")
3093
3094 \f
3095 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3096 ;; Remapping Faces
3097
3098
3099 ;;;###autoload
3100 (defun ps-extend-face-list (face-extension-list &optional merge-p)
3101 "Extend face in `ps-print-face-extension-alist'.
3102
3103 If optional MERGE-P is non-nil, extensions in FACE-EXTENSION-LIST are merged
3104 with face extension in `ps-print-face-extension-alist'; otherwise, overrides.
3105
3106 The elements in FACE-EXTENSION-LIST is like those for `ps-extend-face'.
3107
3108 See `ps-extend-face' for documentation."
3109 (while face-extension-list
3110 (ps-extend-face (car face-extension-list) merge-p)
3111 (setq face-extension-list (cdr face-extension-list))))
3112
3113
3114 ;;;###autoload
3115 (defun ps-extend-face (face-extension &optional merge-p)
3116 "Extend face in `ps-print-face-extension-alist'.
3117
3118 If optional MERGE-P is non-nil, extensions in FACE-EXTENSION list are merged
3119 with face extensions in `ps-print-face-extension-alist'; otherwise, overrides.
3120
3121 The elements of FACE-EXTENSION list have the form:
3122
3123 (FACE-NAME FOREGROUND BACKGROUND EXTENSION...)
3124
3125 FACE-NAME is a face name symbol.
3126
3127 FOREGROUND and BACKGROUND may be nil or a string that denotes the
3128 foreground and background colors respectively.
3129
3130 EXTENSION is one of the following symbols:
3131 bold - use bold font.
3132 italic - use italic font.
3133 underline - put a line under text.
3134 strikeout - like underline, but the line is in middle of text.
3135 overline - like underline, but the line is over the text.
3136 shadow - text will have a shadow.
3137 box - text will be surrounded by a box.
3138 outline - print characters as hollow outlines.
3139
3140 If EXTENSION is any other symbol, it is ignored."
3141 (let* ((face-name (nth 0 face-extension))
3142 (foreground (nth 1 face-extension))
3143 (background (nth 2 face-extension))
3144 (ps-face (cdr (assq face-name ps-print-face-extension-alist)))
3145 (face-vector (or ps-face (vector 0 nil nil)))
3146 (face-bit (ps-extension-bit face-extension)))
3147 ;; extend face
3148 (aset face-vector 0 (if merge-p
3149 (logior (aref face-vector 0) face-bit)
3150 face-bit))
3151 (and foreground (stringp foreground) (aset face-vector 1 foreground))
3152 (and background (stringp background) (aset face-vector 2 background))
3153 ;; if face does not exist, insert it
3154 (or ps-face
3155 (setq ps-print-face-extension-alist
3156 (cons (cons face-name face-vector)
3157 ps-print-face-extension-alist)))))
3158
3159
3160 (defun ps-extension-bit (face-extension)
3161 (let ((face-bit 0))
3162 ;; map valid symbol extension to bit vector
3163 (setq face-extension (cdr (cdr face-extension)))
3164 (while (setq face-extension (cdr face-extension))
3165 (setq face-bit (logior face-bit
3166 (or (cdr (assq (car face-extension)
3167 ps-print-face-map-alist))
3168 0))))
3169 face-bit))
3170
3171 \f
3172 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3173 ;; Adapted from font-lock: (obsolete stuff)
3174 ;; Originally face attributes were specified via `font-lock-face-attributes'.
3175 ;; Users then changed the default face attributes by setting that variable.
3176 ;; However, we try and be back-compatible and respect its value if set except
3177 ;; for faces where M-x customize has been used to save changes for the face.
3178
3179 (defun ps-font-lock-face-attributes ()
3180 (and (boundp 'font-lock-mode) (symbol-value 'font-lock-mode)
3181 (boundp 'font-lock-face-attributes)
3182 (let ((face-attributes font-lock-face-attributes))
3183 (while face-attributes
3184 (let* ((face-attribute
3185 (car (prog1 face-attributes
3186 (setq face-attributes (cdr face-attributes)))))
3187 (face (car face-attribute)))
3188 ;; Rustle up a `defface' SPEC from a
3189 ;; `font-lock-face-attributes' entry.
3190 (unless (get face 'saved-face)
3191 (let ((foreground (nth 1 face-attribute))
3192 (background (nth 2 face-attribute))
3193 (bold-p (nth 3 face-attribute))
3194 (italic-p (nth 4 face-attribute))
3195 (underline-p (nth 5 face-attribute))
3196 face-spec)
3197 (when foreground
3198 (setq face-spec (cons ':foreground
3199 (cons foreground face-spec))))
3200 (when background
3201 (setq face-spec (cons ':background
3202 (cons background face-spec))))
3203 (when bold-p
3204 (setq face-spec (append '(:bold t) face-spec)))
3205 (when italic-p
3206 (setq face-spec (append '(:italic t) face-spec)))
3207 (when underline-p
3208 (setq face-spec (append '(:underline t) face-spec)))
3209 (custom-declare-face face (list (list t face-spec)) nil)
3210 )))))))
3211
3212 \f
3213 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3214 ;; Internal functions and variables
3215
3216
3217 (make-local-hook 'ps-print-hook)
3218 (make-local-hook 'ps-print-begin-sheet-hook)
3219 (make-local-hook 'ps-print-begin-page-hook)
3220 (make-local-hook 'ps-print-begin-column-hook)
3221
3222
3223 (defun ps-print-without-faces (from to &optional filename region-p)
3224 (ps-spool-without-faces from to region-p)
3225 (ps-do-despool filename))
3226
3227
3228 (defun ps-spool-without-faces (from to &optional region-p)
3229 (run-hooks 'ps-print-hook)
3230 (ps-printing-region region-p)
3231 (ps-generate (current-buffer) from to 'ps-generate-postscript))
3232
3233
3234 (defun ps-print-with-faces (from to &optional filename region-p)
3235 (ps-spool-with-faces from to region-p)
3236 (ps-do-despool filename))
3237
3238
3239 (defun ps-spool-with-faces (from to &optional region-p)
3240 (run-hooks 'ps-print-hook)
3241 (ps-printing-region region-p)
3242 (ps-generate (current-buffer) from to 'ps-generate-postscript-with-faces))
3243
3244
3245 (defun ps-count-lines (from to)
3246 (+ (count-lines from to)
3247 (save-excursion
3248 (goto-char to)
3249 (if (= (current-column) 0) 1 0))))
3250
3251
3252 (defvar ps-printing-region nil
3253 "Variable used to indicate if the region that ps-print is printing.
3254 It is a cons, the car of which is the line number where the region begins, and
3255 its cdr is the total number of lines in the buffer. Formatting functions can
3256 use this information to print the original line number (and not the number of
3257 lines printed), and to indicate in the header that the printout is of a partial
3258 file.")
3259
3260
3261 (defvar ps-printing-region-p nil
3262 "Non-nil means ps-print is printing a region.")
3263
3264
3265 (defun ps-printing-region (region-p)
3266 (setq ps-printing-region-p region-p
3267 ps-printing-region
3268 (cons (if region-p
3269 (ps-count-lines (point-min) (region-beginning))
3270 1)
3271 (ps-count-lines (point-min) (point-max)))))
3272
3273 \f
3274 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3275 ;; Internal functions
3276
3277 (defsubst ps-font-alist (font-sym)
3278 (get font-sym 'fonts))
3279
3280 (defun ps-font (font-sym font-type)
3281 "Font family name for text of `font-type', when generating PostScript."
3282 (let* ((font-list (ps-font-alist font-sym))
3283 (normal-font (cdr (assq 'normal font-list))))
3284 (while (and font-list (not (eq font-type (car (car font-list)))))
3285 (setq font-list (cdr font-list)))
3286 (or (cdr (car font-list)) normal-font)))
3287
3288 (defun ps-fonts (font-sym)
3289 (mapcar 'cdr (ps-font-alist font-sym)))
3290
3291 (defun ps-font-number (font-sym font-type)
3292 (or (ps-alist-position font-type (ps-font-alist font-sym))
3293 0))
3294
3295 (defsubst ps-line-height (font-sym)
3296 "The height of a line, for generating PostScript.
3297 This is the value that ps-print uses to determine the height,
3298 y-dimension, of the lines of text it has printed, and thus affects the
3299 point at which page-breaks are placed.
3300 The line-height is *not* the same as the point size of the font."
3301 (get font-sym 'line-height))
3302
3303 (defsubst ps-title-line-height (font-sym)
3304 "The height of a `title' line, for generating PostScript.
3305 This is the value that ps-print uses to determine the height,
3306 y-dimension, of the lines of text it has printed, and thus affects the
3307 point at which page-breaks are placed.
3308 The title-line-height is *not* the same as the point size of the font."
3309 (get font-sym 'title-line-height))
3310
3311 (defsubst ps-space-width (font-sym)
3312 "The width of a space character, for generating PostScript.
3313 This value is used in expanding tab characters."
3314 (get font-sym 'space-width))
3315
3316 (defsubst ps-avg-char-width (font-sym)
3317 "The average width, in points, of a character, for generating PostScript.
3318 This is the value that ps-print uses to determine the length,
3319 x-dimension, of the text it has printed, and thus affects the point at
3320 which long lines wrap around."
3321 (get font-sym 'avg-char-width))
3322
3323 (defun ps-line-lengths-internal ()
3324 "Display the correspondence between a line length and a font size,
3325 using the current ps-print setup.
3326 Try: pr -t file | awk '{printf \"%3d %s\n\", length($0), $0}' | sort -r | head"
3327 (let ((buf (get-buffer-create "*Line-lengths*"))
3328 (ifs ps-font-size-internal) ; initial font size
3329 (icw (ps-avg-char-width 'ps-font-for-text)) ; initial character width
3330 (print-width (progn (ps-get-page-dimensions)
3331 ps-print-width))
3332 (ps-setup (ps-setup)) ; setup for the current buffer
3333 (fs-min 5) ; minimum font size
3334 cw-min ; minimum character width
3335 nb-cpl-max ; maximum nb of characters per line
3336 (fs-max 14) ; maximum font size
3337 cw-max ; maximum character width
3338 nb-cpl-min ; minimum nb of characters per line
3339 fs ; current font size
3340 cw ; current character width
3341 nb-cpl ; current nb of characters per line
3342 )
3343 (setq cw-min (/ (* icw fs-min) ifs)
3344 nb-cpl-max (floor (/ print-width cw-min))
3345 cw-max (/ (* icw fs-max) ifs)
3346 nb-cpl-min (floor (/ print-width cw-max))
3347 nb-cpl nb-cpl-min)
3348 (set-buffer buf)
3349 (goto-char (point-max))
3350 (or (bolp) (insert "\n"))
3351 (insert ps-setup
3352 "nb char per line / font size\n")
3353 (while (<= nb-cpl nb-cpl-max)
3354 (setq cw (/ print-width (float nb-cpl))
3355 fs (/ (* ifs cw) icw))
3356 (insert (format "%3s %s\n" nb-cpl fs))
3357 (setq nb-cpl (1+ nb-cpl)))
3358 (insert "\n")
3359 (display-buffer buf 'not-this-window)))
3360
3361 (defun ps-nb-pages (nb-lines)
3362 "Display correspondence between font size and the number of pages.
3363 The correspondence is based on having NB-LINES lines of text,
3364 and on the current ps-print setup."
3365 (let ((buf (get-buffer-create "*Nb-Pages*"))
3366 (ifs ps-font-size-internal) ; initial font size
3367 (ilh (ps-line-height 'ps-font-for-text)) ; initial line height
3368 (page-height (progn (ps-get-page-dimensions)
3369 ps-print-height))
3370 (ps-setup (ps-setup)) ; setup for the current buffer
3371 (fs-min 4) ; minimum font size
3372 lh-min ; minimum line height
3373 nb-lpp-max ; maximum nb of lines per page
3374 nb-page-min ; minimum nb of pages
3375 (fs-max 14) ; maximum font size
3376 lh-max ; maximum line height
3377 nb-lpp-min ; minimum nb of lines per page
3378 nb-page-max ; maximum nb of pages
3379 fs ; current font size
3380 lh ; current line height
3381 nb-lpp ; current nb of lines per page
3382 nb-page ; current nb of pages
3383 )
3384 (setq lh-min (/ (* ilh fs-min) ifs)
3385 nb-lpp-max (floor (/ page-height lh-min))
3386 nb-page-min (ceiling (/ (float nb-lines) nb-lpp-max))
3387 lh-max (/ (* ilh fs-max) ifs)
3388 nb-lpp-min (floor (/ page-height lh-max))
3389 nb-page-max (ceiling (/ (float nb-lines) nb-lpp-min))
3390 nb-page nb-page-min)
3391 (set-buffer buf)
3392 (goto-char (point-max))
3393 (or (bolp) (insert "\n"))
3394 (insert ps-setup
3395 (format "%d lines\n" nb-lines)
3396 "nb page / font size\n")
3397 (while (<= nb-page nb-page-max)
3398 (setq nb-lpp (ceiling (/ nb-lines (float nb-page)))
3399 lh (/ page-height nb-lpp)
3400 fs (/ (* ifs lh) ilh))
3401 (insert (format "%s %s\n" nb-page fs))
3402 (setq nb-page (1+ nb-page)))
3403 (insert "\n")
3404 (display-buffer buf 'not-this-window)))
3405
3406 ;; macros used in `ps-select-font'
3407 (defmacro ps-lookup (key) `(cdr (assq ,key font-entry)))
3408 (defmacro ps-size-scale (key) `(/ (* (ps-lookup ,key) font-size) size))
3409
3410 (defun ps-select-font (font-family sym font-size title-font-size)
3411 (let ((font-entry (cdr (assq font-family ps-font-info-database))))
3412 (or font-entry
3413 (error "Don't have data to scale font %s. Known fonts families are %s"
3414 font-family
3415 (mapcar 'car ps-font-info-database)))
3416 (let ((size (ps-lookup 'size)))
3417 (put sym 'fonts (ps-lookup 'fonts))
3418 (put sym 'space-width (ps-size-scale 'space-width))
3419 (put sym 'avg-char-width (ps-size-scale 'avg-char-width))
3420 (put sym 'line-height (ps-size-scale 'line-height))
3421 (put sym 'title-line-height
3422 (/ (* (ps-lookup 'line-height) title-font-size) size)))))
3423
3424 (defun ps-get-page-dimensions ()
3425 (let ((page-dimensions (cdr (assq ps-paper-type ps-page-dimensions-database)))
3426 page-width page-height)
3427 (cond
3428 ((null page-dimensions)
3429 (error "`ps-paper-type' must be one of:\n%s"
3430 (mapcar 'car ps-page-dimensions-database)))
3431 ((< ps-number-of-columns 1)
3432 (error "The number of columns %d should be positive"
3433 ps-number-of-columns)))
3434
3435 (ps-select-font ps-font-family 'ps-font-for-text
3436 ps-font-size-internal ps-font-size-internal)
3437 (ps-select-font ps-header-font-family 'ps-font-for-header
3438 ps-header-font-size-internal
3439 ps-header-title-font-size-internal)
3440
3441 (setq page-width (ps-page-dimensions-get-width page-dimensions)
3442 page-height (ps-page-dimensions-get-height page-dimensions))
3443
3444 ;; Landscape mode
3445 (if ps-landscape-mode
3446 ;; exchange width and height
3447 (setq page-width (prog1 page-height (setq page-height page-width))))
3448
3449 ;; It is used to get the lower right corner (only in landscape mode)
3450 (setq ps-landscape-page-height page-height)
3451
3452 ;; | lm | text | ic | text | ic | text | rm |
3453 ;; page-width == lm + n * pw + (n - 1) * ic + rm
3454 ;; => pw == (page-width - lm -rm - (n - 1) * ic) / n
3455 (setq ps-print-width (/ (- page-width
3456 ps-left-margin ps-right-margin
3457 (* (1- ps-number-of-columns) ps-inter-column))
3458 ps-number-of-columns))
3459 (if (<= ps-print-width 0)
3460 (error "Bad horizontal layout:
3461 page-width == %s
3462 ps-left-margin == %s
3463 ps-right-margin == %s
3464 ps-inter-column == %s
3465 ps-number-of-columns == %s
3466 | lm | text | ic | text | ic | text | rm |
3467 page-width == lm + n * print-width + (n - 1) * ic + rm
3468 => print-width == %d !"
3469 page-width
3470 ps-left-margin
3471 ps-right-margin
3472 ps-inter-column
3473 ps-number-of-columns
3474 ps-print-width))
3475
3476 (setq ps-print-height
3477 (- page-height ps-bottom-margin ps-top-margin))
3478 (if (<= ps-print-height 0)
3479 (error "Bad vertical layout:
3480 ps-top-margin == %s
3481 ps-bottom-margin == %s
3482 page-height == bm + print-height + tm
3483 => print-height == %d !"
3484 ps-top-margin
3485 ps-bottom-margin
3486 ps-print-height))
3487 ;; If headers are turned on, deduct the height of the header from
3488 ;; the print height.
3489 (if ps-print-header
3490 (setq ps-header-pad (* ps-header-line-pad
3491 (ps-title-line-height 'ps-font-for-header))
3492 ps-print-height (- ps-print-height
3493 ps-header-offset
3494 ps-header-pad
3495 (ps-title-line-height 'ps-font-for-header)
3496 (* (ps-line-height 'ps-font-for-header)
3497 (1- ps-header-lines))
3498 ps-header-pad)))
3499 (if (<= ps-print-height 0)
3500 (error "Bad vertical layout:
3501 ps-top-margin == %s
3502 ps-bottom-margin == %s
3503 ps-header-offset == %s
3504 ps-header-pad == %s
3505 header-height == %s
3506 page-height == bm + print-height + tm - ho - hh
3507 => print-height == %d !"
3508 ps-top-margin
3509 ps-bottom-margin
3510 ps-header-offset
3511 ps-header-pad
3512 (+ ps-header-pad
3513 (ps-title-line-height 'ps-font-for-header)
3514 (* (ps-line-height 'ps-font-for-header)
3515 (1- ps-header-lines))
3516 ps-header-pad)
3517 ps-print-height))))
3518
3519 (defun ps-print-preprint (&optional filename)
3520 (and filename
3521 (or (numberp filename)
3522 (listp filename))
3523 (let* ((name (concat (file-name-nondirectory (or (buffer-file-name)
3524 (buffer-name)))
3525 ".ps"))
3526 (prompt (format "Save PostScript to file: (default %s) " name))
3527 (res (read-file-name prompt default-directory name nil)))
3528 (while (cond ((not (file-writable-p res))
3529 (ding)
3530 (setq prompt "is unwritable"))
3531 ((file-exists-p res)
3532 (setq prompt "exists")
3533 (not (y-or-n-p (format "File `%s' exists; overwrite? "
3534 res))))
3535 (t nil))
3536 (setq res (read-file-name
3537 (format "File %s; save PostScript to file: " prompt)
3538 (file-name-directory res) nil nil
3539 (file-name-nondirectory res))))
3540 (if (file-directory-p res)
3541 (expand-file-name name (file-name-as-directory res))
3542 res))))
3543
3544 ;; The following functions implement a simple list-buffering scheme so
3545 ;; that ps-print doesn't have to repeatedly switch between buffers
3546 ;; while spooling. The functions `ps-output' and `ps-output-string' build
3547 ;; up the lists; the function `ps-flush-output' takes the lists and
3548 ;; insert its contents into the spool buffer (*PostScript*).
3549
3550 (defvar ps-string-escape-codes
3551 (let ((table (make-vector 256 nil))
3552 (char ?\000))
3553 ;; control characters
3554 (while (<= char ?\037)
3555 (aset table char (format "\\%03o" char))
3556 (setq char (1+ char)))
3557 ;; printable characters
3558 (while (< char ?\177)
3559 (aset table char (format "%c" char))
3560 (setq char (1+ char)))
3561 ;; DEL and 8-bit characters
3562 (while (<= char ?\377)
3563 (aset table char (format "\\%o" char))
3564 (setq char (1+ char)))
3565 ;; Override ASCII formatting characters with named escape code:
3566 (aset table ?\n "\\n") ; [NL] linefeed
3567 (aset table ?\r "\\r") ; [CR] carriage return
3568 (aset table ?\t "\\t") ; [HT] horizontal tab
3569 (aset table ?\b "\\b") ; [BS] backspace
3570 (aset table ?\f "\\f") ; [NP] form feed
3571 ;; Escape PostScript escape and string delimiter characters:
3572 (aset table ?\\ "\\\\")
3573 (aset table ?\( "\\(")
3574 (aset table ?\) "\\)")
3575 table)
3576 "Vector used to map characters to PostScript string escape codes.")
3577
3578 (defun ps-output-string-prim (string)
3579 (insert "(") ;insert start-string delimiter
3580 (save-excursion ;insert string
3581 (insert (string-as-unibyte string)))
3582 ;; Find and quote special characters as necessary for PS
3583 ;; This skips everything except control chars, non-ASCII chars, (, ) and \.
3584 (while (progn (skip-chars-forward " -'*-[]-~") (not (eobp)))
3585 (let ((special (following-char)))
3586 (delete-char 1)
3587 (insert (aref ps-string-escape-codes special))))
3588 (goto-char (point-max))
3589 (insert ")")) ;insert end-string delimiter
3590
3591 (defun ps-init-output-queue ()
3592 (setq ps-output-head '("")
3593 ps-output-tail ps-output-head))
3594
3595 (defun ps-output (&rest args)
3596 (setcdr ps-output-tail args)
3597 (while (cdr ps-output-tail)
3598 (setq ps-output-tail (cdr ps-output-tail))))
3599
3600 (defun ps-output-string (string)
3601 (ps-output t string))
3602
3603 (defun ps-output-list (the-list)
3604 (mapcar 'ps-output the-list))
3605
3606 ;; Output strings in the list ARGS in the PostScript prologue part.
3607 (defun ps-output-prologue (args)
3608 (ps-output 'prologue (if (stringp args) (list args) args)))
3609
3610 (defun ps-flush-output ()
3611 (save-excursion
3612 (set-buffer ps-spool-buffer)
3613 (goto-char (point-max))
3614 (while ps-output-head
3615 (let ((it (car ps-output-head)))
3616 (cond
3617 ((eq t it)
3618 (setq ps-output-head (cdr ps-output-head))
3619 (ps-output-string-prim (car ps-output-head)))
3620 ((eq 'prologue it)
3621 (setq ps-output-head (cdr ps-output-head))
3622 (save-excursion
3623 (search-backward "\nBeginDoc")
3624 (forward-char 1)
3625 (apply 'insert (car ps-output-head))))
3626 (t
3627 (insert it))))
3628 (setq ps-output-head (cdr ps-output-head))))
3629 (ps-init-output-queue))
3630
3631 (defun ps-insert-file (fname)
3632 (ps-flush-output)
3633 ;; Check to see that the file exists and is readable; if not, throw
3634 ;; an error.
3635 (or (file-readable-p fname)
3636 (error "Could not read file `%s'" fname))
3637 (save-excursion
3638 (set-buffer ps-spool-buffer)
3639 (goto-char (point-max))
3640 (insert-file fname)))
3641
3642 ;; These functions insert the arrays that define the contents of the
3643 ;; headers.
3644
3645 (defun ps-generate-header-line (fonttag &optional content)
3646 (ps-output " [ " fonttag " ")
3647 (cond
3648 ;; Literal strings should be output as is -- the string must
3649 ;; contain its own PS string delimiters, '(' and ')', if necessary.
3650 ((stringp content)
3651 (ps-output content))
3652
3653 ;; Functions are called -- they should return strings; they will be
3654 ;; inserted as strings and the PS string delimiters added.
3655 ((and (symbolp content) (fboundp content))
3656 (ps-output-string (funcall content)))
3657
3658 ;; Variables will have their contents inserted. They should
3659 ;; contain strings, and will be inserted as strings.
3660 ((and (symbolp content) (boundp content))
3661 (ps-output-string (symbol-value content)))
3662
3663 ;; Anything else will get turned into an empty string.
3664 (t
3665 (ps-output-string "")))
3666 (ps-output " ]\n"))
3667
3668 (defun ps-generate-header (name contents)
3669 (ps-output "/" name " [\n")
3670 (if (> ps-header-lines 0)
3671 (let ((count 1))
3672 (ps-generate-header-line "/h0" (car contents))
3673 (while (and (< count ps-header-lines)
3674 (setq contents (cdr contents)))
3675 (ps-generate-header-line "/h1" (car contents))
3676 (setq count (1+ count)))
3677 (ps-output "] def\n"))))
3678
3679
3680 (defun ps-output-boolean (name bool &optional no-def)
3681 (ps-output (format "/%s %s%s"
3682 name (if bool "true" "false") (if no-def "\n" " def\n"))))
3683
3684
3685 (defun ps-background-pages (page-list func)
3686 (if page-list
3687 (mapcar
3688 #'(lambda (pages)
3689 (let ((start (if (consp pages) (car pages) pages))
3690 (end (if (consp pages) (cdr pages) pages)))
3691 (and (integerp start) (integerp end) (<= start end)
3692 (add-to-list 'ps-background-pages (vector start end func)))))
3693 page-list)
3694 (setq ps-background-all-pages (cons func ps-background-all-pages))))
3695
3696
3697 (defconst ps-boundingbox-re
3698 "^%%BoundingBox:\
3699 \\s-+\\([0-9.]+\\)\\s-+\\([0-9.]+\\)\\s-+\\([0-9.]+\\)\\s-+\\([0-9.]+\\)")
3700
3701
3702 (defun ps-get-boundingbox ()
3703 (save-excursion
3704 (set-buffer ps-spool-buffer)
3705 (save-excursion
3706 (if (re-search-forward ps-boundingbox-re nil t)
3707 (vector (string-to-number ; lower x
3708 (buffer-substring (match-beginning 1) (match-end 1)))
3709 (string-to-number ; lower y
3710 (buffer-substring (match-beginning 2) (match-end 2)))
3711 (string-to-number ; upper x
3712 (buffer-substring (match-beginning 3) (match-end 3)))
3713 (string-to-number ; upper y
3714 (buffer-substring (match-beginning 4) (match-end 4))))
3715 (vector 0 0 0 0)))))
3716
3717
3718 ;; Emacs understands the %f format; we'll use it to limit color RGB values
3719 ;; to three decimals to cut down some on the size of the PostScript output.
3720 ;; Lucid emacsen will have to make do with %s (princ) for floats.
3721
3722 (defvar ps-float-format (if (eq ps-print-emacs-type 'emacs)
3723 "%0.3f " ; emacs
3724 "%s ")) ; Lucid emacsen
3725
3726
3727 (defun ps-float-format (value &optional default)
3728 (let ((literal (or value default)))
3729 (if literal
3730 (format (if (numberp literal)
3731 ps-float-format
3732 "%s ")
3733 literal)
3734 " ")))
3735
3736
3737 (defun ps-background-text ()
3738 (mapcar
3739 #'(lambda (text)
3740 (setq ps-background-text-count (1+ ps-background-text-count))
3741 (ps-output (format "/ShowBackText-%d {\n" ps-background-text-count))
3742 (ps-output-string (nth 0 text)) ; text
3743 (ps-output
3744 "\n"
3745 (ps-float-format (nth 4 text) 200.0) ; font size
3746 (format "/%s " (or (nth 3 text) "Times-Roman")) ; font name
3747 (ps-float-format (nth 6 text)
3748 "PrintHeight PrintPageWidth atan") ; rotation
3749 (ps-float-format (nth 5 text) 0.85) ; gray
3750 (ps-float-format (nth 1 text) "0") ; x position
3751 (ps-float-format (nth 2 text) "BottomMargin") ; y position
3752 "\nShowBackText} def\n")
3753 (ps-background-pages (nthcdr 7 text) ; page list
3754 (format "ShowBackText-%d\n"
3755 ps-background-text-count)))
3756 ps-print-background-text))
3757
3758
3759 (defun ps-background-image ()
3760 (mapcar
3761 #'(lambda (image)
3762 (let ((image-file (expand-file-name (nth 0 image))))
3763 (if (file-readable-p image-file)
3764 (progn
3765 (setq ps-background-image-count (1+ ps-background-image-count))
3766 (ps-output
3767 (format "/ShowBackImage-%d {\n--back-- "
3768 ps-background-image-count)
3769 (ps-float-format (nth 5 image) 0.0) ; rotation
3770 (ps-float-format (nth 3 image) 1.0) ; x scale
3771 (ps-float-format (nth 4 image) 1.0) ; y scale
3772 (ps-float-format (nth 1 image) ; x position
3773 "PrintPageWidth 2 div")
3774 (ps-float-format (nth 2 image) ; y position
3775 "PrintHeight 2 div BottomMargin add")
3776 "\nBeginBackImage\n")
3777 (ps-insert-file image-file)
3778 ;; coordinate adjustment to centralize image
3779 ;; around x and y position
3780 (let ((box (ps-get-boundingbox)))
3781 (save-excursion
3782 (set-buffer ps-spool-buffer)
3783 (save-excursion
3784 (if (re-search-backward "^--back--" nil t)
3785 (replace-match
3786 (format "%s %s"
3787 (ps-float-format
3788 (- (+ (/ (- (aref box 2) (aref box 0)) 2.0)
3789 (aref box 0))))
3790 (ps-float-format
3791 (- (+ (/ (- (aref box 3) (aref box 1)) 2.0)
3792 (aref box 1)))))
3793 t)))))
3794 (ps-output "\nEndBackImage} def\n")
3795 (ps-background-pages (nthcdr 6 image) ; page list
3796 (format "ShowBackImage-%d\n"
3797 ps-background-image-count))))))
3798 ps-print-background-image))
3799
3800
3801 (defun ps-background (page-number)
3802 (let (has-local-background)
3803 (mapcar #'(lambda (range)
3804 (and (<= (aref range 0) page-number)
3805 (<= page-number (aref range 1))
3806 (if has-local-background
3807 (ps-output (aref range 2))
3808 (setq has-local-background t)
3809 (ps-output "/printLocalBackground {\n"
3810 (aref range 2)))))
3811 ps-background-pages)
3812 (and has-local-background (ps-output "} def\n"))))
3813
3814
3815 ;; Return a list of the distinct elements of LIST.
3816 ;; Elements are compared with `equal'.
3817 (defun ps-remove-duplicates (list)
3818 (let (new (tail list))
3819 (while tail
3820 (or (member (car tail) new)
3821 (setq new (cons (car tail) new)))
3822 (setq tail (cdr tail)))
3823 (nreverse new)))
3824
3825
3826 ;; Find the first occurrence of ITEM in LIST.
3827 ;; Return the index of the matching item, or nil if not found.
3828 ;; Elements are compared with `eq'.
3829 (defun ps-alist-position (item list)
3830 (let ((tail list) (index 0) found)
3831 (while tail
3832 (if (setq found (eq (car (car tail)) item))
3833 (setq tail nil)
3834 (setq index (1+ index)
3835 tail (cdr tail))))
3836 (and found index)))
3837
3838
3839 (defconst ps-n-up-database
3840 '((a4
3841 (1 nil 1 1 0)
3842 (2 t 1 2 0)
3843 (4 nil 2 2 0)
3844 (6 t 2 3 1)
3845 (8 t 2 4 0)
3846 (9 nil 3 3 0)
3847 (12 t 3 4 2)
3848 (16 nil 4 4 0)
3849 (18 t 3 6 0)
3850 (20 nil 5 4 1)
3851 (25 nil 5 5 0)
3852 (30 nil 6 5 1)
3853 (32 t 4 8 0)
3854 (36 nil 6 6 0)
3855 (42 nil 7 6 1)
3856 (49 nil 7 7 0)
3857 (50 t 5 10 0)
3858 (56 nil 8 7 1)
3859 (64 nil 8 8 0)
3860 (72 nil 9 8 1)
3861 (81 nil 9 9 0)
3862 (90 nil 10 9 1)
3863 (100 nil 10 10 0))
3864 (a3
3865 (1 nil 1 1 0)
3866 (2 t 1 2 0)
3867 (4 nil 2 2 0)
3868 (6 t 2 3 1)
3869 (8 t 2 4 0)
3870 (9 nil 3 3 0)
3871 (12 nil 4 3 1)
3872 (16 nil 4 4 0)
3873 (18 t 3 6 0)
3874 (20 nil 5 4 1)
3875 (25 nil 5 5 0)
3876 (30 nil 6 5 1)
3877 (32 t 4 8 0)
3878 (36 nil 6 6 0)
3879 (42 nil 7 6 1)
3880 (49 nil 7 7 0)
3881 (50 t 5 10 0)
3882 (56 nil 8 7 1)
3883 (64 nil 8 8 0)
3884 (72 nil 9 8 1)
3885 (81 nil 9 9 0)
3886 (90 nil 10 9 1)
3887 (100 nil 10 10 0))
3888 (letter
3889 (1 nil 1 1 0)
3890 (4 nil 2 2 0)
3891 (6 t 2 3 0)
3892 (9 nil 3 3 0)
3893 (12 nil 4 3 1)
3894 (16 nil 4 4 0)
3895 (20 nil 5 4 1)
3896 (25 nil 5 5 0)
3897 (30 nil 6 5 1)
3898 (36 nil 6 6 0)
3899 (40 t 5 8 0)
3900 (42 nil 7 6 1)
3901 (49 nil 7 7 0)
3902 (56 nil 8 7 1)
3903 (64 nil 8 8 0)
3904 (72 nil 9 8 1)
3905 (81 nil 9 9 0)
3906 (90 nil 10 9 1)
3907 (100 nil 10 10 0))
3908 (legal
3909 (1 nil 1 1 0)
3910 (2 t 1 2 0)
3911 (4 nil 2 2 0)
3912 (6 nil 3 2 1)
3913 (9 nil 3 3 0)
3914 (10 t 2 5 0)
3915 (12 nil 4 3 1)
3916 (16 nil 4 4 0)
3917 (20 nil 5 4 1)
3918 (25 nil 5 5 0)
3919 (30 nil 6 5 1)
3920 (36 nil 6 6 0)
3921 (42 nil 7 6 1)
3922 (49 nil 7 7 0)
3923 (56 nil 8 7 1)
3924 (64 nil 8 8 0)
3925 (70 t 5 14 0)
3926 (72 nil 9 8 1)
3927 (81 nil 9 9 0)
3928 (90 nil 10 9 1)
3929 (100 nil 10 10 0))
3930 (letter-small
3931 (1 nil 1 1 0)
3932 (4 nil 2 2 0)
3933 (6 t 2 3 0)
3934 (9 nil 3 3 0)
3935 (12 t 3 4 1)
3936 (15 t 3 5 0)
3937 (16 nil 4 4 0)
3938 (20 nil 5 4 1)
3939 (25 nil 5 5 0)
3940 (28 t 4 7 0)
3941 (30 nil 6 5 1)
3942 (36 nil 6 6 0)
3943 (40 t 5 8 0)
3944 (42 nil 7 6 1)
3945 (49 nil 7 7 0)
3946 (56 nil 8 7 1)
3947 (60 t 6 10 0)
3948 (64 nil 8 8 0)
3949 (72 ni 9 8 1)
3950 (81 nil 9 9 0)
3951 (84 t 7 12 0)
3952 (90 nil 10 9 1)
3953 (100 nil 10 10 0))
3954 (tabloid
3955 (1 nil 1 1 0)
3956 (2 t 1 2 0)
3957 (4 nil 2 2 0)
3958 (6 t 2 3 1)
3959 (8 t 2 4 0)
3960 (9 nil 3 3 0)
3961 (12 nil 4 3 1)
3962 (16 nil 4 4 0)
3963 (20 nil 5 4 1)
3964 (25 nil 5 5 0)
3965 (30 nil 6 5 1)
3966 (36 nil 6 6 0)
3967 (42 nil 7 6 1)
3968 (49 nil 7 7 0)
3969 (56 nil 8 7 1)
3970 (64 nil 8 8 0)
3971 (72 nil 9 8 1)
3972 (81 nil 9 9 0)
3973 (84 t 6 14 0)
3974 (90 nil 10 9 1)
3975 (100 nil 10 10 0))
3976 ;; Ledger paper size is a special case, it is the only paper size where the
3977 ;; normal size is landscaped, that is, the height is smaller than width.
3978 ;; So, we use the special value `pag' in the `landscape' field.
3979 (ledger
3980 (1 nil 1 1 0)
3981 (2 pag 1 2 0)
3982 (4 nil 2 2 0)
3983 (6 pag 2 3 1)
3984 (8 pag 2 4 0)
3985 (9 nil 3 3 0)
3986 (12 nil 4 3 1)
3987 (16 nil 4 4 0)
3988 (20 nil 5 4 1)
3989 (25 nil 5 5 0)
3990 (30 nil 6 5 1)
3991 (36 nil 6 6 0)
3992 (42 nil 7 6 1)
3993 (49 nil 7 7 0)
3994 (56 nil 8 7 1)
3995 (64 nil 8 8 0)
3996 (72 nil 9 8 1)
3997 (81 nil 9 9 0)
3998 (84 pag 6 14 0)
3999 (90 nil 10 9 1)
4000 (100 nil 10 10 0))
4001 (statement
4002 (1 nil 1 1 0)
4003 (2 t 1 2 0)
4004 (4 nil 2 2 0)
4005 (6 nil 3 2 1)
4006 (9 nil 3 3 0)
4007 (10 t 2 5 0)
4008 (12 nil 4 3 1)
4009 (16 nil 4 4 0)
4010 (20 nil 5 4 1)
4011 (21 t 3 7 0)
4012 (25 nil 5 5 0)
4013 (30 nil 6 5 1)
4014 (36 nil 6 6 0)
4015 (40 t 4 10 0)
4016 (42 nil 7 6 1)
4017 (49 nil 7 7 0)
4018 (56 nil 8 7 1)
4019 (60 t 5 12 0)
4020 (64 nil 8 8 0)
4021 (72 nil 9 8 1)
4022 (81 nil 9 9 0)
4023 (90 nil 10 9 1)
4024 (100 nil 10 10 0))
4025 (executive
4026 (1 nil 1 1 0)
4027 (4 nil 2 2 0)
4028 (6 t 2 3 0)
4029 (9 nil 3 3 0)
4030 (12 nil 4 3 1)
4031 (16 nil 4 4 0)
4032 (20 nil 5 4 1)
4033 (25 nil 5 5 0)
4034 (28 t 4 7 0)
4035 (30 nil 6 5 1)
4036 (36 nil 6 6 0)
4037 (42 nil 7 6 1)
4038 (45 t 5 9 0)
4039 (49 nil 7 7 0)
4040 (56 nil 8 7 1)
4041 (60 t 6 10 0)
4042 (64 nil 8 8 0)
4043 (72 nil 9 8 1)
4044 (81 nil 9 9 0)
4045 (84 t 7 12 0)
4046 (90 nil 10 9 1)
4047 (100 nil 10 10 0))
4048 (a4small
4049 (1 nil 1 1 0)
4050 (2 t 1 2 0)
4051 (4 nil 2 2 0)
4052 (6 t 2 3 1)
4053 (8 t 2 4 0)
4054 (9 nil 3 3 0)
4055 (12 nil 4 3 1)
4056 (16 nil 4 4 0)
4057 (18 t 3 6 0)
4058 (20 nil 5 4 1)
4059 (25 nil 5 5 0)
4060 (30 nil 6 5 1)
4061 (32 t 4 8 0)
4062 (36 nil 6 6 0)
4063 (42 nil 7 6 1)
4064 (49 nil 7 7 0)
4065 (50 t 5 10 0)
4066 (56 nil 8 7 1)
4067 (64 nil 8 8 0)
4068 (72 nil 9 8 1)
4069 (78 t 6 13 0)
4070 (81 nil 9 9 0)
4071 (90 nil 10 9 1)
4072 (100 nil 10 10 0))
4073 (b4
4074 (1 nil 1 1 0)
4075 (2 t 1 2 0)
4076 (4 nil 2 2 0)
4077 (6 t 2 3 1)
4078 (8 t 2 4 0)
4079 (9 nil 3 3 0)
4080 (12 nil 4 3 1)
4081 (16 nil 4 4 0)
4082 (18 t 3 6 0)
4083 (20 nil 5 4 1)
4084 (25 nil 5 5 0)
4085 (30 nil 6 5 1)
4086 (32 t 4 8 0)
4087 (36 nil 6 6 0)
4088 (42 nil 7 6 1)
4089 (49 nil 7 7 0)
4090 (50 t 5 10 0)
4091 (56 nil 8 7 1)
4092 (64 nil 8 8 0)
4093 (72 nil 9 8 1)
4094 (81 nil 9 9 0)
4095 (90 nil 10 9 1)
4096 (100 nil 10 10 0))
4097 (b5
4098 (1 nil 1 1 0)
4099 (2 t 1 2 0)
4100 (4 nil 2 2 0)
4101 (6 t 2 3 1)
4102 (8 t 2 4 0)
4103 (9 nil 3 3 0)
4104 (12 nil 4 3 1)
4105 (16 nil 4 4 0)
4106 (18 t 3 6 0)
4107 (20 nil 5 4 1)
4108 (25 nil 5 5 0)
4109 (30 nil 6 5 1)
4110 (32 t 4 8 0)
4111 (36 nil 6 6 0)
4112 (42 nil 7 6 1)
4113 (49 nil 7 7 0)
4114 (50 t 5 10 0)
4115 (56 nil 8 7 1)
4116 (64 nil 8 8 0)
4117 (72 nil 9 8 0)
4118 (81 nil 9 9 0)
4119 (90 nil 10 9 1)
4120 (98 t 7 14 0)
4121 (100 nil 10 10 0)))
4122 "Alist which is the page matrix database used for N-up printing.
4123
4124 Each element has the following form:
4125
4126 (PAGE
4127 (MAX LANDSCAPE LINES COLUMNS COL-MISSING)
4128 ...)
4129
4130 Where:
4131 PAGE is the page size used (see `ps-paper-type').
4132 MAX is the maximum elements of this page matrix.
4133 LANDSCAPE specifies if page matrix is landscaped, has the following valid
4134 values:
4135 nil the sheet is in portrait mode.
4136 t the sheet is in landscape mode.
4137 pag the sheet is in portrait mode and page is in landscape mode.
4138 LINES is the number of lines of page matrix.
4139 COLUMNS is the number of columns of page matrix.
4140 COL-MISSING is the number of columns missing to fill the sheet.")
4141
4142
4143 (defmacro ps-n-up-landscape (mat) `(nth 1 ,mat))
4144 (defmacro ps-n-up-lines (mat) `(nth 2 ,mat))
4145 (defmacro ps-n-up-columns (mat) `(nth 3 ,mat))
4146 (defmacro ps-n-up-missing (mat) `(nth 4 ,mat))
4147
4148
4149 (defun ps-n-up-printing ()
4150 ;; force `ps-n-up-printing' be in range 1 to 100.
4151 (setq ps-n-up-printing (max (min ps-n-up-printing 100) 1))
4152 ;; find suitable page matrix for a given `ps-paper-type'.
4153 (let ((the-list (cdr (assq ps-paper-type ps-n-up-database))))
4154 (and the-list
4155 (while (> ps-n-up-printing (caar the-list))
4156 (setq the-list (cdr the-list))))
4157 (car the-list)))
4158
4159
4160 (defconst ps-n-up-filling-database
4161 '((left-top
4162 "PageWidth" ; N-Up-XColumn
4163 "0" ; N-Up-YColumn
4164 "N-Up-End 1 sub PageWidth mul neg" ; N-Up-XLine
4165 "LandscapePageHeight neg" ; N-Up-YLine
4166 "N-Up-Lines" ; N-Up-Repeat
4167 "N-Up-Columns" ; N-Up-End
4168 "0" ; N-Up-XStart
4169 "0") ; N-Up-YStart
4170 (left-bottom
4171 "PageWidth" ; N-Up-XColumn
4172 "0" ; N-Up-YColumn
4173 "N-Up-End 1 sub PageWidth mul neg" ; N-Up-XLine
4174 "LandscapePageHeight" ; N-Up-YLine
4175 "N-Up-Lines" ; N-Up-Repeat
4176 "N-Up-Columns" ; N-Up-End
4177 "0" ; N-Up-XStart
4178 "N-Up-Repeat 1 sub LandscapePageHeight mul neg") ; N-Up-YStart
4179 (right-top
4180 "PageWidth neg" ; N-Up-XColumn
4181 "0" ; N-Up-YColumn
4182 "N-Up-End 1 sub PageWidth mul" ; N-Up-XLine
4183 "LandscapePageHeight neg" ; N-Up-YLine
4184 "N-Up-Lines" ; N-Up-Repeat
4185 "N-Up-Columns" ; N-Up-End
4186 "N-Up-End 1 sub PageWidth mul" ; N-Up-XStart
4187 "0") ; N-Up-YStart
4188 (right-bottom
4189 "PageWidth neg" ; N-Up-XColumn
4190 "0" ; N-Up-YColumn
4191 "N-Up-End 1 sub PageWidth mul" ; N-Up-XLine
4192 "LandscapePageHeight" ; N-Up-YLine
4193 "N-Up-Lines" ; N-Up-Repeat
4194 "N-Up-Columns" ; N-Up-End
4195 "N-Up-End 1 sub PageWidth mul" ; N-Up-XStart
4196 "N-Up-Repeat 1 sub LandscapePageHeight mul neg") ; N-Up-YStart
4197 (top-left
4198 "0" ; N-Up-XColumn
4199 "LandscapePageHeight neg" ; N-Up-YColumn
4200 "PageWidth" ; N-Up-XLine
4201 "N-Up-End 1 sub LandscapePageHeight mul" ; N-Up-YLine
4202 "N-Up-Columns" ; N-Up-Repeat
4203 "N-Up-Lines" ; N-Up-End
4204 "0" ; N-Up-XStart
4205 "0") ; N-Up-YStart
4206 (bottom-left
4207 "0" ; N-Up-XColumn
4208 "LandscapePageHeight" ; N-Up-YColumn
4209 "PageWidth" ; N-Up-XLine
4210 "N-Up-End 1 sub LandscapePageHeight mul neg" ; N-Up-YLine
4211 "N-Up-Columns" ; N-Up-Repeat
4212 "N-Up-Lines" ; N-Up-End
4213 "0" ; N-Up-XStart
4214 "N-Up-End 1 sub LandscapePageHeight mul neg") ; N-Up-YStart
4215 (top-right
4216 "0" ; N-Up-XColumn
4217 "LandscapePageHeight neg" ; N-Up-YColumn
4218 "PageWidth neg" ; N-Up-XLine
4219 "N-Up-End 1 sub LandscapePageHeight mul" ; N-Up-YLine
4220 "N-Up-Columns" ; N-Up-Repeat
4221 "N-Up-Lines" ; N-Up-End
4222 "N-Up-Repeat 1 sub PageWidth mul" ; N-Up-XStart
4223 "0") ; N-Up-YStart
4224 (bottom-right
4225 "0" ; N-Up-XColumn
4226 "LandscapePageHeight" ; N-Up-YColumn
4227 "PageWidth neg" ; N-Up-XLine
4228 "N-Up-End 1 sub LandscapePageHeight mul neg" ; N-Up-YLine
4229 "N-Up-Columns" ; N-Up-Repeat
4230 "N-Up-Lines" ; N-Up-End
4231 "N-Up-Repeat 1 sub PageWidth mul" ; N-Up-XStart
4232 "N-Up-End 1 sub LandscapePageHeight mul neg")) ; N-Up-YStart
4233 "Alist for n-up printing initializations.
4234
4235 Each element has the following form:
4236
4237 (KIND XCOL YCOL XLIN YLIN REPEAT END XSTART YSTART)
4238
4239 Where:
4240 KIND is a valid value of `ps-n-up-filling'.
4241 XCOL YCOL are the relative position for the next column.
4242 XLIN YLIN are the relative position for the beginning of next line.
4243 REPEAT is the number of repetions for external loop.
4244 END is the number of repetions for internal loop and also the number of pages in
4245 a row.
4246 XSTART YSTART are the relative position for the first page in a sheet.")
4247
4248
4249 (defun ps-n-up-filling ()
4250 (cdr (or (assq ps-n-up-filling ps-n-up-filling-database)
4251 (assq 'left-top ps-n-up-filling-database))))
4252
4253
4254 (defmacro ps-n-up-xcolumn (init) `(nth 0 ,init))
4255 (defmacro ps-n-up-ycolumn (init) `(nth 1 ,init))
4256 (defmacro ps-n-up-xline (init) `(nth 2 ,init))
4257 (defmacro ps-n-up-yline (init) `(nth 3 ,init))
4258 (defmacro ps-n-up-repeat (init) `(nth 4 ,init))
4259 (defmacro ps-n-up-end (init) `(nth 5 ,init))
4260 (defmacro ps-n-up-xstart (init) `(nth 6 ,init))
4261 (defmacro ps-n-up-ystart (init) `(nth 7 ,init))
4262
4263
4264 (defun ps-begin-file ()
4265 (ps-get-page-dimensions)
4266 (setq ps-page-postscript 0
4267 ps-page-order 0
4268 ps-background-text-count 0
4269 ps-background-image-count 0
4270 ps-background-pages nil
4271 ps-background-all-pages nil)
4272
4273 (let ((dimensions (cdr (assq ps-paper-type ps-page-dimensions-database)))
4274 (tumble (if ps-landscape-mode (not ps-spool-tumble) ps-spool-tumble))
4275 (n-up (ps-n-up-printing))
4276 (n-up-filling (ps-n-up-filling)))
4277 (and (> ps-n-up-printing 1) (setq tumble (not tumble)))
4278 (ps-output
4279 ps-adobe-tag
4280 "%%Title: " (buffer-name) ; Take job name from name of
4281 ; first buffer printed
4282 "\n%%Creator: " (user-full-name)
4283 " (using ps-print v" ps-print-version
4284 ")\n%%CreationDate: "
4285 (time-stamp-hh:mm:ss) " " (time-stamp-mon-dd-yyyy)
4286 "\n%%Orientation: "
4287 (if ps-landscape-mode "Landscape" "Portrait")
4288 "\n%%DocumentNeededResources: font Times-Roman Times-Italic\n%%+ font "
4289 (mapconcat 'identity
4290 (ps-remove-duplicates
4291 (append (ps-fonts 'ps-font-for-text)
4292 (list (ps-font 'ps-font-for-header 'normal)
4293 (ps-font 'ps-font-for-header 'bold))))
4294 "\n%%+ font ")
4295 "\n%%DocumentMedia: " (ps-page-dimensions-get-media dimensions)
4296 (format " %d" (round (ps-page-dimensions-get-width dimensions)))
4297 (format " %d" (round (ps-page-dimensions-get-height dimensions)))
4298 " 0 () ()\n%%PageOrder: Ascend\n%%Pages: (atend)\n%%Requirements:"
4299 (if ps-spool-duplex
4300 (format " duplex%s" (if tumble "(tumble)\n" "\n"))
4301 "\n"))
4302
4303 (let ((comments (if (functionp ps-print-prologue-header)
4304 (funcall ps-print-prologue-header)
4305 ps-print-prologue-header)))
4306 (and (stringp comments)
4307 (ps-output comments)))
4308
4309 (ps-output "%%EndComments\n\n%%BeginPrologue\n\n"
4310 "/gs_languagelevel /languagelevel where {pop languagelevel}{1}ifelse def\n\n")
4311
4312 (ps-output-boolean "SkipFirstPage " ps-banner-page-when-duplexing)
4313 (ps-output-boolean "LandscapeMode "
4314 (or ps-landscape-mode
4315 (eq (ps-n-up-landscape n-up) 'pag)))
4316 (ps-output (format "/NumberOfColumns %d def\n" ps-number-of-columns)
4317
4318 (format "/LandscapePageHeight %s def\n" ps-landscape-page-height)
4319 (format "/PrintPageWidth %s def\n"
4320 (- (* (+ ps-print-width ps-inter-column)
4321 ps-number-of-columns)
4322 ps-inter-column))
4323 (format "/PrintWidth %s def\n" ps-print-width)
4324 (format "/PrintHeight %s def\n" ps-print-height)
4325
4326 (format "/LeftMargin %s def\n" ps-left-margin)
4327 (format "/RightMargin %s def\n" ps-right-margin)
4328 (format "/InterColumn %s def\n" ps-inter-column)
4329
4330 (format "/BottomMargin %s def\n" ps-bottom-margin)
4331 (format "/TopMargin %s def\n" ps-top-margin) ; not used
4332 (format "/HeaderOffset %s def\n" ps-header-offset)
4333 (format "/HeaderPad %s def\n" ps-header-pad))
4334
4335 (ps-output-boolean "PrintHeader " ps-print-header)
4336 (ps-output-boolean "PrintOnlyOneHeader" ps-print-only-one-header)
4337 (ps-output-boolean "PrintHeaderFrame " ps-print-header-frame)
4338 (ps-output-boolean "ShowNofN " ps-show-n-of-n)
4339 (ps-output-boolean "DuplexValue " ps-spool-duplex)
4340 (ps-output-boolean "TumbleValue " tumble)
4341
4342 (let ((line-height (ps-line-height 'ps-font-for-text)))
4343 (ps-output (format "/LineHeight %s def\n" line-height)
4344 (format "/LinesPerColumn %d def\n"
4345 (round (/ (+ ps-print-height
4346 (* line-height 0.45))
4347 line-height)))))
4348
4349 (ps-output-boolean "Zebra " ps-zebra-stripes)
4350 (ps-output-boolean "PrintLineNumber " ps-line-number)
4351 (ps-output (format "/ZebraHeight %d def\n" ps-zebra-stripe-height)
4352 (format "/ZebraGray %s def\n" ps-zebra-gray)
4353 "/UseSetpagedevice "
4354 (if (eq ps-spool-config 'setpagedevice)
4355 "/setpagedevice where {pop true}{false}ifelse def\n"
4356 "false def\n")
4357 "\n/PageWidth "
4358 "PrintPageWidth LeftMargin add RightMargin add def\n\n"
4359 (format "/N-Up %d def\n" ps-n-up-printing))
4360 (ps-output-boolean "N-Up-Landscape" (eq (ps-n-up-landscape n-up) t))
4361 (ps-output-boolean "N-Up-Border " ps-n-up-border-p)
4362 (ps-output (format "/N-Up-Lines %d def\n" (ps-n-up-lines n-up))
4363 (format "/N-Up-Columns %d def\n" (ps-n-up-columns n-up))
4364 (format "/N-Up-Missing %d def\n" (ps-n-up-missing n-up))
4365 (format "/N-Up-Margin %s" ps-n-up-margin)
4366 " def\n/N-Up-Repeat "
4367 (if ps-landscape-mode
4368 (ps-n-up-end n-up-filling)
4369 (ps-n-up-repeat n-up-filling))
4370 " def\n/N-Up-End "
4371 (if ps-landscape-mode
4372 (ps-n-up-repeat n-up-filling)
4373 (ps-n-up-end n-up-filling))
4374 " def\n/N-Up-XColumn " (ps-n-up-xcolumn n-up-filling)
4375 " def\n/N-Up-YColumn " (ps-n-up-ycolumn n-up-filling)
4376 " def\n/N-Up-XLine " (ps-n-up-xline n-up-filling)
4377 " def\n/N-Up-YLine " (ps-n-up-yline n-up-filling)
4378 " def\n/N-Up-XStart " (ps-n-up-xstart n-up-filling)
4379 " def\n/N-Up-YStart " (ps-n-up-ystart n-up-filling) " def\n")
4380
4381 (ps-background-text)
4382 (ps-background-image)
4383 (setq ps-background-all-pages (nreverse ps-background-all-pages)
4384 ps-background-pages (nreverse ps-background-pages))
4385
4386 (ps-output ps-print-prologue-1)
4387
4388 (ps-output "/printGlobalBackground {\n")
4389 (ps-output-list ps-background-all-pages)
4390 (ps-output "} def\n/printLocalBackground {\n} def\n")
4391
4392 ;; Header fonts
4393 (ps-output (format "/h0 %s (%s) cvn DefFont\n" ; /h0 14 /Helvetica-Bold DefFont
4394 ps-header-title-font-size-internal
4395 (ps-font 'ps-font-for-header 'bold))
4396 (format "/h1 %s (%s) cvn DefFont\n" ; /h1 12 /Helvetica DefFont
4397 ps-header-font-size-internal
4398 (ps-font 'ps-font-for-header 'normal)))
4399
4400 (ps-output ps-print-prologue-2)
4401
4402 ;; Text fonts
4403 (let ((font (ps-font-alist 'ps-font-for-text))
4404 (i 0))
4405 (while font
4406 (ps-output (format "/f%d %s (%s) cvn DefFont\n"
4407 i
4408 ps-font-size-internal
4409 (ps-font 'ps-font-for-text (car (car font)))))
4410 (setq font (cdr font)
4411 i (1+ i))))
4412
4413 (let ((font-entry (cdr (assq ps-font-family ps-font-info-database))))
4414 (ps-output (format "/SpaceWidthRatio %f def\n"
4415 (/ (ps-lookup 'space-width) (ps-lookup 'size)))))
4416
4417 (ps-output "\n%%EndPrologue\n\n%%BeginSetup\n")
4418 (unless (eq ps-spool-config 'lpr-switches)
4419 (ps-output "\n%%BeginFeature: *Duplex "
4420 (ps-boolean-capitalized ps-spool-duplex)
4421 " *Tumble "
4422 (ps-boolean-capitalized tumble)
4423 ps-print-duplex-feature
4424 "%%EndFeature\n")))
4425 (ps-output "\n/Lines 0 def\n/PageCount 0 def\n\nBeginDoc\n%%EndSetup\n"))
4426
4427
4428 (defun ps-boolean-capitalized (bool)
4429 (if bool "True" "False"))
4430
4431
4432 (defun ps-header-dirpart ()
4433 (let ((fname (buffer-file-name)))
4434 (if fname
4435 (if (string-equal (buffer-name) (file-name-nondirectory fname))
4436 (file-name-directory fname)
4437 fname)
4438 "")))
4439
4440
4441 (defun ps-get-buffer-name ()
4442 (cond
4443 ;; Indulge Jim this little easter egg:
4444 ((string= (buffer-name) "ps-print.el")
4445 "Hey, Cool! It's ps-print.el!!!")
4446 ;; Indulge Jack this other little easter egg:
4447 ((string= (buffer-name) "sokoban.el")
4448 "Super! C'est sokoban.el!")
4449 (t (concat
4450 (and ps-printing-region-p "Subset of: ")
4451 (buffer-name)
4452 (and (buffer-modified-p) " (unsaved)")))))
4453
4454
4455 (defun ps-get-font-size (font-sym)
4456 (let ((font-size (symbol-value font-sym)))
4457 (cond ((numberp font-size)
4458 font-size)
4459 ((and (consp font-size)
4460 (numberp (car font-size))
4461 (numberp (cdr font-size)))
4462 (if ps-landscape-mode
4463 (car font-size)
4464 (cdr font-size)))
4465 (t
4466 (error "Invalid font size `%S' for `%S'" font-size font-sym)))))
4467
4468
4469 (defun ps-begin-job ()
4470 (save-excursion
4471 (set-buffer ps-spool-buffer)
4472 (goto-char (point-max))
4473 (and (re-search-backward "^%%Trailer$" nil t)
4474 (delete-region (match-beginning 0) (point-max))))
4475 (setq ps-showline-count (car ps-printing-region)
4476 ps-page-count 0
4477 ps-font-size-internal (ps-get-font-size 'ps-font-size)
4478 ps-header-font-size-internal (ps-get-font-size 'ps-header-font-size)
4479 ps-header-title-font-size-internal
4480 (ps-get-font-size 'ps-header-title-font-size)
4481 ps-control-or-escape-regexp
4482 (cond ((eq ps-print-control-characters '8-bit)
4483 (string-as-unibyte "[\000-\037\177-\377]"))
4484 ((eq ps-print-control-characters 'control-8-bit)
4485 (string-as-unibyte "[\000-\037\177-\237]"))
4486 ((eq ps-print-control-characters 'control)
4487 "[\000-\037\177]")
4488 (t "[\t\n\f]"))))
4489
4490 (defmacro ps-page-number ()
4491 `(1+ (/ (1- ps-page-count) ps-number-of-columns)))
4492
4493 (defun ps-end-file ()
4494 ;; Back to the PS output buffer to set the last page n-up printing
4495 (save-excursion
4496 (let ((pages-per-sheet (mod ps-page-postscript ps-n-up-printing))
4497 case-fold-search)
4498 (set-buffer ps-spool-buffer)
4499 (goto-char (point-max))
4500 (and (> pages-per-sheet 0)
4501 (re-search-backward "^[0-9]+ BeginSheet$" nil t)
4502 (replace-match (format "%d BeginSheet" pages-per-sheet) t))))
4503 ;; Set dummy page
4504 (and ps-spool-duplex (= (mod ps-page-order 2) 1)
4505 (ps-dummy-page))
4506 ;; Set end of PostScript file
4507 (ps-output "EndSheet\n\n%%Trailer\n%%Pages: "
4508 (format "%d" ps-page-order)
4509 "\n\nEndDoc\n\n%%EOF\n"))
4510
4511
4512 (defun ps-next-page ()
4513 (ps-end-page)
4514 (ps-flush-output)
4515 (ps-begin-page))
4516
4517
4518 (defun ps-header-sheet ()
4519 ;; Print only when a new sheet begins.
4520 (setq ps-page-postscript (1+ ps-page-postscript)
4521 ps-page-order (1+ ps-page-order))
4522 (and (> ps-page-order 1)
4523 (ps-output "EndSheet\n"))
4524 (ps-output (format "\n%%%%Page: %d %d\n"
4525 ps-page-postscript ps-page-order))
4526 (ps-output (format "%d BeginSheet\nBeginDSCPage\n" ps-n-up-printing)))
4527
4528
4529 (defsubst ps-header-page ()
4530 ;; set total line and page number when printing has finished
4531 ;; (see `ps-generate')
4532 (run-hooks
4533 (if (prog1
4534 (zerop (mod ps-page-count ps-number-of-columns))
4535 (setq ps-page-count (1+ ps-page-count)))
4536 (prog1
4537 (if (zerop (mod ps-page-postscript ps-n-up-printing))
4538 ;; Print only when a new sheet begins.
4539 (progn
4540 (ps-header-sheet)
4541 'ps-print-begin-sheet-hook)
4542 ;; Print only when a new page begins.
4543 (setq ps-page-postscript (1+ ps-page-postscript))
4544 (ps-output "BeginDSCPage\n")
4545 'ps-print-begin-page-hook)
4546 (ps-background ps-page-postscript))
4547 ;; Print only when a new column begins.
4548 (ps-output "BeginDSCPage\n")
4549 'ps-print-begin-column-hook)))
4550
4551 (defun ps-begin-page ()
4552 (ps-get-page-dimensions)
4553 (setq ps-width-remaining ps-print-width
4554 ps-height-remaining ps-print-height)
4555
4556 (ps-header-page)
4557
4558 (ps-output (format "/LineNumber %d def\n" ps-showline-count)
4559 (format "/PageNumber %d def\n" (if ps-print-only-one-header
4560 (ps-page-number)
4561 ps-page-count)))
4562
4563 (when ps-print-header
4564 (ps-generate-header "HeaderLinesLeft" ps-left-header)
4565 (ps-generate-header "HeaderLinesRight" ps-right-header)
4566 (ps-output (format "%d SetHeaderLines\n" ps-header-lines)))
4567
4568 (ps-output "BeginPage\n")
4569 (ps-set-font ps-current-font)
4570 (ps-set-bg ps-current-bg)
4571 (ps-set-color ps-current-color)
4572 (ps-mule-begin-page))
4573
4574 (defun ps-end-page ()
4575 (ps-output "EndPage\nEndDSCPage\n"))
4576
4577 (defun ps-dummy-page ()
4578 (let ((ps-n-up-printing 0))
4579 (ps-header-sheet))
4580 (ps-output "/PrintHeader false def
4581 /ColumnIndex 0 def
4582 /PrintLineNumber false def
4583 BeginPage
4584 EndPage
4585 EndDSCPage\n")
4586 (setq ps-page-postscript ps-n-up-printing))
4587
4588 (defun ps-next-line ()
4589 (setq ps-showline-count (1+ ps-showline-count))
4590 (let ((lh (ps-line-height 'ps-font-for-text)))
4591 (if (< ps-height-remaining lh)
4592 (ps-next-page)
4593 (setq ps-width-remaining ps-print-width
4594 ps-height-remaining (- ps-height-remaining lh))
4595 (ps-output "HL\n"))))
4596
4597 (defun ps-continue-line ()
4598 (let ((lh (ps-line-height 'ps-font-for-text)))
4599 (if (< ps-height-remaining lh)
4600 (ps-next-page)
4601 (setq ps-width-remaining ps-print-width
4602 ps-height-remaining (- ps-height-remaining lh))
4603 (ps-output "SL\n"))))
4604
4605 (defun ps-find-wrappoint (from to char-width)
4606 (let ((avail (truncate (/ ps-width-remaining char-width)))
4607 (todo (- to from)))
4608 (if (< todo avail)
4609 (cons to (* todo char-width))
4610 (cons (+ from avail) ps-width-remaining))))
4611
4612 (defun ps-basic-plot-string (from to &optional bg-color)
4613 (let* ((wrappoint (ps-find-wrappoint from to
4614 (ps-avg-char-width 'ps-font-for-text)))
4615 (to (car wrappoint))
4616 (string (buffer-substring-no-properties from to)))
4617 (ps-mule-prepare-ascii-font string)
4618 (ps-output-string string)
4619 (ps-output " S\n")
4620 wrappoint))
4621
4622 (defun ps-basic-plot-whitespace (from to &optional bg-color)
4623 (let* ((wrappoint (ps-find-wrappoint from to
4624 (ps-space-width 'ps-font-for-text)))
4625 (to (car wrappoint)))
4626 (ps-output (format "%d W\n" (- to from)))
4627 wrappoint))
4628
4629 (defun ps-plot (plotfunc from to &optional bg-color)
4630 (while (< from to)
4631 (let* ((wrappoint (funcall plotfunc from to bg-color))
4632 (plotted-to (car wrappoint))
4633 (plotted-width (cdr wrappoint)))
4634 (setq from plotted-to
4635 ps-width-remaining (- ps-width-remaining plotted-width))
4636 (if (< from to)
4637 (ps-continue-line))))
4638 (if ps-razzle-dazzle
4639 (let* ((q-todo (- (point-max) (point-min)))
4640 (q-done (- (point) (point-min)))
4641 (chunkfrac (/ q-todo 8))
4642 (chunksize (min chunkfrac 1000)))
4643 (if (> (- q-done ps-razchunk) chunksize)
4644 (progn
4645 (setq ps-razchunk q-done)
4646 (message "Formatting...%3d%%"
4647 (if (< q-todo 100)
4648 (/ (* 100 q-done) q-todo)
4649 (/ q-done (/ q-todo 100)))
4650 ))))))
4651
4652 (defvar ps-last-font nil)
4653
4654 (defun ps-set-font (font)
4655 (setq ps-last-font (format "f%d" (setq ps-current-font font)))
4656 (ps-output (format "/%s F\n" ps-last-font)))
4657
4658 (defun ps-set-bg (color)
4659 (if (setq ps-current-bg color)
4660 (ps-output (format ps-color-format
4661 (nth 0 color) (nth 1 color) (nth 2 color))
4662 " true BG\n")
4663 (ps-output "false BG\n")))
4664
4665 (defun ps-set-color (color)
4666 (setq ps-current-color (or color ps-default-fg))
4667 (ps-output (format ps-color-format
4668 (nth 0 ps-current-color)
4669 (nth 1 ps-current-color) (nth 2 ps-current-color))
4670 " FG\n"))
4671
4672
4673 (defvar ps-current-effect 0)
4674
4675
4676 (defun ps-plot-region (from to font &optional fg-color bg-color effects)
4677 (if (not (equal font ps-current-font))
4678 (ps-set-font font))
4679
4680 ;; Specify a foreground color only if one's specified and it's
4681 ;; different than the current.
4682 (if (not (equal fg-color ps-current-color))
4683 (ps-set-color fg-color))
4684
4685 (if (not (equal bg-color ps-current-bg))
4686 (ps-set-bg bg-color))
4687
4688 ;; Specify effects (underline, overline, box, etc)
4689 (cond
4690 ((not (integerp effects))
4691 (ps-output "0 EF\n")
4692 (setq ps-current-effect 0))
4693 ((/= effects ps-current-effect)
4694 (ps-output (number-to-string effects) " EF\n")
4695 (setq ps-current-effect effects)))
4696
4697 ;; Starting at the beginning of the specified region...
4698 (save-excursion
4699 (goto-char from)
4700
4701 ;; ...break the region up into chunks separated by tabs, linefeeds,
4702 ;; pagefeeds, control characters, and plot each chunk.
4703 (while (< from to)
4704 (if (re-search-forward ps-control-or-escape-regexp to t)
4705 ;; region with some control characters or some multi-byte characters
4706 (let* ((match-point (match-beginning 0))
4707 (match (char-after match-point)))
4708 (when (< from match-point)
4709 (ps-mule-set-ascii-font)
4710 (ps-plot 'ps-basic-plot-string from match-point bg-color))
4711 (cond
4712 ((= match ?\t) ; tab
4713 (let ((linestart (line-beginning-position)))
4714 (forward-char -1)
4715 (setq from (+ linestart (current-column)))
4716 (when (re-search-forward "[ \t]+" to t)
4717 (ps-mule-set-ascii-font)
4718 (ps-plot 'ps-basic-plot-whitespace
4719 from (+ linestart (current-column))
4720 bg-color))))
4721
4722 ((= match ?\n) ; newline
4723 (ps-next-line))
4724
4725 ((= match ?\f) ; form feed
4726 ;; do not skip page if previous character is NEWLINE and
4727 ;; it is a beginning of page.
4728 (or (and (= (char-after (1- match-point)) ?\n)
4729 (= ps-height-remaining ps-print-height))
4730 (ps-next-page)))
4731
4732 ((> match 255) ; a multi-byte character
4733 (let ((charset (char-charset match)))
4734 (or (eq charset 'composition)
4735 (while (eq (charset-after) charset)
4736 (forward-char 1)))
4737 (ps-plot 'ps-mule-plot-string match-point (point) bg-color)))
4738 ; characters from ^@ to ^_ and
4739 (t ; characters from 127 to 255
4740 (ps-control-character match)))
4741 (setq from (point)))
4742 ;; region without control characters nor multi-byte characters
4743 (ps-mule-set-ascii-font)
4744 (ps-plot 'ps-basic-plot-string from to bg-color)
4745 (setq from to)))))
4746
4747 (defvar ps-string-control-codes
4748 (let ((table (make-vector 256 nil))
4749 (char ?\000))
4750 ;; control character
4751 (while (<= char ?\037)
4752 (aset table char (format "^%c" (+ char ?@)))
4753 (setq char (1+ char)))
4754 ;; printable character
4755 (while (< char ?\177)
4756 (aset table char (format "%c" char))
4757 (setq char (1+ char)))
4758 ;; DEL
4759 (aset table char "^?")
4760 ;; 8-bit character
4761 (while (<= (setq char (1+ char)) ?\377)
4762 (aset table char (format "\\%o" char)))
4763 table)
4764 "Vector used to map characters to a printable string.")
4765
4766 (defun ps-control-character (char)
4767 (let* ((str (aref ps-string-control-codes char))
4768 (from (1- (point)))
4769 (len (length str))
4770 (to (+ from len))
4771 (char-width (ps-avg-char-width 'ps-font-for-text))
4772 (wrappoint (ps-find-wrappoint from to char-width)))
4773 (if (< (car wrappoint) to)
4774 (ps-continue-line))
4775 (setq ps-width-remaining (- ps-width-remaining (* len char-width)))
4776 (ps-mule-prepare-ascii-font str)
4777 (ps-output-string str)
4778 (ps-output " S\n")))
4779
4780 (defun ps-color-value (x-color-value)
4781 ;; Scale 16-bit X-COLOR-VALUE to PostScript color value in [0, 1] interval.
4782 (/ x-color-value ps-print-color-scale))
4783
4784
4785 (cond ((eq ps-print-emacs-type 'emacs) ; emacs
4786
4787 (defun ps-color-values (x-color)
4788 (if (fboundp 'x-color-values)
4789 (x-color-values x-color)
4790 (error "No available function to determine X color values.")))
4791 )
4792 ; xemacs
4793 ; lucid
4794 (t ; epoch
4795 (defun ps-color-values (x-color)
4796 (cond ((fboundp 'x-color-values)
4797 (x-color-values x-color))
4798 ((and (fboundp 'color-instance-rgb-components)
4799 (ps-color-device))
4800 (color-instance-rgb-components
4801 (if (color-instance-p x-color)
4802 x-color
4803 (make-color-instance
4804 (if (color-specifier-p x-color)
4805 (color-name x-color)
4806 x-color)))))
4807 (t
4808 (error "No available function to determine X color values."))))
4809 ))
4810
4811
4812 (defun ps-face-attributes (face)
4813 "Return face attribute vector.
4814
4815 If FACE is not in `ps-print-face-extension-alist' or in
4816 `ps-print-face-alist', insert it on `ps-print-face-alist' and
4817 return the attribute vector.
4818
4819 If FACE is not a valid face name, it is used default face."
4820 (cdr (or (assq face ps-print-face-extension-alist)
4821 (assq face ps-print-face-alist)
4822 (let* ((the-face (if (facep face) face 'default))
4823 (new-face (ps-screen-to-bit-face the-face)))
4824 (or (and (eq the-face 'default)
4825 (assq the-face ps-print-face-alist))
4826 (setq ps-print-face-alist (cons new-face ps-print-face-alist)))
4827 new-face))))
4828
4829
4830 (defun ps-face-attribute-list (face-or-list)
4831 (if (listp face-or-list)
4832 ;; list of faces
4833 (let ((effects 0)
4834 foreground background face-attr)
4835 (while face-or-list
4836 (setq face-attr (ps-face-attributes (car face-or-list))
4837 effects (logior effects (aref face-attr 0)))
4838 (or foreground (setq foreground (aref face-attr 1)))
4839 (or background (setq background (aref face-attr 2)))
4840 (setq face-or-list (cdr face-or-list)))
4841 (vector effects foreground background))
4842 ;; simple face
4843 (ps-face-attributes face-or-list)))
4844
4845
4846 (defconst ps-font-type (vector nil 'bold 'italic 'bold-italic))
4847
4848
4849 (defun ps-plot-with-face (from to face)
4850 (cond
4851 ((null face) ; print text with null face
4852 (ps-plot-region from to 0))
4853 ((eq face 'emacs--invisible--face)) ; skip invisible text!!!
4854 (t ; otherwise, text has a valid face
4855 (let* ((face-bit (ps-face-attribute-list face))
4856 (effect (aref face-bit 0))
4857 (foreground (aref face-bit 1))
4858 (background (aref face-bit 2))
4859 (fg-color (if (and ps-color-p foreground)
4860 (mapcar 'ps-color-value
4861 (ps-color-values foreground))
4862 ps-default-color))
4863 (bg-color (and ps-color-p background
4864 (mapcar 'ps-color-value
4865 (ps-color-values background)))))
4866 (ps-plot-region
4867 from to
4868 (ps-font-number 'ps-font-for-text
4869 (or (aref ps-font-type (logand effect 3))
4870 face))
4871 fg-color bg-color (lsh effect -2)))))
4872 (goto-char to))
4873
4874
4875 (defun ps-xemacs-face-kind-p (face kind kind-regex kind-list)
4876 (let* ((frame-font (or (face-font-instance face)
4877 (face-font-instance 'default)))
4878 (kind-cons (and frame-font
4879 (assq kind
4880 (font-instance-properties frame-font))))
4881 (kind-spec (cdr-safe kind-cons))
4882 (case-fold-search t))
4883 (or (and kind-spec (string-match kind-regex kind-spec))
4884 ;; Kludge-compatible:
4885 (memq face kind-list))))
4886
4887
4888 (cond ((eq ps-print-emacs-type 'emacs) ; emacs
4889
4890 (defun ps-face-bold-p (face)
4891 (or (face-bold-p face)
4892 (memq face ps-bold-faces)))
4893
4894 (defun ps-face-italic-p (face)
4895 (or (face-italic-p face)
4896 (memq face ps-italic-faces)))
4897 )
4898 ; xemacs
4899 ; lucid
4900 (t ; epoch
4901 (defun ps-face-bold-p (face)
4902 (ps-xemacs-face-kind-p face 'WEIGHT_NAME "bold\\|demibold"
4903 ps-bold-faces))
4904
4905 (defun ps-face-italic-p (face)
4906 (or (ps-xemacs-face-kind-p face 'ANGLE_NAME "i\\|o" ps-italic-faces)
4907 (ps-xemacs-face-kind-p face 'SLANT "i\\|o" ps-italic-faces)))
4908 ))
4909
4910
4911 (defun ps-face-underlined-p (face)
4912 (or (face-underline-p face)
4913 (memq face ps-underlined-faces)))
4914
4915
4916 ;; Ensure that face-list is fbound.
4917 (or (fboundp 'face-list) (defalias 'face-list 'list-faces))
4918
4919
4920 (defun ps-build-reference-face-lists ()
4921 ;; Ensure that face database is updated with faces on
4922 ;; `font-lock-face-attributes' (obsolete stuff)
4923 (ps-font-lock-face-attributes)
4924 ;; Now, rebuild reference face lists
4925 (setq ps-print-face-alist nil)
4926 (if ps-auto-font-detect
4927 (mapcar 'ps-map-face (face-list))
4928 (mapcar 'ps-set-face-bold ps-bold-faces)
4929 (mapcar 'ps-set-face-italic ps-italic-faces)
4930 (mapcar 'ps-set-face-underline ps-underlined-faces))
4931 (setq ps-build-face-reference nil))
4932
4933
4934 (defun ps-set-face-bold (face)
4935 (ps-set-face-attribute face 1))
4936
4937 (defun ps-set-face-italic (face)
4938 (ps-set-face-attribute face 2))
4939
4940 (defun ps-set-face-underline (face)
4941 (ps-set-face-attribute face 4))
4942
4943
4944 (defun ps-set-face-attribute (face effect)
4945 (let ((face-bit (cdr (ps-map-face face))))
4946 (aset face-bit 0 (logior (aref face-bit 0) effect))))
4947
4948
4949 (defun ps-map-face (face)
4950 (let* ((face-map (ps-screen-to-bit-face face))
4951 (ps-face-bit (cdr (assq (car face-map) ps-print-face-alist))))
4952 (if ps-face-bit
4953 ;; if face exists, merge both
4954 (let ((face-bit (cdr face-map)))
4955 (aset ps-face-bit 0 (logior (aref ps-face-bit 0) (aref face-bit 0)))
4956 (or (aref ps-face-bit 1) (aset ps-face-bit 1 (aref face-bit 1)))
4957 (or (aref ps-face-bit 2) (aset ps-face-bit 2 (aref face-bit 2))))
4958 ;; if face does not exist, insert it
4959 (setq ps-print-face-alist (cons face-map ps-print-face-alist)))
4960 face-map))
4961
4962
4963 (defun ps-screen-to-bit-face (face)
4964 (cons face
4965 (vector (logior (if (ps-face-bold-p face) 1 0) ; bold
4966 (if (ps-face-italic-p face) 2 0) ; italic
4967 (if (ps-face-underlined-p face) 4 0)) ; underline
4968 (face-foreground face)
4969 (face-background face))))
4970
4971
4972 (cond ((not (eq ps-print-emacs-type 'emacs))
4973 ; xemacs
4974 ; lucid
4975 ; epoch
4976 (defun ps-mapper (extent list)
4977 (nconc list (list (list (extent-start-position extent) 'push extent)
4978 (list (extent-end-position extent) 'pull extent)))
4979 nil)
4980
4981 (defun ps-extent-sorter (a b)
4982 (< (extent-priority a) (extent-priority b)))
4983 ))
4984
4985
4986 (defun ps-print-ensure-fontified (start end)
4987 (and (boundp 'lazy-lock-mode) (symbol-value 'lazy-lock-mode)
4988 (lazy-lock-fontify-region start end)))
4989
4990 (defun ps-generate-postscript-with-faces (from to)
4991 ;; Some initialization...
4992 (setq ps-current-effect 0)
4993
4994 ;; Build the reference lists of faces if necessary.
4995 (if (or ps-always-build-face-reference
4996 ps-build-face-reference)
4997 (progn
4998 (message "Collecting face information...")
4999 (ps-build-reference-face-lists)))
5000 ;; Set the color scale. We do it here instead of in the defvar so
5001 ;; that ps-print can be dumped into emacs. This expression can't be
5002 ;; evaluated at dump-time because X isn't initialized.
5003 (setq ps-color-p (and ps-print-color-p (ps-color-device))
5004 ps-print-color-scale (if ps-color-p
5005 (float (car (ps-color-values "white")))
5006 1.0))
5007 ;; Generate some PostScript.
5008 (save-restriction
5009 (narrow-to-region from to)
5010 (ps-print-ensure-fontified from to)
5011 (let ((face 'default)
5012 (position to))
5013 (cond
5014 ((or (eq ps-print-emacs-type 'lucid)
5015 (eq ps-print-emacs-type 'xemacs))
5016 ;; Build the list of extents...
5017 (let ((a (cons 'dummy nil))
5018 record type extent extent-list)
5019 (map-extents 'ps-mapper nil from to a)
5020 (setq a (sort (cdr a) 'car-less-than-car)
5021 extent-list nil)
5022
5023 ;; Loop through the extents...
5024 (while a
5025 (setq record (car a)
5026
5027 position (car record)
5028 record (cdr record)
5029
5030 type (car record)
5031 record (cdr record)
5032
5033 extent (car record))
5034
5035 ;; Plot up to this record.
5036 ;; XEmacs 19.12: for some reason, we're getting into a
5037 ;; situation in which some of the records have
5038 ;; positions less than 'from'. Since we've narrowed
5039 ;; the buffer, this'll generate errors. This is a
5040 ;; hack, but don't call ps-plot-with-face unless from >
5041 ;; point-min.
5042 (and (>= from (point-min)) (<= position (point-max))
5043 (ps-plot-with-face from position face))
5044
5045 (cond
5046 ((eq type 'push)
5047 (and (extent-face extent)
5048 (setq extent-list (sort (cons extent extent-list)
5049 'ps-extent-sorter))))
5050
5051 ((eq type 'pull)
5052 (setq extent-list (sort (delq extent extent-list)
5053 'ps-extent-sorter))))
5054
5055 (setq face (if extent-list
5056 (extent-face (car extent-list))
5057 'default)
5058 from position
5059 a (cdr a)))))
5060
5061 ((eq ps-print-emacs-type 'emacs)
5062 (let ((property-change from)
5063 (overlay-change from)
5064 (save-buffer-invisibility-spec buffer-invisibility-spec)
5065 (buffer-invisibility-spec nil))
5066 (while (< from to)
5067 (and (< property-change to) ; Don't search for property change
5068 ; unless previous search succeeded.
5069 (setq property-change (next-property-change from nil to)))
5070 (and (< overlay-change to) ; Don't search for overlay change
5071 ; unless previous search succeeded.
5072 (setq overlay-change (min (next-overlay-change from) to)))
5073 (setq position (min property-change overlay-change))
5074 ;; The code below is not quite correct,
5075 ;; because a non-nil overlay invisible property
5076 ;; which is inactive according to the current value
5077 ;; of buffer-invisibility-spec nonetheless overrides
5078 ;; a face text property.
5079 (setq face
5080 (cond ((let ((prop (get-text-property from 'invisible)))
5081 ;; Decide whether this invisible property
5082 ;; really makes the text invisible.
5083 (if (eq save-buffer-invisibility-spec t)
5084 (not (null prop))
5085 (or (memq prop save-buffer-invisibility-spec)
5086 (assq prop save-buffer-invisibility-spec))))
5087 'emacs--invisible--face)
5088 ((get-text-property from 'face))
5089 (t 'default)))
5090 (let ((overlays (overlays-at from))
5091 (face-priority -1)) ; text-property
5092 (while (and overlays
5093 (not (eq face 'emacs--invisible--face)))
5094 (let* ((overlay (car overlays))
5095 (overlay-invisible (overlay-get overlay 'invisible))
5096 (overlay-priority (or (overlay-get overlay 'priority)
5097 0)))
5098 (and (> overlay-priority face-priority)
5099 (setq face
5100 (cond ((if (eq save-buffer-invisibility-spec t)
5101 (not (null overlay-invisible))
5102 (or (memq overlay-invisible
5103 save-buffer-invisibility-spec)
5104 (assq overlay-invisible
5105 save-buffer-invisibility-spec)))
5106 'emacs--invisible--face)
5107 ((overlay-get overlay 'face))
5108 (t face))
5109 face-priority overlay-priority)))
5110 (setq overlays (cdr overlays))))
5111 ;; Plot up to this record.
5112 (ps-plot-with-face from position face)
5113 (setq from position)))))
5114 (ps-plot-with-face from to face))))
5115
5116 (defun ps-generate-postscript (from to)
5117 (ps-plot-region from to 0 nil))
5118
5119 (defun ps-generate (buffer from to genfunc)
5120 (save-excursion
5121 (let ((from (min to from))
5122 (to (max to from))
5123 ;; This avoids trouble if chars with read-only properties
5124 ;; are copied into ps-spool-buffer.
5125 (inhibit-read-only t))
5126 (save-restriction
5127 (narrow-to-region from to)
5128 (and ps-razzle-dazzle
5129 (message "Formatting...%3d%%" (setq ps-razchunk 0)))
5130 (setq ps-source-buffer buffer
5131 ps-spool-buffer (get-buffer-create ps-spool-buffer-name))
5132 (ps-init-output-queue)
5133 (let (safe-marker completed-safely needs-begin-file)
5134 (unwind-protect
5135 (progn
5136 (set-buffer ps-spool-buffer)
5137 (set-buffer-multibyte nil)
5138
5139 ;; Get a marker and make it point to the current end of the
5140 ;; buffer, If an error occurs, we'll delete everything from
5141 ;; the end of this marker onwards.
5142 (setq safe-marker (make-marker))
5143 (set-marker safe-marker (point-max))
5144
5145 (goto-char (point-min))
5146 (or (looking-at (regexp-quote ps-adobe-tag))
5147 (setq needs-begin-file t))
5148 (save-excursion
5149 (set-buffer ps-source-buffer)
5150 (ps-begin-job)
5151 (when needs-begin-file
5152 (ps-begin-file)
5153 (ps-mule-initialize))
5154 (ps-mule-begin-job from to)
5155 (ps-begin-page))
5156 (set-buffer ps-source-buffer)
5157 (funcall genfunc from to)
5158 (ps-end-page)
5159
5160 (ps-end-file)
5161 (ps-flush-output)
5162 (ps-end-job)
5163
5164 ;; Setting this variable tells the unwind form that the
5165 ;; the PostScript was generated without error.
5166 (setq completed-safely t))
5167
5168 ;; Unwind form: If some bad mojo occurred while generating
5169 ;; PostScript, delete all the PostScript that was generated.
5170 ;; This protects the previously spooled files from getting
5171 ;; corrupted.
5172 (and (markerp safe-marker) (not completed-safely)
5173 (progn
5174 (set-buffer ps-spool-buffer)
5175 (delete-region (marker-position safe-marker) (point-max))))))
5176
5177 (and ps-razzle-dazzle (message "Formatting...done"))))))
5178
5179
5180 (defun ps-end-job ()
5181 (let ((total-lines (cdr ps-printing-region))
5182 (total-pages (if ps-print-only-one-header
5183 (ps-page-number)
5184 ps-page-count))
5185 case-fold-search)
5186 (set-buffer ps-spool-buffer)
5187 ;; Back to the PS output buffer to set the page count
5188 (goto-char (point-min))
5189 (and (re-search-forward "^/Lines 0 def\n/PageCount 0 def$" nil t)
5190 (replace-match (format "/Lines %d def\n/PageCount %d def"
5191 total-lines total-pages) t))))
5192
5193
5194 ;; Permit dynamic evaluation at print time of `ps-lpr-switches'.
5195 (defun ps-do-despool (filename)
5196 (if (or (not (boundp 'ps-spool-buffer))
5197 (not (symbol-value 'ps-spool-buffer)))
5198 (message "No spooled PostScript to print")
5199 (if filename
5200 (save-excursion
5201 (and ps-razzle-dazzle (message "Saving..."))
5202 (set-buffer ps-spool-buffer)
5203 (setq filename (expand-file-name filename))
5204 (let ((coding-system-for-write 'raw-text-unix))
5205 (write-region (point-min) (point-max) filename))
5206 (and ps-razzle-dazzle (message "Wrote %s" filename)))
5207 ;; Else, spool to the printer
5208 (and ps-razzle-dazzle (message "Printing..."))
5209 (save-excursion
5210 (set-buffer ps-spool-buffer)
5211 (let* ((coding-system-for-write 'raw-text-unix)
5212 (ps-printer-name (or ps-printer-name
5213 (and (boundp 'printer-name)
5214 printer-name)))
5215 (ps-lpr-switches
5216 (append (and (stringp ps-printer-name)
5217 (list (concat "-P" ps-printer-name)))
5218 ps-lpr-switches)))
5219 (apply (or ps-print-region-function 'call-process-region)
5220 (point-min) (point-max) ps-lpr-command nil
5221 (and (fboundp 'start-process) 0)
5222 nil
5223 (ps-flatten-list ; dynamic evaluation
5224 (mapcar 'ps-eval-switch ps-lpr-switches)))))
5225 (and ps-razzle-dazzle (message "Printing...done")))
5226 (kill-buffer ps-spool-buffer)))
5227
5228 ;; Dynamic evaluation
5229 (defun ps-eval-switch (arg)
5230 (cond ((stringp arg) arg)
5231 ((functionp arg) (apply arg nil))
5232 ((symbolp arg) (symbol-value arg))
5233 ((consp arg) (apply (car arg) (cdr arg)))
5234 (t nil)))
5235
5236 ;; `ps-flatten-list' is defined here (copied from "message.el" and
5237 ;; enhanced to handle dotted pairs as well) until we can get some
5238 ;; sensible autoloads, or `flatten-list' gets put somewhere decent.
5239
5240 ;; (ps-flatten-list '((a . b) c (d . e) (f g h) i . j))
5241 ;; => (a b c d e f g h i j)
5242
5243 (defun ps-flatten-list (&rest list)
5244 (ps-flatten-list-1 list))
5245
5246 (defun ps-flatten-list-1 (list)
5247 (cond ((null list) nil)
5248 ((consp list) (append (ps-flatten-list-1 (car list))
5249 (ps-flatten-list-1 (cdr list))))
5250 (t (list list))))
5251
5252 (defun ps-kill-emacs-check ()
5253 (let (ps-buffer)
5254 (and (setq ps-buffer (get-buffer ps-spool-buffer-name))
5255 (buffer-modified-p ps-buffer)
5256 (y-or-n-p "Unprinted PostScript waiting; print now? ")
5257 (ps-despool))
5258 (and (setq ps-buffer (get-buffer ps-spool-buffer-name))
5259 (buffer-modified-p ps-buffer)
5260 (not (yes-or-no-p "Unprinted PostScript waiting; exit anyway? "))
5261 (error "Unprinted PostScript"))))
5262
5263 (cond ((fboundp 'add-hook)
5264 (funcall 'add-hook 'kill-emacs-hook 'ps-kill-emacs-check))
5265 (kill-emacs-hook
5266 (message "Won't override existing `kill-emacs-hook'"))
5267 (t
5268 (setq kill-emacs-hook 'ps-kill-emacs-check)))
5269
5270 \f
5271 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5272 ;;; Sample Setup Code:
5273
5274 ;; This stuff is for anybody that's brave enough to look this far,
5275 ;; and able to figure out how to use it. It isn't really part of
5276 ;; ps-print, but I'll leave it here in hopes it might be useful:
5277
5278 ;; WARNING!!! The following code is *sample* code only.
5279 ;; Don't use it unless you understand what it does!
5280
5281 (defmacro ps-prsc ()
5282 `(if (eq ps-print-emacs-type 'emacs) [f22] 'f22))
5283 (defmacro ps-c-prsc ()
5284 `(if (eq ps-print-emacs-type 'emacs) [C-f22] '(control f22)))
5285 (defmacro ps-s-prsc ()
5286 `(if (eq ps-print-emacs-type 'emacs) [S-f22] '(shift f22)))
5287
5288 ;; A hook to bind to `rmail-mode-hook' to locally bind prsc and set the
5289 ;; `ps-left-headers' specially for mail messages.
5290 (defun ps-rmail-mode-hook ()
5291 (local-set-key (ps-prsc) 'ps-rmail-print-message-from-summary)
5292 (setq ps-header-lines 3
5293 ps-left-header
5294 ;; The left headers will display the message's subject, its
5295 ;; author, and the name of the folder it was in.
5296 '(ps-article-subject ps-article-author buffer-name)))
5297
5298 ;; See `ps-gnus-print-article-from-summary'. This function does the
5299 ;; same thing for rmail.
5300 (defun ps-rmail-print-message-from-summary ()
5301 (interactive)
5302 (ps-print-message-from-summary 'rmail-summary-buffer "RMAIL"))
5303
5304 ;; Used in `ps-rmail-print-article-from-summary',
5305 ;; `ps-gnus-print-article-from-summary' and `ps-vm-print-message-from-summary'.
5306 (defun ps-print-message-from-summary (summary-buffer summary-default)
5307 (let ((ps-buf (or (and (boundp summary-buffer)
5308 (symbol-value summary-buffer))
5309 summary-default)))
5310 (and (get-buffer ps-buf)
5311 (save-excursion
5312 (set-buffer ps-buf)
5313 (ps-spool-buffer-with-faces)))))
5314
5315 ;; Look in an article or mail message for the Subject: line. To be
5316 ;; placed in `ps-left-headers'.
5317 (defun ps-article-subject ()
5318 (save-excursion
5319 (goto-char (point-min))
5320 (if (re-search-forward "^Subject:[ \t]+\\(.*\\)$" nil t)
5321 (buffer-substring-no-properties (match-beginning 1) (match-end 1))
5322 "Subject ???")))
5323
5324 ;; Look in an article or mail message for the From: line. Sorta-kinda
5325 ;; understands RFC-822 addresses and can pull the real name out where
5326 ;; it's provided. To be placed in `ps-left-headers'.
5327 (defun ps-article-author ()
5328 (save-excursion
5329 (goto-char (point-min))
5330 (if (re-search-forward "^From:[ \t]+\\(.*\\)$" nil t)
5331 (let ((fromstring (buffer-substring-no-properties (match-beginning 1)
5332 (match-end 1))))
5333 (cond
5334
5335 ;; Try first to match addresses that look like
5336 ;; thompson@wg2.waii.com (Jim Thompson)
5337 ((string-match ".*[ \t]+(\\(.*\\))" fromstring)
5338 (substring fromstring (match-beginning 1) (match-end 1)))
5339
5340 ;; Next try to match addresses that look like
5341 ;; Jim Thompson <thompson@wg2.waii.com>
5342 ((string-match "\\(.*\\)[ \t]+<.*>" fromstring)
5343 (substring fromstring (match-beginning 1) (match-end 1)))
5344
5345 ;; Couldn't find a real name -- show the address instead.
5346 (t fromstring)))
5347 "From ???")))
5348
5349 ;; A hook to bind to `gnus-article-prepare-hook'. This will set the
5350 ;; `ps-left-headers' specially for gnus articles. Unfortunately,
5351 ;; `gnus-article-mode-hook' is called only once, the first time the *Article*
5352 ;; buffer enters that mode, so it would only work for the first time
5353 ;; we ran gnus. The second time, this hook wouldn't get set up. The
5354 ;; only alternative is `gnus-article-prepare-hook'.
5355 (defun ps-gnus-article-prepare-hook ()
5356 (setq ps-header-lines 3
5357 ps-left-header
5358 ;; The left headers will display the article's subject, its
5359 ;; author, and the newsgroup it was in.
5360 '(ps-article-subject ps-article-author gnus-newsgroup-name)))
5361
5362 ;; A hook to bind to `vm-mode-hook' to locally bind prsc and set the
5363 ;; `ps-left-headers' specially for mail messages.
5364 (defun ps-vm-mode-hook ()
5365 (local-set-key (ps-prsc) 'ps-vm-print-message-from-summary)
5366 (setq ps-header-lines 3
5367 ps-left-header
5368 ;; The left headers will display the message's subject, its
5369 ;; author, and the name of the folder it was in.
5370 '(ps-article-subject ps-article-author buffer-name)))
5371
5372 ;; Every now and then I forget to switch from the *Summary* buffer to
5373 ;; the *Article* before hitting prsc, and a nicely formatted list of
5374 ;; article subjects shows up at the printer. This function, bound to
5375 ;; prsc for the gnus *Summary* buffer means I don't have to switch
5376 ;; buffers first.
5377 ;; sb: Updated for Gnus 5.
5378 (defun ps-gnus-print-article-from-summary ()
5379 (interactive)
5380 (ps-print-message-from-summary 'gnus-article-buffer "*Article*"))
5381
5382 ;; See `ps-gnus-print-article-from-summary'. This function does the
5383 ;; same thing for vm.
5384 (defun ps-vm-print-message-from-summary ()
5385 (interactive)
5386 (ps-print-message-from-summary 'vm-mail-buffer ""))
5387
5388 ;; A hook to bind to bind to `gnus-summary-setup-buffer' to locally bind
5389 ;; prsc.
5390 (defun ps-gnus-summary-setup ()
5391 (local-set-key (ps-prsc) 'ps-gnus-print-article-from-summary))
5392
5393 ;; Look in an article or mail message for the Subject: line. To be
5394 ;; placed in `ps-left-headers'.
5395 (defun ps-info-file ()
5396 (save-excursion
5397 (goto-char (point-min))
5398 (if (re-search-forward "File:[ \t]+\\([^, \t\n]*\\)" nil t)
5399 (buffer-substring-no-properties (match-beginning 1) (match-end 1))
5400 "File ???")))
5401
5402 ;; Look in an article or mail message for the Subject: line. To be
5403 ;; placed in `ps-left-headers'.
5404 (defun ps-info-node ()
5405 (save-excursion
5406 (goto-char (point-min))
5407 (if (re-search-forward "Node:[ \t]+\\([^,\t\n]*\\)" nil t)
5408 (buffer-substring-no-properties (match-beginning 1) (match-end 1))
5409 "Node ???")))
5410
5411 (defun ps-info-mode-hook ()
5412 (setq ps-left-header
5413 ;; The left headers will display the node name and file name.
5414 '(ps-info-node ps-info-file)))
5415
5416 ;; WARNING! The following function is a *sample* only, and is *not*
5417 ;; meant to be used as a whole unless you understand what the effects
5418 ;; will be! (In fact, this is a copy of Jim's setup for ps-print --
5419 ;; I'd be very surprised if it was useful to *anybody*, without
5420 ;; modification.)
5421
5422 (defun ps-jts-ps-setup ()
5423 (global-set-key (ps-prsc) 'ps-spool-buffer-with-faces) ;f22 is prsc
5424 (global-set-key (ps-s-prsc) 'ps-spool-region-with-faces)
5425 (global-set-key (ps-c-prsc) 'ps-despool)
5426 (add-hook 'gnus-article-prepare-hook 'ps-gnus-article-prepare-hook)
5427 (add-hook 'gnus-summary-mode-hook 'ps-gnus-summary-setup)
5428 (add-hook 'vm-mode-hook 'ps-vm-mode-hook)
5429 (add-hook 'vm-mode-hooks 'ps-vm-mode-hook)
5430 (add-hook 'Info-mode-hook 'ps-info-mode-hook)
5431 (setq ps-spool-duplex t
5432 ps-print-color-p nil
5433 ps-lpr-command "lpr"
5434 ps-lpr-switches '("-Jjct,duplex_long"))
5435 'ps-jts-ps-setup)
5436
5437 ;; WARNING! The following function is a *sample* only, and is *not*
5438 ;; meant to be used as a whole unless it corresponds to your needs.
5439 ;; (In fact, this is a copy of Jack's setup for ps-print --
5440 ;; I would not be that surprised if it was useful to *anybody*,
5441 ;; without modification.)
5442
5443 (defun ps-jack-setup ()
5444 (setq ps-print-color-p nil
5445 ps-lpr-command "lpr"
5446 ps-lpr-switches nil
5447
5448 ps-paper-type 'a4
5449 ps-landscape-mode t
5450 ps-number-of-columns 2
5451
5452 ps-left-margin (/ (* 72 1.0) 2.54) ; 1.0 cm
5453 ps-right-margin (/ (* 72 1.0) 2.54) ; 1.0 cm
5454 ps-inter-column (/ (* 72 1.0) 2.54) ; 1.0 cm
5455 ps-bottom-margin (/ (* 72 1.5) 2.54) ; 1.5 cm
5456 ps-top-margin (/ (* 72 1.5) 2.54) ; 1.5 cm
5457 ps-header-offset (/ (* 72 1.0) 2.54) ; 1.0 cm
5458 ps-header-line-pad .15
5459 ps-print-header t
5460 ps-print-header-frame t
5461 ps-header-lines 2
5462 ps-show-n-of-n t
5463 ps-spool-duplex nil
5464
5465 ps-font-family 'Courier
5466 ps-font-size 5.5
5467 ps-header-font-family 'Helvetica
5468 ps-header-font-size 6
5469 ps-header-title-font-size 8)
5470 'ps-jack-setup)
5471
5472 \f
5473 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5474 ;; To make this file smaller, some commands go in a separate file.
5475 ;; But autoload them here to make the separation invisible.
5476
5477 (autoload 'ps-mule-prepare-ascii-font "ps-mule"
5478 "Setup special ASCII font for STRING.
5479 STRING should contain only ASCII characters.")
5480
5481 (autoload 'ps-mule-set-ascii-font "ps-mule"
5482 "Adjust current font if current charset is not ASCII.")
5483
5484 (autoload 'ps-mule-plot-string "ps-mule"
5485 "Generate PostScript code for ploting characters in the region FROM and TO.
5486
5487 It is assumed that all characters in this region belong to the same charset.
5488
5489 Optional argument BG-COLOR specifies background color.
5490
5491 Returns the value:
5492
5493 (ENDPOS . RUN-WIDTH)
5494
5495 Where ENDPOS is the end position of the sequence and RUN-WIDTH is the width of
5496 the sequence.")
5497
5498 (autoload 'ps-mule-initialize "ps-mule"
5499 "Initialize global data for printing multi-byte characters.")
5500
5501 (autoload 'ps-mule-begin-job "ps-mule"
5502 "Start printing job for multi-byte chars between FROM and TO.
5503 This checks if all multi-byte characters in the region are printable or not.")
5504
5505 (autoload 'ps-mule-begin-page "ps-mule"
5506 "Initialize multi-byte charset for printing current page.")
5507
5508 \f
5509 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5510
5511 (provide 'ps-print)
5512
5513 ;;; ps-print.el ends here