(printer-name): New variable.
[bpt/emacs.git] / lisp / ps-print.el
CommitLineData
535efc38 1;;; ps-print.el --- Print text from the buffer as PostScript
12d89a2e 2
12b88fff 3;; Copyright (C) 1993, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
ef2cbb24 4
090be653 5;; Author: Jim Thompson (was <thompson@wg2.waii.com>)
87a16a06 6;; Author: Jacques Duthen <duthen@cegelec-red.fr>
857686a6 7;; Author: Vinicius Jose Latorre <vinicius@cpqd.com.br>
8bd22fcf 8;; Maintainer: Vinicius Jose Latorre <vinicius@cpqd.com.br>
090be653 9;; Keywords: print, PostScript
7da17ab6
RS
10;; Time-stamp: <98/06/04 15:23:12 vinicius>
11;; Version: 3.06.3
090be653 12
7da17ab6
RS
13(defconst ps-print-version "3.06.3"
14 "ps-print.el, v 3.06.3 <98/06/04 vinicius>
090be653 15
535efc38 16Vinicius's last change version -- this file may have been edited as part of
090be653
RS
17Emacs without changes to the version number. When reporting bugs,
18please also report the version of Emacs, if any, that ps-print was
19distributed with.
20
21Please send all bug fixes and enhancements to
8bd22fcf 22 Vinicius Jose Latorre <vinicius@cpqd.com.br>.
090be653 23")
ef2cbb24 24
86c10ecb 25;; This file is part of GNU Emacs.
ef2cbb24
RS
26
27;; GNU Emacs is free software; you can redistribute it and/or modify
28;; it under the terms of the GNU General Public License as published by
29;; the Free Software Foundation; either version 2, or (at your option)
30;; any later version.
31
32;; GNU Emacs is distributed in the hope that it will be useful,
33;; but WITHOUT ANY WARRANTY; without even the implied warranty of
34;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35;; GNU General Public License for more details.
36
37;; You should have received a copy of the GNU General Public License
b578f267
EN
38;; along with GNU Emacs; see the file COPYING. If not, write to the
39;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
40;; Boston, MA 02111-1307, USA.
ef2cbb24 41
12d89a2e 42;;; Commentary:
ef2cbb24
RS
43
44;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
45;;
12d89a2e 46;; About ps-print
ef2cbb24 47;; --------------
bcc0d457 48;;
ef2cbb24
RS
49;; This package provides printing of Emacs buffers on PostScript
50;; printers; the buffer's bold and italic text attributes are
51;; preserved in the printer output. Ps-print is intended for use with
00aa16af
RS
52;; Emacs 19 or Lucid Emacs, together with a fontifying package such as
53;; font-lock or hilit.
12d89a2e 54;;
87a16a06
RS
55;; ps-print uses the same face attributes defined through font-lock or hilit
56;; to print a PostScript file, but some faces are better seeing on the screen
57;; than on paper, specially when you have a black/white PostScript printer.
58;;
59;; ps-print allows a remap of face to another one that it is better to print,
60;; for example, the face font-lock-comment-face (if you are using font-lock)
61;; could have bold or italic attribute when printing, besides foreground color.
62;; This remap improves printing look (see How Ps-Print Maps Faces).
63;;
bcc0d457 64;;
12d89a2e 65;; Using ps-print
ef2cbb24 66;; --------------
ef2cbb24 67;;
12d89a2e
RS
68;; The Commands
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:
ef2cbb24 89;;
12d89a2e
RS
90;; print - The PostScript image is immediately sent to the
91;; printer;
ef2cbb24 92;;
12d89a2e
RS
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
bcc0d457 96;; to the printer, use the command `ps-despool'.
ef2cbb24 97;;
12d89a2e
RS
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).
06fb6aab 103;;
1061ff16 104;; Ps-print has a hook in the `kill-emacs-hook' so that you won't
a7acbbe4 105;; accidentally quit from Emacs while you have unprinted PostScript
12d89a2e
RS
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
bcc0d457 141;; -----------------
ef2cbb24 142;;
12d89a2e 143;; To print your buffer, type
ef2cbb24 144;;
12d89a2e 145;; M-x ps-print-buffer
ef2cbb24 146;;
12d89a2e
RS
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
bcc0d457 157;; file by giving a prefix argument to `ps-despool':
12d89a2e
RS
158;;
159;; C-u M-x ps-despool
160;;
bcc0d457 161;; When invoked this way, `ps-despool' will prompt you for the name of
12d89a2e
RS
162;; the file to save to.
163;;
bcc0d457
RS
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:
12d89a2e
RS
167;;
168;; (global-set-key 'f22 'ps-spool-buffer-with-faces) ;f22 is prsc
ef2cbb24
RS
169;; (global-set-key '(shift f22) 'ps-spool-region-with-faces)
170;; (global-set-key '(control f22) 'ps-despool)
171;;
12d89a2e
RS
172;;
173;; The Printer Interface
bcc0d457 174;; ---------------------
12d89a2e 175;;
bcc0d457 176;; The variables `ps-lpr-command' and `ps-lpr-switches' determine what
12d89a2e 177;; command is used to send the PostScript images to the printer, and
bcc0d457
RS
178;; what arguments to give the command. These are analogous to
179;; `lpr-command' and `lpr-switches'.
87a16a06 180;;
bcc0d457
RS
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;; NOTE: `ps-lpr-command' and `ps-lpr-switches' take their initial values
185;; from the variables `lpr-command' and `lpr-switches'. If you have
186;; `lpr-command' set to invoke a pretty-printer such as `enscript',
187;; then ps-print won't work properly. `ps-lpr-command' must name
12d89a2e
RS
188;; a program that does not format the files it prints.
189;;
190;;
bcc0d457
RS
191;; The Page Layout
192;; ---------------
12d89a2e 193;;
bcc0d457
RS
194;; All dimensions are floats in PostScript points.
195;; 1 inch == 2.54 cm == 72 points
196;; 1 cm == (/ 1 2.54) inch == (/ 72 2.54) points
12d89a2e 197;;
bcc0d457
RS
198;; The variable `ps-paper-type' determines the size of paper ps-print
199;; formats for; it should contain one of the symbols:
200;; `a4' `a3' `letter' `legal' `letter-small' `tabloid'
201;; `ledger' `statement' `executive' `a4small' `b4' `b5'
12d89a2e 202;;
bcc0d457
RS
203;; The variable `ps-landscape-mode' determines the orientation
204;; of the printing on the page:
205;; nil means `portrait' mode, non-nil means `landscape' mode.
206;; There is no oblique mode yet, though this is easy to do in ps.
87a16a06 207;;
bcc0d457
RS
208;; In landscape mode, the text is NOT scaled: you may print 70 lines
209;; in portrait mode and only 50 lignes in landscape mode.
210;; The margins represent margins in the printed paper:
211;; the top margin is the margin between the top of the page
212;; and the printed header, whatever the orientation is.
043620f4 213;;
bcc0d457
RS
214;; The variable `ps-number-of-columns' determines the number of columns
215;; both in landscape and portrait mode.
216;; You can use:
217;; - (the standard) one column portrait mode
218;; - (my favorite) two columns landscape mode (which spares trees)
219;; but also
220;; - one column landscape mode for files with very long lines.
221;; - multi-column portrait or landscape mode
12d89a2e 222;;
12d89a2e 223;;
bcc0d457
RS
224;; Horizontal layout
225;; -----------------
12d89a2e 226;;
bcc0d457
RS
227;; The horizontal layout is determined by the variables
228;; `ps-left-margin' `ps-inter-column' `ps-right-margin'
229;; as follows:
12d89a2e 230;;
bcc0d457
RS
231;; ------------------------------------------
232;; | | | | | | | |
233;; | lm | text | ic | text | ic | text | rm |
234;; | | | | | | | |
235;; ------------------------------------------
12d89a2e 236;;
bcc0d457
RS
237;; If `ps-number-of-columns' is 1, `ps-inter-column' is not relevant.
238;; Usually, lm = rm > 0 and ic = lm
239;; If (ic < 0), the text of adjacent columns can overlap.
12d89a2e 240;;
12d89a2e 241;;
bcc0d457
RS
242;; Vertical layout
243;; ---------------
244;;
245;; The vertical layout is determined by the variables
246;; `ps-bottom-margin' `ps-top-margin' `ps-header-offset'
247;; as follows:
248;;
249;; |--------| |--------|
250;; | tm | | tm |
251;; |--------| |--------|
252;; | header | | |
253;; |--------| | |
254;; | ho | | |
255;; |--------| or | text |
256;; | | | |
257;; | text | | |
258;; | | | |
259;; |--------| |--------|
260;; | bm | | bm |
261;; |--------| |--------|
262;;
263;; If `ps-print-header' is nil, `ps-header-offset' is not relevant.
264;; The margins represent margins in the printed paper:
265;; the top margin is the margin between the top of the page
266;; and the printed header, whatever the orientation is.
12d89a2e
RS
267;;
268;;
269;; Headers
bcc0d457 270;; -------
12d89a2e 271;;
12b88fff
RS
272;; Ps-print can print headers at the top of each column or at the top
273;; of each page; the default headers contain the following four items:
274;; on the left, the name of the buffer and, if the buffer is visiting
275;; a file, the file's directory; on the right, the page number and
276;; date of printing. The default headers look something like this:
12d89a2e
RS
277;;
278;; ps-print.el 1/21
279;; /home/jct/emacs-lisp/ps/new 94/12/31
06fb6aab 280;;
12d89a2e 281;; When printing on duplex printers, left and right are reversed so
bcc0d457 282;; that the page numbers are toward the outside (cf. `ps-spool-duplex').
12d89a2e 283;;
bcc0d457
RS
284;; Headers are configurable:
285;; To turn them off completely, set `ps-print-header' to nil.
286;; To turn off the header's gaudy framing box,
287;; set `ps-print-header-frame' to nil.
288;;
12b88fff
RS
289;; To print only one header at the top of each page,
290;; set `ps-print-only-one-header' to t.
291;;
bcc0d457 292;; The font family and size of text in the header are determined
06fb6aab 293;; by the variables `ps-header-font-family', `ps-header-font-size' and
bcc0d457
RS
294;; `ps-header-title-font-size' (see below).
295;;
296;; The variable `ps-header-line-pad' determines the portion of a header
297;; title line height to insert between the header frame and the text
298;; it contains, both in the vertical and horizontal directions:
299;; .5 means half a line.
300
301;; Page numbers are printed in `n/m' format, indicating page n of m pages;
302;; to omit the total page count and just print the page number,
303;; set `ps-show-n-of-n' to nil.
12d89a2e
RS
304;;
305;; The amount of information in the header can be changed by changing
bcc0d457 306;; the number of lines. To show less, set `ps-header-lines' to 1, and
12d89a2e 307;; the header will show only the buffer name and page number. To show
bcc0d457 308;; more, set `ps-header-lines' to 3, and the header will show the time of
12d89a2e
RS
309;; printing below the date.
310;;
311;; To change the content of the headers, change the variables
bcc0d457
RS
312;; `ps-left-header' and `ps-right-header'.
313;; These variables are lists, specifying top-to-bottom the text
314;; to display on the left or right side of the header.
315;; Each element of the list should be a string or a symbol.
316;; Strings are inserted directly into the PostScript arrays,
317;; and should contain the PostScript string delimiters '(' and ')'.
12d89a2e
RS
318;;
319;; Symbols in the header format lists can either represent functions
320;; or variables. Functions are called, and should return a string to
321;; show in the header. Variables should contain strings to display in
322;; the header. In either case, function or variable, the PostScript
a7acbbe4 323;; string delimiters are added by ps-print, and should not be part of
12d89a2e
RS
324;; the returned value.
325;;
326;; Here's an example: say we want the left header to display the text
327;;
328;; Moe
329;; Larry
330;; Curly
331;;
332;; where we have a function to return "Moe"
333;;
334;; (defun moe-func ()
335;; "Moe")
336;;
337;; a variable specifying "Larry"
338;;
339;; (setq larry-var "Larry")
340;;
bcc0d457 341;; and a literal for "Curly". Here's how `ps-left-header' should be
12d89a2e
RS
342;; set:
343;;
344;; (setq ps-left-header (list 'moe-func 'larry-var "(Curly)"))
345;;
346;; Note that Curly has the PostScript string delimiters inside his
bcc0d457 347;; quotes -- those aren't misplaced lisp delimiters!
87a16a06 348;;
bcc0d457
RS
349;; Without them, PostScript would attempt to call the undefined
350;; function Curly, which would result in a PostScript error.
87a16a06 351;;
bcc0d457
RS
352;; Since most printers don't report PostScript errors except by
353;; aborting the print job, this kind of error can be hard to track down.
87a16a06 354;;
bcc0d457 355;; Consider yourself warned!
12d89a2e
RS
356;;
357;;
358;; Duplex Printers
bcc0d457 359;; ---------------
12d89a2e
RS
360;;
361;; If you have a duplex-capable printer (one that prints both sides of
bcc0d457
RS
362;; the paper), set `ps-spool-duplex' to t.
363;; Ps-print will insert blank pages to make sure each buffer starts
364;; on the correct side of the paper.
365;; Don't forget to set `ps-lpr-switches' to select duplex printing
366;; for your printer.
367;;
06fb6aab 368;;
857686a6
RS
369;; Control And 8-bit Characters
370;; ----------------------------
371;;
372;; The variable `ps-print-control-characters' specifies whether you want to see
373;; a printable form for control and 8-bit characters, that is, instead of
6bdb808e 374;; sending, for example, a ^D (\004) to printer, it is sent the string "^D".
857686a6
RS
375;;
376;; Valid values for `ps-print-control-characters' are:
377;;
496725ad 378;; 8-bit This is the value to use when you want an ascii encoding of
6bdb808e
RS
379;; any control or non-ascii character. Control characters are
380;; encoded as "^D", and non-ascii characters have an
381;; octal encoding.
382;;
496725ad 383;; control-8-bit This is the value to use when you want an ascii encoding of
6bdb808e
RS
384;; any control character, whether it is 7 or 8-bit.
385;; European 8-bits accented characters are printed according
386;; the current font.
387;;
496725ad 388;; control Only ascii control characters have an ascii encoding.
6bdb808e
RS
389;; European 8-bits accented characters are printed according
390;; the current font.
391;;
392;; nil No ascii encoding. Any character is printed according the
393;; current font.
857686a6
RS
394;;
395;; Any other value is treated as nil.
396;;
496725ad 397;; The default is `control-8-bit'.
857686a6
RS
398;;
399;; Characters TAB, NEWLINE and FORMFEED are always treated by ps-print engine.
400;;
401;;
87a16a06
RS
402;; Line Number
403;; -----------
404;;
a18ed129
RS
405;; The variable `ps-line-number' specifies whether to number each line;
406;; non-nil means do so. The default is nil (don't number each line).
87a16a06
RS
407;;
408;;
409;; Zebra Stripes
410;; -------------
411;;
a18ed129
RS
412;; Zebra stripes are a kind of background that appear "underneath" the text
413;; and can make the text easier to read. They look like this:
87a16a06
RS
414;;
415;; XXXXXXXXXXXXXXXXXXXXXXXX
416;; XXXXXXXXXXXXXXXXXXXXXXXX
535efc38
RS
417;; XXXXXXXXXXXXXXXXXXXXXXXX
418;;
87a16a06
RS
419;;
420;;
421;; XXXXXXXXXXXXXXXXXXXXXXXX
422;; XXXXXXXXXXXXXXXXXXXXXXXX
535efc38 423;; XXXXXXXXXXXXXXXXXXXXXXXX
87a16a06 424;;
06fb6aab 425;; The blocks of X's represent rectangles filled with a light gray color.
a18ed129
RS
426;; Each rectangle extends all the way across the page.
427;;
428;; The height, in lines, of each rectangle is controlled by
535efc38
RS
429;; the variable `ps-zebra-stripe-height', which is 3 by default.
430;; The distance between stripes equals the height of a stripe.
8bd22fcf 431;;
01961237 432;; The variable `ps-zebra-stripes' controls whether to print zebra stripes.
a18ed129
RS
433;; Non-nil means yes, nil means no. The default is nil.
434;;
435;; See also section How Ps-Print Has A Text And/Or Image On Background.
87a16a06 436;;
87a16a06 437;;
12b88fff
RS
438;; Hooks
439;; -----
440;;
441;; Ps-print has the following hook variables:
442;;
443;; `ps-print-hook'
444;; It is evaluated once before any printing process. This is the right
445;; place to initialize ps-print global data.
446;; For an example, see section Adding a New Font Family.
447;;
448;; `ps-print-begin-page-hook'
449;; It is evaluated on each real beginning of page, that is, ps-print
450;; considers each beginning of column as a beginning of page, and a real
451;; beginning of page is when the beginning of column coincides with a
452;; paper change on your printer.
453;;
454;; `ps-print-begin-column-hook'
455;; It is evaluated on each beginning of column, except in the beginning
456;; of column that `ps-print-begin-page-hook' is evaluated.
457;;
458;;
459;; Font Managing
bcc0d457
RS
460;; -------------
461;;
462;; Ps-print now knows rather precisely some fonts:
463;; the variable `ps-font-info-database' contains information
464;; for a list of font families (currently mainly `Courier' `Helvetica'
465;; `Times' `Palatino' `Helvetica-Narrow' `NewCenturySchlbk').
466;; Each font family contains the font names for standard, bold, italic
467;; and bold-italic characters, a reference size (usually 10) and the
468;; corresponding line height, width of a space and average character width.
06fb6aab 469;;
bcc0d457
RS
470;; The variable `ps-font-family' determines which font family
471;; is to be used for ordinary text.
472;; If its value does not correspond to a known font family,
473;; an error message is printed into the `*Messages*' buffer,
474;; which lists the currently available font families.
475;;
476;; The variable `ps-font-size' determines the size (in points)
477;; of the font for ordinary text, when generating Postscript.
478;; Its value is a float.
479;;
480;; Similarly, the variable `ps-header-font-family' determines
481;; which font family is to be used for text in the header.
482;; The variable `ps-header-font-size' determines the font size,
483;; in points, for text in the header.
484;; The variable `ps-header-title-font-size' determines the font size,
485;; in points, for the top line of text in the header.
486;;
487;;
12b88fff 488;; Adding a New Font Family
bcc0d457
RS
489;; ------------------------
490;;
491;; To use a new font family, you MUST first teach ps-print
87a16a06 492;; this font, i.e., add its information to `ps-font-info-database',
bcc0d457
RS
493;; otherwise ps-print cannot correctly place line and page breaks.
494;;
87a16a06 495;; For example, assuming `Helvetica' is unknown,
bcc0d457
RS
496;; you first need to do the following ONLY ONCE:
497;;
498;; - create a new buffer
499;; - generate the PostScript image to a file (C-u M-x ps-print-buffer)
500;; - open this file and find the line:
501;; `% 3 cm 20 cm moveto 10 /Courier ReportFontInfo showpage'
a18ed129 502;; - delete the leading `%' (which is the PostScript comment character)
bcc0d457
RS
503;; - replace in this line `Courier' by the new font (say `Helvetica')
504;; to get the line:
505;; `3 cm 20 cm moveto 10 /Helvetica ReportFontInfo showpage'
506;; - send this file to the printer (or to ghostscript).
507;; You should read the following on the output page:
508;;
509;; For Helvetica 10 point, the line height is 11.56, the space width is 2.78
510;; and a crude estimate of average character width is 5.09243
511;;
512;; - Add these values to the `ps-font-info-database':
513;; (setq ps-font-info-database
12b88fff
RS
514;; (append
515;; '((Helvetica ; the family key
516;; (fonts (normal . "Helvetica")
517;; (bold . "Helvetica-Bold")
518;; (italic . "Helvetica-Oblique")
519;; (bold-italic . "Helvetica-BoldOblique"))
520;; (size . 10.0)
521;; (line-height . 11.56)
522;; (space-width . 2.78)
523;; (avg-char-width . 5.09243)))
524;; ps-font-info-database))
bcc0d457
RS
525;; - Now you can use this font family with any size:
526;; (setq ps-font-family 'Helvetica)
527;; - if you want to use this family in another emacs session, you must
528;; put into your `~/.emacs':
529;; (require 'ps-print)
530;; (setq ps-font-info-database (append ...)))
531;; if you don't want to load ps-print, you have to copy the whole value:
532;; (setq ps-font-info-database '(<your stuff> <the standard stuff>))
12b88fff
RS
533;; or, use `ps-print-hook' (see section Hooks):
534;; (add-hook 'ps-print-hook
535;; '(lambda () (setq ps-font-info-database (append ...))))
bcc0d457
RS
536;;
537;; You can create new `mixed' font families like:
12b88fff
RS
538;; (my-mixed-family
539;; (fonts (normal . "Courier-Bold")
540;; (bold . "Helvetica")
541;; (italic . "Zapf-Chancery-MediumItalic")
542;; (bold-italic . "NewCenturySchlbk-BoldItalic")
543;; (w3-table-hack-x-face . "LineDrawNormal"))
544;; (size . 10.0)
545;; (line-height . 10.55)
546;; (space-width . 6.0)
547;; (avg-char-width . 6.0))
bcc0d457
RS
548;; Now you can use your new font family with any size:
549;; (setq ps-font-family 'my-mixed-family)
550;;
12b88fff
RS
551;; Note that on above example the `w3-table-hack-x-face' entry refers to
552;; a face symbol, so when printing this face it'll be used the font
553;; `LineDrawNormal'. If the face `w3-table-hack-x-face' is remapped to
554;; use bold and/or italic attribute, the corresponding entry (bold, italic
555;; or bold-italic) will be used instead of `w3-table-hack-x-face' entry.
556;;
557;; Note also that the font family entry order is irrelevant, so the above
558;; example could also be written:
559;; (my-mixed-family
560;; (size . 10.0)
561;; (fonts (w3-table-hack-x-face . "LineDrawNormal")
562;; (bold . "Helvetica")
563;; (bold-italic . "NewCenturySchlbk-BoldItalic")
564;; (italic . "Zapf-Chancery-MediumItalic")
565;; (normal . "Courier-Bold"))
566;; (avg-char-width . 6.0)
567;; (space-width . 6.0)
568;; (line-height . 10.55))
569;;
570;; Despite the note above, it is recommended that some convention about
571;; entry order be used.
572;;
bcc0d457
RS
573;; You can get information on all the fonts resident in YOUR printer
574;; by uncommenting the line:
575;; % 3 cm 20 cm moveto ReportAllFontInfo showpage
576;;
a18ed129
RS
577;; The PostScript file should be sent to YOUR PostScript printer.
578;; If you send it to ghostscript or to another PostScript printer,
bcc0d457
RS
579;; you may get slightly different results.
580;; Anyway, as ghostscript fonts are autoload, you won't get
581;; much font info.
582;;
583;;
584;; How Ps-Print Deals With Faces
585;; -----------------------------
12d89a2e 586;;
bcc0d457
RS
587;; The ps-print-*-with-faces commands attempt to determine which faces
588;; should be printed in bold or italic, but their guesses aren't
589;; always right. For example, you might want to map colors into faces
590;; so that blue faces print in bold, and red faces in italic.
12d89a2e 591;;
857686a6
RS
592;; It is possible to force ps-print to consider specific faces bold,
593;; italic or underline, no matter what font they are displayed in, by setting
594;; the variables `ps-bold-faces', `ps-italic-faces' and `ps-underlined-faces'.
595;; These variables contain lists of faces that ps-print should consider bold,
596;; italic or underline; to set them, put code like the following into your
597;; .emacs file:
12d89a2e 598;;
12b88fff 599;; (setq ps-bold-faces '(my-blue-face))
bcc0d457 600;; (setq ps-italic-faces '(my-red-face))
857686a6 601;; (setq ps-underlined-faces '(my-green-face))
bcc0d457
RS
602;;
603;; Faces like bold-italic that are both bold and italic should go in
604;; *both* lists.
605;;
606;; Ps-print keeps internal lists of which fonts are bold and which are
607;; italic; these lists are built the first time you invoke ps-print.
608;; For the sake of efficiency, the lists are built only once; the same
609;; lists are referred in later invocations of ps-print.
610;;
611;; Because these lists are built only once, it's possible for them to
612;; get out of sync, if a face changes, or if new faces are added. To
613;; get the lists back in sync, you can set the variable
614;; `ps-build-face-reference' to t, and the lists will be rebuilt the
857686a6
RS
615;; next time ps-print is invoked. If you need that the lists always be
616;; rebuilt when ps-print is invoked, set the variable
617;; `ps-always-build-face-reference' to t.
bcc0d457
RS
618;;
619;;
620;; How Ps-Print Deals With Color
621;; -----------------------------
622;;
623;; Ps-print detects faces with foreground and background colors
624;; defined and embeds color information in the PostScript image.
625;; The default foreground and background colors are defined by the
626;; variables `ps-default-fg' and `ps-default-bg'.
627;; On black-and-white printers, colors are displayed in grayscale.
628;; To turn off color output, set `ps-print-color-p' to nil.
629;;
630;;
87a16a06
RS
631;; How Ps-Print Maps Faces
632;; -----------------------
633;;
634;; As ps-print uses PostScript to print buffers, it is possible to have
635;; other attributes associated with faces. So the new attributes used
636;; by ps-print are:
637;;
638;; strikeout - like underline, but the line is in middle of text.
639;; overline - like underline, but the line is over the text.
640;; shadow - text will have a shadow.
641;; box - text will be surrounded by a box.
a18ed129 642;; outline - print characters as hollow outlines.
87a16a06 643;;
06fb6aab 644;; See the documentation for `ps-extend-face'.
87a16a06
RS
645;;
646;; Let's, for example, remap font-lock-keyword-face to another foreground color
647;; and bold attribute:
648;;
a18ed129 649;; (ps-extend-face '(font-lock-keyword-face "RoyalBlue" nil bold) 'MERGE)
87a16a06 650;;
6c8f2753
RS
651;; If you want to use a new face, define it first with `defface',
652;; and then call `ps-extend-face' to specify how to print it.
653;;
87a16a06
RS
654;;
655;; How Ps-Print Has A Text And/Or Image On Background
656;; --------------------------------------------------
657;;
658;; Ps-print can print texts and/or EPS PostScript images on background; it is
659;; possible to define the following text attributes: font name, font size,
660;; initial position, angle, gray scale and pages to print.
661;;
662;; It has the following EPS PostScript images attributes: file name containing
663;; the image, initial position, X and Y scales, angle and pages to print.
664;;
665;; See documentation for `ps-print-background-text' and
666;; `ps-print-background-image'.
667;;
668;; For example, if we wish to print text "preliminary" on all pages and text
669;; "special" on page 5 and from page 11 to page 17, we could specify:
670;;
671;; (setq ps-print-background-text
672;; '(("preliminary")
673;; ("special"
674;; "LeftMargin" "BottomMargin PrintHeight add" ; X and Y position
675;; ; (upper left corner)
676;; nil nil nil
12b88fff 677;; "PrintHeight neg PrintPageWidth atan" ; angle
87a16a06
RS
678;; 5 (11 . 17)) ; page list
679;; ))
680;;
681;; Similarly, we could print image "~/images/EPS-image1.ps" on all pages and
682;; image "~/images/EPS-image2.ps" on page 5 and from page 11 to page 17, we
683;; specify:
684;;
685;; (setq ps-print-background-image
686;; '(("~/images/EPS-image1.ps"
687;; "LeftMargin" "BottomMargin") ; X and Y position (lower left corner)
688;; ("~/images/EPS-image2.ps"
689;; "LeftMargin" "BottomMargin PrintHeight 2 div add" ; X and Y position
690;; ; (upper left corner)
691;; nil nil nil
692;; 5 (11 . 17)) ; page list
693;; ))
694;;
695;; If it is not possible to read (or does not exist) an image file, that file
696;; is ignored.
697;;
698;; The printing order is:
699;;
700;; 1. Print zebra stripes
701;; 2. Print background texts that it should be on all pages
702;; 3. Print background images that it should be on all pages
703;; 4. Print background texts only for current page (if any)
704;; 5. Print background images only for current page (if any)
705;; 6. Print header
a18ed129 706;; 7. Print buffer text (with faces, if specified) and line number
87a16a06
RS
707;;
708;;
bcc0d457
RS
709;; Utilities
710;; ---------
711;;
712;; Some tools are provided to help you customize your font setup.
713;;
714;; `ps-setup' returns (some part of) the current setup.
715;;
716;; To avoid wrapping too many lines, you may want to adjust the
717;; left and right margins and the font size. On UN*X systems, do:
718;; pr -t file | awk '{printf "%3d %s\n", length($0), $0}' | sort -r | head
719;; to determine the longest lines of your file.
87a16a06 720;; Then, the command `ps-line-lengths' will give you the correspondence
bcc0d457
RS
721;; between a line length (number of characters) and the maximum font
722;; size which doesn't wrap such a line with the current ps-print setup.
723;;
724;; The commands `ps-nb-pages-buffer' and `ps-nb-pages-region' display
87a16a06 725;; the correspondence between a number of pages and the maximum font
bcc0d457
RS
726;; size which allow the number of lines of the current buffer or of
727;; its current region to fit in this number of pages.
a18ed129
RS
728;;
729;; NOTE: line folding is not taken into account in this process and could
730;; change the results.
b87c5d3d 731;;
b87c5d3d 732;;
b87c5d3d
RS
733;; New since version 1.5
734;; ---------------------
b87c5d3d 735;;
bcc0d457 736;; Color output capability.
b87c5d3d 737;; Automatic detection of font attributes (bold, italic).
b87c5d3d 738;; Configurable headers with page numbers.
b87c5d3d 739;; Slightly faster.
b87c5d3d 740;; Support for different paper sizes.
b87c5d3d
RS
741;; Better conformance to PostScript Document Structure Conventions.
742;;
ef2cbb24 743;;
bcc0d457
RS
744;; New since version 2.8
745;; ---------------------
746;;
12b88fff
RS
747;; [vinicius] 980306 Vinicius Jose Latorre <vinicius@cpqd.com.br>
748;;
749;; Skip invisible text
750;;
751;; [vinicius] 971130 Vinicius Jose Latorre <vinicius@cpqd.com.br>
752;;
753;; Hooks: `ps-print-hook', `ps-print-begin-page-hook' and
754;; `ps-print-begin-column-hook'.
755;; Put one header per page over the columns.
756;; Better database font management.
757;; Better control characters handling.
758;;
857686a6 759;; [vinicius] 971121 Vinicius Jose Latorre <vinicius@cpqd.com.br>
87a16a06 760;;
12b88fff 761;; Dynamic evaluation at print time of `ps-lpr-switches'.
87a16a06
RS
762;; Handle control characters.
763;; Face remapping.
764;; New face attributes.
765;; Line number.
766;; Zebra stripes.
767;; Text and/or image on background.
768;;
bcc0d457
RS
769;; [jack] 960517 Jacques Duthen <duthen@cegelec-red.fr>
770;;
a18ed129 771;; Font family and float size for text and header.
bcc0d457
RS
772;; Landscape mode.
773;; Multiple columns.
774;; Tools for page setup.
775;;
776;;
ef2cbb24
RS
777;; Known bugs and limitations of ps-print:
778;; --------------------------------------
bcc0d457 779;;
043620f4
KH
780;; Although color printing will work in XEmacs 19.12, it doesn't work
781;; well; in particular, bold or italic fonts don't print in the right
782;; background color.
783;;
784;; Invisible properties aren't correctly ignored in XEmacs 19.12.
785;;
b87c5d3d 786;; Automatic font-attribute detection doesn't work well, especially
00aa16af 787;; with hilit19 and older versions of get-create-face. Users having
bcc0d457 788;; problems with auto-font detection should use the lists
857686a6
RS
789;; `ps-italic-faces', `ps-bold-faces' and `ps-underlined-faces' and/or
790;; turn off automatic detection by setting `ps-auto-font-detect' to nil.
00aa16af 791;;
043620f4 792;; Automatic font-attribute detection doesn't work with XEmacs 19.12
857686a6
RS
793;; in tty mode; use the lists `ps-italic-faces', `ps-bold-faces' and
794;; `ps-underlined-faces' instead.
12d89a2e 795;;
00aa16af 796;; Still too slow; could use some hand-optimization.
ef2cbb24 797;;
12d89a2e 798;; Default background color isn't working.
ef2cbb24
RS
799;;
800;; Faces are always treated as opaque.
801;;
12d89a2e 802;; Epoch and Emacs 18 not supported. At all.
ef2cbb24 803;;
06fb6aab 804;; Fixed-pitch fonts work better for line folding, but are not required.
bcc0d457
RS
805;;
806;; `ps-nb-pages-buffer' and `ps-nb-pages-region' don't take care
807;; of folding lines.
ef2cbb24 808;;
12d89a2e 809;;
bcc0d457
RS
810;; Things to change:
811;; ----------------
ef2cbb24 812;;
12b88fff 813;; Avoid page break inside a paragraph.
bcc0d457 814;; Add `ps-non-bold-faces' and `ps-non-italic-faces' (should be easy).
bcc0d457
RS
815;; Improve the memory management for big files (hard?).
816;; `ps-nb-pages-buffer' and `ps-nb-pages-region' should take care
817;; of folding lines.
ef2cbb24 818;;
ef2cbb24 819;;
12d89a2e
RS
820;; Acknowledgements
821;; ----------------
12b88fff 822;;
6bdb808e
RS
823;; Thanks to Roland Ducournau <ducour@lirmm.fr> for
824;; `ps-print-control-characters' variable documentation.
825;;
12b88fff
RS
826;; Thanks to Marcus G Daniels <marcus@cathcart.sysc.pdx.edu> for a better
827;; database font management.
828;;
829;; Thanks to Martin Boyer <gamin@videotron.ca> for some ideas on putting one
6bdb808e
RS
830;; header per page over the columns and correct line numbers when printing a
831;; region.
12b88fff
RS
832;;
833;; Thanks to Steven L Baur <steve@miranova.com> for dynamic evaluation at
834;; print time of `ps-lpr-switches'.
835;;
6bdb808e
RS
836;; Thanks to Kevin Rodgers <kevinr@ihs.com> for handling control characters
837;; (his code was severely modified, but the main idea was kept).
838;;
12b88fff
RS
839;; Thanks to some suggestions on:
840;; * Face color map: Marco Melgazzi <marco@techie.com>
841;; * XEmacs compatibility: William J. Henney <will@astrosmo.unam.mx>
984e7bd9 842;; * Check `ps-paper-type': Sudhakar Frederick <sfrederi@asc.corp.mot.com>
12b88fff 843;;
857686a6
RS
844;; Thanks to Jacques Duthen <duthen@cegelec-red.fr> (Jack) for the 3.4 version
845;; I started from. [vinicius]
846;;
bcc0d457
RS
847;; Thanks to Jim Thompson <?@?> for the 2.8 version I started from.
848;; [jack]
849;;
12d89a2e
RS
850;; Thanks to Kevin Rodgers <kevinr@ihs.com> for adding support for
851;; color and the invisible property.
ef2cbb24 852;;
12d89a2e
RS
853;; Thanks to Avishai Yacobi, avishaiy@mcil.comm.mot.com, for writing
854;; the initial port to Emacs 19. His code is no longer part of
855;; ps-print, but his work is still appreciated.
ef2cbb24 856;;
12d89a2e
RS
857;; Thanks to Remi Houdaille and Michel Train, michel@metasoft.fdn.org,
858;; for adding underline support. Their code also is no longer part of
859;; ps-print, but their efforts are not forgotten.
860;;
861;; Thanks also to all of you who mailed code to add features to
862;; ps-print; although I didn't use your code, I still appreciate your
863;; sharing it with me.
864;;
865;; Thanks to all who mailed comments, encouragement, and criticism.
866;; Thanks also to all who responded to my survey; I had too many
867;; responses to reply to them all, but I greatly appreciate your
868;; interest.
869;;
870;; Jim
871;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ef2cbb24
RS
872
873;;; Code:
874
090be653
RS
875(unless (featurep 'lisp-float-type)
876 (error "`ps-print' requires floating point support"))
ef2cbb24
RS
877
878;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
12d89a2e
RS
879;; User Variables:
880
bcc0d457
RS
881;;; Interface to the command system
882
e0af0d3e 883(defgroup ps-print nil
8bd22fcf 884 "PostScript generator for Emacs 19"
e0af0d3e
RS
885 :prefix "ps-"
886 :group 'wp)
887
888(defgroup ps-print-horizontal nil
889 "Horizontal page layout"
890 :prefix "ps-"
891 :tag "Horizontal"
892 :group 'ps-print)
893
894(defgroup ps-print-vertical nil
895 "Vertical page layout"
896 :prefix "ps-"
897 :tag "Vertical"
898 :group 'ps-print)
899
900(defgroup ps-print-header nil
901 "Headers layout"
902 :prefix "ps-"
903 :tag "Header"
904 :group 'ps-print)
905
906(defgroup ps-print-font nil
907 "Fonts customization"
908 :prefix "ps-"
909 :tag "Font"
910 :group 'ps-print)
911
912(defgroup ps-print-color nil
913 "Color customization"
914 :prefix "ps-"
915 :tag "Color"
916 :group 'ps-print)
917
918(defgroup ps-print-face nil
919 "Faces customization"
920 :prefix "ps-"
921 :tag "PS Faces"
922 :group 'ps-print
923 :group 'faces)
924
925
926(defcustom ps-lpr-command lpr-command
927 "*The shell command for printing a PostScript file."
928 :type 'string
929 :group 'ps-print)
930
931(defcustom ps-lpr-switches lpr-switches
932 "*A list of extra switches to pass to `ps-lpr-command'."
933 :type '(repeat string)
934 :group 'ps-print)
12d89a2e 935
bcc0d457 936;;; Page layout
12d89a2e 937
bcc0d457
RS
938;; All page dimensions are in PostScript points.
939;; 1 inch == 2.54 cm == 72 points
940;; 1 cm == (/ 1 2.54) inch == (/ 72 2.54) points
941
942;; Letter 8.5 inch x 11.0 inch
943;; Legal 8.5 inch x 14.0 inch
944;; A4 8.26 inch x 11.69 inch = 21.0 cm x 29.7 cm
945
946;; LetterSmall 7.68 inch x 10.16 inch
947;; Tabloid 11.0 inch x 17.0 inch
948;; Ledger 17.0 inch x 11.0 inch
949;; Statement 5.5 inch x 8.5 inch
950;; Executive 7.5 inch x 10.0 inch
951;; A3 11.69 inch x 16.5 inch = 29.7 cm x 42.0 cm
952;; A4Small 7.47 inch x 10.85 inch
953;; B4 10.125 inch x 14.33 inch
954;; B5 7.16 inch x 10.125 inch
955
e0af0d3e 956(defcustom ps-page-dimensions-database
bcc0d457
RS
957 (list (list 'a4 (/ (* 72 21.0) 2.54) (/ (* 72 29.7) 2.54))
958 (list 'a3 (/ (* 72 29.7) 2.54) (/ (* 72 42.0) 2.54))
959 (list 'letter (* 72 8.5) (* 72 11.0))
960 (list 'legal (* 72 8.5) (* 72 14.0))
961 (list 'letter-small (* 72 7.68) (* 72 10.16))
962 (list 'tabloid (* 72 11.0) (* 72 17.0))
963 (list 'ledger (* 72 17.0) (* 72 11.0))
964 (list 'statement (* 72 5.5) (* 72 8.5))
965 (list 'executive (* 72 7.5) (* 72 10.0))
966 (list 'a4small (* 72 7.47) (* 72 10.85))
967 (list 'b4 (* 72 10.125) (* 72 14.33))
968 (list 'b5 (* 72 7.16) (* 72 10.125)))
969 "*List associating a symbolic paper type to its width and height.
e0af0d3e
RS
970see `ps-paper-type'."
971 :type '(repeat (list :tag "Paper Type"
972 (symbol :tag "Name")
973 (number :tag "Width")
974 (number :tag "Height")))
975 :group 'ps-print)
976
857686a6 977;;;###autoload
e0af0d3e 978(defcustom ps-paper-type 'letter
bcc0d457 979 "*Specifies the size of paper to format for.
090be653 980Should be one of the paper types defined in `ps-page-dimensions-database', for
e0af0d3e
RS
981example `letter', `legal' or `a4'."
982 :type '(symbol :validate (lambda (wid)
87a16a06
RS
983 (if (assq (widget-value wid)
984 ps-page-dimensions-database)
e0af0d3e
RS
985 nil
986 (widget-put wid :error "Unknown paper size")
987 wid)))
988 :group 'ps-print)
989
87a16a06 990(defcustom ps-landscape-mode nil
e0af0d3e
RS
991 "*Non-nil means print in landscape mode."
992 :type 'boolean
993 :group 'ps-print)
994
857686a6
RS
995(defcustom ps-print-control-characters 'control-8-bit
996 "*Specifies the printable form for control and 8-bit characters.
6bdb808e 997That is, instead of sending, for example, a ^D (\004) to printer,
984e7bd9 998you can send ^ and D.
6bdb808e 999
857686a6 1000Valid values are:
6bdb808e 1001
984e7bd9
RS
1002 `8-bit' This is the value to use when you want an ASCII encoding of
1003 any control or non-ASCII character. Control characters are
6bdb808e
RS
1004 encoded as \"^D\", and non-ascii characters have an
1005 octal encoding.
1006
984e7bd9 1007 `control-8-bit' This is the value to use when you want an ASCII encoding of
6bdb808e
RS
1008 any control character, whether it is 7 or 8-bit.
1009 European 8-bits accented characters are printed according
1010 the current font.
1011
984e7bd9 1012 `control' Only ascii control characters have an ASCII encoding.
6bdb808e
RS
1013 European 8-bits accented characters are printed according
1014 the current font.
1015
984e7bd9 1016 nil No ASCII encoding. Any character is printed according the
6bdb808e
RS
1017 current font.
1018
857686a6 1019Any other value is treated as nil."
12b88fff 1020 :type '(choice (const 8-bit) (const control-8-bit)
ab2739aa 1021 (const control) (other :tag "nil" nil))
857686a6
RS
1022 :group 'ps-print)
1023
e0af0d3e
RS
1024(defcustom ps-number-of-columns (if ps-landscape-mode 2 1)
1025 "*Specifies the number of columns"
87a16a06
RS
1026 :type 'number
1027 :group 'ps-print)
1028
535efc38 1029(defcustom ps-zebra-stripes nil
87a16a06 1030 "*Non-nil means print zebra stripes.
06fb6aab 1031See also documentation for `ps-zebra-stripe-height'."
87a16a06
RS
1032 :type 'boolean
1033 :group 'ps-print)
1034
535efc38 1035(defcustom ps-zebra-stripe-height 3
87a16a06 1036 "*Number of zebra stripe lines.
06fb6aab 1037See also documentation for `ps-zebra-stripes'."
87a16a06
RS
1038 :type 'number
1039 :group 'ps-print)
1040
1041(defcustom ps-line-number nil
1042 "*Non-nil means print line number."
1043 :type 'boolean
1044 :group 'ps-print)
1045
1046(defcustom ps-print-background-image nil
1047 "*EPS image list to be printed on background.
1048
1049The elements are:
1050
1051 (FILENAME X Y XSCALE YSCALE ROTATION PAGES...)
1052
1053FILENAME is a file name which contains an EPS image or some PostScript
1054programming like EPS.
1055FILENAME is ignored, if it doesn't exist or is read protected.
1056
1057X and Y are relative positions on paper to put the image.
1058If X and Y are nil, the image is centralized on paper.
1059
1060XSCALE and YSCALE are scale factor to be applied to image before printing.
1061If XSCALE and YSCALE are nil, the original size is used.
1062
1063ROTATION is the image rotation angle; if nil, the default is 0.
1064
1065PAGES designates the page to print background image.
1066PAGES may be a number or a cons cell (FROM . TO) designating FROM page
1067to TO page.
1068If PAGES is nil, print background image on all pages.
1069
1070X, Y, XSCALE, YSCALE and ROTATION may be a floating point number,
1071an integer number or a string. If it is a string, the string should contain
1072PostScript programming that returns a float or integer value.
1073
1074For example, if you wish to print an EPS image on all pages do:
1075
1076 '((\"~/images/EPS-image.ps\"))"
35378a09
KH
1077 :type '(repeat (list file
1078 (choice :tag "X" number string (const nil))
1079 (choice :tag "Y" number string (const nil))
1080 (choice :tag "X Scale" number string (const nil))
1081 (choice :tag "Y Scale" number string (const nil))
1082 (choice :tag "Rotation" number string (const nil))
1083 (repeat :tag "Pages" :inline t
1084 (radio integer
1085 (cons :tag "Range"
1086 (integer :tag "From")
1087 (integer :tag "To"))))))
87a16a06
RS
1088 :group 'ps-print)
1089
1090(defcustom ps-print-background-text nil
1091 "*Text list to be printed on background.
1092
1093The elements are:
1094
1095 (STRING X Y FONT FONTSIZE GRAY ROTATION PAGES...)
1096
1097STRING is the text to be printed on background.
1098
1099X and Y are positions on paper to put the text.
1100If X and Y are nil, the text is positioned at lower left corner.
1101
1102FONT is a font name to be used on printing the text.
1103If nil, \"Times-Roman\" is used.
1104
1105FONTSIZE is font size to be used, if nil, 200 is used.
1106
1107GRAY is the text gray factor (should be very light like 0.8).
1108If nil, the default is 0.85.
1109
1110ROTATION is the text rotation angle; if nil, the angle is given by
1111the diagonal from lower left corner to upper right corner.
1112
1113PAGES designates the page to print background text.
1114PAGES may be a number or a cons cell (FROM . TO) designating FROM page
1115to TO page.
1116If PAGES is nil, print background text on all pages.
1117
1118X, Y, FONTSIZE, GRAY and ROTATION may be a floating point number,
1119an integer number or a string. If it is a string, the string should contain
1120PostScript programming that returns a float or integer value.
1121
1122For example, if you wish to print text \"Preliminary\" on all pages do:
1123
1124 '((\"Preliminary\"))"
35378a09
KH
1125 :type '(repeat (list string
1126 (choice :tag "X" number string (const nil))
1127 (choice :tag "Y" number string (const nil))
1128 (choice :tag "Font" string (const nil))
1129 (choice :tag "Fontsize" number string (const nil))
1130 (choice :tag "Gray" number string (const nil))
1131 (choice :tag "Rotation" number string (const nil))
1132 (repeat :tag "Pages" :inline t
1133 (radio integer
1134 (cons :tag "Range"
1135 (integer :tag "From")
1136 (integer :tag "To"))))))
e0af0d3e 1137 :group 'ps-print)
bcc0d457
RS
1138
1139;;; Horizontal layout
1140
1141;; ------------------------------------------
1142;; | | | | | | | |
1143;; | lm | text | ic | text | ic | text | rm |
1144;; | | | | | | | |
1145;; ------------------------------------------
1146
e0af0d3e
RS
1147(defcustom ps-left-margin (/ (* 72 2.0) 2.54) ; 2 cm
1148 "*Left margin in points (1/72 inch)."
1149 :type 'number
1150 :group 'ps-print-horizontal)
bcc0d457 1151
e0af0d3e
RS
1152(defcustom ps-right-margin (/ (* 72 2.0) 2.54) ; 2 cm
1153 "*Right margin in points (1/72 inch)."
1154 :type 'number
1155 :group 'ps-print-horizontal)
bcc0d457 1156
e0af0d3e
RS
1157(defcustom ps-inter-column (/ (* 72 2.0) 2.54) ; 2 cm
1158 "*Horizontal space between columns in points (1/72 inch)."
1159 :type 'number
1160 :group 'ps-print-horizontal)
bcc0d457
RS
1161
1162;;; Vertical layout
1163
1164;; |--------|
1165;; | tm |
1166;; |--------|
1167;; | header |
1168;; |--------|
1169;; | ho |
1170;; |--------|
1171;; | text |
1172;; |--------|
1173;; | bm |
1174;; |--------|
1175
e0af0d3e
RS
1176(defcustom ps-bottom-margin (/ (* 72 1.5) 2.54) ; 1.5 cm
1177 "*Bottom margin in points (1/72 inch)."
1178 :type 'number
1179 :group 'ps-print-vertical)
bcc0d457 1180
e0af0d3e
RS
1181(defcustom ps-top-margin (/ (* 72 1.5) 2.54) ; 1.5 cm
1182 "*Top margin in points (1/72 inch)."
1183 :type 'number
1184 :group 'ps-print-vertical)
bcc0d457 1185
e0af0d3e
RS
1186(defcustom ps-header-offset (/ (* 72 1.0) 2.54) ; 1.0 cm
1187 "*Vertical space in points (1/72 inch) between the main text and the header."
1188 :type 'number
1189 :group 'ps-print-vertical)
bcc0d457 1190
e0af0d3e 1191(defcustom ps-header-line-pad 0.15
bcc0d457 1192 "*Portion of a header title line height to insert between the header frame
e0af0d3e
RS
1193and the text it contains, both in the vertical and horizontal directions."
1194 :type 'number
1195 :group 'ps-print-vertical)
bcc0d457
RS
1196
1197;;; Header setup
12d89a2e 1198
e0af0d3e 1199(defcustom ps-print-header t
86c10ecb
RS
1200 "*Non-nil means print a header at the top of each page.
1201By default, the header displays the buffer name, page number, and, if
1202the buffer is visiting a file, the file's directory. Headers are
ae7f6761 1203customizable by changing variables `ps-left-header' and
e0af0d3e
RS
1204`ps-right-header'."
1205 :type 'boolean
1206 :group 'ps-print-header)
1207
12b88fff
RS
1208(defcustom ps-print-only-one-header nil
1209 "*Non-nil means print only one header at the top of each page.
1210This is useful when printing more than one column, so it is possible
1211to have only one header over all columns or one header per column.
1212See also `ps-print-header'."
1213 :type 'boolean
1214 :group 'ps-print-header)
1215
e0af0d3e
RS
1216(defcustom ps-print-header-frame t
1217 "*Non-nil means draw a gaudy frame around the header."
1218 :type 'boolean
1219 :group 'ps-print-header)
1220
1221(defcustom ps-header-lines 2
8bd22fcf 1222 "*Number of lines to display in page header, when generating PostScript."
e0af0d3e
RS
1223 :type 'integer
1224 :group 'ps-print-header)
bcc0d457
RS
1225(make-variable-buffer-local 'ps-header-lines)
1226
e0af0d3e 1227(defcustom ps-show-n-of-n t
00aa16af 1228 "*Non-nil means show page numbers as N/M, meaning page N of M.
8bd22fcf
KH
1229NOTE: page numbers are displayed as part of headers,
1230 see variable `ps-print-headers'."
e0af0d3e
RS
1231 :type 'boolean
1232 :group 'ps-print-header)
12d89a2e 1233
e0af0d3e 1234(defcustom ps-spool-duplex nil ; Not many people have duplex
bcc0d457
RS
1235 ; printers, so default to nil.
1236 "*Non-nil indicates spooling is for a two-sided printer.
1237For a duplex printer, the `ps-spool-*' commands will insert blank pages
1238as needed between print jobs so that the next buffer printed will
1239start on the right page. Also, if headers are turned on, the headers
1240will be reversed on duplex printers so that the page numbers fall to
e0af0d3e
RS
1241the left on even-numbered pages."
1242 :type 'boolean
1243 :group 'ps-print-header)
bcc0d457
RS
1244
1245;;; Fonts
1246
e0af0d3e 1247(defcustom ps-font-info-database
bcc0d457 1248 '((Courier ; the family key
12b88fff
RS
1249 (fonts (normal . "Courier")
1250 (bold . "Courier-Bold")
1251 (italic . "Courier-Oblique")
1252 (bold-italic . "Courier-BoldOblique"))
1253 (size . 10.0)
1254 (line-height . 10.55)
1255 (space-width . 6.0)
1256 (avg-char-width . 6.0))
bcc0d457 1257 (Helvetica ; the family key
12b88fff
RS
1258 (fonts (normal . "Helvetica")
1259 (bold . "Helvetica-Bold")
1260 (italic . "Helvetica-Oblique")
1261 (bold-italic . "Helvetica-BoldOblique"))
1262 (size . 10.0)
1263 (line-height . 11.56)
1264 (space-width . 2.78)
1265 (avg-char-width . 5.09243))
bcc0d457 1266 (Times
12b88fff
RS
1267 (fonts (normal . "Times-Roman")
1268 (bold . "Times-Bold")
1269 (italic . "Times-Italic")
1270 (bold-italic . "Times-BoldItalic"))
1271 (size . 10.0)
1272 (line-height . 11.0)
1273 (space-width . 2.5)
1274 (avg-char-width 4.71432))
bcc0d457 1275 (Palatino
12b88fff
RS
1276 (fonts (normal . "Palatino-Roman")
1277 (bold . "Palatino-Bold")
1278 (italic . "Palatino-Italic")
1279 (bold-italic . "Palatino-BoldItalic"))
1280 (size . 10.0)
1281 (line-height . 12.1)
1282 (space-width . 2.5)
1283 (avg-char-width . 5.08676))
bcc0d457 1284 (Helvetica-Narrow
12b88fff
RS
1285 (fonts (normal . "Helvetica-Narrow")
1286 (bold . "Helvetica-Narrow-Bold")
1287 (italic . "Helvetica-Narrow-Oblique")
1288 (bold-italic . "Helvetica-Narrow-BoldOblique"))
1289 (size . 10.0)
1290 (line-height . 11.56)
1291 (space-width . 2.2796)
1292 (avg-char-width . 4.17579))
bcc0d457 1293 (NewCenturySchlbk
12b88fff
RS
1294 (fonts (normal . "NewCenturySchlbk-Roman")
1295 (bold . "NewCenturySchlbk-Bold")
1296 (italic . "NewCenturySchlbk-Italic")
1297 (bold-italic . "NewCenturySchlbk-BoldItalic"))
1298 (size . 10.0)
1299 (line-height 12.15)
1300 (space-width . 2.78)
1301 (avg-char-width . 5.31162))
bcc0d457
RS
1302 ;; got no bold for the next ones
1303 (AvantGarde-Book
12b88fff
RS
1304 (fonts (normal . "AvantGarde-Book")
1305 (italic . "AvantGarde-BookOblique"))
1306 (size . 10.0)
1307 (line-height . 11.77)
1308 (space-width . 2.77)
1309 (avg-char-width . 5.45189))
bcc0d457 1310 (AvantGarde-Demi
12b88fff
RS
1311 (fonts (normal . "AvantGarde-Demi")
1312 (italic . "AvantGarde-DemiOblique"))
1313 (size . 10.0)
1314 (line-height . 12.72)
1315 (space-width . 2.8)
1316 (avg-char-width . 5.51351))
bcc0d457 1317 (Bookman-Demi
12b88fff
RS
1318 (fonts (normal . "Bookman-Demi")
1319 (italic . "Bookman-DemiItalic"))
1320 (size . 10.0)
1321 (line-height . 11.77)
1322 (space-width . 3.4)
1323 (avg-char-width . 6.05946))
bcc0d457 1324 (Bookman-Light
12b88fff
RS
1325 (fonts (normal . "Bookman-Light")
1326 (italic . "Bookman-LightItalic"))
1327 (size . 10.0)
1328 (line-height . 11.79)
1329 (space-width . 3.2)
1330 (avg-char-width . 5.67027))
bcc0d457
RS
1331 ;; got no bold and no italic for the next ones
1332 (Symbol
12b88fff
RS
1333 (fonts (normal . "Symbol"))
1334 (size . 10.0)
1335 (line-height . 13.03)
1336 (space-width . 2.5)
1337 (avg-char-width . 3.24324))
bcc0d457 1338 (Zapf-Dingbats
12b88fff
RS
1339 (fonts (normal . "Zapf-Dingbats"))
1340 (size . 10.0)
1341 (line-height . 9.63)
1342 (space-width . 2.78)
1343 (avg-char-width . 2.78))
bcc0d457 1344 (Zapf-Chancery-MediumItalic
12b88fff
RS
1345 (fonts (normal . "Zapf-Chancery-MediumItalic"))
1346 (size . 10.0)
1347 (line-height . 11.45)
1348 (space-width . 2.2)
1349 (avg-char-width . 4.10811))
87a16a06 1350 )
bcc0d457
RS
1351 "*Font info database: font family (the key), name, bold, italic, bold-italic,
1352reference size, line height, space width, average character width.
1353To get the info for another specific font (say Helvetica), do the following:
1354- create a new buffer
1355- generate the PostScript image to a file (C-u M-x ps-print-buffer)
8bd22fcf 1356- open this file and delete the leading `%' (which is the PostScript
bcc0d457 1357 comment character) from the line
87a16a06 1358 `% 3 cm 20 cm moveto 10 /Courier ReportFontInfo showpage'
bcc0d457 1359 to get the line
87a16a06 1360 `3 cm 20 cm moveto 10 /Helvetica ReportFontInfo showpage'
bcc0d457 1361- add the values to `ps-font-info-database'.
e0af0d3e
RS
1362You can get all the fonts of YOUR printer using `ReportAllFontInfo'."
1363 :type '(repeat (list :tag "Font Definition"
12b88fff
RS
1364 (symbol :tag "Font Family")
1365 (cons (const fonts)
1366 (repeat (cons (choice (const normal)
1367 (const bold)
1368 (const italic)
1369 (const bold-italic)
1370 (symbol :tag "Face"))
1371 (string :tag "Font Name"))))
1372 (cons (const size)
1373 (number :tag "Reference Size"))
1374 (cons (const line-height)
1375 (number :tag "Line Height"))
1376 (cons (const space-width)
1377 (number :tag "Space Width"))
1378 (cons (const avg-char-width)
1379 (number :tag "Average Character Width"))))
e0af0d3e
RS
1380 :group 'ps-print-font)
1381
1382(defcustom ps-font-family 'Courier
8bd22fcf 1383 "Font family name for ordinary text, when generating PostScript."
e0af0d3e
RS
1384 :type 'symbol
1385 :group 'ps-print-font)
1386
1387(defcustom ps-font-size (if ps-landscape-mode 7 8.5)
8bd22fcf 1388 "Font size, in points, for ordinary text, when generating PostScript."
e0af0d3e
RS
1389 :type 'number
1390 :group 'ps-print-font)
1391
1392(defcustom ps-header-font-family 'Helvetica
8bd22fcf 1393 "Font family name for text in the header, when generating PostScript."
e0af0d3e
RS
1394 :type 'symbol
1395 :group 'ps-print-font)
1396
1397(defcustom ps-header-font-size (if ps-landscape-mode 10 12)
8bd22fcf 1398 "Font size, in points, for text in the header, when generating PostScript."
e0af0d3e
RS
1399 :type 'number
1400 :group 'ps-print-font)
1401
1402(defcustom ps-header-title-font-size (if ps-landscape-mode 12 14)
496725ad 1403 "Font size, in points, for the top line of text in header, in PostScript."
e0af0d3e
RS
1404 :type 'number
1405 :group 'ps-print-font)
bcc0d457
RS
1406
1407;;; Colors
1408
87a16a06
RS
1409;; Printing color requires x-color-values.
1410(defcustom ps-print-color-p (or (fboundp 'x-color-values) ; Emacs
857686a6
RS
1411 (fboundp 'color-instance-rgb-components))
1412 ; XEmacs
e0af0d3e
RS
1413 "*If non-nil, print the buffer's text in color."
1414 :type 'boolean
1415 :group 'ps-print-color)
12d89a2e 1416
e0af0d3e
RS
1417(defcustom ps-default-fg '(0.0 0.0 0.0)
1418 "*RGB values of the default foreground color. Defaults to black."
1419 :type '(list (number :tag "Red") (number :tag "Green") (number :tag "Blue"))
1420 :group 'ps-print-color)
12d89a2e 1421
e0af0d3e
RS
1422(defcustom ps-default-bg '(1.0 1.0 1.0)
1423 "*RGB values of the default background color. Defaults to white."
1424 :type '(list (number :tag "Red") (number :tag "Green") (number :tag "Blue"))
1425 :group 'ps-print-color)
12d89a2e 1426
e0af0d3e 1427(defcustom ps-auto-font-detect t
12d89a2e 1428 "*Non-nil means automatically detect bold/italic face attributes.
7f72c06f 1429If nil, we rely solely on the lists `ps-bold-faces', `ps-italic-faces',
e0af0d3e
RS
1430and `ps-underlined-faces'."
1431 :type 'boolean
1432 :group 'ps-print-font)
12d89a2e 1433
e0af0d3e 1434(defcustom ps-bold-faces
090be653
RS
1435 (unless ps-print-color-p
1436 '(font-lock-function-name-face
1437 font-lock-builtin-face
1438 font-lock-variable-name-face
1439 font-lock-keyword-face
1440 font-lock-warning-face))
86c10ecb 1441 "*A list of the \(non-bold\) faces that should be printed in bold font.
8bd22fcf 1442This applies to generating PostScript."
e0af0d3e
RS
1443 :type '(repeat face)
1444 :group 'ps-print-face)
12d89a2e 1445
e0af0d3e 1446(defcustom ps-italic-faces
090be653
RS
1447 (unless ps-print-color-p
1448 '(font-lock-variable-name-face
8bd22fcf 1449 font-lock-type-face
090be653
RS
1450 font-lock-string-face
1451 font-lock-comment-face
1452 font-lock-warning-face))
86c10ecb 1453 "*A list of the \(non-italic\) faces that should be printed in italic font.
8bd22fcf 1454This applies to generating PostScript."
e0af0d3e
RS
1455 :type '(repeat face)
1456 :group 'ps-print-face)
12d89a2e 1457
e0af0d3e 1458(defcustom ps-underlined-faces
090be653
RS
1459 (unless ps-print-color-p
1460 '(font-lock-function-name-face
883212ce 1461 font-lock-constant-face
090be653 1462 font-lock-warning-face))
86c10ecb 1463 "*A list of the \(non-underlined\) faces that should be printed underlined.
8bd22fcf 1464This applies to generating PostScript."
e0af0d3e
RS
1465 :type '(repeat face)
1466 :group 'ps-print-face)
12d89a2e 1467
e0af0d3e 1468(defcustom ps-left-header
12d89a2e 1469 (list 'ps-get-buffer-name 'ps-header-dirpart)
bcc0d457 1470 "*The items to display (each on a line) on the left part of the page header.
8bd22fcf 1471This applies to generating PostScript.
12d89a2e 1472
86c10ecb 1473The value should be a list of strings and symbols, each representing an
12d89a2e
RS
1474entry in the PostScript array HeaderLinesLeft.
1475
1476Strings are inserted unchanged into the array; those representing
1477PostScript string literals should be delimited with PostScript string
1478delimiters '(' and ')'.
1479
1480For symbols with bound functions, the function is called and should
1481return a string to be inserted into the array. For symbols with bound
1482values, the value should be a string to be inserted into the array.
1483In either case, function or variable, the string value has PostScript
e0af0d3e
RS
1484string delimiters added to it."
1485 :type '(repeat (choice string symbol))
a6c6e755 1486 :group 'ps-print-header)
12d89a2e
RS
1487(make-variable-buffer-local 'ps-left-header)
1488
e0af0d3e 1489(defcustom ps-right-header
090be653 1490 (list "/pagenumberstring load" 'time-stamp-mon-dd-yyyy 'time-stamp-hh:mm:ss)
bcc0d457 1491 "*The items to display (each on a line) on the right part of the page header.
8bd22fcf 1492This applies to generating PostScript.
12d89a2e 1493
86c10ecb 1494See the variable `ps-left-header' for a description of the format of
e0af0d3e
RS
1495this variable."
1496 :type '(repeat (choice string symbol))
a6c6e755 1497 :group 'ps-print-header)
12d89a2e 1498(make-variable-buffer-local 'ps-right-header)
ef2cbb24 1499
e0af0d3e
RS
1500(defcustom ps-razzle-dazzle t
1501 "*Non-nil means report progress while formatting buffer."
1502 :type 'boolean
1503 :group 'ps-print)
12d89a2e 1504
a18ed129 1505(defcustom ps-adobe-tag "%!PS-Adobe-3.0\n"
12d89a2e
RS
1506 "*Contains the header line identifying the output as PostScript.
1507By default, `ps-adobe-tag' contains the standard identifier. Some
a18ed129
RS
1508printers require slightly different versions of this line."
1509 :type 'string
1510 :group 'ps-print)
12d89a2e 1511
e0af0d3e 1512(defcustom ps-build-face-reference t
12d89a2e
RS
1513 "*Non-nil means build the reference face lists.
1514
1515Ps-print sets this value to nil after it builds its internal reference
1516lists of bold and italic faces. By settings its value back to t, you
1517can force ps-print to rebuild the lists the next time you invoke one
86c10ecb 1518of the ...-with-faces commands.
12d89a2e
RS
1519
1520You should set this value back to t after you change the attributes of
1521any face, or create new faces. Most users shouldn't have to worry
e0af0d3e
RS
1522about its setting, though."
1523 :type 'boolean
1524 :group 'ps-print-face)
12d89a2e 1525
e0af0d3e 1526(defcustom ps-always-build-face-reference nil
12d89a2e
RS
1527 "*Non-nil means always rebuild the reference face lists.
1528
1529If this variable is non-nil, ps-print will rebuild its internal
1530reference lists of bold and italic faces *every* time one of the
496725ad 1531...-with-faces commands is called. Most users shouldn't need to set this
e0af0d3e
RS
1532variable."
1533 :type 'boolean
1534 :group 'ps-print-face)
ef2cbb24
RS
1535
1536;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
12d89a2e 1537;; User commands
ef2cbb24 1538
00aa16af 1539;;;###autoload
ef2cbb24 1540(defun ps-print-buffer (&optional filename)
12d89a2e 1541 "Generate and print a PostScript image of the buffer.
ef2cbb24 1542
86c10ecb 1543When called with a numeric prefix argument (C-u), prompts the user for
ef2cbb24
RS
1544the name of a file to save the PostScript image in, instead of sending
1545it to the printer.
1546
1547More specifically, the FILENAME argument is treated as follows: if it
1548is nil, send the image to the printer. If FILENAME is a string, save
1549the PostScript image in a file with that name. If FILENAME is a
12d89a2e 1550number, prompt the user for the name of the file to save in."
00aa16af 1551 (interactive (list (ps-print-preprint current-prefix-arg)))
87a16a06 1552 (ps-print-without-faces (point-min) (point-max) filename))
ef2cbb24
RS
1553
1554
00aa16af 1555;;;###autoload
ef2cbb24 1556(defun ps-print-buffer-with-faces (&optional filename)
12d89a2e 1557 "Generate and print a PostScript image of the buffer.
12d89a2e 1558Like `ps-print-buffer', but includes font, color, and underline
107e7c70
KH
1559information in the generated image. This command works only if you
1560are using a window system, so it has a way to determine color values."
00aa16af 1561 (interactive (list (ps-print-preprint current-prefix-arg)))
87a16a06 1562 (ps-print-with-faces (point-min) (point-max) filename))
ef2cbb24 1563
ef2cbb24 1564
00aa16af 1565;;;###autoload
ef2cbb24 1566(defun ps-print-region (from to &optional filename)
12d89a2e 1567 "Generate and print a PostScript image of the region.
12d89a2e 1568Like `ps-print-buffer', but prints just the current region."
00aa16af 1569 (interactive (list (point) (mark) (ps-print-preprint current-prefix-arg)))
a18ed129 1570 (ps-print-without-faces from to filename t))
ef2cbb24 1571
ef2cbb24 1572
00aa16af 1573;;;###autoload
ef2cbb24 1574(defun ps-print-region-with-faces (from to &optional filename)
12d89a2e 1575 "Generate and print a PostScript image of the region.
12d89a2e 1576Like `ps-print-region', but includes font, color, and underline
107e7c70
KH
1577information in the generated image. This command works only if you
1578are using a window system, so it has a way to determine color values."
00aa16af 1579 (interactive (list (point) (mark) (ps-print-preprint current-prefix-arg)))
a18ed129 1580 (ps-print-with-faces from to filename t))
ef2cbb24 1581
ef2cbb24 1582
00aa16af 1583;;;###autoload
ef2cbb24 1584(defun ps-spool-buffer ()
12d89a2e 1585 "Generate and spool a PostScript image of the buffer.
12d89a2e
RS
1586Like `ps-print-buffer' except that the PostScript image is saved in a
1587local buffer to be sent to the printer later.
ef2cbb24 1588
12d89a2e 1589Use the command `ps-despool' to send the spooled images to the printer."
ef2cbb24 1590 (interactive)
87a16a06 1591 (ps-spool-without-faces (point-min) (point-max)))
ef2cbb24 1592
ef2cbb24 1593
00aa16af 1594;;;###autoload
ef2cbb24 1595(defun ps-spool-buffer-with-faces ()
12d89a2e 1596 "Generate and spool a PostScript image of the buffer.
12d89a2e 1597Like `ps-spool-buffer', but includes font, color, and underline
107e7c70 1598information in the generated image. This command works only if you
1cd7962f 1599are using a window system, so it has a way to determine color values.
ef2cbb24 1600
12d89a2e 1601Use the command `ps-despool' to send the spooled images to the printer."
ef2cbb24 1602 (interactive)
87a16a06 1603 (ps-spool-with-faces (point-min) (point-max)))
ef2cbb24 1604
ef2cbb24 1605
00aa16af 1606;;;###autoload
ef2cbb24 1607(defun ps-spool-region (from to)
12d89a2e 1608 "Generate a PostScript image of the region and spool locally.
12d89a2e 1609Like `ps-spool-buffer', but spools just the current region.
ef2cbb24 1610
12d89a2e 1611Use the command `ps-despool' to send the spooled images to the printer."
ef2cbb24 1612 (interactive "r")
a18ed129 1613 (ps-spool-without-faces from to t))
ef2cbb24 1614
ef2cbb24 1615
00aa16af 1616;;;###autoload
ef2cbb24 1617(defun ps-spool-region-with-faces (from to)
12d89a2e 1618 "Generate a PostScript image of the region and spool locally.
12d89a2e 1619Like `ps-spool-region', but includes font, color, and underline
107e7c70 1620information in the generated image. This command works only if you
1cd7962f 1621are using a window system, so it has a way to determine color values.
ef2cbb24 1622
12d89a2e 1623Use the command `ps-despool' to send the spooled images to the printer."
ef2cbb24 1624 (interactive "r")
a18ed129 1625 (ps-spool-with-faces from to t))
ef2cbb24 1626
00aa16af 1627;;;###autoload
ef2cbb24
RS
1628(defun ps-despool (&optional filename)
1629 "Send the spooled PostScript to the printer.
1630
1631When called with a numeric prefix argument (C-u), prompt the user for
1632the name of a file to save the spooled PostScript in, instead of sending
1633it to the printer.
1634
1635More specifically, the FILENAME argument is treated as follows: if it
1636is nil, send the image to the printer. If FILENAME is a string, save
1637the PostScript image in a file with that name. If FILENAME is a
1638number, prompt the user for the name of the file to save in."
00aa16af
RS
1639 (interactive (list (ps-print-preprint current-prefix-arg)))
1640 (ps-do-despool filename))
12d89a2e 1641
bcc0d457
RS
1642;;;###autoload
1643(defun ps-line-lengths ()
06fb6aab 1644 "Display the correspondence between a line length and a font size,
bcc0d457
RS
1645using the current ps-print setup.
1646Try: pr -t file | awk '{printf \"%3d %s\n\", length($0), $0}' | sort -r | head"
1647 (interactive)
1648 (ps-line-lengths-internal))
1649
1650;;;###autoload
1651(defun ps-nb-pages-buffer (nb-lines)
06fb6aab
RS
1652 "Display number of pages to print this buffer, for various font heights.
1653The table depends on the current ps-print setup."
bcc0d457
RS
1654 (interactive (list (count-lines (point-min) (point-max))))
1655 (ps-nb-pages nb-lines))
1656
1657;;;###autoload
1658(defun ps-nb-pages-region (nb-lines)
06fb6aab
RS
1659 "Display number of pages to print the region, for various font heights.
1660The table depends on the current ps-print setup."
bcc0d457
RS
1661 (interactive (list (count-lines (mark) (point))))
1662 (ps-nb-pages nb-lines))
1663
1664;;;###autoload
1665(defun ps-setup ()
496725ad 1666 "Return the current PostScript-generation setup."
a18ed129
RS
1667 (format
1668 "
1669\(setq ps-print-color-p %s
bcc0d457
RS
1670 ps-lpr-command \"%s\"
1671 ps-lpr-switches %s
1672
8bd22fcf
KH
1673 ps-paper-type '%s
1674 ps-landscape-mode %s
1675 ps-number-of-columns %s
bcc0d457 1676
8bd22fcf 1677 ps-zebra-stripes %s
01961237 1678 ps-zebra-stripe-height %s
8bd22fcf 1679 ps-line-number %s
a18ed129 1680
857686a6
RS
1681 ps-print-control-characters %s
1682
a18ed129
RS
1683 ps-print-background-image %s
1684
1685 ps-print-background-text %s
1686
1687 ps-left-margin %s
1688 ps-right-margin %s
1689 ps-inter-column %s
1690 ps-bottom-margin %s
1691 ps-top-margin %s
1692 ps-header-offset %s
bcc0d457
RS
1693 ps-header-line-pad %s
1694 ps-print-header %s
1695 ps-print-header-frame %s
1696 ps-header-lines %s
1697 ps-show-n-of-n %s
1698 ps-spool-duplex %s
1699
a18ed129
RS
1700 ps-font-family '%s
1701 ps-font-size %s
1702 ps-header-font-family '%s
1703 ps-header-font-size %s
1704 ps-header-title-font-size %s)
bcc0d457 1705"
a18ed129
RS
1706 ps-print-color-p
1707 ps-lpr-command
1708 ps-lpr-switches
1709 ps-paper-type
1710 ps-landscape-mode
1711 ps-number-of-columns
01961237
RS
1712 ps-zebra-stripes
1713 ps-zebra-stripe-height
a18ed129 1714 ps-line-number
857686a6 1715 ps-print-control-characters
a18ed129
RS
1716 ps-print-background-image
1717 ps-print-background-text
1718 ps-left-margin
1719 ps-right-margin
1720 ps-inter-column
1721 ps-bottom-margin
1722 ps-top-margin
1723 ps-header-offset
1724 ps-header-line-pad
1725 ps-print-header
1726 ps-print-header-frame
1727 ps-header-lines
1728 ps-show-n-of-n
1729 ps-spool-duplex
1730 ps-font-family
1731 ps-font-size
1732 ps-header-font-family
1733 ps-header-font-size
1734 ps-header-title-font-size))
bcc0d457 1735
12d89a2e
RS
1736;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1737;; Utility functions and variables:
1738
6770a60f
RS
1739(defvar ps-print-emacs-type
1740 (cond ((string-match "XEmacs" emacs-version) 'xemacs)
1741 ((string-match "Lucid" emacs-version) 'lucid)
1742 ((string-match "Epoch" emacs-version) 'epoch)
1743 (t 'emacs)))
1744
1745(if (or (eq ps-print-emacs-type 'lucid)
1746 (eq ps-print-emacs-type 'xemacs))
043620f4
KH
1747 (if (< emacs-minor-version 12)
1748 (setq ps-print-color-p nil))
12d89a2e
RS
1749 (require 'faces)) ; face-font, face-underline-p,
1750 ; x-font-regexp
1751
857686a6
RS
1752;; Return t if the device (which can be changed during an emacs session)
1753;; can handle colors.
1754;; This is function is not yet implemented for GNU emacs.
1755(defun ps-color-device ()
1756 (if (and (eq ps-print-emacs-type 'xemacs)
1757 (>= emacs-minor-version 12))
1758 (eq (device-class) 'color)
1759 t))
1760
12d89a2e
RS
1761(require 'time-stamp)
1762
bcc0d457
RS
1763(defvar ps-print-prologue-1
1764 "% ISOLatin1Encoding stolen from ps_init.ps in GhostScript 2.6.1.4:
12d89a2e 1765/ISOLatin1Encoding where { pop } {
bcc0d457
RS
1766% -- The ISO Latin-1 encoding vector isn't known, so define it.
1767% -- The first half is the same as the standard encoding,
1768% -- except for minus instead of hyphen at code 055.
12d89a2e
RS
1769/ISOLatin1Encoding
1770StandardEncoding 0 45 getinterval aload pop
1771 /minus
1772StandardEncoding 46 82 getinterval aload pop
1773%*** NOTE: the following are missing in the Adobe documentation,
1774%*** but appear in the displayed table:
1775%*** macron at 0225, dieresis at 0230, cedilla at 0233, space at 0240.
bcc0d457 1776% 0200 (128)
12d89a2e
RS
1777 /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
1778 /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
1779 /dotlessi /grave /acute /circumflex /tilde /macron /breve /dotaccent
1780 /dieresis /.notdef /ring /cedilla /.notdef /hungarumlaut /ogonek /caron
bcc0d457 1781% 0240 (160)
12d89a2e
RS
1782 /space /exclamdown /cent /sterling
1783 /currency /yen /brokenbar /section
1784 /dieresis /copyright /ordfeminine /guillemotleft
1785 /logicalnot /hyphen /registered /macron
1786 /degree /plusminus /twosuperior /threesuperior
1787 /acute /mu /paragraph /periodcentered
1788 /cedilla /onesuperior /ordmasculine /guillemotright
1789 /onequarter /onehalf /threequarters /questiondown
bcc0d457 1790% 0300 (192)
12d89a2e
RS
1791 /Agrave /Aacute /Acircumflex /Atilde
1792 /Adieresis /Aring /AE /Ccedilla
1793 /Egrave /Eacute /Ecircumflex /Edieresis
1794 /Igrave /Iacute /Icircumflex /Idieresis
1795 /Eth /Ntilde /Ograve /Oacute
1796 /Ocircumflex /Otilde /Odieresis /multiply
1797 /Oslash /Ugrave /Uacute /Ucircumflex
1798 /Udieresis /Yacute /Thorn /germandbls
bcc0d457 1799% 0340 (224)
12d89a2e
RS
1800 /agrave /aacute /acircumflex /atilde
1801 /adieresis /aring /ae /ccedilla
1802 /egrave /eacute /ecircumflex /edieresis
1803 /igrave /iacute /icircumflex /idieresis
1804 /eth /ntilde /ograve /oacute
1805 /ocircumflex /otilde /odieresis /divide
1806 /oslash /ugrave /uacute /ucircumflex
1807 /udieresis /yacute /thorn /ydieresis
1808256 packedarray def
1809} ifelse
1810
1811/reencodeFontISO { %def
1812 dup
87a16a06 1813 length 12 add dict % Make a new font (a new dict the same size
bcc0d457 1814 % as the old one) with room for our new symbols.
12d89a2e 1815
bcc0d457 1816 begin % Make the new font the current dictionary.
12d89a2e
RS
1817
1818
1819 { 1 index /FID ne
1820 { def } { pop pop } ifelse
bcc0d457
RS
1821 } forall % Copy each of the symbols from the old dictionary
1822 % to the new one except for the font ID.
12d89a2e 1823
12b88fff
RS
1824 currentdict /FontType get 0 ne {
1825 /Encoding ISOLatin1Encoding def % Override the encoding with
12d89a2e 1826 % the ISOLatin1 encoding.
12b88fff 1827 } if
12d89a2e
RS
1828
1829 % Use the font's bounding box to determine the ascent, descent,
1830 % and overall height; don't forget that these values have to be
1831 % transformed using the font's matrix.
bcc0d457
RS
1832
1833% ^ (x2 y2)
1834% | |
1835% | v
1836% | +----+ - -
1837% | | | ^
1838% | | | | Ascent (usually > 0)
1839% | | | |
1840% (0 0) -> +--+----+-------->
1841% | | |
1842% | | v Descent (usually < 0)
1843% (x1 y1) --> +----+ - -
1844
12b88fff
RS
1845 currentdict /FontType get 0 ne {
1846 FontBBox % -- x1 y1 x2 y2
1847 FontMatrix transform /Ascent exch def pop
1848 FontMatrix transform /Descent exch def pop
1849 } {
1850 /PrimaryFont FDepVector 0 get def
1851 PrimaryFont /FontBBox get aload pop
1852 PrimaryFont /FontMatrix get transform /Ascent exch def pop
1853 PrimaryFont /FontMatrix get transform /Descent exch def pop
1854 } ifelse
1855
bcc0d457 1856 /FontHeight Ascent Descent sub def % use `sub' because descent < 0
12d89a2e 1857
bcc0d457 1858 % Define these in case they're not in the FontInfo
87a16a06
RS
1859 % (also, here they're easier to get to).
1860 /UnderlinePosition Descent 0.70 mul def
1861 /OverlinePosition Descent UnderlinePosition sub Ascent add def
1862 /StrikeoutPosition Ascent 0.30 mul def
1863 /LineThickness 0 50 FontMatrix transform exch pop def
1864 /Xshadow 0 80 FontMatrix transform exch pop def
1865 /Yshadow 0 -90 FontMatrix transform exch pop def
1866 /SpaceBackground Descent neg UnderlinePosition add def
1867 /XBox Descent neg def
1868 /YBox LineThickness 0.7 mul def
12d89a2e 1869
bcc0d457
RS
1870 currentdict % Leave the new font on the stack
1871 end % Stop using the font as the current dictionary.
1872 definefont % Put the font into the font dictionary
1873 pop % Discard the returned font.
12d89a2e 1874} bind def
ef2cbb24 1875
bcc0d457 1876/DefFont { % Font definition
12d89a2e
RS
1877 findfont exch scalefont reencodeFontISO
1878} def
1879
bcc0d457 1880/F { % Font selection
12d89a2e 1881 findfont
87a16a06
RS
1882 dup /Ascent get /Ascent exch def
1883 dup /Descent get /Descent exch def
1884 dup /FontHeight get /FontHeight exch def
1885 dup /UnderlinePosition get /UnderlinePosition exch def
1886 dup /OverlinePosition get /OverlinePosition exch def
1887 dup /StrikeoutPosition get /StrikeoutPosition exch def
1888 dup /LineThickness get /LineThickness exch def
1889 dup /Xshadow get /Xshadow exch def
1890 dup /Yshadow get /Yshadow exch def
1891 dup /SpaceBackground get /SpaceBackground exch def
1892 dup /XBox get /XBox exch def
1893 dup /YBox get /YBox exch def
12d89a2e
RS
1894 setfont
1895} def
1896
1897/FG /setrgbcolor load def
1898
1899/bg false def
1900/BG {
1901 dup /bg exch def
87a16a06
RS
1902 {mark 4 1 roll ]}
1903 {[ 1.0 1.0 1.0 ]}
1904 ifelse
1905 /bgcolor exch def
12d89a2e
RS
1906} def
1907
bcc0d457
RS
1908% B width C
1909% +-----------+
1910% | Ascent (usually > 0)
1911% A + +
1912% | Descent (usually < 0)
1913% +-----------+
1914% E width D
1915
12d89a2e 1916/dobackground { % width --
bcc0d457 1917 currentpoint % -- width x y
12d89a2e
RS
1918 gsave
1919 newpath
bcc0d457
RS
1920 moveto % A (x y)
1921 0 Ascent rmoveto % B
1922 dup 0 rlineto % C
1923 0 Descent Ascent sub rlineto % D
1924 neg 0 rlineto % E
12d89a2e
RS
1925 closepath
1926 bgcolor aload pop setrgbcolor
1927 fill
1928 grestore
1929} def
1930
bcc0d457
RS
1931/eolbg { % dobackground until right margin
1932 PrintWidth % -- x-eol
1933 currentpoint pop % -- cur-x
1934 sub % -- width until eol
1935 dobackground
12d89a2e
RS
1936} def
1937
87a16a06 1938/PLN {PrintLineNumber {doLineNumber}if} def
12d89a2e
RS
1939
1940/SL { % Soft Linefeed
1941 bg { eolbg } if
bcc0d457 1942 0 currentpoint exch pop LineHeight sub moveto
12d89a2e
RS
1943} def
1944
87a16a06 1945/HL {SL PLN} def % Hard Linefeed
12d89a2e
RS
1946
1947% Some debug
1948/dcp { currentpoint exch 40 string cvs print (, ) print = } def
87a16a06 1949/dp { print 2 copy exch 40 string cvs print (, ) print = } def
12d89a2e
RS
1950
1951/W {
bcc0d457
RS
1952 ( ) stringwidth % Get the width of a space in the current font.
1953 pop % Discard the Y component.
1954 mul % Multiply the width of a space
1955 % by the number of spaces to plot
12d89a2e
RS
1956 bg { dup dobackground } if
1957 0 rmoveto
87a16a06
RS
1958} def
1959
1960/Effect 0 def
1961/EF {/Effect exch def} def
1962
1963% stack: string |- --
1964% effect: 1 - underline 2 - strikeout 4 - overline
1965% 8 - shadow 16 - box 32 - outline
1966/S {
1967 /xx currentpoint dup Descent add /yy exch def
1968 Ascent add /YY exch def def
1969 dup stringwidth pop xx add /XX exch def
1970 Effect 8 and 0 ne {
1971 /yy yy Yshadow add def
1972 /XX XX Xshadow add def
1973 } if
1974 bg {
1975 true
1976 Effect 16 and 0 ne
1977 {SpaceBackground doBox}
1978 {xx yy XX YY doRect}
1979 ifelse
1980 } if % background
1981 Effect 16 and 0 ne {false 0 doBox}if % box
1982 Effect 8 and 0 ne {dup doShadow}if % shadow
1983 Effect 32 and 0 ne
1984 {true doOutline} % outline
1985 {show} % normal text
1986 ifelse
1987 Effect 1 and 0 ne {UnderlinePosition Hline}if % underline
1988 Effect 2 and 0 ne {StrikeoutPosition Hline}if % strikeout
1989 Effect 4 and 0 ne {OverlinePosition Hline}if % overline
1990} bind def
1991
1992% stack: position |- --
1993/Hline {
1994 currentpoint exch pop add dup
1995 gsave
1996 newpath
1997 xx exch moveto
1998 XX exch lineto
1999 closepath
2000 LineThickness setlinewidth stroke
2001 grestore
2002} bind def
2003
2004% stack: fill-or-not delta |- --
2005/doBox {
2006 /dd exch def
2007 xx XBox sub dd sub yy YBox sub dd sub
2008 XX XBox add dd add YY YBox add dd add
2009 doRect
2010} bind def
2011
2012% stack: fill-or-not lower-x lower-y upper-x upper-y |- --
2013/doRect {
2014 /rYY exch def
2015 /rXX exch def
2016 /ryy exch def
2017 /rxx exch def
2018 gsave
2019 newpath
2020 rXX rYY moveto
2021 rxx rYY lineto
2022 rxx ryy lineto
2023 rXX ryy lineto
2024 closepath
2025 % top of stack: fill-or-not
2026 {FillBgColor}
2027 {LineThickness setlinewidth stroke}
2028 ifelse
2029 grestore
2030} bind def
2031
2032% stack: string |- --
2033/doShadow {
2034 gsave
2035 Xshadow Yshadow rmoveto
2036 false doOutline
2037 grestore
2038} bind def
2039
2040/st 1 string def
2041
2042% stack: string fill-or-not |- --
2043/doOutline {
2044 /-fillp- exch def
2045 /-ox- currentpoint /-oy- exch def def
2046 gsave
2047 LineThickness setlinewidth
2048 {
2049 st 0 3 -1 roll put
2050 st dup true charpath
2051 -fillp- {gsave FillBgColor grestore}if
2052 stroke stringwidth
2053 -oy- add /-oy- exch def
2054 -ox- add /-ox- exch def
2055 -ox- -oy- moveto
2056 } forall
2057 grestore
2058 -ox- -oy- moveto
2059} bind def
2060
2061% stack: --
2062/FillBgColor {bgcolor aload pop setrgbcolor fill} bind def
2063
2064/L0 6 /Times-Italic DefFont
2065
2066% stack: --
2067/doLineNumber {
f68af055
RS
2068 /LineNumber where
2069 {
2070 pop
2071 currentfont
2072 gsave
2073 0.0 0.0 0.0 setrgbcolor
2074 /L0 findfont setfont
2075 LineNumber Lines ge
2076 {(end )}
2077 {LineNumber 6 string cvs ( ) strcat}
2078 ifelse
2079 dup stringwidth pop neg 0 rmoveto
2080 show
2081 grestore
2082 setfont
2083 /LineNumber LineNumber 1 add def
2084 } if
87a16a06
RS
2085} def
2086
2087% stack: --
2088/printZebra {
2089 gsave
2090 0.985 setgray
857686a6 2091 /double-zebra ZebraHeight ZebraHeight add def
87a16a06
RS
2092 /yiter double-zebra LineHeight mul neg def
2093 /xiter PrintWidth InterColumn add def
2094 NumberOfColumns {LinesPerColumn doColumnZebra xiter 0 rmoveto}repeat
2095 grestore
2096} def
2097
2098% stack: lines-per-column |- --
2099/doColumnZebra {
2100 gsave
857686a6 2101 dup double-zebra idiv {ZebraHeight doZebra 0 yiter rmoveto}repeat
87a16a06 2102 double-zebra mod
857686a6 2103 dup 0 le {pop}{dup ZebraHeight gt {pop ZebraHeight}if doZebra}ifelse
87a16a06
RS
2104 grestore
2105} def
2106
2107% stack: zebra-height (in lines) |- --
2108/doZebra {
2109 /zh exch 0.05 sub LineHeight mul def
2110 gsave
2111 0 LineHeight 0.65 mul rmoveto
2112 PrintWidth 0 rlineto
2113 0 zh neg rlineto
2114 PrintWidth neg 0 rlineto
2115 0 zh rlineto
2116 fill
2117 grestore
2118} def
2119
2120% tx ty rotation xscale yscale xpos ypos BeginBackImage
2121/BeginBackImage {
2122 /-save-image- save def
2123 /showpage {}def
2124 translate
2125 scale
2126 rotate
2127 translate
2128} def
2129
2130/EndBackImage {
2131 -save-image- restore
2132} def
2133
2134% string fontsize fontname rotation gray xpos ypos ShowBackText
2135/ShowBackText {
2136 gsave
2137 translate
2138 setgray
2139 rotate
2140 findfont exch dup /-offset- exch -0.25 mul def scalefont setfont
2141 0 -offset- moveto
2142 /-saveLineThickness- LineThickness def
2143 /LineThickness 1 def
2144 false doOutline
2145 /LineThickness -saveLineThickness- def
2146 grestore
12d89a2e
RS
2147} def
2148
bcc0d457
RS
2149/BeginDoc {
2150 % ---- save the state of the document (useful for ghostscript!)
2151 /docState save def
2152 % ---- [jack] Kludge: my ghostscript window is 21x27.7 instead of 21x29.7
2153 /JackGhostscript where {
2154 pop 1 27.7 29.7 div scale
2155 } if
2156 LandscapeMode {
2157 % ---- translate to bottom-right corner of Portrait page
2158 LandscapePageHeight 0 translate
2159 90 rotate
2160 } if
2161 /ColumnWidth PrintWidth InterColumn add def
2162 % ---- translate to lower left corner of TEXT
2163 LeftMargin BottomMargin translate
2164 % ---- define where printing will start
2165 /f0 F % this installs Ascent
2166 /PrintStartY PrintHeight Ascent sub def
2167 /ColumnIndex 1 def
2168} def
2169
2170/EndDoc {
2171 % ---- on last page but not last column, spit out the page
2172 ColumnIndex 1 eq not { showpage } if
2173 % ---- restore the state of the document (useful for ghostscript!)
2174 docState restore
2175} def
2176
12d89a2e 2177/BeginDSCPage {
bcc0d457 2178 % ---- when 1st column, save the state of the page
a18ed129 2179 ColumnIndex 1 eq { /pageState save def } if
bcc0d457
RS
2180 % ---- save the state of the column
2181 /columnState save def
12d89a2e
RS
2182} def
2183
12b88fff
RS
2184/PrintHeaderWidth PrintOnlyOneHeader{PrintPageWidth}{PrintWidth}ifelse def
2185
12d89a2e 2186/BeginPage {
a18ed129
RS
2187 % ---- when 1st column, print all background effects
2188 ColumnIndex 1 eq {
2189 0 PrintStartY moveto % move to where printing will start
2190 Zebra {printZebra}if
2191 printGlobalBackground
2192 printLocalBackground
2193 } if
12d89a2e 2194 PrintHeader {
12b88fff
RS
2195 PrintOnlyOneHeader{ColumnIndex 1 eq}{true}ifelse {
2196 PrintHeaderFrame {HeaderFrame}if
2197 HeaderText
2198 } if
12d89a2e 2199 } if
bcc0d457 2200 0 PrintStartY moveto % move to where printing will start
87a16a06 2201 PLN
12d89a2e
RS
2202} def
2203
2204/EndPage {
2205 bg { eolbg } if
12d89a2e
RS
2206} def
2207
2208/EndDSCPage {
bcc0d457
RS
2209 ColumnIndex NumberOfColumns eq {
2210 % ---- on last column, spit out the page
2211 showpage
2212 % ---- restore the state of the page
2213 pageState restore
2214 /ColumnIndex 1 def
2215 } { % else
2216 % ---- restore the state of the current column
2217 columnState restore
2218 % ---- and translate to the next column
2219 ColumnWidth 0 translate
2220 /ColumnIndex ColumnIndex 1 add def
2221 } ifelse
12d89a2e
RS
2222} def
2223
bcc0d457 2224/SetHeaderLines { % nb-lines --
12d89a2e 2225 /HeaderLines exch def
bcc0d457
RS
2226 % ---- bottom up
2227 HeaderPad
2228 HeaderLines 1 sub HeaderLineHeight mul add
2229 HeaderTitleLineHeight add
2230 HeaderPad add
2231 /HeaderHeight exch def
12d89a2e
RS
2232} def
2233
bcc0d457
RS
2234% |---------|
2235% | tm |
2236% |---------|
2237% | header |
2238% |-+-------| <-- (x y)
2239% | ho |
2240% |---------|
2241% | text |
2242% |-+-------| <-- (0 0)
2243% | bm |
2244% |---------|
2245
2246/HeaderFrameStart { % -- x y
2247 0 PrintHeight HeaderOffset add
12d89a2e
RS
2248} def
2249
2250/HeaderFramePath {
12b88fff
RS
2251 PrintHeaderWidth 0 rlineto
2252 0 HeaderHeight rlineto
2253 PrintHeaderWidth neg 0 rlineto
2254 0 HeaderHeight neg rlineto
12d89a2e
RS
2255} def
2256
2257/HeaderFrame {
2258 gsave
2259 0.4 setlinewidth
bcc0d457 2260 % ---- fill a black rectangle (the shadow of the next one)
12d89a2e
RS
2261 HeaderFrameStart moveto
2262 1 -1 rmoveto
2263 HeaderFramePath
2264 0 setgray fill
bcc0d457 2265 % ---- do the next rectangle ...
12d89a2e
RS
2266 HeaderFrameStart moveto
2267 HeaderFramePath
bcc0d457
RS
2268 gsave 0.9 setgray fill grestore % filled with grey
2269 gsave 0 setgray stroke grestore % drawn with black
12d89a2e
RS
2270 grestore
2271} def
2272
2273/HeaderStart {
2274 HeaderFrameStart
bcc0d457
RS
2275 exch HeaderPad add exch % horizontal pad
2276 % ---- bottom up
2277 HeaderPad add % vertical pad
2278 HeaderDescent sub
2279 HeaderLineHeight HeaderLines 1 sub mul add
12d89a2e
RS
2280} def
2281
2282/strcat {
2283 dup length 3 -1 roll dup length dup 4 -1 roll add string dup
2284 0 5 -1 roll putinterval
2285 dup 4 2 roll exch putinterval
2286} def
2287
2288/pagenumberstring {
2289 PageNumber 32 string cvs
2290 ShowNofN {
2291 (/) strcat
2292 PageCount 32 string cvs strcat
2293 } if
2294} def
2295
2296/HeaderText {
2297 HeaderStart moveto
2298
bcc0d457
RS
2299 HeaderLinesRight HeaderLinesLeft % -- rightLines leftLines
2300
2301 % ---- hack: `PN 1 and' == `PN 2 modulo'
2302
2303 % ---- if duplex and even page number, then exchange left and right
12d89a2e
RS
2304 Duplex PageNumber 1 and 0 eq and { exch } if
2305
bcc0d457 2306 { % ---- process the left lines
12d89a2e
RS
2307 aload pop
2308 exch F
2309 gsave
2310 dup xcheck { exec } if
2311 show
2312 grestore
2313 0 HeaderLineHeight neg rmoveto
2314 } forall
2315
2316 HeaderStart moveto
2317
bcc0d457 2318 { % ---- process the right lines
12d89a2e
RS
2319 aload pop
2320 exch F
2321 gsave
2322 dup xcheck { exec } if
2323 dup stringwidth pop
12b88fff 2324 PrintHeaderWidth exch sub HeaderPad 2 mul sub 0 rmoveto
12d89a2e
RS
2325 show
2326 grestore
2327 0 HeaderLineHeight neg rmoveto
2328 } forall
2329} def
2330
2331/ReportFontInfo {
2332 2 copy
bcc0d457 2333 /t0 3 1 roll DefFont
12d89a2e 2334 /t0 F
00aa16af 2335 /lh FontHeight def
12d89a2e
RS
2336 /sw ( ) stringwidth pop def
2337 /aw (01234567890abcdefghijklmnopqrstuvwxyz) dup length exch
2338 stringwidth pop exch div def
bcc0d457 2339 /t1 12 /Helvetica-Oblique DefFont
12d89a2e 2340 /t1 F
12d89a2e
RS
2341 gsave
2342 (For ) show
2343 128 string cvs show
2344 ( ) show
2345 32 string cvs show
2346 ( point, the line height is ) show
2347 lh 32 string cvs show
2348 (, the space width is ) show
2349 sw 32 string cvs show
2350 (,) show
2351 grestore
00aa16af 2352 0 FontHeight neg rmoveto
bcc0d457
RS
2353 gsave
2354 (and a crude estimate of average character width is ) show
2355 aw 32 string cvs show
2356 (.) show
2357 grestore
2358 0 FontHeight neg rmoveto
2359} def
2360
2361/cm { % cm to point
2362 72 mul 2.54 div
2363} def
2364
2365/ReportAllFontInfo {
2366 FontDirectory
2367 { % key = font name value = font dictionary
2368 pop 10 exch ReportFontInfo
2369 } forall
12d89a2e
RS
2370} def
2371
bcc0d457
RS
2372% 3 cm 20 cm moveto 10 /Courier ReportFontInfo showpage
2373% 3 cm 20 cm moveto ReportAllFontInfo showpage
2374
2375")
2376
2377(defvar ps-print-prologue-2
2378 "
2379% ---- These lines must be kept together because...
2380
2381/h0 F
2382/HeaderTitleLineHeight FontHeight def
2383
2384/h1 F
2385/HeaderLineHeight FontHeight def
2386/HeaderDescent Descent def
2387
2388% ---- ...because `F' has a side-effect on `FontHeight' and `Descent'
2389
12d89a2e
RS
2390")
2391
2392;; Start Editing Here:
ef2cbb24 2393
12d89a2e
RS
2394(defvar ps-source-buffer nil)
2395(defvar ps-spool-buffer-name "*PostScript*")
2396(defvar ps-spool-buffer nil)
ef2cbb24 2397
12d89a2e
RS
2398(defvar ps-output-head nil)
2399(defvar ps-output-tail nil)
ef2cbb24 2400
7da17ab6 2401(defvar ps-page-postscript 0)
12d89a2e 2402(defvar ps-page-count 0)
87a16a06
RS
2403(defvar ps-showline-count 1)
2404
857686a6
RS
2405(defvar ps-control-or-escape-regexp nil)
2406
87a16a06
RS
2407(defvar ps-background-pages nil)
2408(defvar ps-background-all-pages nil)
2409(defvar ps-background-text-count 0)
2410(defvar ps-background-image-count 0)
ef2cbb24 2411
12d89a2e 2412(defvar ps-current-font 0)
12d89a2e
RS
2413(defvar ps-default-color (if ps-print-color-p ps-default-fg)) ; black
2414(defvar ps-current-color ps-default-color)
2415(defvar ps-current-bg nil)
2416
2417(defvar ps-razchunk 0)
2418
bcc0d457
RS
2419(defvar ps-color-format
2420 (if (eq ps-print-emacs-type 'emacs)
12d89a2e 2421
12b88fff
RS
2422 ;; Emacs understands the %f format; we'll use it to limit color RGB
2423 ;; values to three decimals to cut down some on the size of the
2424 ;; PostScript output.
2425 "%0.3f %0.3f %0.3f"
12d89a2e 2426
12b88fff 2427 ;; Lucid emacsen will have to make do with %s (princ) for floats.
bcc0d457 2428 "%s %s %s"))
12d89a2e
RS
2429
2430;; These values determine how much print-height to deduct when headers
2431;; are turned on. This is a pretty clumsy way of handling it, but
2432;; it'll do for now.
12d89a2e 2433
bcc0d457 2434(defvar ps-header-pad 0
496725ad
RS
2435 "Vertical and horizontal space between the header frame and the text.
2436This is in units of points (1/72 inch).")
12d89a2e 2437
bcc0d457 2438;; Define accessors to the dimensions list.
12d89a2e 2439
bcc0d457
RS
2440(defmacro ps-page-dimensions-get-width (dims) `(nth 0 ,dims))
2441(defmacro ps-page-dimensions-get-height (dims) `(nth 1 ,dims))
12d89a2e 2442
87a16a06 2443(defvar ps-landscape-page-height nil)
12d89a2e 2444
12d89a2e
RS
2445(defvar ps-print-width nil)
2446(defvar ps-print-height nil)
2447
8bd22fcf
KH
2448(defvar ps-height-remaining nil)
2449(defvar ps-width-remaining nil)
12d89a2e 2450
bcc0d457
RS
2451(defvar ps-print-color-scale nil)
2452
87a16a06
RS
2453\f
2454;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2455;; Internal Variables
2456
2457
2458(defvar ps-print-face-extension-alist nil
a18ed129 2459 "Alist of symbolic faces *WITH* extension features (box, outline, etc).
87a16a06
RS
2460An element of this list has the following form:
2461
2462 (FACE . [BITS FG BG])
2463
2464 FACE is a symbol denoting a face name
2465 BITS is a bit vector, where each bit correspond
2466 to a feature (bold, underline, etc)
2467 (see documentation for `ps-print-face-map-alist')
2468 FG foreground color (string or nil)
2469 BG background color (string or nil)
2470
a18ed129
RS
2471Don't change this list directly; instead,
2472use `ps-extend-face' and `ps-extend-face-list'.
2473See documentation for `ps-extend-face' for valid extension symbol.")
2474
2475
2476(defvar ps-print-face-alist nil
2477 "Alist of symbolic faces *WITHOUT* extension features (box, outline, etc).
2478
2479An element of this list has the same form as an element of
2480`ps-print-face-extension-alist'.
2481
2482Don't change this list directly; this list is used by `ps-face-attributes',
2483`ps-map-face' and `ps-build-reference-face-lists'.")
87a16a06
RS
2484
2485
2486(defconst ps-print-face-map-alist
2487 '((bold . 1)
2488 (italic . 2)
2489 (underline . 4)
2490 (strikeout . 8)
2491 (overline . 16)
2492 (shadow . 32)
2493 (box . 64)
2494 (outline . 128))
2495 "Alist of all features and the corresponding bit mask.
2496Each symbol correspond to one bit in a bit vector.")
2497
2498\f
2499;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
a18ed129 2500;; Remapping Faces
87a16a06
RS
2501
2502
2503;;;###autoload
2504(defun ps-extend-face-list (face-extension-list &optional merge-p)
2505 "Extend face in `ps-print-face-extension-alist'.
2506
a18ed129
RS
2507If optional MERGE-P is non-nil, extensions in FACE-EXTENSION-LIST are merged
2508with face extension in `ps-print-face-extension-alist'; otherwise, overrides.
87a16a06
RS
2509
2510The elements in FACE-EXTENSION-LIST is like those for `ps-extend-face'.
2511
2512See `ps-extend-face' for documentation."
2513 (while face-extension-list
2514 (ps-extend-face (car face-extension-list) merge-p)
2515 (setq face-extension-list (cdr face-extension-list))))
2516
2517
2518;;;###autoload
2519(defun ps-extend-face (face-extension &optional merge-p)
2520 "Extend face in `ps-print-face-extension-alist'.
2521
6bdb808e 2522If optional MERGE-P is non-nil, extensions in FACE-EXTENSION list are merged
a18ed129 2523with face extensions in `ps-print-face-extension-alist'; otherwise, overrides.
87a16a06
RS
2524
2525The elements of FACE-EXTENSION list have the form:
2526
2527 (FACE-NAME FOREGROUND BACKGROUND EXTENSION...)
2528
2529FACE-NAME is a face name symbol.
2530
2531FOREGROUND and BACKGROUND may be nil or a string that denotes the
2532foreground and background colors respectively.
2533
2534EXTENSION is one of the following symbols:
2535 bold - use bold font.
2536 italic - use italic font.
2537 underline - put a line under text.
2538 strikeout - like underline, but the line is in middle of text.
2539 overline - like underline, but the line is over the text.
2540 shadow - text will have a shadow.
2541 box - text will be surrounded by a box.
a18ed129 2542 outline - print characters as hollow outlines.
87a16a06
RS
2543
2544If EXTENSION is any other symbol, it is ignored."
2545 (let* ((face-name (nth 0 face-extension))
2546 (foreground (nth 1 face-extension))
2547 (background (nth 2 face-extension))
2548 (ps-face (cdr (assq face-name ps-print-face-extension-alist)))
2549 (face-vector (or ps-face (vector 0 nil nil)))
2550 (face-bit (ps-extension-bit face-extension)))
2551 ;; extend face
2552 (aset face-vector 0 (if merge-p
2553 (logior (aref face-vector 0) face-bit)
2554 face-bit))
2555 (and foreground (stringp foreground) (aset face-vector 1 foreground))
2556 (and background (stringp background) (aset face-vector 2 background))
2557 ;; if face does not exist, insert it
2558 (or ps-face
2559 (setq ps-print-face-extension-alist
2560 (cons (cons face-name face-vector)
2561 ps-print-face-extension-alist)))))
2562
2563
2564(defun ps-extension-bit (face-extension)
2565 (let ((face-bit 0))
2566 ;; map valid symbol extension to bit vector
2567 (setq face-extension (cdr (cdr face-extension)))
2568 (while (setq face-extension (cdr face-extension))
2569 (setq face-bit (logior face-bit
2570 (or (cdr (assq (car face-extension)
2571 ps-print-face-map-alist))
2572 0))))
2573 face-bit))
2574
2575\f
857686a6
RS
2576;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2577;; Adapted from font-lock:
2578;; Originally face attributes were specified via `font-lock-face-attributes'.
2579;; Users then changed the default face attributes by setting that variable.
2580;; However, we try and be back-compatible and respect its value if set except
2581;; for faces where M-x customize has been used to save changes for the face.
2582
2583(defun ps-font-lock-face-attributes ()
2584 (and (boundp 'font-lock-mode) (symbol-value 'font-lock-mode)
2585 (boundp 'font-lock-face-attributes)
2586 (let ((face-attributes font-lock-face-attributes))
2587 (while face-attributes
6bdb808e
RS
2588 (let* ((face-attribute
2589 (car (prog1 face-attributes
2590 (setq face-attributes (cdr face-attributes)))))
857686a6
RS
2591 (face (car face-attribute)))
2592 ;; Rustle up a `defface' SPEC from a
2593 ;; `font-lock-face-attributes' entry.
2594 (unless (get face 'saved-face)
2595 (let ((foreground (nth 1 face-attribute))
2596 (background (nth 2 face-attribute))
2597 (bold-p (nth 3 face-attribute))
2598 (italic-p (nth 4 face-attribute))
2599 (underline-p (nth 5 face-attribute))
2600 face-spec)
2601 (when foreground
2602 (setq face-spec (cons ':foreground
2603 (cons foreground face-spec))))
2604 (when background
2605 (setq face-spec (cons ':background
2606 (cons background face-spec))))
2607 (when bold-p
2608 (setq face-spec (append '(:bold t) face-spec)))
2609 (when italic-p
2610 (setq face-spec (append '(:italic t) face-spec)))
2611 (when underline-p
2612 (setq face-spec (append '(:underline t) face-spec)))
2613 (custom-declare-face face (list (list t face-spec)) nil)
2614 )))))))
2615
2616\f
87a16a06
RS
2617;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2618;; Internal functions and variables
2619
2620
12b88fff
RS
2621(make-local-hook 'ps-print-hook)
2622(make-local-hook 'ps-print-begin-page-hook)
2623(make-local-hook 'ps-print-begin-column-hook)
2624
2625
a18ed129 2626(defun ps-print-without-faces (from to &optional filename region-p)
857686a6 2627 (ps-spool-without-faces from to region-p)
87a16a06
RS
2628 (ps-do-despool filename))
2629
2630
a18ed129 2631(defun ps-spool-without-faces (from to &optional region-p)
12b88fff 2632 (run-hooks 'ps-print-hook)
a18ed129 2633 (ps-printing-region region-p)
87a16a06
RS
2634 (ps-generate (current-buffer) from to 'ps-generate-postscript))
2635
2636
a18ed129 2637(defun ps-print-with-faces (from to &optional filename region-p)
857686a6 2638 (ps-spool-with-faces from to region-p)
87a16a06
RS
2639 (ps-do-despool filename))
2640
2641
a18ed129 2642(defun ps-spool-with-faces (from to &optional region-p)
12b88fff 2643 (run-hooks 'ps-print-hook)
a18ed129 2644 (ps-printing-region region-p)
87a16a06
RS
2645 (ps-generate (current-buffer) from to 'ps-generate-postscript-with-faces))
2646
2647
a18ed129
RS
2648(defsubst ps-count-lines (from to)
2649 (+ (count-lines from to)
857686a6
RS
2650 (save-excursion
2651 (goto-char to)
2652 (if (= (current-column) 0) 1 0))))
87a16a06
RS
2653
2654
a18ed129 2655(defvar ps-printing-region nil
496725ad 2656 "Variable used to indicate if ps-print is printing a region.
a18ed129
RS
2657If non-nil, it is a cons, the car of which is the line number
2658where the region begins, and its cdr is the total number of lines
2659in the buffer. Formatting functions can use this information
2660to print the original line number (and not the number of lines printed),
2661and to indicate in the header that the printout is of a partial file.")
87a16a06
RS
2662
2663
a18ed129
RS
2664(defun ps-printing-region (region-p)
2665 (setq ps-printing-region
2666 (and region-p
2667 (cons (ps-count-lines (point-min) (region-beginning))
2668 (ps-count-lines (point-min) (point-max))))))
87a16a06
RS
2669
2670\f
12d89a2e
RS
2671;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2672;; Internal functions
2673
7ae35a2f 2674(defsubst ps-font-alist (font-sym)
12b88fff
RS
2675 (get font-sym 'fonts))
2676
2677(defun ps-font (font-sym font-type)
2678 "Font family name for text of `font-type', when generating PostScript."
7ae35a2f 2679 (let* ((font-list (ps-font-alist font-sym))
12b88fff 2680 (normal-font (cdr (assq 'normal font-list))))
6bdb808e
RS
2681 (while (and font-list (not (eq font-type (car (car font-list)))))
2682 (setq font-list (cdr font-list)))
2683 (or (cdr (car font-list)) normal-font)))
12b88fff
RS
2684
2685(defun ps-fonts (font-sym)
7ae35a2f 2686 (mapcar 'cdr (ps-font-alist font-sym)))
12b88fff
RS
2687
2688(defun ps-font-number (font-sym font-type)
7ae35a2f 2689 (or (ps-alist-position font-type (ps-font-alist font-sym))
12b88fff
RS
2690 0))
2691
2692(defsubst ps-line-height (font-sym)
2693 "The height of a line, for generating PostScript.
2694This is the value that ps-print uses to determine the height,
2695y-dimension, of the lines of text it has printed, and thus affects the
2696point at which page-breaks are placed.
2697The line-height is *not* the same as the point size of the font."
2698 (get font-sym 'line-height))
2699
2700(defsubst ps-title-line-height (font-sym)
2701 "The height of a `title' line, for generating PostScript.
2702This is the value that ps-print uses to determine the height,
2703y-dimension, of the lines of text it has printed, and thus affects the
2704point at which page-breaks are placed.
2705The title-line-height is *not* the same as the point size of the font."
2706 (get font-sym 'title-line-height))
2707
2708(defsubst ps-space-width (font-sym)
2709 "The width of a space character, for generating PostScript.
2710This value is used in expanding tab characters."
2711 (get font-sym 'space-width))
2712
2713(defsubst ps-avg-char-width (font-sym)
2714 "The average width, in points, of a character, for generating PostScript.
2715This is the value that ps-print uses to determine the length,
2716x-dimension, of the text it has printed, and thus affects the point at
2717which long lines wrap around."
2718 (get font-sym 'avg-char-width))
2719
bcc0d457 2720(defun ps-line-lengths-internal ()
87a16a06 2721 "Display the correspondence between a line length and a font size,
bcc0d457
RS
2722using the current ps-print setup.
2723Try: pr -t file | awk '{printf \"%3d %s\n\", length($0), $0}' | sort -r | head"
2724 (let ((buf (get-buffer-create "*Line-lengths*"))
2725 (ifs ps-font-size) ; initial font size
12b88fff 2726 (icw (ps-avg-char-width 'ps-font-for-text)) ; initial character width
bcc0d457
RS
2727 (print-width (progn (ps-get-page-dimensions)
2728 ps-print-width))
2729 (ps-setup (ps-setup)) ; setup for the current buffer
2730 (fs-min 5) ; minimum font size
2731 cw-min ; minimum character width
2732 nb-cpl-max ; maximum nb of characters per line
2733 (fs-max 14) ; maximum font size
2734 cw-max ; maximum character width
2735 nb-cpl-min ; minimum nb of characters per line
2736 fs ; current font size
2737 cw ; current character width
2738 nb-cpl ; current nb of characters per line
2739 )
2740 (setq cw-min (/ (* icw fs-min) ifs)
2741 nb-cpl-max (floor (/ print-width cw-min))
2742 cw-max (/ (* icw fs-max) ifs)
8bd22fcf
KH
2743 nb-cpl-min (floor (/ print-width cw-max))
2744 nb-cpl nb-cpl-min)
bcc0d457
RS
2745 (set-buffer buf)
2746 (goto-char (point-max))
8bd22fcf
KH
2747 (or (bolp) (insert "\n"))
2748 (insert ps-setup
2749 "nb char per line / font size\n")
bcc0d457 2750 (while (<= nb-cpl nb-cpl-max)
8bd22fcf
KH
2751 (setq cw (/ print-width (float nb-cpl))
2752 fs (/ (* ifs cw) icw))
bcc0d457
RS
2753 (insert (format "%3s %s\n" nb-cpl fs))
2754 (setq nb-cpl (1+ nb-cpl)))
2755 (insert "\n")
2756 (display-buffer buf 'not-this-window)))
2757
2758(defun ps-nb-pages (nb-lines)
496725ad
RS
2759 "Display correspondence between font size and the number of pages.
2760The correspondence is based on having NB-LINES lines of text,
2761and on the current ps-print setup."
bcc0d457
RS
2762 (let ((buf (get-buffer-create "*Nb-Pages*"))
2763 (ifs ps-font-size) ; initial font size
12b88fff 2764 (ilh (ps-line-height 'ps-font-for-text)) ; initial line height
bcc0d457
RS
2765 (page-height (progn (ps-get-page-dimensions)
2766 ps-print-height))
2767 (ps-setup (ps-setup)) ; setup for the current buffer
2768 (fs-min 4) ; minimum font size
2769 lh-min ; minimum line height
2770 nb-lpp-max ; maximum nb of lines per page
2771 nb-page-min ; minimum nb of pages
2772 (fs-max 14) ; maximum font size
2773 lh-max ; maximum line height
2774 nb-lpp-min ; minimum nb of lines per page
2775 nb-page-max ; maximum nb of pages
2776 fs ; current font size
2777 lh ; current line height
2778 nb-lpp ; current nb of lines per page
2779 nb-page ; current nb of pages
2780 )
2781 (setq lh-min (/ (* ilh fs-min) ifs)
2782 nb-lpp-max (floor (/ page-height lh-min))
2783 nb-page-min (ceiling (/ (float nb-lines) nb-lpp-max))
2784 lh-max (/ (* ilh fs-max) ifs)
2785 nb-lpp-min (floor (/ page-height lh-max))
8bd22fcf
KH
2786 nb-page-max (ceiling (/ (float nb-lines) nb-lpp-min))
2787 nb-page nb-page-min)
bcc0d457
RS
2788 (set-buffer buf)
2789 (goto-char (point-max))
8bd22fcf
KH
2790 (or (bolp) (insert "\n"))
2791 (insert ps-setup
2792 (format "%d lines\n" nb-lines)
2793 "nb page / font size\n")
bcc0d457
RS
2794 (while (<= nb-page nb-page-max)
2795 (setq nb-lpp (ceiling (/ nb-lines (float nb-page)))
2796 lh (/ page-height nb-lpp)
2797 fs (/ (* ifs lh) ilh))
2798 (insert (format "%s %s\n" nb-page fs))
2799 (setq nb-page (1+ nb-page)))
2800 (insert "\n")
2801 (display-buffer buf 'not-this-window)))
2802
6bdb808e
RS
2803;; macros used in `ps-select-font'
2804(defmacro ps-lookup (key) `(cdr (assq ,key font-entry)))
2805(defmacro ps-size-scale (key) `(/ (* (ps-lookup ,key) font-size) size))
2806
12b88fff
RS
2807(defun ps-select-font (font-family sym font-size title-font-size)
2808 (let ((font-entry (cdr (assq font-family ps-font-info-database))))
2809 (or font-entry
2810 (error "Don't have data to scale font %s. Known fonts families are %s"
2811 font-family
2812 (mapcar 'car ps-font-info-database)))
6bdb808e
RS
2813 (let ((size (ps-lookup 'size)))
2814 (put sym 'fonts (ps-lookup 'fonts))
2815 (put sym 'space-width (ps-size-scale 'space-width))
2816 (put sym 'avg-char-width (ps-size-scale 'avg-char-width))
2817 (put sym 'line-height (ps-size-scale 'line-height))
2818 (put sym 'title-line-height
2819 (/ (* (ps-lookup 'line-height) title-font-size) size)))))
bcc0d457 2820
12d89a2e 2821(defun ps-get-page-dimensions ()
bcc0d457
RS
2822 (let ((page-dimensions (cdr (assq ps-paper-type ps-page-dimensions-database)))
2823 page-width page-height)
2824 (cond
2825 ((null page-dimensions)
2826 (error "`ps-paper-type' must be one of:\n%s"
2827 (mapcar 'car ps-page-dimensions-database)))
2828 ((< ps-number-of-columns 1)
12b88fff 2829 (error "The number of columns %d should be positive"
8bd22fcf 2830 ps-number-of-columns)))
bcc0d457 2831
12b88fff
RS
2832 (ps-select-font ps-font-family 'ps-font-for-text
2833 ps-font-size ps-font-size)
2834 (ps-select-font ps-header-font-family 'ps-font-for-header
2835 ps-header-font-size ps-header-title-font-size)
bcc0d457
RS
2836
2837 (setq page-width (ps-page-dimensions-get-width page-dimensions)
2838 page-height (ps-page-dimensions-get-height page-dimensions))
2839
2840 ;; Landscape mode
2841 (if ps-landscape-mode
2842 ;; exchange width and height
2843 (setq page-width (prog1 page-height (setq page-height page-width))))
2844
2845 ;; It is used to get the lower right corner (only in landscape mode)
2846 (setq ps-landscape-page-height page-height)
2847
2848 ;; | lm | text | ic | text | ic | text | rm |
2849 ;; page-width == lm + n * pw + (n - 1) * ic + rm
2850 ;; => pw == (page-width - lm -rm - (n - 1) * ic) / n
8bd22fcf
KH
2851 (setq ps-print-width (/ (- page-width
2852 ps-left-margin ps-right-margin
2853 (* (1- ps-number-of-columns) ps-inter-column))
2854 ps-number-of-columns))
bcc0d457
RS
2855 (if (<= ps-print-width 0)
2856 (error "Bad horizontal layout:
2857page-width == %s
2858ps-left-margin == %s
2859ps-right-margin == %s
2860ps-inter-column == %s
2861ps-number-of-columns == %s
2862| lm | text | ic | text | ic | text | rm |
2863page-width == lm + n * print-width + (n - 1) * ic + rm
2864=> print-width == %d !"
2865 page-width
2866 ps-left-margin
2867 ps-right-margin
2868 ps-inter-column
2869 ps-number-of-columns
2870 ps-print-width))
2871
2872 (setq ps-print-height
2873 (- page-height ps-bottom-margin ps-top-margin))
2874 (if (<= ps-print-height 0)
2875 (error "Bad vertical layout:
2876ps-top-margin == %s
2877ps-bottom-margin == %s
2878page-height == bm + print-height + tm
2879=> print-height == %d !"
2880 ps-top-margin
2881 ps-bottom-margin
2882 ps-print-height))
2883 ;; If headers are turned on, deduct the height of the header from
2884 ;; the print height.
8bd22fcf 2885 (if ps-print-header
12b88fff
RS
2886 (setq ps-header-pad (* ps-header-line-pad
2887 (ps-title-line-height 'ps-font-for-header))
8bd22fcf
KH
2888 ps-print-height (- ps-print-height
2889 ps-header-offset
2890 ps-header-pad
12b88fff
RS
2891 (ps-title-line-height 'ps-font-for-header)
2892 (* (ps-line-height 'ps-font-for-header)
2893 (1- ps-header-lines))
8bd22fcf 2894 ps-header-pad)))
bcc0d457
RS
2895 (if (<= ps-print-height 0)
2896 (error "Bad vertical layout:
2897ps-top-margin == %s
2898ps-bottom-margin == %s
2899ps-header-offset == %s
2900ps-header-pad == %s
2901header-height == %s
2902page-height == bm + print-height + tm - ho - hh
2903=> print-height == %d !"
2904 ps-top-margin
2905 ps-bottom-margin
2906 ps-header-offset
2907 ps-header-pad
2908 (+ ps-header-pad
12b88fff
RS
2909 (ps-title-line-height 'ps-font-for-header)
2910 (* (ps-line-height 'ps-font-for-header)
2911 (1- ps-header-lines))
bcc0d457
RS
2912 ps-header-pad)
2913 ps-print-height))))
ef2cbb24 2914
12d89a2e 2915(defun ps-print-preprint (&optional filename)
8bd22fcf
KH
2916 (and filename
2917 (or (numberp filename)
2918 (listp filename))
2919 (let* ((name (concat (buffer-name) ".ps"))
2920 (prompt (format "Save PostScript to file: (default %s) " name))
2921 (res (read-file-name prompt default-directory name nil)))
2922 (if (file-directory-p res)
2923 (expand-file-name name (file-name-as-directory res))
2924 res))))
12d89a2e
RS
2925
2926;; The following functions implement a simple list-buffering scheme so
2927;; that ps-print doesn't have to repeatedly switch between buffers
857686a6
RS
2928;; while spooling. The functions `ps-output' and `ps-output-string' build
2929;; up the lists; the function `ps-flush-output' takes the lists and
12d89a2e
RS
2930;; insert its contents into the spool buffer (*PostScript*).
2931
857686a6
RS
2932(defvar ps-string-escape-codes
2933 (let ((table (make-vector 256 nil))
2934 (char ?\000))
2935 ;; control characters
2936 (while (<= char ?\037)
2937 (aset table char (format "\\%03o" char))
2938 (setq char (1+ char)))
2939 ;; printable characters
2940 (while (< char ?\177)
2941 (aset table char (format "%c" char))
2942 (setq char (1+ char)))
2943 ;; DEL and 8-bit characters
2944 (while (<= char ?\377)
2945 (aset table char (format "\\%o" char))
2946 (setq char (1+ char)))
2947 ;; Override ASCII formatting characters with named escape code:
2948 (aset table ?\n "\\n") ; [NL] linefeed
2949 (aset table ?\r "\\r") ; [CR] carriage return
2950 (aset table ?\t "\\t") ; [HT] horizontal tab
2951 (aset table ?\b "\\b") ; [BS] backspace
2952 (aset table ?\f "\\f") ; [NP] form feed
2953 ;; Escape PostScript escape and string delimiter characters:
2954 (aset table ?\\ "\\\\")
2955 (aset table ?\( "\\(")
2956 (aset table ?\) "\\)")
2957 table)
2958 "Vector used to map characters to PostScript string escape codes.")
2959
12d89a2e
RS
2960(defun ps-output-string-prim (string)
2961 (insert "(") ;insert start-string delimiter
2962 (save-excursion ;insert string
2963 (insert string))
12d89a2e 2964 ;; Find and quote special characters as necessary for PS
b61e2c11
RS
2965 ;; This skips everything except control chars, nonascii chars,
2966 ;; (, ) and \.
2967 (while (progn (skip-chars-forward " -'*-[]-~") (not (eobp)))
2968 (let ((special (following-char)))
bb58920c
EZ
2969 (if (> (char-bytes special) 1)
2970 (forward-char)
2971 (delete-char 1)
2972 (insert (aref ps-string-escape-codes special)))))
12d89a2e
RS
2973 (goto-char (point-max))
2974 (insert ")")) ;insert end-string delimiter
ef2cbb24 2975
12d89a2e 2976(defun ps-init-output-queue ()
8bd22fcf
KH
2977 (setq ps-output-head '("")
2978 ps-output-tail ps-output-head))
ef2cbb24 2979
12d89a2e
RS
2980(defun ps-output (&rest args)
2981 (setcdr ps-output-tail args)
2982 (while (cdr ps-output-tail)
2983 (setq ps-output-tail (cdr ps-output-tail))))
ef2cbb24 2984
12d89a2e
RS
2985(defun ps-output-string (string)
2986 (ps-output t string))
ef2cbb24 2987
87a16a06
RS
2988(defun ps-output-list (the-list)
2989 (mapcar 'ps-output the-list))
2990
12d89a2e
RS
2991(defun ps-flush-output ()
2992 (save-excursion
2993 (set-buffer ps-spool-buffer)
2994 (goto-char (point-max))
2995 (while ps-output-head
2996 (let ((it (car ps-output-head)))
2997 (if (not (eq t it))
2998 (insert it)
2999 (setq ps-output-head (cdr ps-output-head))
3000 (ps-output-string-prim (car ps-output-head))))
3001 (setq ps-output-head (cdr ps-output-head))))
3002 (ps-init-output-queue))
3003
3004(defun ps-insert-file (fname)
3005 (ps-flush-output)
12d89a2e 3006 ;; Check to see that the file exists and is readable; if not, throw
87a16a06
RS
3007 ;; an error.
3008 (or (file-readable-p fname)
12d89a2e 3009 (error "Could not read file `%s'" fname))
12d89a2e
RS
3010 (save-excursion
3011 (set-buffer ps-spool-buffer)
3012 (goto-char (point-max))
3013 (insert-file fname)))
06fb6aab 3014
12d89a2e
RS
3015;; These functions insert the arrays that define the contents of the
3016;; headers.
ef2cbb24 3017
12d89a2e
RS
3018(defun ps-generate-header-line (fonttag &optional content)
3019 (ps-output " [ " fonttag " ")
3020 (cond
3021 ;; Literal strings should be output as is -- the string must
3022 ;; contain its own PS string delimiters, '(' and ')', if necessary.
3023 ((stringp content)
3024 (ps-output content))
3025
3026 ;; Functions are called -- they should return strings; they will be
3027 ;; inserted as strings and the PS string delimiters added.
3028 ((and (symbolp content) (fboundp content))
3029 (ps-output-string (funcall content)))
3030
3031 ;; Variables will have their contents inserted. They should
3032 ;; contain strings, and will be inserted as strings.
3033 ((and (symbolp content) (boundp content))
3034 (ps-output-string (symbol-value content)))
3035
3036 ;; Anything else will get turned into an empty string.
3037 (t
3038 (ps-output-string "")))
3039 (ps-output " ]\n"))
3040
3041(defun ps-generate-header (name contents)
3042 (ps-output "/" name " [\n")
3043 (if (> ps-header-lines 0)
3044 (let ((count 1))
3045 (ps-generate-header-line "/h0" (car contents))
3046 (while (and (< count ps-header-lines)
3047 (setq contents (cdr contents)))
3048 (ps-generate-header-line "/h1" (car contents))
8bd22fcf 3049 (setq count (1+ count)))
12d89a2e
RS
3050 (ps-output "] def\n"))))
3051
3052(defun ps-output-boolean (name bool)
3053 (ps-output (format "/%s %s def\n" name (if bool "true" "false"))))
ef2cbb24 3054
06fb6aab 3055
87a16a06
RS
3056(defun ps-background-pages (page-list func)
3057 (if page-list
3058 (mapcar
3059 '(lambda (pages)
3060 (let ((start (if (consp pages) (car pages) pages))
3061 (end (if (consp pages) (cdr pages) pages)))
3062 (and (integerp start) (integerp end) (<= start end)
3063 (add-to-list 'ps-background-pages (vector start end func)))))
3064 page-list)
3065 (setq ps-background-all-pages (cons func ps-background-all-pages))))
3066
3067
3068(defun ps-get-boundingbox ()
3069 (save-excursion
3070 (set-buffer ps-spool-buffer)
3071 (save-excursion
3072 (if (re-search-forward
3073 "^%%BoundingBox:\\s-+\\([0-9.]+\\)\\s-+\\([0-9.]+\\)\\s-+\\([0-9.]+\\)\\s-+\\([0-9.]+\\)"
3074 nil t)
3075 (vector (string-to-number ; lower x
3076 (buffer-substring (match-beginning 1) (match-end 1)))
3077 (string-to-number ; lower y
3078 (buffer-substring (match-beginning 2) (match-end 2)))
3079 (string-to-number ; upper x
3080 (buffer-substring (match-beginning 3) (match-end 3)))
3081 (string-to-number ; upper y
3082 (buffer-substring (match-beginning 4) (match-end 4))))
3083 (vector 0 0 0 0)))))
3084
3085
3086;; Emacs understands the %f format; we'll use it to limit color RGB values
3087;; to three decimals to cut down some on the size of the PostScript output.
3088;; Lucid emacsen will have to make do with %s (princ) for floats.
3089
3090(defvar ps-float-format (if (eq ps-print-emacs-type 'emacs)
3091 "%0.3f " ; emacs
3092 "%s ")) ; Lucid emacsen
3093
3094
3095(defun ps-float-format (value &optional default)
3096 (let ((literal (or value default)))
3097 (if literal
3098 (format (if (numberp literal)
3099 ps-float-format
3100 "%s ")
3101 literal)
3102 " ")))
3103
3104
3105(defun ps-background-text ()
3106 (mapcar
3107 '(lambda (text)
3108 (setq ps-background-text-count (1+ ps-background-text-count))
3109 (ps-output (format "/ShowBackText-%d {\n" ps-background-text-count))
3110 (ps-output-string (nth 0 text)) ; text
3111 (ps-output
3112 "\n"
3113 (ps-float-format (nth 4 text) 200.0) ; font size
3114 (format "/%s " (or (nth 3 text) "Times-Roman")) ; font name
3115 (ps-float-format (nth 6 text)
3116 "PrintHeight PrintPageWidth atan") ; rotation
3117 (ps-float-format (nth 5 text) 0.85) ; gray
3118 (ps-float-format (nth 1 text) "0") ; x position
3119 (ps-float-format (nth 2 text) "BottomMargin") ; y position
3120 "\nShowBackText} def\n")
3121 (ps-background-pages (nthcdr 7 text) ; page list
3122 (format "ShowBackText-%d\n"
3123 ps-background-text-count)))
3124 ps-print-background-text))
3125
3126
3127(defun ps-background-image ()
3128 (mapcar
3129 '(lambda (image)
3130 (let ((image-file (expand-file-name (nth 0 image))))
3131 (if (file-readable-p image-file)
3132 (progn
3133 (setq ps-background-image-count (1+ ps-background-image-count))
3134 (ps-output
3135 (format "/ShowBackImage-%d {\n--back-- " ps-background-image-count)
3136 (ps-float-format (nth 5 image) 0.0) ; rotation
3137 (ps-float-format (nth 3 image) 1.0) ; x scale
3138 (ps-float-format (nth 4 image) 1.0) ; y scale
3139 (ps-float-format (nth 1 image) ; x position
3140 "PrintPageWidth 2 div")
3141 (ps-float-format (nth 2 image) ; y position
3142 "PrintHeight 2 div BottomMargin add")
3143 "\nBeginBackImage\n")
3144 (ps-insert-file image-file)
3145 ;; coordinate adjustment to centralize image
3146 ;; around x and y position
3147 (let ((box (ps-get-boundingbox)))
3148 (save-excursion
3149 (set-buffer ps-spool-buffer)
3150 (save-excursion
3151 (if (re-search-backward "^--back--" nil t)
3152 (replace-match
3153 (format "%s %s"
3154 (ps-float-format
3155 (- (+ (/ (- (aref box 2) (aref box 0)) 2.0)
3156 (aref box 0))))
3157 (ps-float-format
3158 (- (+ (/ (- (aref box 3) (aref box 1)) 2.0)
3159 (aref box 1)))))
3160 t)))))
3161 (ps-output "\nEndBackImage} def\n")
3162 (ps-background-pages (nthcdr 6 image) ; page list
3163 (format "ShowBackImage-%d\n"
3164 ps-background-image-count))))))
3165 ps-print-background-image))
3166
3167
a18ed129 3168(defun ps-background (page-number)
87a16a06
RS
3169 (let (has-local-background)
3170 (mapcar '(lambda (range)
a18ed129
RS
3171 (and (<= (aref range 0) page-number)
3172 (<= page-number (aref range 1))
87a16a06
RS
3173 (if has-local-background
3174 (ps-output (aref range 2))
3175 (setq has-local-background t)
3176 (ps-output "/printLocalBackground {\n"
3177 (aref range 2)))))
3178 ps-background-pages)
3179 (and has-local-background (ps-output "} def\n"))))
3180
3181
0140c600
EZ
3182;; Return a list of the distinct elements of LIST.
3183;; Elements are compared with `equal'.
3184(defun ps-remove-duplicates (list)
3185 (let (new (tail list))
3186 (while tail
3187 (or (member (car tail) new)
3188 (setq new (cons (car tail) new)))
3189 (setq tail (cdr tail)))
3190 (nreverse new)))
3191
6bdb808e
RS
3192;; Find the first occurrence of ITEM in LIST.
3193;; Return the index of the matching item, or nil if not found.
3194;; Elements are compared with `eq'.
7ae35a2f 3195(defun ps-alist-position (item list)
6bdb808e
RS
3196 (let ((tail list) (index 0) found)
3197 (while tail
7ae35a2f 3198 (if (setq found (eq (car (car tail)) item))
6bdb808e
RS
3199 (setq tail nil)
3200 (setq index (1+ index)
3201 tail (cdr tail))))
3202 (and found index)))
3203
3204
ef2cbb24 3205(defun ps-begin-file ()
bcc0d457 3206 (ps-get-page-dimensions)
7da17ab6 3207 (setq ps-page-postscript 0
87a16a06
RS
3208 ps-background-text-count 0
3209 ps-background-image-count 0
3210 ps-background-pages nil
3211 ps-background-all-pages nil)
12d89a2e 3212
8bd22fcf
KH
3213 (ps-output ps-adobe-tag
3214 "%%Title: " (buffer-name) ; Take job name from name of
3215 ; first buffer printed
3216 "\n%%Creator: " (user-full-name)
857686a6
RS
3217 " (using ps-print v" ps-print-version
3218 ")\n%%CreationDate: "
87a16a06
RS
3219 (time-stamp-hh:mm:ss) " " (time-stamp-mon-dd-yyyy)
3220 "\n%%Orientation: "
8bd22fcf
KH
3221 (if ps-landscape-mode "Landscape" "Portrait")
3222 "\n%% DocumentFonts: Times-Roman Times-Italic "
12b88fff 3223 (mapconcat 'identity
0140c600 3224 (ps-remove-duplicates
12b88fff
RS
3225 (append (ps-fonts 'ps-font-for-text)
3226 (list (ps-font 'ps-font-for-header 'normal)
0140c600 3227 (ps-font 'ps-font-for-header 'bold))))
12b88fff 3228 " ")
8bd22fcf
KH
3229 "\n%%Pages: (atend)\n"
3230 "%%EndComments\n\n")
12d89a2e 3231
bcc0d457 3232 (ps-output-boolean "LandscapeMode" ps-landscape-mode)
8bd22fcf 3233 (ps-output (format "/NumberOfColumns %d def\n" ps-number-of-columns)
12d89a2e 3234
8bd22fcf
KH
3235 (format "/LandscapePageHeight %s def\n" ps-landscape-page-height)
3236 (format "/PrintPageWidth %s def\n"
87a16a06
RS
3237 (- (* (+ ps-print-width ps-inter-column)
3238 ps-number-of-columns)
8bd22fcf
KH
3239 ps-inter-column))
3240 (format "/PrintWidth %s def\n" ps-print-width)
3241 (format "/PrintHeight %s def\n" ps-print-height)
12d89a2e 3242
8bd22fcf
KH
3243 (format "/LeftMargin %s def\n" ps-left-margin)
3244 (format "/RightMargin %s def\n" ps-right-margin) ; not used
3245 (format "/InterColumn %s def\n" ps-inter-column)
bcc0d457 3246
8bd22fcf
KH
3247 (format "/BottomMargin %s def\n" ps-bottom-margin)
3248 (format "/TopMargin %s def\n" ps-top-margin) ; not used
3249 (format "/HeaderOffset %s def\n" ps-header-offset)
3250 (format "/HeaderPad %s def\n" ps-header-pad))
06fb6aab 3251
12b88fff
RS
3252 (ps-output-boolean "PrintHeader" ps-print-header)
3253 (ps-output-boolean "PrintOnlyOneHeader" ps-print-only-one-header)
3254 (ps-output-boolean "PrintHeaderFrame" ps-print-header-frame)
3255 (ps-output-boolean "ShowNofN" ps-show-n-of-n)
3256 (ps-output-boolean "Duplex" ps-spool-duplex)
bcc0d457 3257
12b88fff
RS
3258 (let ((line-height (ps-line-height 'ps-font-for-text)))
3259 (ps-output (format "/LineHeight %s def\n" line-height)
3260 (format "/LinesPerColumn %d def\n"
3261 (round (/ (+ ps-print-height
3262 (* line-height 0.45))
3263 line-height)))))
87a16a06 3264
535efc38 3265 (ps-output-boolean "Zebra" ps-zebra-stripes)
87a16a06 3266 (ps-output-boolean "PrintLineNumber" ps-line-number)
7da17ab6 3267 (ps-output (format "/ZebraHeight %d def\n" ps-zebra-stripe-height))
87a16a06
RS
3268
3269 (ps-background-text)
3270 (ps-background-image)
3271 (setq ps-background-all-pages (nreverse ps-background-all-pages)
3272 ps-background-pages (nreverse ps-background-pages))
12d89a2e 3273
bcc0d457 3274 (ps-output ps-print-prologue-1)
12d89a2e 3275
87a16a06
RS
3276 (ps-output "/printGlobalBackground {\n")
3277 (ps-output-list ps-background-all-pages)
3278 (ps-output "} def\n/printLocalBackground {\n} def\n")
3279
bcc0d457 3280 ;; Header fonts
8bd22fcf 3281 (ps-output (format "/h0 %s /%s DefFont\n" ; /h0 14 /Helvetica-Bold DefFont
12b88fff
RS
3282 ps-header-title-font-size (ps-font 'ps-font-for-header
3283 'bold))
8bd22fcf 3284 (format "/h1 %s /%s DefFont\n" ; /h1 12 /Helvetica DefFont
12b88fff
RS
3285 ps-header-font-size (ps-font 'ps-font-for-header
3286 'normal)))
bcc0d457
RS
3287
3288 (ps-output ps-print-prologue-2)
3289
3290 ;; Text fonts
7ae35a2f 3291 (let ((font (ps-font-alist 'ps-font-for-text))
6bdb808e
RS
3292 (i 0))
3293 (while font
3294 (ps-output (format "/f%d %s /%s DefFont\n"
3295 i
3296 ps-font-size
3297 (ps-font 'ps-font-for-text (car (car font)))))
3298 (setq font (cdr font)
3299 i (1+ i))))
bcc0d457 3300
8bd22fcf
KH
3301 (ps-output "\nBeginDoc\n\n"
3302 "%%EndPrologue\n"))
ef2cbb24 3303
12d89a2e
RS
3304(defun ps-header-dirpart ()
3305 (let ((fname (buffer-file-name)))
3306 (if fname
3307 (if (string-equal (buffer-name) (file-name-nondirectory fname))
3308 (file-name-directory fname)
3309 fname)
3310 "")))
ef2cbb24 3311
12d89a2e 3312(defun ps-get-buffer-name ()
bcc0d457
RS
3313 (cond
3314 ;; Indulge Jim this little easter egg:
3315 ((string= (buffer-name) "ps-print.el")
3316 "Hey, Cool! It's ps-print.el!!!")
3317 ;; Indulge Jack this other little easter egg:
3318 ((string= (buffer-name) "sokoban.el")
3319 "Super! C'est sokoban.el!")
87a16a06 3320 (t (concat
a18ed129 3321 (and ps-printing-region "Subset of: ")
87a16a06
RS
3322 (buffer-name)
3323 (and (buffer-modified-p) " (unsaved)")))))
ef2cbb24 3324
12d89a2e 3325(defun ps-begin-job ()
7da17ab6
RS
3326 (save-excursion
3327 (set-buffer ps-spool-buffer)
3328 (goto-char (point-max))
3329 (and (re-search-backward "^%%Trailer$" nil t)
3330 (delete-region (match-beginning 0) (point-max))))
3331 (setq ps-showline-count (if ps-printing-region (car ps-printing-region) 1)
3332 ps-page-count 0
857686a6 3333 ps-control-or-escape-regexp
12b88fff
RS
3334 (cond ((eq ps-print-control-characters '8-bit)
3335 "[\000-\037\177-\377]")
3336 ((eq ps-print-control-characters 'control-8-bit)
3337 "[\000-\037\177-\237]")
3338 ((eq ps-print-control-characters 'control)
3339 "[\000-\037\177]")
857686a6 3340 (t "[\t\n\f]"))))
ef2cbb24 3341
12b88fff
RS
3342(defmacro ps-page-number ()
3343 `(1+ (/ (1- ps-page-count) ps-number-of-columns)))
3344
ef2cbb24 3345(defun ps-end-file ()
984e7bd9 3346 (ps-output "\n%%Trailer\n%%Pages: "
7da17ab6 3347 (format "%d" ps-page-postscript)
984e7bd9 3348 "\n\nEndDoc\n\n%%EOF\n"))
87a16a06
RS
3349
3350
ef2cbb24
RS
3351(defun ps-next-page ()
3352 (ps-end-page)
12d89a2e
RS
3353 (ps-flush-output)
3354 (ps-begin-page))
3355
12b88fff 3356(defun ps-header-page ()
7da17ab6
RS
3357 ;; set total line and page number when printing has finished
3358 ;; (see `ps-generate')
12b88fff
RS
3359 (if (prog1
3360 (zerop (mod ps-page-count ps-number-of-columns))
6bdb808e 3361 (setq ps-page-count (1+ ps-page-count)))
a18ed129 3362 ;; Print only when a new real page begins.
7da17ab6
RS
3363 (progn
3364 (setq ps-page-postscript (1+ ps-page-postscript))
3365 (ps-output (format "\n%%%%Page: %d %d\n"
3366 ps-page-postscript ps-page-postscript))
3367 (ps-output "/Lines 0 def\n/PageCount 0 def\nBeginDSCPage\n")
3368 (ps-background ps-page-postscript)
12b88fff 3369 (run-hooks 'ps-print-begin-page-hook))
a18ed129 3370 ;; Print when any other page begins.
7da17ab6 3371 (ps-output "/Lines 0 def\n/PageCount 0 def\nBeginDSCPage\n")
12b88fff 3372 (run-hooks 'ps-print-begin-column-hook)))
a18ed129 3373
8bd22fcf 3374(defun ps-begin-page ()
12d89a2e 3375 (ps-get-page-dimensions)
8bd22fcf
KH
3376 (setq ps-width-remaining ps-print-width
3377 ps-height-remaining ps-print-height)
12d89a2e 3378
a18ed129 3379 (ps-header-page)
12d89a2e 3380
87a16a06 3381 (ps-output (format "/LineNumber %d def\n" ps-showline-count)
12b88fff
RS
3382 (format "/PageNumber %d def\n" (if ps-print-only-one-header
3383 (ps-page-number)
3384 ps-page-count)))
12d89a2e 3385
090be653
RS
3386 (when ps-print-header
3387 (ps-generate-header "HeaderLinesLeft" ps-left-header)
3388 (ps-generate-header "HeaderLinesRight" ps-right-header)
3389 (ps-output (format "%d SetHeaderLines\n" ps-header-lines)))
12d89a2e
RS
3390
3391 (ps-output "BeginPage\n")
87a16a06
RS
3392 (ps-set-font ps-current-font)
3393 (ps-set-bg ps-current-bg)
3394 (ps-set-color ps-current-color))
ef2cbb24
RS
3395
3396(defun ps-end-page ()
a18ed129 3397 (ps-output "EndPage\nEndDSCPage\n"))
12d89a2e
RS
3398
3399(defun ps-dummy-page ()
12b88fff 3400 (ps-header-page)
a18ed129 3401 (ps-output "/PrintHeader false def
12d89a2e
RS
3402BeginPage
3403EndPage
3404EndDSCPage\n"))
06fb6aab 3405
ef2cbb24 3406(defun ps-next-line ()
87a16a06 3407 (setq ps-showline-count (1+ ps-showline-count))
12b88fff
RS
3408 (let ((lh (ps-line-height 'ps-font-for-text)))
3409 (if (< ps-height-remaining lh)
3410 (ps-next-page)
3411 (setq ps-width-remaining ps-print-width
3412 ps-height-remaining (- ps-height-remaining lh))
3413 (ps-output "HL\n"))))
ef2cbb24
RS
3414
3415(defun ps-continue-line ()
12b88fff
RS
3416 (let ((lh (ps-line-height 'ps-font-for-text)))
3417 (if (< ps-height-remaining lh)
3418 (ps-next-page)
3419 (setq ps-width-remaining ps-print-width
3420 ps-height-remaining (- ps-height-remaining lh))
3421 (ps-output "SL\n"))))
12d89a2e
RS
3422
3423(defun ps-find-wrappoint (from to char-width)
3424 (let ((avail (truncate (/ ps-width-remaining char-width)))
3425 (todo (- to from)))
3426 (if (< todo avail)
3427 (cons to (* todo char-width))
3428 (cons (+ from avail) ps-width-remaining))))
3429
3430(defun ps-basic-plot-string (from to &optional bg-color)
12b88fff
RS
3431 (let* ((wrappoint (ps-find-wrappoint from to
3432 (ps-avg-char-width 'ps-font-for-text)))
12d89a2e 3433 (to (car wrappoint))
055e7bf2 3434 (string (buffer-substring-no-properties from to)))
12d89a2e 3435 (ps-output-string string)
bcc0d457 3436 (ps-output " S\n")
12d89a2e
RS
3437 wrappoint))
3438
3439(defun ps-basic-plot-whitespace (from to &optional bg-color)
12b88fff
RS
3440 (let* ((wrappoint (ps-find-wrappoint from to
3441 (ps-space-width 'ps-font-for-text)))
12d89a2e 3442 (to (car wrappoint)))
12d89a2e
RS
3443 (ps-output (format "%d W\n" (- to from)))
3444 wrappoint))
3445
3446(defun ps-plot (plotfunc from to &optional bg-color)
ef2cbb24 3447 (while (< from to)
12d89a2e
RS
3448 (let* ((wrappoint (funcall plotfunc from to bg-color))
3449 (plotted-to (car wrappoint))
3450 (plotted-width (cdr wrappoint)))
8bd22fcf
KH
3451 (setq from plotted-to
3452 ps-width-remaining (- ps-width-remaining plotted-width))
12d89a2e
RS
3453 (if (< from to)
3454 (ps-continue-line))))
ef2cbb24
RS
3455 (if ps-razzle-dazzle
3456 (let* ((q-todo (- (point-max) (point-min)))
12d89a2e 3457 (q-done (- (point) (point-min)))
ef2cbb24 3458 (chunkfrac (/ q-todo 8))
857686a6 3459 (chunksize (min chunkfrac 1000)))
ef2cbb24 3460 (if (> (- q-done ps-razchunk) chunksize)
8bd22fcf 3461 (progn
ef2cbb24 3462 (setq ps-razchunk q-done)
8bd22fcf
KH
3463 (message "Formatting...%3d%%"
3464 (if (< q-todo 100)
3465 (/ (* 100 q-done) q-todo)
3466 (/ q-done (/ q-todo 100)))
3467 ))))))
12d89a2e
RS
3468
3469(defun ps-set-font (font)
8bd22fcf 3470 (ps-output (format "/f%d F\n" (setq ps-current-font font))))
12d89a2e 3471
12d89a2e
RS
3472(defun ps-set-bg (color)
3473 (if (setq ps-current-bg color)
8bd22fcf
KH
3474 (ps-output (format ps-color-format
3475 (nth 0 color) (nth 1 color) (nth 2 color))
12d89a2e
RS
3476 " true BG\n")
3477 (ps-output "false BG\n")))
3478
3479(defun ps-set-color (color)
a18ed129 3480 (setq ps-current-color (or color ps-default-fg))
8bd22fcf
KH
3481 (ps-output (format ps-color-format
3482 (nth 0 ps-current-color)
043620f4
KH
3483 (nth 1 ps-current-color) (nth 2 ps-current-color))
3484 " FG\n"))
12d89a2e 3485
12d89a2e 3486
87a16a06 3487(defvar ps-current-effect 0)
12d89a2e 3488
87a16a06
RS
3489
3490(defun ps-plot-region (from to font &optional fg-color bg-color effects)
12d89a2e
RS
3491 (if (not (equal font ps-current-font))
3492 (ps-set-font font))
06fb6aab 3493
12d89a2e
RS
3494 ;; Specify a foreground color only if one's specified and it's
3495 ;; different than the current.
3496 (if (not (equal fg-color ps-current-color))
3497 (ps-set-color fg-color))
06fb6aab 3498
12d89a2e
RS
3499 (if (not (equal bg-color ps-current-bg))
3500 (ps-set-bg bg-color))
06fb6aab 3501
87a16a06
RS
3502 ;; Specify effects (underline, overline, box, etc)
3503 (cond
3504 ((not (integerp effects))
3505 (ps-output "0 EF\n")
3506 (setq ps-current-effect 0))
3507 ((/= effects ps-current-effect)
3508 (ps-output (number-to-string effects) " EF\n")
3509 (setq ps-current-effect effects)))
ef2cbb24 3510
12d89a2e 3511 ;; Starting at the beginning of the specified region...
ef2cbb24
RS
3512 (save-excursion
3513 (goto-char from)
12d89a2e
RS
3514
3515 ;; ...break the region up into chunks separated by tabs, linefeeds,
87a16a06 3516 ;; pagefeeds, control characters, and plot each chunk.
ef2cbb24 3517 (while (< from to)
857686a6 3518 (if (re-search-forward ps-control-or-escape-regexp to t)
a18ed129 3519 ;; region with some control characters
12b88fff
RS
3520 (let* ((match-point (match-beginning 0))
3521 (match (char-after match-point)))
857686a6
RS
3522 (ps-plot 'ps-basic-plot-string from (1- (point)) bg-color)
3523 (cond
3524 ((= match ?\t) ; tab
3525 (let ((linestart (save-excursion (beginning-of-line) (point))))
3526 (forward-char -1)
3527 (setq from (+ linestart (current-column)))
3528 (if (re-search-forward "[ \t]+" to t)
3529 (ps-plot 'ps-basic-plot-whitespace
3530 from (+ linestart (current-column))
3531 bg-color))))
3532
3533 ((= match ?\n) ; newline
3534 (ps-next-line))
3535
3536 ((= match ?\f) ; form feed
12b88fff
RS
3537 ;; do not skip page if previous character is NEWLINE and
3538 ;; it is a beginning of page.
3539 (or (and (= (char-after (1- match-point)) ?\n)
3540 (= ps-height-remaining ps-print-height))
3541 (ps-next-page)))
857686a6
RS
3542 ; characters from ^@ to ^_ and
3543 (t ; characters from 127 to 255
3544 (ps-control-character match)))
87a16a06
RS
3545 (setq from (point)))
3546 ;; region without control characters
3547 (ps-plot 'ps-basic-plot-string from to bg-color)
3548 (setq from to)))))
3549
857686a6
RS
3550(defvar ps-string-control-codes
3551 (let ((table (make-vector 256 nil))
3552 (char ?\000))
3553 ;; control character
3554 (while (<= char ?\037)
3555 (aset table char (format "^%c" (+ char ?@)))
3556 (setq char (1+ char)))
3557 ;; printable character
3558 (while (< char ?\177)
3559 (aset table char (format "%c" char))
3560 (setq char (1+ char)))
3561 ;; DEL
3562 (aset table char "^?")
3563 ;; 8-bit character
3564 (while (<= (setq char (1+ char)) ?\377)
3565 (aset table char (format "\\%o" char)))
3566 table)
3567 "Vector used to map characters to a printable string.")
3568
3569(defun ps-control-character (char)
3570 (let* ((str (aref ps-string-control-codes char))
3571 (from (1- (point)))
87a16a06
RS
3572 (len (length str))
3573 (to (+ from len))
12b88fff
RS
3574 (char-width (ps-avg-char-width 'ps-font-for-text))
3575 (wrappoint (ps-find-wrappoint from to char-width)))
87a16a06
RS
3576 (if (< (car wrappoint) to)
3577 (ps-continue-line))
12b88fff 3578 (setq ps-width-remaining (- ps-width-remaining (* len char-width)))
87a16a06
RS
3579 (ps-output-string str)
3580 (ps-output " S\n")))
ef2cbb24 3581
12d89a2e
RS
3582(defun ps-color-value (x-color-value)
3583 ;; Scale 16-bit X-COLOR-VALUE to PostScript color value in [0, 1] interval.
3584 (/ x-color-value ps-print-color-scale))
ef2cbb24 3585
043620f4
KH
3586(defun ps-color-values (x-color)
3587 (cond ((fboundp 'x-color-values)
3588 (x-color-values x-color))
12b88fff
RS
3589 ((and (fboundp 'color-instance-rgb-components)
3590 (ps-color-device))
3591 (color-instance-rgb-components
3592 (if (color-instance-p x-color)
3593 x-color
3594 (make-color-instance
3595 (if (color-specifier-p x-color)
3596 (color-name x-color)
3597 x-color)))))
043620f4
KH
3598 (t (error "No available function to determine X color values."))))
3599
87a16a06 3600
a18ed129
RS
3601(defun ps-face-attributes (face)
3602 "Return face attribute vector.
87a16a06 3603
a18ed129
RS
3604If FACE is not in `ps-print-face-extension-alist' or in
3605`ps-print-face-alist', insert it on `ps-print-face-alist' and
3606return the attribute vector.
87a16a06
RS
3607
3608If FACE is not a valid face name, it is used default face."
a18ed129
RS
3609 (cdr (or (assq face ps-print-face-extension-alist)
3610 (assq face ps-print-face-alist)
3611 (let* ((the-face (if (facep face) face 'default))
3612 (new-face (ps-screen-to-bit-face the-face)))
3613 (or (and (eq the-face 'default)
3614 (assq the-face ps-print-face-alist))
3615 (setq ps-print-face-alist (cons new-face ps-print-face-alist)))
3616 new-face))))
87a16a06 3617
043620f4
KH
3618
3619(defun ps-face-attribute-list (face-or-list)
3620 (if (listp face-or-list)
87a16a06 3621 ;; list of faces
857686a6
RS
3622 (let ((effects 0)
3623 foreground background face-attr)
043620f4 3624 (while face-or-list
857686a6 3625 (setq face-attr (ps-face-attributes (car face-or-list))
87a16a06
RS
3626 effects (logior effects (aref face-attr 0)))
3627 (or foreground (setq foreground (aref face-attr 1)))
3628 (or background (setq background (aref face-attr 2)))
043620f4 3629 (setq face-or-list (cdr face-or-list)))
87a16a06
RS
3630 (vector effects foreground background))
3631 ;; simple face
043620f4
KH
3632 (ps-face-attributes face-or-list)))
3633
87a16a06 3634
12b88fff
RS
3635(defconst ps-font-type (vector nil 'bold 'italic 'bold-italic))
3636
3637
12d89a2e 3638(defun ps-plot-with-face (from to face)
12b88fff
RS
3639 (cond
3640 ((null face) ; print text with null face
87a16a06 3641 (ps-plot-region from to 0))
12b88fff
RS
3642 ((eq face 'emacs--invisible--face)) ; skip invisible text!!!
3643 (t ; otherwise, text has a valid face
3644 (let* ((face-bit (ps-face-attribute-list face))
3645 (effect (aref face-bit 0))
3646 (foreground (aref face-bit 1))
3647 (background (aref face-bit 2))
3648 (fg-color (if (and ps-print-color-p foreground (ps-color-device))
3649 (mapcar 'ps-color-value
3650 (ps-color-values foreground))
3651 ps-default-color))
3652 (bg-color (and ps-print-color-p background (ps-color-device)
3653 (mapcar 'ps-color-value
3654 (ps-color-values background)))))
3655 (ps-plot-region
3656 from to
3657 (ps-font-number 'ps-font-for-text
3658 (or (aref ps-font-type (logand effect 3))
3659 face))
3660 fg-color bg-color (lsh effect -2)))))
87a16a06 3661 (goto-char to))
12d89a2e
RS
3662
3663
12d89a2e 3664(defun ps-xemacs-face-kind-p (face kind kind-regex kind-list)
857686a6
RS
3665 (let* ((frame-font (or (face-font-instance face)
3666 (face-font-instance 'default)))
3667 (kind-cons (and frame-font
3668 (assq kind (font-instance-properties frame-font))))
12d89a2e
RS
3669 (kind-spec (cdr-safe kind-cons))
3670 (case-fold-search t))
12d89a2e
RS
3671 (or (and kind-spec (string-match kind-regex kind-spec))
3672 ;; Kludge-compatible:
3673 (memq face kind-list))))
3674
3675(defun ps-face-bold-p (face)
6770a60f 3676 (if (eq ps-print-emacs-type 'emacs)
06fb6aab
RS
3677 (or (face-bold-p face)
3678 (memq face ps-bold-faces))
8bd22fcf 3679 (ps-xemacs-face-kind-p face 'WEIGHT_NAME "bold\\|demibold" ps-bold-faces)))
12d89a2e
RS
3680
3681(defun ps-face-italic-p (face)
6770a60f 3682 (if (eq ps-print-emacs-type 'emacs)
06fb6aab
RS
3683 (or (face-italic-p face)
3684 (memq face ps-italic-faces))
8bd22fcf
KH
3685 (or (ps-xemacs-face-kind-p face 'ANGLE_NAME "i\\|o" ps-italic-faces)
3686 (ps-xemacs-face-kind-p face 'SLANT "i\\|o" ps-italic-faces))))
12d89a2e
RS
3687
3688(defun ps-face-underlined-p (face)
3689 (or (face-underline-p face)
3690 (memq face ps-underlined-faces)))
3691
a18ed129 3692
043620f4
KH
3693;; Ensure that face-list is fbound.
3694(or (fboundp 'face-list) (defalias 'face-list 'list-faces))
12d89a2e 3695
a18ed129 3696
12d89a2e 3697(defun ps-build-reference-face-lists ()
857686a6
RS
3698 ;; Ensure that face database is updated with faces on
3699 ;; `font-lock-face-attributes' (obsolete stuff)
3700 (ps-font-lock-face-attributes)
3701 ;; Now, rebuild reference face lists
a18ed129 3702 (setq ps-print-face-alist nil)
12d89a2e 3703 (if ps-auto-font-detect
a18ed129
RS
3704 (mapcar 'ps-map-face (face-list))
3705 (mapcar 'ps-set-face-bold ps-bold-faces)
3706 (mapcar 'ps-set-face-italic ps-italic-faces)
3707 (mapcar 'ps-set-face-underline ps-underlined-faces))
12d89a2e 3708 (setq ps-build-face-reference nil))
ef2cbb24 3709
a18ed129
RS
3710
3711(defun ps-set-face-bold (face)
3712 (ps-set-face-attribute face 1))
3713
3714(defun ps-set-face-italic (face)
3715 (ps-set-face-attribute face 2))
3716
3717(defun ps-set-face-underline (face)
3718 (ps-set-face-attribute face 4))
3719
3720
3721(defun ps-set-face-attribute (face effect)
3722 (let ((face-bit (cdr (ps-map-face face))))
3723 (aset face-bit 0 (logior (aref face-bit 0) effect))))
3724
3725
3726(defun ps-map-face (face)
3727 (let* ((face-map (ps-screen-to-bit-face face))
3728 (ps-face-bit (cdr (assq (car face-map) ps-print-face-alist))))
3729 (if ps-face-bit
3730 ;; if face exists, merge both
3731 (let ((face-bit (cdr face-map)))
3732 (aset ps-face-bit 0 (logior (aref ps-face-bit 0) (aref face-bit 0)))
3733 (or (aref ps-face-bit 1) (aset ps-face-bit 1 (aref face-bit 1)))
3734 (or (aref ps-face-bit 2) (aset ps-face-bit 2 (aref face-bit 2))))
3735 ;; if face does not exist, insert it
3736 (setq ps-print-face-alist (cons face-map ps-print-face-alist)))
3737 face-map))
3738
3739
3740(defun ps-screen-to-bit-face (face)
3741 (cons face
3742 (vector (logior (if (ps-face-bold-p face) 1 0) ; bold
3743 (if (ps-face-italic-p face) 2 0) ; italic
3744 (if (ps-face-underlined-p face) 4 0)) ; underline
3745 (face-foreground face)
3746 (face-background face))))
3747
3748
ef2cbb24
RS
3749(defun ps-mapper (extent list)
3750 (nconc list (list (list (extent-start-position extent) 'push extent)
06fb6aab 3751 (list (extent-end-position extent) 'pull extent)))
ef2cbb24
RS
3752 nil)
3753
00aa16af
RS
3754(defun ps-extent-sorter (a b)
3755 (< (extent-priority a) (extent-priority b)))
043620f4
KH
3756
3757(defun ps-print-ensure-fontified (start end)
857686a6 3758 (and (boundp 'lazy-lock-mode) (symbol-value 'lazy-lock-mode)
8bd22fcf
KH
3759 (if (fboundp 'lazy-lock-fontify-region)
3760 (lazy-lock-fontify-region start end) ; the new
3761 (lazy-lock-fontify-buffer)))) ; the old
043620f4 3762
ef2cbb24 3763(defun ps-generate-postscript-with-faces (from to)
87a16a06 3764 ;; Some initialization...
857686a6 3765 (setq ps-current-effect 0)
87a16a06 3766
00aa16af 3767 ;; Build the reference lists of faces if necessary.
12d89a2e
RS
3768 (if (or ps-always-build-face-reference
3769 ps-build-face-reference)
3770 (progn
3771 (message "Collecting face information...")
3772 (ps-build-reference-face-lists)))
00aa16af
RS
3773 ;; Set the color scale. We do it here instead of in the defvar so
3774 ;; that ps-print can be dumped into emacs. This expression can't be
3775 ;; evaluated at dump-time because X isn't initialized.
3776 (setq ps-print-color-scale
857686a6 3777 (if (and ps-print-color-p (ps-color-device))
043620f4 3778 (float (car (ps-color-values "white")))
00aa16af
RS
3779 1.0))
3780 ;; Generate some PostScript.
ef2cbb24
RS
3781 (save-restriction
3782 (narrow-to-region from to)
12d89a2e
RS
3783 (let ((face 'default)
3784 (position to))
043620f4 3785 (ps-print-ensure-fontified from to)
87a16a06
RS
3786 (cond
3787 ((or (eq ps-print-emacs-type 'lucid)
3788 (eq ps-print-emacs-type 'xemacs))
3789 ;; Build the list of extents...
3790 (let ((a (cons 'dummy nil))
3791 record type extent extent-list)
3792 (map-extents 'ps-mapper nil from to a)
8bd22fcf
KH
3793 (setq a (sort (cdr a) 'car-less-than-car)
3794 extent-list nil)
87a16a06
RS
3795
3796 ;; Loop through the extents...
3797 (while a
8bd22fcf 3798 (setq record (car a)
87a16a06 3799
8bd22fcf
KH
3800 position (car record)
3801 record (cdr record)
87a16a06 3802
8bd22fcf
KH
3803 type (car record)
3804 record (cdr record)
87a16a06 3805
8bd22fcf 3806 extent (car record))
87a16a06
RS
3807
3808 ;; Plot up to this record.
3809 ;; XEmacs 19.12: for some reason, we're getting into a
3810 ;; situation in which some of the records have
3811 ;; positions less than 'from'. Since we've narrowed
3812 ;; the buffer, this'll generate errors. This is a
3813 ;; hack, but don't call ps-plot-with-face unless from >
3814 ;; point-min.
8bd22fcf
KH
3815 (and (>= from (point-min)) (<= position (point-max))
3816 (ps-plot-with-face from position face))
87a16a06
RS
3817
3818 (cond
3819 ((eq type 'push)
3820 (if (extent-face extent)
3821 (setq extent-list (sort (cons extent extent-list)
3822 'ps-extent-sorter))))
3823
3824 ((eq type 'pull)
3825 (setq extent-list (sort (delq extent extent-list)
3826 'ps-extent-sorter))))
3827
3828 (setq face
3829 (if extent-list
3830 (extent-face (car extent-list))
8bd22fcf 3831 'default)
87a16a06 3832
8bd22fcf
KH
3833 from position
3834 a (cdr a)))))
87a16a06
RS
3835
3836 ((eq ps-print-emacs-type 'emacs)
3837 (let ((property-change from)
3838 (overlay-change from))
3839 (while (< from to)
3840 (if (< property-change to) ; Don't search for property change
12d89a2e 3841 ; unless previous search succeeded.
87a16a06
RS
3842 (setq property-change
3843 (next-property-change from nil to)))
3844 (if (< overlay-change to) ; Don't search for overlay change
12d89a2e 3845 ; unless previous search succeeded.
87a16a06
RS
3846 (setq overlay-change
3847 (min (next-overlay-change from) to)))
3848 (setq position
3849 (min property-change overlay-change))
3850 ;; The code below is not quite correct,
3851 ;; because a non-nil overlay invisible property
3852 ;; which is inactive according to the current value
3853 ;; of buffer-invisibility-spec nonetheless overrides
3854 ;; a face text property.
3855 (setq face
3856 (cond ((let ((prop (get-text-property from 'invisible)))
3857 ;; Decide whether this invisible property
3858 ;; really makes the text invisible.
3859 (if (eq buffer-invisibility-spec t)
3860 (not (null prop))
3861 (or (memq prop buffer-invisibility-spec)
3862 (assq prop buffer-invisibility-spec))))
12b88fff 3863 'emacs--invisible--face)
87a16a06
RS
3864 ((get-text-property from 'face))
3865 (t 'default)))
3866 (let ((overlays (overlays-at from))
3867 (face-priority -1)) ; text-property
3868 (while overlays
3869 (let* ((overlay (car overlays))
3870 (overlay-face (overlay-get overlay 'face))
3871 (overlay-invisible (overlay-get overlay 'invisible))
3872 (overlay-priority (or (overlay-get overlay
3873 'priority)
3874 0)))
8bd22fcf
KH
3875 (and (or overlay-invisible overlay-face)
3876 (> overlay-priority face-priority)
3877 (setq face (cond ((if (eq buffer-invisibility-spec t)
3878 (not (null overlay-invisible))
3879 (or (memq overlay-invisible
3880 buffer-invisibility-spec)
3881 (assq overlay-invisible
3882 buffer-invisibility-spec)))
3883 nil)
3884 ((and face overlay-face)))
3885 face-priority overlay-priority)))
87a16a06
RS
3886 (setq overlays (cdr overlays))))
3887 ;; Plot up to this record.
3888 (ps-plot-with-face from position face)
3889 (setq from position)))))
3890 (ps-plot-with-face from to face))))
ef2cbb24
RS
3891
3892(defun ps-generate-postscript (from to)
12d89a2e 3893 (ps-plot-region from to 0 nil))
ef2cbb24
RS
3894
3895(defun ps-generate (buffer from to genfunc)
87a16a06
RS
3896 (save-excursion
3897 (let ((from (min to from))
3898 (to (max to from))
3899 ;; This avoids trouble if chars with read-only properties
3900 ;; are copied into ps-spool-buffer.
3901 (inhibit-read-only t))
3902 (save-restriction
3903 (narrow-to-region from to)
857686a6
RS
3904 (and ps-razzle-dazzle
3905 (message "Formatting...%3d%%" (setq ps-razchunk 0)))
87a16a06 3906 (set-buffer buffer)
8bd22fcf
KH
3907 (setq ps-source-buffer buffer
3908 ps-spool-buffer (get-buffer-create ps-spool-buffer-name))
87a16a06
RS
3909 (ps-init-output-queue)
3910 (let (safe-marker completed-safely needs-begin-file)
3911 (unwind-protect
00aa16af
RS
3912 (progn
3913 (set-buffer ps-spool-buffer)
7da17ab6 3914 (set-buffer-multibyte nil)
87a16a06
RS
3915 ;; Get a marker and make it point to the current end of the
3916 ;; buffer, If an error occurs, we'll delete everything from
3917 ;; the end of this marker onwards.
3918 (setq safe-marker (make-marker))
3919 (set-marker safe-marker (point-max))
3920
3921 (goto-char (point-min))
8bd22fcf
KH
3922 (or (looking-at (regexp-quote ps-adobe-tag))
3923 (setq needs-begin-file t))
87a16a06
RS
3924 (save-excursion
3925 (set-buffer ps-source-buffer)
3926 (if needs-begin-file (ps-begin-file))
3927 (ps-begin-job)
3928 (ps-begin-page))
3929 (set-buffer ps-source-buffer)
3930 (funcall genfunc from to)
3931 (ps-end-page)
3932
8bd22fcf
KH
3933 (and ps-spool-duplex (= (mod ps-page-count 2) 1)
3934 (ps-dummy-page))
7da17ab6 3935 (ps-end-file)
87a16a06
RS
3936 (ps-flush-output)
3937
3938 ;; Back to the PS output buffer to set the page count
7da17ab6
RS
3939 (let ((total-lines (if ps-printing-region
3940 (cdr ps-printing-region)
3941 (ps-count-lines (point-min) (point-max))))
3942 (total-pages (if ps-print-only-one-header
3943 (ps-page-number)
3944 ps-page-count)))
3945 (set-buffer ps-spool-buffer)
3946 (goto-char (point-min))
3947 (while (re-search-forward "^/Lines 0 def\n/PageCount 0 def$"
3948 nil t)
3949 (replace-match (format "/Lines %d def\n/PageCount %d def"
3950 total-lines total-pages) t)))
87a16a06
RS
3951
3952 ;; Setting this variable tells the unwind form that the
8bd22fcf 3953 ;; the PostScript was generated without error.
87a16a06
RS
3954 (setq completed-safely t))
3955
3956 ;; Unwind form: If some bad mojo occurred while generating
8bd22fcf 3957 ;; PostScript, delete all the PostScript that was generated.
87a16a06
RS
3958 ;; This protects the previously spooled files from getting
3959 ;; corrupted.
8bd22fcf
KH
3960 (and (markerp safe-marker) (not completed-safely)
3961 (progn
3962 (set-buffer ps-spool-buffer)
3963 (delete-region (marker-position safe-marker) (point-max))))))
87a16a06 3964
857686a6 3965 (and ps-razzle-dazzle (message "Formatting...done"))))))
ef2cbb24 3966
857686a6 3967;; Permit dynamic evaluation at print time of `ps-lpr-switches'.
ef2cbb24 3968(defun ps-do-despool (filename)
12d89a2e 3969 (if (or (not (boundp 'ps-spool-buffer))
bcc0d457 3970 (not (symbol-value 'ps-spool-buffer)))
12d89a2e 3971 (message "No spooled PostScript to print")
ef2cbb24
RS
3972 (if filename
3973 (save-excursion
857686a6 3974 (and ps-razzle-dazzle (message "Saving..."))
12d89a2e 3975 (set-buffer ps-spool-buffer)
ef2cbb24 3976 (setq filename (expand-file-name filename))
7ffaf659
EZ
3977 (let ((coding-system-for-write 'raw-text-unix))
3978 (write-region (point-min) (point-max) filename))
857686a6 3979 (and ps-razzle-dazzle (message "Wrote %s" filename)))
ef2cbb24 3980 ;; Else, spool to the printer
857686a6 3981 (and ps-razzle-dazzle (message "Printing..."))
ef2cbb24 3982 (save-excursion
12d89a2e 3983 (set-buffer ps-spool-buffer)
7ffaf659
EZ
3984 (let ((coding-system-for-write 'raw-text-unix))
3985 (if (and (eq system-type 'ms-dos)
3986 (stringp (symbol-value 'dos-ps-printer)))
3987 (write-region (point-min) (point-max)
3988 (symbol-value 'dos-ps-printer) t 0)
62901aee
RS
3989 (apply 'call-process-region
3990 (point-min) (point-max) ps-lpr-command nil
857686a6 3991 (and (fboundp 'start-process) 0)
62901aee 3992 nil
857686a6
RS
3993 (ps-flatten-list ; dynamic evaluation
3994 (mapcar 'ps-eval-switch ps-lpr-switches))))))
3995 (and ps-razzle-dazzle (message "Printing...done")))
12d89a2e
RS
3996 (kill-buffer ps-spool-buffer)))
3997
857686a6
RS
3998;; Dynamic evaluation
3999(defun ps-eval-switch (arg)
4000 (cond ((stringp arg) arg)
4001 ((functionp arg) (apply arg nil))
4002 ((symbolp arg) (symbol-value arg))
4003 ((consp arg) (apply (car arg) (cdr arg)))
4004 (t nil)))
4005
4006;; `ps-flatten-list' is defined here (copied from "message.el" and
4007;; enhanced to handle dotted pairs as well) until we can get some
4008;; sensible autoloads, or `flatten-list' gets put somewhere decent.
4009
4010;; (ps-flatten-list '((a . b) c (d . e) (f g h) i . j))
4011;; => (a b c d e f g h i j)
4012
4013(defun ps-flatten-list (&rest list)
4014 (ps-flatten-list-1 list))
4015
4016(defun ps-flatten-list-1 (list)
4017 (cond ((null list) nil)
4018 ((consp list) (append (ps-flatten-list-1 (car list))
4019 (ps-flatten-list-1 (cdr list))))
4020 (t (list list))))
4021
12d89a2e
RS
4022(defun ps-kill-emacs-check ()
4023 (let (ps-buffer)
8bd22fcf
KH
4024 (and (setq ps-buffer (get-buffer ps-spool-buffer-name))
4025 (buffer-modified-p ps-buffer)
4026 (y-or-n-p "Unprinted PostScript waiting; print now? ")
4027 (ps-despool))
4028 (and (setq ps-buffer (get-buffer ps-spool-buffer-name))
4029 (buffer-modified-p ps-buffer)
4030 (not (yes-or-no-p "Unprinted PostScript waiting; exit anyway? "))
4031 (error "Unprinted PostScript"))))
12d89a2e
RS
4032
4033(if (fboundp 'add-hook)
bcc0d457 4034 (funcall 'add-hook 'kill-emacs-hook 'ps-kill-emacs-check)
12d89a2e
RS
4035 (if kill-emacs-hook
4036 (message "Won't override existing kill-emacs-hook")
4037 (setq kill-emacs-hook 'ps-kill-emacs-check)))
ef2cbb24 4038
12d89a2e 4039;;; Sample Setup Code:
ef2cbb24 4040
12d89a2e 4041;; This stuff is for anybody that's brave enough to look this far,
87a16a06
RS
4042;; and able to figure out how to use it. It isn't really part of
4043;; ps-print, but I'll leave it here in hopes it might be useful:
ef2cbb24 4044
043620f4
KH
4045;; WARNING!!! The following code is *sample* code only. Don't use it
4046;; unless you understand what it does!
4047
87a16a06
RS
4048(defmacro ps-prsc ()
4049 `(if (eq ps-print-emacs-type 'emacs) [f22] 'f22))
4050(defmacro ps-c-prsc ()
4051 `(if (eq ps-print-emacs-type 'emacs) [C-f22] '(control f22)))
4052(defmacro ps-s-prsc ()
4053 `(if (eq ps-print-emacs-type 'emacs) [S-f22] '(shift f22)))
00aa16af 4054
a18ed129
RS
4055;; A hook to bind to `rmail-mode-hook' to locally bind prsc and set the
4056;; `ps-left-headers' specially for mail messages.
4057(defun ps-rmail-mode-hook ()
4058 (local-set-key (ps-prsc) 'ps-rmail-print-message-from-summary)
4059 (setq ps-header-lines 3
4060 ps-left-header
4061 ;; The left headers will display the message's subject, its
4062 ;; author, and the name of the folder it was in.
4063 '(ps-article-subject ps-article-author buffer-name)))
4064
4065;; See `ps-gnus-print-article-from-summary'. This function does the
4066;; same thing for rmail.
4067(defun ps-rmail-print-message-from-summary ()
4068 (interactive)
4069 (ps-print-message-from-summary 'rmail-summary-buffer "RMAIL"))
4070
4071;; Used in `ps-rmail-print-article-from-summary',
4072;; `ps-gnus-print-article-from-summary' and `ps-vm-print-message-from-summary'.
4073(defun ps-print-message-from-summary (summary-buffer summary-default)
4074 (let ((ps-buf (or (and (boundp summary-buffer)
4075 (symbol-value summary-buffer))
4076 summary-default)))
4077 (and (get-buffer ps-buf)
4078 (save-excursion
4079 (set-buffer ps-buf)
4080 (ps-spool-buffer-with-faces)))))
4081
12d89a2e 4082;; Look in an article or mail message for the Subject: line. To be
87a16a06 4083;; placed in `ps-left-headers'.
12d89a2e 4084(defun ps-article-subject ()
ef2cbb24 4085 (save-excursion
12d89a2e 4086 (goto-char (point-min))
45a870d9 4087 (if (re-search-forward "^Subject:[ \t]+\\(.*\\)$" nil t)
055e7bf2 4088 (buffer-substring-no-properties (match-beginning 1) (match-end 1))
12d89a2e
RS
4089 "Subject ???")))
4090
4091;; Look in an article or mail message for the From: line. Sorta-kinda
4092;; understands RFC-822 addresses and can pull the real name out where
87a16a06 4093;; it's provided. To be placed in `ps-left-headers'.
12d89a2e
RS
4094(defun ps-article-author ()
4095 (save-excursion
4096 (goto-char (point-min))
a97592dd 4097 (if (re-search-forward "^From:[ \t]+\\(.*\\)$" nil t)
87a16a06
RS
4098 (let ((fromstring (buffer-substring-no-properties (match-beginning 1)
4099 (match-end 1))))
12d89a2e
RS
4100 (cond
4101
4102 ;; Try first to match addresses that look like
4103 ;; thompson@wg2.waii.com (Jim Thompson)
4104 ((string-match ".*[ \t]+(\\(.*\\))" fromstring)
4105 (substring fromstring (match-beginning 1) (match-end 1)))
4106
4107 ;; Next try to match addresses that look like
4108 ;; Jim Thompson <thompson@wg2.waii.com>
4109 ((string-match "\\(.*\\)[ \t]+<.*>" fromstring)
4110 (substring fromstring (match-beginning 1) (match-end 1)))
4111
4112 ;; Couldn't find a real name -- show the address instead.
4113 (t fromstring)))
4114 "From ???")))
4115
a18ed129 4116;; A hook to bind to `gnus-article-prepare-hook'. This will set the
87a16a06
RS
4117;; `ps-left-headers' specially for gnus articles. Unfortunately,
4118;; `gnus-article-mode-hook' is called only once, the first time the *Article*
12d89a2e
RS
4119;; buffer enters that mode, so it would only work for the first time
4120;; we ran gnus. The second time, this hook wouldn't get set up. The
87a16a06 4121;; only alternative is `gnus-article-prepare-hook'.
12d89a2e 4122(defun ps-gnus-article-prepare-hook ()
8bd22fcf
KH
4123 (setq ps-header-lines 3
4124 ps-left-header
12d89a2e
RS
4125 ;; The left headers will display the article's subject, its
4126 ;; author, and the newsgroup it was in.
8bd22fcf 4127 '(ps-article-subject ps-article-author gnus-newsgroup-name)))
12d89a2e 4128
a18ed129
RS
4129;; A hook to bind to `vm-mode-hook' to locally bind prsc and set the
4130;; `ps-left-headers' specially for mail messages.
12d89a2e 4131(defun ps-vm-mode-hook ()
00aa16af 4132 (local-set-key (ps-prsc) 'ps-vm-print-message-from-summary)
8bd22fcf
KH
4133 (setq ps-header-lines 3
4134 ps-left-header
12d89a2e
RS
4135 ;; The left headers will display the message's subject, its
4136 ;; author, and the name of the folder it was in.
8bd22fcf 4137 '(ps-article-subject ps-article-author buffer-name)))
12d89a2e
RS
4138
4139;; Every now and then I forget to switch from the *Summary* buffer to
4140;; the *Article* before hitting prsc, and a nicely formatted list of
4141;; article subjects shows up at the printer. This function, bound to
4142;; prsc for the gnus *Summary* buffer means I don't have to switch
4143;; buffers first.
87a16a06 4144;; sb: Updated for Gnus 5.
12d89a2e
RS
4145(defun ps-gnus-print-article-from-summary ()
4146 (interactive)
a18ed129 4147 (ps-print-message-from-summary 'gnus-article-buffer "*Article*"))
ef2cbb24 4148
87a16a06 4149;; See `ps-gnus-print-article-from-summary'. This function does the
12d89a2e
RS
4150;; same thing for vm.
4151(defun ps-vm-print-message-from-summary ()
4152 (interactive)
a18ed129 4153 (ps-print-message-from-summary 'vm-mail-buffer ""))
ef2cbb24 4154
87a16a06 4155;; A hook to bind to bind to `gnus-summary-setup-buffer' to locally bind
12d89a2e
RS
4156;; prsc.
4157(defun ps-gnus-summary-setup ()
00aa16af 4158 (local-set-key (ps-prsc) 'ps-gnus-print-article-from-summary))
12d89a2e
RS
4159
4160;; Look in an article or mail message for the Subject: line. To be
87a16a06 4161;; placed in `ps-left-headers'.
12d89a2e
RS
4162(defun ps-info-file ()
4163 (save-excursion
4164 (goto-char (point-min))
a97592dd 4165 (if (re-search-forward "File:[ \t]+\\([^, \t\n]*\\)" nil t)
055e7bf2 4166 (buffer-substring-no-properties (match-beginning 1) (match-end 1))
12d89a2e
RS
4167 "File ???")))
4168
4169;; Look in an article or mail message for the Subject: line. To be
87a16a06 4170;; placed in `ps-left-headers'.
12d89a2e
RS
4171(defun ps-info-node ()
4172 (save-excursion
4173 (goto-char (point-min))
a97592dd 4174 (if (re-search-forward "Node:[ \t]+\\([^,\t\n]*\\)" nil t)
055e7bf2 4175 (buffer-substring-no-properties (match-beginning 1) (match-end 1))
12d89a2e
RS
4176 "Node ???")))
4177
4178(defun ps-info-mode-hook ()
4179 (setq ps-left-header
4180 ;; The left headers will display the node name and file name.
8bd22fcf 4181 '(ps-info-node ps-info-file)))
12d89a2e 4182
043620f4
KH
4183;; WARNING! The following function is a *sample* only, and is *not*
4184;; meant to be used as a whole unless you understand what the effects
87a16a06
RS
4185;; will be! (In fact, this is a copy of Jim's setup for ps-print --
4186;; I'd be very surprised if it was useful to *anybody*, without
043620f4
KH
4187;; modification.)
4188
12d89a2e 4189(defun ps-jts-ps-setup ()
00aa16af
RS
4190 (global-set-key (ps-prsc) 'ps-spool-buffer-with-faces) ;f22 is prsc
4191 (global-set-key (ps-s-prsc) 'ps-spool-region-with-faces)
4192 (global-set-key (ps-c-prsc) 'ps-despool)
12d89a2e
RS
4193 (add-hook 'gnus-article-prepare-hook 'ps-gnus-article-prepare-hook)
4194 (add-hook 'gnus-summary-mode-hook 'ps-gnus-summary-setup)
4195 (add-hook 'vm-mode-hook 'ps-vm-mode-hook)
00aa16af 4196 (add-hook 'vm-mode-hooks 'ps-vm-mode-hook)
12d89a2e 4197 (add-hook 'Info-mode-hook 'ps-info-mode-hook)
8bd22fcf
KH
4198 (setq ps-spool-duplex t
4199 ps-print-color-p nil
4200 ps-lpr-command "lpr"
4201 ps-lpr-switches '("-Jjct,duplex_long"))
bcc0d457
RS
4202 'ps-jts-ps-setup)
4203
4204;; WARNING! The following function is a *sample* only, and is *not*
4205;; meant to be used as a whole unless it corresponds to your needs.
4206;; (In fact, this is a copy of Jack's setup for ps-print --
4207;; I would not be that surprised if it was useful to *anybody*,
4208;; without modification.)
4209
4210(defun ps-jack-setup ()
87a16a06 4211 (setq ps-print-color-p nil
bcc0d457 4212 ps-lpr-command "lpr"
8bd22fcf 4213 ps-lpr-switches nil
bcc0d457 4214
87a16a06
RS
4215 ps-paper-type 'a4
4216 ps-landscape-mode t
bcc0d457
RS
4217 ps-number-of-columns 2
4218
4219 ps-left-margin (/ (* 72 1.0) 2.54) ; 1.0 cm
4220 ps-right-margin (/ (* 72 1.0) 2.54) ; 1.0 cm
4221 ps-inter-column (/ (* 72 1.0) 2.54) ; 1.0 cm
4222 ps-bottom-margin (/ (* 72 1.5) 2.54) ; 1.5 cm
4223 ps-top-margin (/ (* 72 1.5) 2.54) ; 1.5 cm
4224 ps-header-offset (/ (* 72 1.0) 2.54) ; 1.0 cm
4225 ps-header-line-pad .15
4226 ps-print-header t
4227 ps-print-header-frame t
4228 ps-header-lines 2
4229 ps-show-n-of-n t
4230 ps-spool-duplex nil
4231
4232 ps-font-family 'Courier
4233 ps-font-size 5.5
4234 ps-header-font-family 'Helvetica
4235 ps-header-font-size 6
4236 ps-header-title-font-size 8)
4237 'ps-jack-setup)
12d89a2e
RS
4238
4239(provide 'ps-print)
b87c5d3d 4240
12d89a2e 4241;;; ps-print.el ends here