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