;;; ps-mode.el --- PostScript mode for GNU Emacs.
;; Author: Peter Kleiweg
;; Created: 20 Aug 1997
;; Version: ps-mode.el, v1.0d 1998/12/19
;; Keywords: PostScript, languages
;; LCD Archive Entry:
;; ps-mode|Peter Kleiweg|p.c.j.kleiweg@rug.nl|
;; PostScript mode for GNU Emacs|
;; 1998/12/19|1.0d|~/modes/ps-mode.el.Z|
;;; Commentary:
;; A major mode for editing PostScript
;; Requires: easymenu, hilit19
;;; Code:
(if window-system
(require 'hilit19))
(require 'easymenu)
;; user options
(defvar ps-tab 4
"User option: number of spaces to use when indenting.")
(defvar ps-auto-indent t
"User option: t means use autoindent.")
(defvar ps-paper-size '(595 842)
"User option: default paper size.
When inserting an EPSF template the values of ps-paper-size are used
to set the boundingbox to include the whole page.
When the figure is finished these values should be replaced.
Some often used papersizes are listed below.
a4: 595 842
legal: 612 1008
letter: 612 792
note: 540 720
")
(defvar ps-run-tmp-dir nil
"User option: name of directory to place temporary file.
If nil, the following are tried in turn, until success:
1. \"$TEMP\"
2. \"$TMP\"
3. \"$HOME/tmp\"
4. \"/tmp\"
")
(defvar ps-run-prompt "\\(GS\\(<[0-9]+\\)?>\\)+"
"User option: regexp to match prompt in interactive PostScript.")
(defvar ps-run-x '("gs" "-r72" "-sPAPERSIZE=a4")
"User option: command as list to run PostScript with graphic display.")
(defvar ps-run-dumb '("gs" "-dNODISPLAY")
"User option: command as list to run PostScript without graphic display.")
(defvar ps-run-init nil
"User option: string of commands to send to PostScript to start interactive.
Example: \"executive\\n\"
You won't need this option for Ghostscript.
")
(defvar ps-run-error-line-numbers nil
"User option: t means: error messages contain line numbers.
nil means: error messages contain byte counts.")
(defvar ps-print-function 'lpr-buffer
"User option: name of Lisp function to print current buffer as PostScript.
This function will be used to print regions as well.
Example:
(setq
ps-print-function
'(lambda ()
(let (
(lpr-switches nil)
(lpr-command \"lpr\"))
(lpr-buffer))))
")
;;
(defvar ps-mode-map nil
"Local keymap to use in ps-mode.")
(defvar ps-mode-syntax-table nil
"Syntax table used while in ps-mode.")
(defvar ps-run-mode-map nil
"Local keymap to use in ps-run-mode.")
(defvar ps-tmp-file nil
"Name of temporary file, set by ps-run.")
(defvar ps-run-mark nil
"Mark to start of region sent to PostScript.")
(defvar ps-run-parent nil
"Parent window of interactive PostScript.")
;;
;;;###autoload
(defun ps-mode ()
"Major mode for editing PostScript with GNU Emacs.
Entry to this mode calls `ps-mode-hook'.
Things to add to your .emacs file:
(autoload 'ps-mode \"ps-mode\" \"Major mode for editing PostScript\" t)
(setq auto-mode-alist
(append
'((\"\\\\.ps$\" . ps-mode)
(\"\\\\.eps$\" . ps-mode)
(\"\\\\.epsf$\" . ps-mode))
auto-mode-alist))
The following variables hold user options, and could be
given other values from within your .emacs file:
ps-auto-indent
ps-tab
ps-paper-size
ps-run-tmp-dir
ps-run-prompt
ps-run-x
ps-run-dumb
ps-run-init
ps-run-error-line-numbers
ps-print-function
Type \\[describe-variable] for documentation on these options.
\\{ps-mode-map}
When starting an interactive PostScript process with \\[ps-run-start],
a second window will be displayed, and `ps-run-mode-hook' will be called.
The keymap for this second window is:
\\{ps-run-mode-map}
When Ghostscript encounters an error it displays an error message
with a file position. Clicking mouse-2 on this number will bring
point to the corresponding spot in the PostScript window, if input
to the interpreter was sent from that window.
Typing \\\\[ps-run-goto-error] when the cursor is at the number has the same effect.
"
(interactive)
(setq major-mode 'ps-mode
mode-name "PostScript")
(use-local-map ps-mode-map)
(set-syntax-table ps-mode-syntax-table)
(run-hooks 'ps-mode-hook))
;; key-handlers
(defun ps-newline ()
"Insert newline, indent if after begin group."
(interactive)
(if (not ps-auto-indent)
(insert "\n")
(progn
(let
( (here (point))
pos
)
(if (re-search-backward "\\({\\|\\[\\|<<\\)\\=" (- here 2) t)
(progn
(beginning-of-line)
(looking-at "[ \t]*")
(goto-char (match-end 0))
(setq pos (current-column))
(goto-char here)
(insert
"\n"
(make-string (/ (+ pos ps-tab) tab-width) ?\t)
(make-string (mod (+ pos ps-tab) tab-width) ?\ )))
(progn
(goto-char here)
(insert "\n")
; copy leading whitespace from previous line
(setq here (point))
(forward-line -1)
(looking-at "[ \t]*")
(forward-line 1)
(insert (buffer-substring (match-beginning 0) (match-end 0))))))
; remove trailing whitespace previous line
(save-excursion
(forward-line -1)
(beginning-of-line)
(if (looking-at "[ \t]*$")
(replace-match "")
(if (looking-at "\\(.*[^ \t\n]\\)[ \t]+$")
(replace-match "\\1"))))
(if (looking-at "[ \t]+")
(replace-match "")))))
(defun ps-r-brace ()
"INSERT `}' and perform balance."
(interactive)
(insert "}")
(ps-r-balance "{" "}"))
(defun ps-r-angle ()
"Insert `]' and perform balance."
(interactive)
(insert "]")
(ps-r-balance "[" "]"))
(defun ps-r-gt ()
"Insert `>' and perform balance."
(interactive)
(insert ">")
(ps-r-balance "<<" ">>"))
(defun ps-r-balance (left right)
"Put RIGHT below start of line matching LEFT if only leading whitespace."
(if ps-auto-indent
(save-excursion
(let
( (here (point))
(len (length right))
begin
end
)
(setq end (- here len))
(beginning-of-line)
(if (looking-at (concat "[ \t]*" (regexp-quote right)))
(if (= (match-end 0) here)
(progn
(goto-char here)
(backward-sexp 1)
(setq begin (point))
(if (looking-at (regexp-quote left))
(progn
(beginning-of-line)
(looking-at "[ \t]*")
(goto-char end)
(beginning-of-line)
(insert (buffer-substring (match-beginning 0) (match-end 0)))
(looking-at "[ \t]*")
(replace-match "")))))))))
(blink-matching-open))
(defun ps-other-newline ()
"Perform newline in *ps run* buffer"
(interactive)
(let ((buf (current-buffer)))
(set-buffer "*ps run*")
(ps-run-newline)
(set-buffer buf)))
;; print PostScript
(defun ps-print-buffer ()
"Print buffer as PostScript"
(interactive)
(eval (list ps-print-function)))
(defun ps-print-region (begin end)
"Print region as PostScript, %!PS prepended, showpage appended"
(interactive "r")
(let ((oldbuf (current-buffer))
(tmpbuf (get-buffer-create "*ps print*")))
(copy-to-buffer tmpbuf begin end)
(set-buffer tmpbuf)
(goto-char 1)
(insert "%!PS\n")
(goto-char (point-max))
(insert "\nshowpage\n")
(eval (list ps-print-function))
(set-buffer oldbuf)
(kill-buffer tmpbuf)))
;; convert 8-bit to octal codes
(defun ps-octal-buffer ()
"Change 8-bit characters to octal codes in buffer."
(interactive)
(ps-octal-region (point-min) (point-max)))
(defun ps-octal-region (begin end)
"Change 8-bit characters to octal codes in region."
(interactive "r")
(if buffer-read-only
(progn
(ding)
(message "Buffer is read only"))
(save-excursion
(let (endm i)
(setq endm (make-marker))
(set-marker endm end)
(goto-char begin)
(setq i 0)
(while (re-search-forward "[\200-\377]" (marker-position endm) t)
(setq i (1+ i))
(backward-char)
(insert (format "\\%03o" (string-to-char (buffer-substring (point) (1+ (point))))))
(delete-char 1))
(message (format "%d change%s made" i (if (= i 1) "" "s")))
(setq endm nil)))))
;; cookbook
(defun ps-center ()
"Insert /center."
(interactive)
(insert "/center {
dup stringwidth pop
2 div neg 0 rmoveto
} bind def
"))
(defun ps-right ()
"Insert /right."
(interactive)
(insert "/right {
dup stringwidth pop
neg 0 rmoveto
} bind def
"))
(defun ps-RE ()
"Insert /RE."
(interactive)
(insert "% `new-font-name' `encoding-vector' `old-font-name' RE -
/RE {
findfont
dup maxlength dict begin {
1 index /FID ne { def } { pop pop } ifelse
} forall
/Encoding exch def
dup /FontName exch def
currentdict end definefont pop
} bind def
"))
(defun ps-latin-extended ()
"Insert /ISOLatin1Extended
This encoding vector contains all the entries from ISOLatin1Encoding
plus the usually uncoded characters inserted on positions 1 through 28.
"
(interactive)
(insert "% ISOLatin1Encoding, extended with remaining uncoded glyphs
/ISOLatin1Extended [
/.notdef /Lslash /lslash /OE /oe /Scaron /scaron /Zcaron /zcaron
/Ydieresis /trademark /bullet /dagger /daggerdbl /ellipsis /emdash
/endash /fi /fl /florin /fraction /guilsinglleft /guilsinglright
/perthousand /quotedblbase /quotedblleft /quotedblright
/quotesinglbase /quotesingle /.notdef /.notdef /.notdef /space
/exclam /quotedbl /numbersign /dollar /percent /ampersand
/quoteright /parenleft /parenright /asterisk /plus /comma /minus
/period /slash /zero /one /two /three /four /five /six /seven /eight
/nine /colon /semicolon /less /equal /greater /question /at /A /B /C
/D /E /F /G /H /I /J /K /L /M /N /O /P /Q /R /S /T /U /V /W /X /Y /Z
/bracketleft /backslash /bracketright /asciicircum /underscore
/quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o /p /q /r /s
/t /u /v /w /x /y /z /braceleft /bar /braceright /asciitilde
/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
/.notdef /.notdef /.notdef /dotlessi /grave /acute /circumflex
/tilde /macron /breve /dotaccent /dieresis /.notdef /ring /cedilla
/.notdef /hungarumlaut /ogonek /caron /space /exclamdown /cent
/sterling /currency /yen /brokenbar /section /dieresis /copyright
/ordfeminine /guillemotleft /logicalnot /hyphen /registered /macron
/degree /plusminus /twosuperior /threesuperior /acute /mu /paragraph
/periodcentered /cedilla /onesuperior /ordmasculine /guillemotright
/onequarter /onehalf /threequarters /questiondown /Agrave /Aacute
/Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla /Egrave /Eacute
/Ecircumflex /Edieresis /Igrave /Iacute /Icircumflex /Idieresis /Eth
/Ntilde /Ograve /Oacute /Ocircumflex /Otilde /Odieresis /multiply
/Oslash /Ugrave /Uacute /Ucircumflex /Udieresis /Yacute /Thorn
/germandbls /agrave /aacute /acircumflex /atilde /adieresis /aring
/ae /ccedilla /egrave /eacute /ecircumflex /edieresis /igrave
/iacute /icircumflex /idieresis /eth /ntilde /ograve /oacute
/ocircumflex /otilde /odieresis /divide /oslash /ugrave /uacute
/ucircumflex /udieresis /yacute /thorn /ydieresis
] def
"))
(defun ps-heapsort ()
"Insert /Heapsort."
(interactive)
(insert "% `array-element' Heapsort-cvi-or-cvr-or-cvs `number-or-string'
/Heapsort-cvi-or-cvr-or-cvs {
% 0 get
} bind def
% `array' Heapsort `sorted-array'
/Heapsort {
dup length /hsR exch def
/hsL hsR 2 idiv 1 add def
{
hsR 2 lt { exit } if
hsL 1 gt {
/hsL hsL 1 sub def
} {
/hsR hsR 1 sub def
dup dup dup 0 get exch dup hsR get
0 exch put
hsR exch put
} ifelse
dup hsL 1 sub get /hsT exch def
/hsJ hsL def
{
/hsS hsJ def
/hsJ hsJ dup add def
hsJ hsR gt { exit } if
hsJ hsR lt {
dup dup hsJ 1 sub get Heapsort-cvi-or-cvr-or-cvs
exch hsJ get Heapsort-cvi-or-cvr-or-cvs
lt { /hsJ hsJ 1 add def } if
} if
dup hsJ 1 sub get Heapsort-cvi-or-cvr-or-cvs
hsT Heapsort-cvi-or-cvr-or-cvs
le { exit } if
dup dup hsS 1 sub exch hsJ 1 sub get put
} loop
dup hsS 1 sub hsT put
} loop
} bind def
"))
;; epsf document lay-out
(defun ps-epsf-sparse ()
"Insert sparse EPSF template."
(interactive)
(goto-char (point-max))
(if (not (re-search-backward "%%EOF[ \t\n]*\\'" nil t))
(progn
(goto-char (point-max))
(insert "\n%%EOF\n")))
(goto-char (point-max))
(if (not (re-search-backward "\\bshowpage[ \t\n]+%%EOF[ \t\n]*\\'" nil t))
(progn
(re-search-backward "%%EOF")
(insert "showpage\n")))
(goto-char (point-max))
(if (not (re-search-backward "\\bend[ \t\n]+\\bshowpage[ \t\n]+%%EOF[ \t\n]*\\'" nil t))
(progn
(re-search-backward "showpage")
(insert "\nend\n")))
(goto-char (point-min))
(insert "%!PS-Adobe-3.0 EPSF-3.0\n%%BoundingBox: 0 0 ")
(insert (format "%d %d\n\n" (car ps-paper-size) (car (cdr ps-paper-size))))
(insert "64 dict begin\n\n"))
(defun ps-epsf-rich ()
"Insert rich EPSF template."
(interactive)
(ps-epsf-sparse)
(forward-line -3)
(if buffer-file-name
(insert "%%Title: " (file-name-nondirectory buffer-file-name) "\n"))
(insert "%%Creator: " (user-full-name) "\n")
(insert "%%CreationDate: " (current-time-string) "\n")
(insert "%%EndComments\n")
(forward-line 3)
)
;; Interactive PostScript interpreter
(defun ps-run-running ()
"Error if not in ps-mode or not running PostScript."
(if (not (equal major-mode 'ps-mode))
(error "This function can only be called from PostScript mode"))
(if (not (equal (process-status "ps-run") 'run))
(error "No PostScript process running")))
(defun ps-run-start ()
"Start interactive PostScript."
(interactive)
(let
( (command (if (and window-system ps-run-x) ps-run-x ps-run-dumb))
(init-file nil)
(process-connection-type nil)
(oldbuf (current-buffer))
(oldwin (selected-window))
i
)
(if (not command)
(error "No command specified to run interactive PostScript"))
(if (or (not ps-run-mark) (not (markerp ps-run-mark)))
(setq ps-run-mark (make-marker)))
(if ps-run-init
(progn
(setq init-file (ps-run-make-tmp-filename))
(write-region ps-run-init 0 init-file)
(setq init-file (list init-file))))
(pop-to-buffer "*ps run*")
(ps-run-mode)
(if (process-status "ps-run")
(delete-process "ps-run"))
(erase-buffer)
(setq i (append command init-file))
(while i
(insert (car i) (if (cdr i) " " "\n"))
(setq i (cdr i)))
(eval (append '(start-process "ps-run" "*ps run*") command init-file))
(select-window oldwin)))
(defun ps-run-quit ()
"Quit interactive PostScript."
(interactive)
(ps-run-send-string "quit" t)
(ps-run-cleanup))
(defun ps-run-kill ()
"Kill interactive PostScript."
(interactive)
(delete-process "ps-run")
(ps-run-cleanup))
(defun ps-run-clear ()
"Clear/reset PostScript graphics."
(interactive)
(ps-run-send-string "showpage" t)
(sit-for 1)
(ps-run-send-string "" t))
(defun ps-run-buffer ()
"Send buffer to PostScript interpreter."
(interactive)
(ps-run-region (point-min) (point-max)))
(defun ps-run-region (begin end)
"Send region to PostScript interpreter."
(interactive "r")
(ps-run-running)
(setq ps-run-parent (buffer-name))
(let ((f (ps-run-make-tmp-filename)))
(set-marker ps-run-mark begin)
(write-region begin end f)
(ps-run-send-string (format "(%s) run" f) t)))
(defun ps-run-boundingbox ()
"View BoundingBox"
(interactive)
(ps-run-running)
(let (
x1 y1 x2 y2 f
(buf (current-buffer))
)
(save-excursion
(goto-char 1)
(re-search-forward
"^%%BoundingBox:[ \t]+\\([0-9]+\\)[ \t]+\\([0-9]+\\)[ \t]+\\([0-9]+\\)[ \t]+\\([0-9]+\\)")
(setq x1 (buffer-substring (match-beginning 1) (match-end 1)))
(setq y1 (buffer-substring (match-beginning 2) (match-end 2)))
(setq x2 (buffer-substring (match-beginning 3) (match-end 3)))
(setq y2 (buffer-substring (match-beginning 4) (match-end 4))))
(if (not (< (string-to-number x1) (string-to-number x2)))
(error "x1 (%s) should be less than x2 (%s)" x1 x2))
(if (not (< (string-to-number y1) (string-to-number y2)))
(error "y1 (%s) should be less than y2 (%s)" y1 y2))
(setq f (ps-run-make-tmp-filename))
(write-region
(format
"gsave
initgraphics
2 setlinewidth
%s %s moveto
%s %s lineto
%s %s lineto
%s %s lineto
closepath
gsave
[ 4 20 ] 0 setdash
1 0 0 setrgbcolor
stroke
grestore
gsave
[ 4 20 ] 8 setdash
0 1 0 setrgbcolor
stroke
grestore
[ 4 20 ] 16 setdash
0 0 1 setrgbcolor
stroke
grestore
" x1 y1 x2 y1 x2 y2 x1 y2)
0
f)
(ps-run-send-string (format "(%s) run" f) t)
(set-buffer buf)))
(defun ps-run-send-string (string &optional echo)
(let ((oldwin (selected-window)))
(pop-to-buffer "*ps run*")
(goto-char (point-max))
(if echo
(insert string "\n"))
(set-marker (process-mark (get-process "ps-run")) (point))
(process-send-string "ps-run" (concat string "\n"))
(select-window oldwin)))
;
(defun ps-run-make-tmp-filename ()
(if (not ps-tmp-file)
(progn
(if (not ps-run-tmp-dir)
(if (not (setq ps-run-tmp-dir (getenv "TEMP")))
(if (not (setq ps-run-tmp-dir (getenv "TMP")))
(if (setq ps-run-tmp-dir (getenv "HOME"))
(progn
(setq
ps-run-tmp-dir
(concat (file-name-as-directory ps-run-tmp-dir) "tmp"))
(if (not (file-directory-p ps-run-tmp-dir))
(setq ps-run-tmp-dir nil)))))))
(if (not ps-run-tmp-dir)
(setq ps-run-tmp-dir "/tmp"))
(setq
ps-tmp-file
(make-temp-name
(concat
(if ps-run-tmp-dir
(file-name-as-directory ps-run-tmp-dir)
"")
"ps-run")))))
ps-tmp-file)
; Remove temporary file
; This shouldn't fail twice, because it is called at kill-emacs
(defun ps-run-cleanup ()
(if ps-tmp-file
(let ((i ps-tmp-file))
(setq ps-tmp-file nil)
(if (file-exists-p i)
(delete-file i)))))
;
(defun ps-run-mode ()
"Major mode in interactive PostScript window.
This mode is invoked from ps-mode and should not be called directly.
\\{ps-run-mode-map}
"
(setq major-mode 'ps-run-mode
mode-name "Interactive PS"
mode-line-process '(":%s"))
(use-local-map ps-run-mode-map)
(run-hooks 'ps-run-mode-hook))
(defun ps-run-mouse-goto-error (event)
"Set point at mouse click, then call ps-run-goto-error."
(interactive "e")
(mouse-set-point event)
(ps-run-goto-error))
(defun ps-run-newline ()
"Process newline in PostScript interpreter window."
(interactive)
(end-of-line)
(insert "\n")
(forward-line -1)
(if (looking-at ps-run-prompt)
(goto-char (match-end 0)))
(looking-at ".*")
(goto-char (1+ (match-end 0)))
(ps-run-send-string (buffer-substring (match-beginning 0) (match-end 0))))
(defun ps-run-goto-error ()
"Jump to buffer position read as integer at point.
Use line numbers if ps-run-error-line-numbers is not nil"
(interactive)
(let ((p (point)))
(if (not (looking-at "[0-9]"))
(goto-char (max 1 (1- (point)))))
(if (looking-at "[0-9]")
(progn
(forward-char 1)
(forward-word -1)
(if (looking-at "[0-9]+")
(let (i)
(setq
i
(string-to-int
(buffer-substring (match-beginning 0) (match-end 0))))
(goto-char p)
(pop-to-buffer ps-run-parent)
(if ps-run-error-line-numbers
(progn
(goto-char (marker-position ps-run-mark))
(forward-line (1- i)))
(goto-char (+ i (marker-position ps-run-mark))))))))))
;; highlighting
(if window-system
(hilit-set-mode-patterns
'ps-mode
'(("\\`%!.*$" nil define)
("^%%BoundingBox:[ \t]+-?[0-9]+[ \t]+-?[0-9]+[ \t]+-?[0-9]+[ \t]+-?[0-9]+"
nil define)
("%.*$" nil comment)
("<<\\|>>" nil defun)
("(\\(\\\\)\\|[^)]\\)*)" nil string)
("<[ \t\n0-9a-fA-F]*>" nil string)
("<~" "~>" string)
("^/[^][ \t\n{}()<>/]*" nil defun)
; ("/[^][ \t\n{}()<>/]*" nil decl)
("\\b\\(bind\\|def\\|dict\\|begin\\|end\\|mark\\)\\b" nil keyword)
("\\bshowpage\\b" nil keyword)
("\\b\\(exec\\|exit\\|if\\|ifelse\\|for\\|forall\\|repeat\\|loop\\)\\b"
nil keyword)
("\\b\\(stop\\|stopped\\|quit\\|start\\)\\b" nil keyword)
("\\b\\(gsave\\|grestore\\|save\\|restore\\)\\b" nil keyword)
("\\b\\(null\\|true\\|false\\)\\b" nil keyword)
)))
;; mouse menu
(defconst ps-mode-menu-main
'("PostScript"
["EPSF template, sparse" ps-epsf-sparse t]
["EPSF template, rich" ps-epsf-rich t]
"---"
("Cookbook"
["RE" ps-RE t]
["ISOLatin1Extended" ps-latin-extended t]
["center" ps-center t]
["right" ps-right t]
["Heapsort" ps-heapsort t])
("Fonts (1)"
["Times-Roman" (insert "/Times-Roman ") t]
["Times-Bold" (insert "/Times-Bold ") t]
["Times-Italic" (insert "/Times-Italic ") t]
["Times-BoldItalic" (insert "/Times-BoldItalic ") t]
["Helvetica" (insert "/Helvetica ") t]
["Helvetica-Bold" (insert "/Helvetica-Bold ") t]
["Helvetica-Oblique" (insert "/Helvetica-Oblique ") t]
["Helvetica-BoldOblique" (insert "/Helvetica-BoldOblique ") t]
["Courier" (insert "/Courier ") t]
["Courier-Bold" (insert "/Courier-Bold ") t]
["Courier-Oblique" (insert "/Courier-Oblique ") t]
["Courier-BoldOblique" (insert "/Courier-BoldOblique ") t]
["Symbol" (insert "/Symbol") t ])
("Fonts (2)"
["AvantGarde-Book" (insert "/AvantGarde-Book ") t]
["AvantGarde-Demi" (insert "/AvantGarde-Demi ") t]
["AvantGarde-BookOblique" (insert "/AvantGarde-BookOblique ") t]
["AvantGarde-DemiOblique" (insert "/AvantGarde-DemiOblique ") t]
["Bookman-Light" (insert "/Bookman-Light ") t]
["Bookman-Demi" (insert "/Bookman-Demi ") t]
["Bookman-LightItalic" (insert "/Bookman-LightItalic ") t]
["Bookman-DemiItalic" (insert "/Bookman-DemiItalic ") t]
["Helvetica-Narrow" (insert "/Helvetica-Narrow ") t]
["Helvetica-Narrow-Bold" (insert "/Helvetica-Narrow-Bold ") t]
["Helvetica-Narrow-Oblique" (insert "/Helvetica-Narrow-Oblique ") t]
["Helvetica-Narrow-BoldOblique" (insert "/Helvetica-Narrow-BoldOblique ") t]
["NewCenturySchlbk-Roman" (insert "/NewCenturySchlbk-Roman ") t]
["NewCenturySchlbk-Bold" (insert "/NewCenturySchlbk-Bold ") t]
["NewCenturySchlbk-Italic" (insert "/NewCenturySchlbk-Italic ") t]
["NewCenturySchlbk-BoldItalic" (insert "/NewCenturySchlbk-BoldItalic ") t]
["Palatino-Roman" (insert "/Palatino-Roman ") t]
["Palatino-Bold" (insert "/Palatino-Bold ") t]
["Palatino-Italic" (insert "/Palatino-Italic ") t]
["Palatino-BoldItalic" (insert "/Palatino-BoldItalic ") t]
["ZapfChancery-MediumItalic" (insert "/ZapfChancery-MediumItalic ") t]
["ZapfDingbats" (insert "/ZapfDingbats ") t])
"---"
["8-bit to octal buffer" ps-octal-buffer t]
["8-bit to octal region" ps-octal-region (mark t)]
"---"
("Auto indent"
["On" (setq ps-auto-indent t) (not ps-auto-indent)]
["Off" (setq ps-auto-indent nil) ps-auto-indent])
"---"
["Start PostScript"
ps-run-start
(not (equal (process-status "ps-run") 'run))]
["Quit PostScript" ps-run-quit (process-status "ps-run")]
["Kill PostScript" ps-run-kill (process-status "ps-run")]
["Send buffer to interpreter"
ps-run-buffer
(process-status "ps-run")]
["Send region to interpreter"
ps-run-region
(and (mark t) (process-status "ps-run"))]
["View BoundingBox"
ps-run-boundingbox
(process-status "ps-run")]
["Clear/Reset PostScript graphics"
ps-run-clear
(process-status "ps-run")]
"---"
["Print buffer as PostScript"
ps-print-buffer
t]
["Print region as PostScript"
ps-print-region
(mark t)]))
;; keys
(if (not ps-mode-syntax-table)
(progn
(setq ps-mode-syntax-table (make-syntax-table))
(modify-syntax-entry ?\" "w " ps-mode-syntax-table)
(modify-syntax-entry ?\% "< " ps-mode-syntax-table)
(modify-syntax-entry ?\n "> " ps-mode-syntax-table)
(modify-syntax-entry ?\r "> " ps-mode-syntax-table)
(modify-syntax-entry ?\f "> " ps-mode-syntax-table)
(modify-syntax-entry ?\< "(>" ps-mode-syntax-table)
(modify-syntax-entry ?\> ")<" ps-mode-syntax-table)))
(if ps-mode-map nil
(progn
(setq ps-mode-map (make-sparse-keymap))
(define-key ps-mode-map [return] 'ps-newline)
(define-key ps-mode-map "\177" 'backward-delete-char-untabify)
(define-key ps-mode-map "\r" 'ps-newline)
(define-key ps-mode-map "}" 'ps-r-brace)
(define-key ps-mode-map "]" 'ps-r-angle)
(define-key ps-mode-map ">" 'ps-r-gt)
(define-key ps-mode-map "\C-c\C-j" 'ps-other-newline)
(define-key ps-mode-map "\C-c\C-t" 'ps-epsf-rich)
(define-key ps-mode-map "\C-c\C-s" 'ps-run-start)
(define-key ps-mode-map "\C-c\C-q" 'ps-run-quit)
(define-key ps-mode-map "\C-c\C-k" 'ps-run-kill)
(define-key ps-mode-map "\C-c\C-b" 'ps-run-buffer)
(define-key ps-mode-map "\C-c\C-r" 'ps-run-region)
(define-key ps-mode-map "\C-c\C-v" 'ps-run-boundingbox)
(define-key ps-mode-map "\C-c\C-c" 'ps-run-clear)
(define-key ps-mode-map "\C-c\C-p" 'ps-print-buffer)
(easy-menu-define ps-mode-main ps-mode-map "PostScript" ps-mode-menu-main)))
(if ps-run-mode-map nil
(progn
(setq ps-run-mode-map (make-sparse-keymap))
(define-key ps-run-mode-map [return] 'ps-run-newline)
(define-key ps-run-mode-map "\r" 'ps-run-newline)
(define-key ps-run-mode-map "\C-c\C-q" 'ps-run-quit)
(define-key ps-run-mode-map "\C-c\C-k" 'ps-run-kill)
(define-key ps-run-mode-map "\C-c\C-e" 'ps-run-goto-error)
(define-key ps-run-mode-map [mouse-2] 'ps-run-mouse-goto-error)))
(add-hook 'kill-emacs-hook 'ps-run-cleanup)
(provide 'ps-mode)
;;; ps-mode.el ends here