1 /*
2 * file_ps.c -- postscript export filter for hnb
3 *
4 * Copyright (C) 2001-2003 �yvind Kol�s <pippin@users.sourceforge.net>
5 *
6 * This program is free software; you can redistribute it and/or modify it under
7 * the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2, or (at your option) any later
9 * version.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program; if not, write to the Free Software Foundation, Inc., 59
18 * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21
22
23 #if HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <stdio.h>
28 #include <string.h>
29 #include <stdlib.h>
30
31 #include "cli.h"
32 #include "tree.h"
33 #include "file.h"
34 #include "query.h"
35 #include "util_string.h"
36
37 #define indent(count,char) {int j;for(j=0;j<count;j++)fprintf(file,char);}
38
39 /* *INDENT-OFF* */
40
41 static char *psquote[]={
42 "(", "\\(",
43 ")", "\\)",
44 "�", "\\346",
45 "�", "\\370",
46 "�", "\\345",
47 "�", "\\306",
48 "�", "\\330",
49 "�", "\\305",NULL
50 };
51
52 /* *INDENT-ON* */
53
ps_export_node(FILE * file,int level,int flags,char * data)54 static void ps_export_node (FILE * file, int level, int flags, char *data)
55 {
56 char *quoted=string_replace(data,psquote);
57 indent (level, "\t");
58 fprintf (file, "( ) S 10 ss %i LM 0 a (%s ) P\n", level * 22,
59 quoted);
60 free(quoted);
61 }
62
export_ps(int argc,char ** argv,void * data)63 static uint64_t export_ps (int argc, char **argv, void *data)
64 {
65 Node *node = (Node *) data;
66 char *filename = argc==2?argv[1]:"";
67 Node *tnode;
68 int level, flags, startlevel;
69 char *cdata;
70 FILE *file;
71
72 if (!strcmp (filename, "-"))
73 file = stdout;
74 else
75 file = fopen (filename, "w");
76 if (!file) {
77 cli_outfunf ("postscript export, unable to open \"%s\"", filename);
78 return PTR_TO_UINT64(node);
79 }
80 startlevel = nodes_left (node);
81
82 tnode = node;
83
84 fprintf (file, "%%!PS %% all files must open with this header\n\
85 %%%%BeginResource minidict.ps\n\
86 %%%%Creator: byram@cappella-archive.com\n\
87 %%%%For: Direct PostScript Mark-up\n\
88 %%%%Date: 24 Feb 2002\n\
89 %%%%EndComments\n\
90 /_Z { /defaults save def } def\n\
91 /ZZ { defaults restore } def\n\
92 /PW { /pw exch def } def 595 PW %% paper width\n\
93 /PH { /ph exch def } def 842 PH %% paper height\n\
94 %% Defaults: tm = text height: rm = text width\n\
95 /FM { /fm exch def } def 72 FM %% footer margin\n\
96 /TM { /tm exch def } def 680 TM %% top margin\n\
97 /RM { /rm exch def } def 480 RM %% right margin\n\
98 /BM { /bm exch def } def 0 BM %% bottom margin\n\
99 /LM { /lm exch def } def 0 LM %% left margin\n\
100 /LG { /lg exch def } def 11 LG %% linespacing\n\
101 \n\
102 /PG { /pg exch def } def 1 PG %% first number\n\
103 /margins { 680 TM 480 RM 0 BM 0 LM } def\n\
104 \n\
105 /MF { %% fontname newfontname -> - make a new encoded font \n\
106 /newfontname exch def /fontname exch def /fontdict fontname findfont def /newfont fontdict\n\
107 maxlength dict def fontdict { exch dup /FID eq { pop pop } { exch newfont 3 1\n\
108 roll put } ifelse } forall newfont /FontName newfontname put encoding_vector\n\
109 length 256 eq { newfont /Encoding encoding_vector put } if newfontname newfont\n\
110 definefont pop } def\n\
111 \n\
112 /encoding_vector [ /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n\
113 /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n\
114 /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n\
115 /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n\
116 /.notdef /.notdef /space /exclam /quotedbl /numbersign /dollar /percent\n\
117 /ampersand /quoteright /parenleft /parenright /asterisk /plus /comma /hyphen\n\
118 /period /slash /zero /one /two /three /four /five /six /seven /eight /nine\n\
119 /colon /semicolon /less /equal /greater /question /at /A /B /C /D /E /F /G /H\n\
120 /I /J /K /L /M /N /O /P /Q /R /S /T /U /V /W /X /Y /Z /bracketleft /backslash\n\
121 /bracketright /asciicircum /underscore /quoteleft /a /b /c /d /e /f /g /h /i\n\
122 /j /k /l /m /n /o /p /q /r /s /t /u /v /w /x /y /z /braceleft /bar\n\
123 /braceright /tilde /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n\
124 /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n\
125 /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n\
126 /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n\
127 /.notdef /.notdef /.notdef /space /exclamdown /cent /sterling /currency /yen\n\
128 /brokenbar /section /dieresis /copyright /ordfeminine /guillemotleft\n\
129 /logicalnot /hyphen /registered /macron /degree /plusminus /twosuperior\n\
130 /threesuperior /acute /mu /paragraph /bullet /cedilla /onesuperior\n\
131 /ordmasculine /guillemotright /onequarter /onehalf /threequarters /questiondown\n\
132 /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla /Egrave\n\
133 /Eacute /Ecircumflex /Edieresis /Igrave /Iacute /Icircumflex /Idieresis /Eth\n\
134 /Ntilde /Ograve /Oacute /Ocircumflex /Otilde /Odieresis /multiply /Oslash\n\
135 /Ugrave /Uacute /Ucircumflex /Udieresis /Yacute /Thorn /germandbls /agrave\n\
136 /aacute /acircumflex /atilde /adieresis /aring /ae /ccedilla /egrave /eacute\n\
137 /ecircumflex /edieresis /igrave /iacute /icircumflex /idieresis /eth /ntilde\n\
138 /ograve /oacute /ocircumflex /otilde /odieresis /divide /oslash /ugrave\n\
139 /uacute /ucircumflex /udieresis /yacute /thorn /ydieresis \n\
140 ] def\n\
141 \n\
142 /Times-Roman /Times-Roman-IL1 MF\n\
143 /Times-Italic /Times-Italic-IL1 MF\n\
144 /Times-Bold /Times-Bold-IL1 MF\n\
145 /Helvetica /Helvetica-IL1 MF\n\
146 /Helvetica-Oblique /Helvetica-Oblique-IL1 MF\n\
147 /Helvetica-Bold /Helvetica-Bold-IL1 MF\n\
148 \n\
149 /textbox {\n\
150 margins 10 rom 12 LG lm tm moveto } def\n\
151 /midpage { pw rm sub 2 div fm translate\n\
152 textbox numbering 10 ss} def\n\
153 /1upA4 { _Z minidict begin\n\
154 /p1 { gsave midpage\n\
155 /jump { bm tm gt { showpage grestore p1 } if\n\
156 } def } def p1\n\
157 } def\n\
158 /newpage { 10 neg TM tm pop jump } def\n\
159 %% close file\n\
160 /close { showpage grestore clear end ZZ } def\n\
161 /minidict 90 dict def \n\
162 minidict begin \n\
163 /gs /gsave load def \n\
164 /gr /grestore load def \n\
165 /a { tm exch sub TM lm tm moveto } bind def\n\
166 /Q { lg 8 div a } def\n\
167 /H { lg 2 div a } def\n\
168 /L { lg a } def \n\
169 /centre { dup stringwidth pop 2 div rm 2 div\n\
170 exch sub lm add tm moveto } bind def\n\
171 /numbering { gs rm 2 div bm 25 sub moveto\n\
172 pg pg 1 add PG 4 string cvs 7 ss show gr } def\n\
173 /find { search { pop 3 -1 roll 1 add 3 1 roll }\n\
174 { pop exit } ifelse } def\n\
175 /spacecount { 0 exch ( ) { find } loop } def\n\
176 /toofar? { ( ) search pop dup stringwidth pop\n\
177 currentpoint pop add rm gt } bind def\n\
178 /pagejump { jump toofar? { L jump s s }\n\
179 { s s } ifelse } def\n\
180 /s /show load def %% \n\
181 /n { bm tm gt { jump s L } { s L } ifelse} bind def\n\
182 /c { centre s L } def \n\
183 /S { dup spacecount { pagejump } repeat pop } def\n\
184 /P { S L } bind def \n\
185 /J { P } def \n\
186 /T { lm pop tm moveto } def %% tabs\n\
187 /F { findfont exch scalefont setfont } bind def\n\
188 /rom { /Times-Roman-IL1 F } def\n\
189 /it { /Times-Italic-IL1 F } def\n\
190 /bol { /Times-Bold-IL1 F } def\n\
191 /ss { /Helvetica-IL1 F } def\n\
192 /si { /Helvetica-Oblique-IL1 } def\n\
193 /sb { /Helvetica-Bold-IL1 F } def\n\
194 \n\
195 end %% close minidict: *this is important*\n\
196 %%%% EndResource\n\
197 \n\
198 \n\
199 %%%%BeginPageSetup \n\
200 1upA4 %% open the page \n\
201 %%%%EndPageSetup \n\
202 0 a\n\
203 \n\
204 %%%%BeginScript \n\
205 12 si 0 a\n\
206 12 sb (hnb postscript export) c 11 ss L\n\
207 ");
208
209 while ((tnode != 0) & (nodes_left (tnode) >= startlevel)) {
210 level = nodes_left (tnode) - startlevel;
211 flags = node_getflags (tnode);
212 cdata = fixnullstring (node_get (tnode, TEXT));
213 ps_export_node (file, level, flags, cdata);
214 if (node_up (tnode) && node_up (tnode) == node_backrecurse (tnode))
215 fprintf (file, " H\n");
216
217 tnode = node_recurse (tnode);
218 }
219
220 fprintf (file, "\
221 %%%%Trailer \n\
222 close\n\
223 %%%%EOF\n");
224
225 cli_outfunf ("postscript export, saved output to \"%s\"", filename);
226 if (file != stdout)
227 fclose (file);
228 return PTR_TO_UINT64(node);
229 }
230
231 /*
232 !init_file_ps();
233 */
init_file_ps()234 void init_file_ps ()
235 {
236 cli_add_command ("export_ps", export_ps, "<filename>");
237 cli_add_help ("export_ps",
238 "Exports the current node, it's siblings and all sublevels to a postscript file suitable for printing");
239 }
240