Use new form of calendar-read-date.
[emacs.git] / lisp / ps-print.el
blobcd089a8b448317c023fb10d2e357b6885a606b4a
1 ;; Jim's Pretty-Good PostScript Generator for Emacs 19 (ps-print).
2 ;; Copyright (C) 1993, 1994 Free Software Foundation, Inc.
4 ;; Author: James C. Thompson <thompson@wg2.waii.com>
5 ;; Keywords: faces, postscript, printing
7 ;; This file is part of GNU Emacs.
9 ;; GNU Emacs is free software; you can redistribute it and/or modify
10 ;; it under the terms of the GNU General Public License as published by
11 ;; the Free Software Foundation; either version 2, or (at your option)
12 ;; any later version.
14 ;; GNU Emacs is distributed in the hope that it will be useful,
15 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 ;; GNU General Public License for more details.
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with GNU Emacs; see the file COPYING. If not, write to
21 ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23 ;; Acknowledgements
24 ;; ----------------
25 ;; Thanks to Avishai Yacobi, avishaiy@mcil.comm.mot.com, for writing
26 ;; the Emacs 19 port.
28 ;; Thanks to Remi Houdaille and Michel Train, michel@metasoft.fdn.org,
29 ;; for adding underline support and title code. (Titling will appear
30 ;; in the next release.)
32 ;; Thanks to Heiko Muenkel, muenkel@tnt.uni-hannover.de, for showing
33 ;; me how to handle ISO-8859/1 characters.
35 ;; Code to handle ISO-8859/1 characters borrowed from the mp prologue
36 ;; file mp.pro.ps, used with permission of Rich Burridge of Sun
37 ;; Microsystems (Rich.Burridge@eng.sun.com).
39 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
41 ;; About ps-print:
42 ;; --------------
43 ;; This package provides printing of Emacs buffers on PostScript
44 ;; printers; the buffer's bold and italic text attributes are
45 ;; preserved in the printer output. Ps-print is intended for use with
46 ;; Emacs 19 (Lucid or FSF) and a fontifying package such as font-lock
47 ;; or hilit.
48 ;;
49 ;; Installing ps-print:
50 ;; -------------------
51 ;; Place ps-print somewhere in your load-path and byte-compile it.
52 ;; Load ps-print with (require 'ps-print).
54 ;; Using ps-print:
55 ;; --------------
56 ;; The variables ps-bold-faces and ps-italic-faces *must* contain
57 ;; lists of the faces that you wish to print in bold or italic font.
58 ;; These variables already contain some default values, but most users
59 ;; will probably have to add some of their own. To add a face to one
60 ;; of these lists, put code something like the following into your
61 ;; .emacs startup file:
63 ;; (setq ps-bold-faces (cons 'my-bold-face ps-bold-faces))
65 ;; Ps-print's printer interface is governed by the variables ps-lpr-
66 ;; command and ps-lpr-switches; these are analogous to the variables
67 ;; lpr-command and lpr-switches in the Emacs lpr package.
69 ;; To use ps-print, invoke the command ps-print-buffer-with-faces.
70 ;; This will generate a PostScript image of the current buffer and
71 ;; send it to the printer. Precede this command with a numeric prefix
72 ;; (C-u), and the PostScript output will be saved in a file; you will
73 ;; be prompted for a filename. Also see the functions ps-print-
74 ;; buffer, ps-print-region, and ps-print-region-with-faces.
76 ;; I recommend binding ps-print-buffer-with-faces to a key sequence;
77 ;; on a Sun 4 keyboard, for example, you can bind to the PrSc key (aka
78 ;; r22):
80 ;; (global-set-key 'f22 'ps-print-buffer-with-faces)
81 ;; (global-set-key '(shift f22) 'ps-print-region-with-faces)
83 ;; Or, as I now prefer, you can also bind the ps-spool- functions to
84 ;; keys; here's my bindings:
86 ;; (global-set-key 'f22 'ps-spool-buffer-with-faces)
87 ;; (global-set-key '(shift f22) 'ps-spool-region-with-faces)
88 ;; (global-set-key '(control f22) 'ps-despool)
90 ;; Using ps-print with other Emacses:
91 ;; ---------------------------------
92 ;; Although it was intended for use with Emacs 19, ps-print will also work
93 ;; with Emacs version 18; you won't get fancy fontified output, but it
94 ;; should work.
95 ;;
96 ;; A few words about support:
97 ;; -------------------------
98 ;; Despite its appearance, with comment blocks, usage instructions, and
99 ;; documentation strings, ps-print is not a supported package. That's all
100 ;; a masquerade. Ps-print is something I threw together in my spare time--
101 ;; an evening here, a Saturday there--to make my printouts look like my
102 ;; Emacs buffers. It works, but is not complete.
104 ;; Unfortunately, supporting elisp code is not my job and, now that I have
105 ;; what I need out of ps-print, additional support is going to be up to
106 ;; you, the user. But that's the spirit of Emacs, isn't it? I call on
107 ;; all who use this package to help in developing it further. If you
108 ;; notice a bug, fix it and send me the patches. If you add a feature,
109 ;; again, send me the patches. I will collect all such contributions and
110 ;; periodically post the updates to the appropriate places.
112 ;; A few more words about support:
113 ;; ------------------------------
114 ;; The response to my call for public support of ps-print has been
115 ;; terrific. With the exception of the spooling mechanism, all the new
116 ;; features in this version of ps-print were contributed by users. I have
117 ;; some contributed code for printing headers that I'll add to the next
118 ;; release of ps-print, but there are still other features that users can
119 ;; write. See the "Features to Add" list a little further on, and keep
120 ;; that elisp rolling in.
122 ;; Please send all bug fixes and enhancements to me, thompson@wg2.waii.com.
124 ;; New in version 1.5
125 ;; ------------------
126 ;; Support for Emacs 19. Works with both overlays and text
127 ;; properties.
129 ;; Underlining.
131 ;; Local spooling; see function ps-spool-buffer.
133 ;; Support for ISO8859-1 character set.
135 ;; Page breaks are now handled correctly.
137 ;; Percentages reported while formatting are now correct.
139 ;; Known bugs and limitations of ps-print:
140 ;; --------------------------------------
141 ;; Slow. (Byte-compiling helps.)
143 ;; The PostScript needs review/cleanup/enhancing by a PS expert.
145 ;; ASCII Control characters other than tab, linefeed and pagefeed are
146 ;; not handled.
148 ;; The mechanism for determining whether a stretch of characters
149 ;; should be printed bold, italic, or plain is crude and extremely
150 ;; limited.
152 ;; Faces are always treated as opaque.
154 ;; Font names are hardcoded.
156 ;; Epoch not fully supported.
158 ;; Tested with only one PostScript printer.
160 ;; Features to add:
161 ;; ---------------
162 ;; Line numbers.
164 ;; Simple headers with date, filename, and page numbers.
166 ;; Gaudy headers a`la enscript and mp.
168 ;; 2-up and 4-up capability.
170 ;; Wide-print capability.
173 ;;; Code:
175 (defconst ps-print-version (substring "$Revision: 1.5 $" 11 -2)
176 "$Id: ps-print.el,v 1.5 1994/04/22 13:25:18 jct Exp $
178 Please send all bug fixes and enhancements to Jim Thompson,
179 thompson@wg2.waii.com.")
181 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
182 (defvar ps-lpr-command (if (memq system-type
183 '(usg-unix-v hpux silicon-graphics-unix))
184 "lp" "lpr")
185 "The shell command for printing a PostScript file.")
187 (defvar ps-lpr-switches nil
188 "A list of extra switches to pass to ps-lpr-command.")
190 (defvar ps-bold-faces
191 '(bold
192 bold-italic
193 font-lock-function-name-face
194 message-headers
196 "A list of the faces that should be printed italic.")
198 (defvar ps-italic-faces
199 '(italic
200 bold-italic
201 font-lock-function-name-face
202 font-lock-string-face
203 font-lock-comment-face
204 message-header-contents
205 message-highlighted-header-contents
206 message-cited-text
208 "A list of the faces that should be printed bold.")
210 (defvar ps-underline-faces
211 '(underline
212 font-lock-string-face)
213 "A list of the faces that should be printed underline.")
215 (defvar ps-razzle-dazzle t
216 "Non-nil means report progress while formatting buffer")
218 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
220 (defun ps-print-buffer (&optional filename)
222 "Generate and print a PostScript image of the buffer.
224 When called with a numeric prefix argument (C-u), prompt the user for
225 the name of a file to save the PostScript image in, instead of sending
226 it to the printer.
228 More specifically, the FILENAME argument is treated as follows: if it
229 is nil, send the image to the printer. If FILENAME is a string, save
230 the PostScript image in a file with that name. If FILENAME is a
231 number, prompt the user for the name of the file to save in.
233 The image is rendered using the PostScript font Courier.
235 See also: ps-print-buffer-with-faces
236 ps-spool-buffer
237 ps-spool-buffer-with-faces"
239 (interactive "P")
240 (setq filename (ps-preprint filename))
241 (ps-generate (current-buffer) (point-min) (point-max)
242 'ps-generate-postscript)
243 (ps-do-despool filename))
246 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
248 (defun ps-print-buffer-with-faces (&optional filename)
250 "Generate and print a PostScript image of the buffer.
252 This function works like ps-print-buffer, with the additional benefit
253 that any bold/italic formatting information present in the buffer
254 (contained in extents and faces) will be retained in the PostScript
255 image. In other words, WYSIAWYG -- What You See Is (Almost) What You
256 Get.
258 Ps-print uses three lists to determine which faces should be printed
259 bold, italic, and/or underlined; the lists are named ps-bold-faces, ps-
260 italic-faces, and ps-underline-faces. A given face should appear on as
261 many lists as are appropriate; for example, face bold-italic is in both
262 the lists ps-bold-faces and ps-italic-faces. The lists are pre-built
263 with the standard bold, italic, and bold-italic faces, with font-lock's
264 faces, and with the faces used by gnus and rmail.
266 The image is rendered using the PostScript fonts Courier, Courier-Bold,
267 Courier-Oblique, and Courier-BoldOblique.
269 See also: ps-print-buffer
270 ps-spool-buffer
271 ps-spool-buffer-with-faces."
273 (interactive "P")
274 (setq filename (ps-preprint filename))
275 (ps-generate (current-buffer) (point-min) (point-max)
276 'ps-generate-postscript-with-faces)
277 (ps-do-despool filename))
279 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
281 (defun ps-print-region (from to &optional filename)
283 "Generate and print a PostScript image of the region.
285 When called with a numeric prefix argument (C-u), prompt the user for
286 the name of a file to save the PostScript image in, instead of sending
287 it to the printer.
289 This function is essentially the same as ps-print-buffer except that it
290 prints just a region, and not the entire buffer. For more information,
291 see the function ps-print-buffer.
293 See also: ps-print-region-with-faces
294 ps-spool-region
295 ps-spool-region-with-faces"
297 (interactive "r\nP")
298 (setq filename (ps-preprint filename))
299 (ps-generate (current-buffer) from to
300 'ps-generate-postscript)
301 (ps-do-despool filename))
303 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
305 (defun ps-print-region-with-faces (from to &optional filename)
307 "Generate and print a PostScript image of the region.
309 This function is essentially the same as ps-print-buffer except that it
310 prints just a region, and not the entire buffer. See the functions
311 ps-print-region and ps-print-buffer-with-faces for
312 more information.
314 See also: ps-print-region
315 ps-spool-region
316 ps-spool-region-with-faces"
318 (interactive "r\nP")
319 (setq filename (ps-preprint filename))
320 (ps-generate (current-buffer) from to
321 'ps-generate-postscript-with-faces)
322 (ps-do-despool filename))
324 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
326 (defun ps-spool-buffer ()
328 "Generate and spool a PostScript image of the buffer.
330 This function is essentially the same as function ps-print-buffer
331 except that the PostScript image is saved in a local buffer to be sent
332 to the printer later.
334 Each time you call one of the ps-spool- functions, the generated
335 PostScript is appended to a buffer named *PostScript*; to send the
336 spooled PostScript to the printer, or save it to a file, use the command
337 ps-despool.
339 If the variable ps-spool-duplex is non-nil, then the spooled PostScript
340 is padded with blank pages, when needed, so that each printed buffer
341 will start on a front page when printed on a duplex printer (a printer
342 that prints on both sides on the paper). Users of non-duplex printers
343 will want to leave ps-spool-duplex nil.
345 The spooling mechanism was designed for printing lots of small files
346 (mail messages or netnews articles) to save paper that would otherwise
347 be wasted on banner pages, and to make it easier to find your output at
348 the printer (it's easier to pick up one 50-page printout than to find 50
349 single-page printouts).
351 Ps-print has a hook in the kill-emacs-hook list so that you won't
352 accidently quit from Emacs while you have unprinted PostScript waiting
353 in the spool buffer. If you do attempt to exit with spooled PostScript,
354 you'll be asked if you want to print it, and if you decline, you'll be
355 asked to confirm the exit; this is modeled on the confirmation that
356 Emacs uses for modified buffers.
358 See also: ps-despool
359 ps-print-buffer
360 ps-print-buffer-with-faces
361 ps-spool-buffer-with-faces"
363 (interactive)
364 (ps-generate (current-buffer) (point-min) (point-max)
365 'ps-generate-postscript))
367 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
369 (defun ps-spool-buffer-with-faces ()
371 "Generate and spool PostScript image of the buffer.
373 This function is essentially the same as function ps-print-buffer-with-
374 faces except that the PostScript image is saved in a local buffer to be
375 sent to the printer later.
377 Use the function ps-despool to send the spooled images to the printer.
378 See the function ps-spool-buffer for a description of the spooling
379 mechanism.
381 See also: ps-despool
382 ps-spool-buffer
383 ps-print-buffer
384 ps-print-buffer-with-faces"
386 (interactive)
387 (ps-generate (current-buffer) (point-min) (point-max)
388 'ps-generate-postscript-with-faces))
390 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
392 (defun ps-spool-region (from to)
394 "Generate PostScript image of the region and spool locally.
396 This function is essentially the same as function ps-print-region except
397 that the PostScript image is saved in a local buffer to be sent to the
398 printer later.
400 Use the function ps-despool to send the spooled images to the printer.
401 See the function ps-spool-buffer for a description of the spooling
402 mechanism.
404 See also: ps-despool
405 ps-spool-buffer
406 ps-print-buffer
407 ps-print-buffer-with-faces"
409 (interactive "r")
410 (ps-generate (current-buffer) from to
411 'ps-generate-postscript))
413 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
415 (defun ps-spool-region-with-faces (from to)
417 "Generate PostScript image of the region and spool locally.
419 This function is essentially the same as function ps-print-region-with-
420 faces except that the PostScript image is saved in a local buffer to be
421 sent to the printer later.
423 Use the function ps-despool to send the spooled images to the printer.
424 See the function ps-spool-buffer for a description of the spooling
425 mechanism.
427 See also: ps-despool
428 ps-spool-buffer
429 ps-print-buffer
430 ps-print-buffer-with-faces"
432 (interactive "r")
433 (ps-generate (current-buffer) from to
434 'ps-generate-postscript-with-faces))
436 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
438 (defvar ps-spool-duplex nil ; Not many people have duplex
439 ; printers, so default to nil.
440 "*Non-nil indicates spooling is for a two-sided printer.
441 For a duplex printer, the ps-spool functions will insert blank pages
442 as needed between print jobs so that the next buffer printed will
443 start on the right page.")
445 (defun ps-despool (&optional filename)
446 "Send the spooled PostScript to the printer.
448 When called with a numeric prefix argument (C-u), prompt the user for
449 the name of a file to save the spooled PostScript in, instead of sending
450 it to the printer.
452 More specifically, the FILENAME argument is treated as follows: if it
453 is nil, send the image to the printer. If FILENAME is a string, save
454 the PostScript image in a file with that name. If FILENAME is a
455 number, prompt the user for the name of the file to save in."
457 (interactive "P")
459 ;; If argument FILENAME is nil, send the image to the printer; if
460 ;; FILENAME is a string, save the PostScript image in that filename;
461 ;; if FILENAME is a number, prompt the user for the name of the file
462 ;; to save in.
464 (setq filename (ps-preprint filename))
465 (ps-do-despool filename))
467 ;; Here end the definitions that users need to know about; proceed
468 ;; further at your own risk!
469 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
471 (defun ps-kill-emacs-check ()
472 (if (and (setq ps-buffer (get-buffer ps-spool-buffer-name))
473 (buffer-modified-p ps-buffer))
474 (if (y-or-n-p "Unprinted PostScript waiting... print now? ")
475 (ps-despool)))
477 (if (and (setq ps-buffer (get-buffer ps-spool-buffer-name))
478 (buffer-modified-p ps-buffer))
479 (if (yes-or-no-p "Unprinted PostScript waiting; exit anyway? ")
481 (error "Unprinted PostScript"))))
483 (if (fboundp 'add-hook)
484 (add-hook 'kill-emacs-hook 'ps-kill-emacs-check)
485 (if kill-emacs-hook
486 (message "Won't override existing kill-emacs-hook.")
487 (setq kill-emacs-hook 'ps-kill-emacs-check)))
489 (defun ps-preprint (&optional filename)
490 (if (and filename
491 (or (numberp filename)
492 (listp filename)))
493 (setq filename
494 (let* ((name (concat (buffer-name) ".ps"))
495 (prompt (format "Save PostScript to file: (default %s) "
496 name)))
497 (read-file-name prompt default-directory
498 name nil)))))
500 (defvar ps-spool-buffer-name "*PostScript*")
502 (defvar ps-col 0)
503 (defvar ps-row 0)
504 (defvar ps-xpos 0)
505 (defvar ps-ypos 0)
507 (defvar ps-chars-per-line 80)
508 (defvar ps-lines-per-page 66)
510 (defvar ps-page-start-ypos 745)
511 (defvar ps-line-start-xpos 40)
513 (defvar ps-char-xpos-inc 6)
514 (defvar ps-line-ypos-inc 11)
516 (defvar ps-current-font 0)
518 (defvar ps-multiple nil)
519 (defvar ps-virtual-page-number 0)
521 (defun ps-begin-file ()
522 (save-excursion
523 (set-buffer ps-output-buffer)
524 (goto-char (point-min))
525 (setq ps-real-page-number 1)
526 (insert
527 "%!PS-Adobe-1.0
529 /S /show load def
530 /M /moveto load def
531 /L { gsave newpath 3 1 roll 1 sub M 0 rlineto closepath stroke grestore } def
533 /F{$fd exch get setfont}def
535 /StartPage{/svpg save def}def
536 /EndPage{svpg restore showpage}def
538 /SetUpFonts
539 {dup/$fd exch array def{findfont exch scalefont $fd 3 1 roll put}repeat}def
541 % Define /ISOLatin1Encoding only if it's not already there.
542 /ISOLatin1Encoding where { pop save true }{ false } ifelse
543 /ISOLatin1Encoding [ StandardEncoding 0 45 getinterval aload pop /minus
544 StandardEncoding 46 98 getinterval aload pop /dotlessi /grave /acute
545 /circumflex /tilde /macron /breve /dotaccent /dieresis /.notdef /ring
546 /cedilla /.notdef /hungarumlaut /ogonek /caron /space /exclamdown /cent
547 /sterling /currency /yen /brokenbar /section /dieresis /copyright
548 /ordfeminine /guillemotleft /logicalnot /hyphen /registered /macron
549 /degree /plusminus /twosuperior /threesuperior /acute /mu /paragraph
550 /periodcentered /cedilla /onesuperior /ordmasculine /guillemotright
551 /onequarter /onehalf /threequarters /questiondown /Agrave /Aacute
552 /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla /Egrave /Eacute
553 /Ecircumflex /Edieresis /Igrave /Iacute /Icircumflex /Idieresis /Eth
554 /Ntilde /Ograve /Oacute /Ocircumflex /Otilde /Odieresis /multiply
555 /Oslash /Ugrave /Uacute /Ucircumflex /Udieresis /Yacute /Thorn
556 /germandbls /agrave /aacute /acircumflex /atilde /adieresis /aring /ae
557 /ccedilla /egrave /eacute /ecircumflex /edieresis /igrave /iacute
558 /icircumflex /idieresis /eth /ntilde /ograve /oacute /ocircumflex
559 /otilde /odieresis /divide /oslash /ugrave /uacute /ucircumflex
560 /udieresis /yacute /thorn /ydieresis ] def
561 { restore } if
563 /reencodeISO { %def
564 findfont dup length dict begin
565 { 1 index /FID ne { def }{ pop pop } ifelse } forall
566 /Encoding ISOLatin1Encoding def
567 currentdict end definefont pop
568 } bind def
570 /CourierISO /Courier reencodeISO
571 /Courier-ObliqueISO /Courier-Oblique reencodeISO
572 /Courier-BoldISO /Courier-Bold reencodeISO
573 /Courier-BoldObliqueISO /Courier-BoldOblique reencodeISO
575 3 10 /Courier-BoldObliqueISO
576 2 10 /Courier-ObliqueISO
577 1 10 /Courier-BoldISO
578 0 10 /CourierISO
579 4 SetUpFonts
581 .4 setlinewidth
582 ")))
584 (defun ps-end-file ()
587 (defun ps-next-page ()
588 (ps-end-page)
589 (ps-begin-page)
590 (ps-set-font ps-current-font)
591 (ps-init-page))
593 (defun ps-top-of-page () (ps-next-page))
595 (defun ps-init-page ()
596 (setq ps-row 0)
597 (setq ps-col 0)
598 (setq ps-ypos ps-page-start-ypos)
599 (setq ps-xpos ps-line-start-xpos)
600 (ps-set-font))
602 (defun ps-begin-page ()
603 (save-excursion
604 (set-buffer ps-output-buffer)
605 (goto-char (point-max))
606 (insert (format "%%%%Page: ? %d\n" ps-real-page-number))
607 (setq ps-real-page-number (+ 1 ps-real-page-number))
608 (insert "StartPage\n0.4 setlinewidth\n")))
610 (defun ps-end-page ()
611 (save-excursion
612 (set-buffer ps-output-buffer)
613 (goto-char (point-max))
614 (insert "EndPage\n")))
616 (defun ps-next-line ()
617 (setq ps-row (+ ps-row 1))
618 (if (>= ps-row ps-lines-per-page)
619 (ps-next-page)
620 (setq ps-col 0)
621 (setq ps-xpos ps-line-start-xpos)
622 (setq ps-ypos (- ps-ypos ps-line-ypos-inc))))
624 (defun ps-continue-line ()
625 (ps-next-line))
627 (defvar ps-source-buffer nil)
628 (defvar ps-output-buffer nil)
630 (defun ps-basic-plot-string (from to &optional underline-p)
631 (setq text (buffer-substring from to))
632 (save-excursion
633 (set-buffer ps-output-buffer)
634 (goto-char (point-max))
635 (setq count (- to from))
637 (if underline-p
638 (insert (format "%d %d %d L\n" ps-xpos ps-ypos
639 (* count ps-char-xpos-inc))))
641 (insert (format "%d %d M (" ps-xpos ps-ypos))
642 (save-excursion
643 (insert text))
645 (while (re-search-forward "[()\\]" nil t)
646 (save-excursion
647 (forward-char -1)
648 (insert "\\")))
650 (end-of-line)
651 (insert ") S\n")
653 (setq ps-xpos (+ ps-xpos (* count ps-char-xpos-inc)))))
655 (defun ps-basic-plot-whitespace (from to underline-p)
656 (setq count (- to from))
657 (setq ps-xpos (+ ps-xpos (* count ps-char-xpos-inc))))
659 (defun ps-plot (plotfunc from to &optional underline-p)
661 (while (< from to)
662 (setq count (- to from))
663 ;; Test to see whether this region will fit on the current line
664 (if (<= (+ ps-col count) ps-chars-per-line)
665 (progn
666 ;; It fits; plot it.
667 (funcall plotfunc from to underline-p)
668 (setq from to))
670 ;; It needs to be wrapped; plot part of it, then loop
671 (setq chars-that-will-fit (- ps-chars-per-line ps-col))
672 (funcall plotfunc from (+ from chars-that-will-fit))
674 (ps-continue-line)
676 (setq from (+ from chars-that-will-fit))))
678 (if ps-razzle-dazzle
679 (let* ((q-todo (- (point-max) (point-min)))
680 (q-done (- to (point-min)))
681 (chunkfrac (/ q-todo 8))
682 (chunksize (if (> chunkfrac 10000) 10000 chunkfrac)))
683 (if (> (- q-done ps-razchunk) chunksize)
684 (progn
685 (setq ps-razchunk q-done)
686 (setq foo
687 (if (< q-todo 100)
688 (* (/ q-done q-todo) 100)
689 (setq basis (/ q-todo 100))
690 (/ q-done basis)))
692 (message "Formatting... %d%%" foo))))))
694 (defun ps-set-font (&optional font)
695 (save-excursion
696 (set-buffer ps-output-buffer)
697 (goto-char (point-max))
698 (insert (format "%d F\n" (if font font ps-current-font))))
699 (if font
700 (setq ps-current-font font)))
702 (defun ps-plot-region (from to font &optional underline-p)
704 (ps-set-font font)
706 (save-excursion
707 (goto-char from)
708 (while (< from to)
709 (if (re-search-forward "[\t\n\014]" to t)
710 (let ((match (char-after (match-beginning 0))))
711 (cond
712 ((= match ?\n)
713 (ps-plot 'ps-basic-plot-string from (- (point) 1) underline-p)
714 (ps-next-line))
716 ((= match ?\t)
717 (ps-plot 'ps-basic-plot-string from (- (point) 1) underline-p)
718 (setq linestart (save-excursion (beginning-of-line) (point)))
719 (forward-char -1)
720 (setq from (+ linestart (current-column)))
721 (if (re-search-forward "[ \t]+" to t)
722 (ps-plot 'ps-basic-plot-whitespace from
723 (+ linestart (current-column)))))
725 ((= match ?\014)
726 (ps-plot 'ps-basic-plot-string from (- (point) 1) underline-p)
727 (ps-top-of-page)))
728 (setq from (point)))
730 (ps-plot 'ps-basic-plot-string from to underline-p)
731 (setq from to)))))
733 (defun ps-format-buffer ()
734 (interactive)
736 (setq ps-source-buffer (current-buffer))
737 (setq ps-output-buffer (get-buffer-create "%PostScript%"))
739 (save-excursion
740 (set-buffer ps-output-buffer)
741 (delete-region (point-max) (point-min)))
743 (ps-begin-file)
744 (ps-begin-page)
745 (ps-init-page)
747 (ps-plot-region (point-min) (point-max) 0)
749 (ps-end-page)
750 (ps-end-file)
753 (defun ps-mapper (extent list)
754 (nconc list (list (list (extent-start-position extent) 'push extent)
755 (list (extent-end-position extent) 'pull extent)))
756 nil)
758 (defun ps-sorter (a b)
759 (< (car a) (car b)))
761 (defun ps-extent-sorter (a b)
762 (< (extent-priority a) (extent-priority b)))
764 (defun overlay-priority (p)
765 (if (setq priority (overlay-get p 'priority)) priority 0))
767 (defun ps-overlay-sorter (a b)
768 (> (overlay-priority a) (overlay-priority b)))
770 (defun ps-plot-with-face (from to face)
772 (setq bold-p (memq face ps-bold-faces))
773 (setq italic-p (memq face ps-italic-faces))
774 (setq underline-p (memq face ps-underline-faces))
776 (cond
777 ((and bold-p italic-p)
778 (ps-plot-region from to 3 underline-p))
779 (italic-p
780 (ps-plot-region from to 2 underline-p))
781 (bold-p
782 (ps-plot-region from to 1 underline-p))
784 (ps-plot-region from to 0 underline-p))))
787 (defun ps-generate-postscript-with-faces (from to)
789 (save-restriction
790 (narrow-to-region from to)
791 (setq face 'default)
793 (cond ((string-match "Lucid" emacs-version)
794 ;; Build the list of extents...
795 (let ((a (cons 'dummy nil)))
796 (map-extents 'ps-mapper nil from to a)
797 (setq a (cdr a))
798 (setq a (sort a 'ps-sorter))
800 (setq extent-list nil)
802 ;; Loop through the extents...
803 (while a
804 (setq record (car a))
806 (setq position (car record))
807 (setq record (cdr record))
809 (setq type (car record))
810 (setq record (cdr record))
812 (setq extent (car record))
814 ;; Plot up to this record.
815 (ps-plot-with-face from position face)
817 (cond
818 ((eq type 'push)
819 (setq extent-list (sort (cons extent extent-list)
820 'ps-extent-sorter)))
822 ((eq type 'pull)
823 (setq extent-list (sort (delq extent extent-list)
824 'ps-extent-sorter))))
826 (setq face
827 (if extent-list
828 (extent-face (car extent-list))
829 'default))
831 (setq from position)
832 (setq a (cdr a)))))
834 ((string-match "^19" emacs-version)
836 (while (< from to)
838 (setq prop-position
839 (if (setq p (next-property-change from))
840 (if (> p to) to p)
841 to))
843 (setq over-position
844 (if (setq p (next-overlay-change from))
845 (if (> p to) to p)
846 to))
848 (setq position
849 (if (< prop-position over-position)
850 prop-position
851 over-position))
853 (setq face
854 (if (setq f (get-text-property from 'face)) f 'default))
856 (if (setq overlays (overlays-at from))
857 (progn
858 (setq overlays (sort overlays 'ps-overlay-sorter))
859 (while overlays
860 (if (setq face (overlay-get (car overlays) 'face))
861 (setq overlays nil)
862 (setq overlays (cdr overlays))))))
864 ;; Plot up to this record.
865 (ps-plot-with-face from position face)
867 (setq from position))))
869 (ps-plot-with-face from to face)))
871 (defun ps-generate-postscript (from to)
872 (ps-plot-region from to 0))
874 (defun ps-generate (buffer from to genfunc)
876 (save-restriction
877 (narrow-to-region from to)
878 (if ps-razzle-dazzle
879 (message "Formatting... %d%%" (setq ps-razchunk 0)))
881 (set-buffer buffer)
882 (setq ps-source-buffer buffer)
883 (setq ps-output-buffer (get-buffer-create ps-spool-buffer-name))
885 (unwind-protect
886 (progn
888 (set-buffer ps-output-buffer)
889 (goto-char (point-min))
890 (if (looking-at (regexp-quote "%!PS-Adobe-1.0"))
891 (ps-set-font ps-current-font)
892 (ps-begin-file))
893 (ps-begin-page)
894 (ps-init-page)
896 (goto-char (point-max))
897 (if (and ps-spool-duplex
898 (re-search-backward "^%%Page")
899 (looking-at "^%%Page.*[24680]$"))
900 (ps-next-page))
902 (set-buffer ps-source-buffer)
903 (funcall genfunc from to)
905 (ps-end-page)))
907 (if ps-razzle-dazzle
908 (message "Formatting... Done."))))
910 (defun ps-do-despool (filename)
912 (if (or (not (boundp 'ps-output-buffer))
913 (not ps-output-buffer))
914 (message "No spooled PostScript to print.")
916 (ps-end-file)
918 (if filename
919 (save-excursion
920 (if ps-razzle-dazzle
921 (message "Saving..."))
923 (set-buffer ps-output-buffer)
924 (setq filename (expand-file-name filename))
925 (write-region (point-min) (point-max) filename)
927 (if ps-razzle-dazzle
928 (message "Wrote %s" filename)))
930 ;; Else, spool to the printer
931 (if ps-razzle-dazzle
932 (message "Printing..."))
934 (save-excursion
935 (set-buffer ps-output-buffer)
936 (apply 'call-process-region
937 (point-min) (point-max) ps-lpr-command nil 0 nil
938 ps-lpr-switches))
940 (if ps-razzle-dazzle
941 (message "Printing... Done.")))
943 (kill-buffer ps-output-buffer)))
945 (defun ps-testpattern ()
946 (setq foo 1)
947 (while (< foo 60)
948 (insert "|" (make-string foo ?\ ) (format "%d\n" foo))
949 (setq foo (+ 1 foo))))
951 (defun pts (stuff)
952 (save-excursion
953 (set-buffer "*scratch*")
954 (goto-char (point-max))
955 (insert "---------------------------------\n"
956 (symbol-name stuff) ":\n"
957 (prin1-to-string (symbol-value stuff))
958 "\n")))
960 (provide 'ps-print)
962 ;; ps-print.el ends here