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