ee0b2eeaf04c2c9cbfd2d418b5586a1e2f9d856b
[alioth/magicpoint.git] / print.c
1 /*
2  * Copyright (C) 1997 and 1998 WIDE Project.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  * 3. Neither the name of the project nor the names of its contributors
13  *    may be used to endorse or promote products derived from this software
14  *    without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLER
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28
29 #include "mgp.h"
30 #if HAVE_LOCALE_H
31 #include <locale.h>
32 #endif
33
34 static u_int align = AL_LEFT;
35 static char *curprefix = NULL;
36 static char *tabprefix = NULL;
37 static u_int lineheight;
38 static u_int linewidth;
39 static u_int gaplevel = 0;
40 static int char_off = 0;        /* y-offset of the chars (relative to the
41                                    current line, used for super/subscript */
42
43 #define DEFAULT_PAPER_SIZE      "a4"
44 #define PRINT_ASCIIFONT         "Times-Roman"
45 #define PRINT_ASCIITHICKFONT    "Helvetica"
46 #define PRINT_KANJIFONT         "Ryumin-Light-H"
47 #define PRINT_KANJITHICKFONT    "GothicBBB-Medium-H"
48
49 static FILE *fp;
50 static u_int reverse;
51 static char outputfile[MAXVALLEN];
52 static int colorps = 0;
53 static int painticon = 0;
54 static u_int curlinenum;
55 static u_int curpagenum=0;
56 static u_int xprefix = 0;
57 static u_int tabxprefix = 0;
58 static u_int valign = VL_BOTTOM;
59
60 /* by Arnd Schmitter 23.07.2004 */
61 static int lg; /* Counts the Recursionlevel in print_page() for new Pause-Mode */
62 static int PauseMode=0; /* Should Pause-Statements splitet into multiple Pages ? */
63
64 static struct imagepool {
65         struct ctrl *image;
66         int xoffset;
67         int xsiz;
68         int ysiz;
69         int eps;
70         int target_text;    /* by A. Ito */
71 } imagepool[256];               /*enough?*/
72 static int nimagepool = 0;
73 static struct textpool {
74         int pfx;
75         int xoffset;
76         int yoffset;     /* offset for super/subscript */
77         int xsiz;
78         struct fontmap *font;
79         int size;
80         char *text;
81         u_long fore;
82         u_long back;
83         char *charset;
84 } textpool[1024];               /*enough?*/
85 static int ntextpool = 0;
86
87 u_long fore;
88 u_long back;
89
90 /* lang code */
91 #define ASCII   0
92 #define KANJI   1
93 #define NOPE    -1
94
95 static int maxfontid = 0;
96 static struct fontmap {
97         int ctrl;
98         int lang;
99         char *font;
100         char *psfont;
101         int fontid;     /* flag bit for generating font map */
102         int loaded;
103 } fontmap[] = {
104         { CTL_XFONT2, ASCII, "century schoolbook l-medium-r", "NewCenturySchlbk-Roman" },
105         { CTL_XFONT2, ASCII, "century schoolbook l-medium-i", "NewCenturySchlbk-Italic" },
106         { CTL_XFONT2, ASCII, "century schoolbook l-bold-r", "NewCenturySchlbk-Bold" },
107         { CTL_XFONT2, ASCII, "century schoolbook l-bold-i", "NewCenturySchlbk-BoldItalic" },
108         { CTL_XFONT2, ASCII, "times-medium-r",  "Times-Roman" },
109         { CTL_XFONT2, ASCII, "times-medium-i",  "Times-Italic" },
110         { CTL_XFONT2, ASCII, "times-bold-r",    "Times-Bold" },
111         { CTL_XFONT2, ASCII, "times-bold-i",    "Times-BoldItalic" },
112         { CTL_XFONT2, ASCII, "helvetica-medium-r",      "Helvetica" },
113         { CTL_XFONT2, ASCII, "helvetica-medium-o",      "Helvetica-Oblique" },
114         { CTL_XFONT2, ASCII, "helvetica-bold-r",        "Helvetica-Bold" },
115         { CTL_XFONT2, ASCII, "helvetica-bold-o",        "Helvetica-BoldOblique" },
116         { CTL_XFONT2, ASCII, "courier-medium-r",        "Courier" },
117         { CTL_XFONT2, ASCII, "courier-medium-o",        "Courier-Oblique" },
118         { CTL_XFONT2, ASCII, "courier-bold-r",  "Courier-Bold" },
119         { CTL_XFONT2, ASCII, "courier-bold-i",  "Courier-BoldOblique" },
120         { CTL_XFONT2, ASCII, "times*",          "Times" },
121         { CTL_XFONT2, ASCII, "helvetica*",      "Helvetica" },
122         { CTL_XFONT2, ASCII, "courier*",                "Courier" },
123         { CTL_XFONT2, ASCII, "symbol*",         "Symbol" },
124         { CTL_XFONT2, ASCII, "*",               "Helvetica" },  /*last resort*/
125         { CTL_XFONT2, KANJI, "*",               "Ryumin-Light-H" }, /*last resort*/
126         /*PSFONT*/
127         { CTL_PSFONT, ASCII, "Times-Roman", "Times-Roman" },
128         { CTL_PSFONT, ASCII, "Times-Italic", "Times-Italic" },
129         { CTL_PSFONT, ASCII, "Times-Bold", "Times-Bold" },
130         { CTL_PSFONT, ASCII, "Times-BoldItalic", "Times-BoldItalic" },
131         { CTL_PSFONT, ASCII, "Helvetica", "Helvetica" },
132         { CTL_PSFONT, ASCII, "Helvetica-BoldOblique", "Helvetica-BoldOblique" },
133         { CTL_PSFONT, ASCII, "Helvetica-Bold", "Helvetica-Bold" },
134         { CTL_PSFONT, ASCII, "Courier", "Courier" },
135         { CTL_PSFONT, ASCII, "Courier-Oblique", "Courier-Oblique" },
136         { CTL_PSFONT, ASCII, "Courier-Bold", "Courier-Bold" },
137         { CTL_PSFONT, ASCII, "Courier-BoldOblique", "Courier-BoldOblique" },
138         { CTL_PSFONT, ASCII, "AvantGarde-Book", "AvantGarde-Book" },
139         { CTL_PSFONT, ASCII, "AvantGarde-BookOblique", "AvantGarde-BookOblique" },
140         { CTL_PSFONT, ASCII, "AvantGarde-Demi", "AvantGarde-Demi" },
141         { CTL_PSFONT, ASCII, "AvantGarde-DemiQblique", "AvantGarde-DemiQblique" },
142         { CTL_PSFONT, ASCII, "Bookman-Demi", "Bookman-Demi" },
143         { CTL_PSFONT, ASCII, "Bookman-DemiItalic", "Bookman-DemiItalic" },
144         { CTL_PSFONT, ASCII, "Bookman-Light", "Bookman-Light" },
145         { CTL_PSFONT, ASCII, "Bookman-LightItalic", "Bookman-LightItalic" },
146         { CTL_PSFONT, ASCII, "Helvetica-Narrow", "Helvetica-Narrow" },
147         { CTL_PSFONT, ASCII, "Helvetic-NarrowOblique","Helvetic-NarrowOblique"},
148         { CTL_PSFONT, ASCII, "Helvetica-NarrowBold", "Helvetica-NarrowBold" },
149         { CTL_PSFONT, ASCII, "Helvetica-NarrowBoldOblique", "Helvetica-NarrowBoldOblique" },
150         { CTL_PSFONT, ASCII, "Helvetica-Oblique", "Helvetica-Oblique" },
151         { CTL_PSFONT, ASCII, "NewCenturySchlbk-Roman", "NewCenturySchlbk-Roman" },
152         { CTL_PSFONT, ASCII, "NewCenturySchlbk-Bold", "NewCenturySchlbk-Bold" },
153         { CTL_PSFONT, ASCII, "NewCenturySchlbk-Italic", "NewCenturySchlbk-Italic" },
154         { CTL_PSFONT, ASCII, "NewCenturySchlbk-BoldItalic", "NewCenturySchlbk-BoldItalic" },
155         { CTL_PSFONT, ASCII, "Palatino-Roman", "Palatino-Roman" },
156         { CTL_PSFONT, ASCII, "Palatino-Bold", "Palatino-Bold" },
157         { CTL_PSFONT, ASCII, "Palatino-Italic", "Palatino-Italic" },
158         { CTL_PSFONT, ASCII, "Palatino-BoldItalic", "Palatino-BoldItalic" },
159         { CTL_PSFONT, ASCII, "ZapfChancery-MediumItalic", "ZapfChancery-MediumItalic" },
160         { CTL_PSFONT, ASCII, "Symbol", "Symbol" },
161         { CTL_PSFONT, ASCII, "ZapfDingbats", "ZapfDingbats" },
162         { CTL_PSFONT, ASCII, "*", "Helvetica" }, /*Last Resort*/
163         { -1 },
164 };
165 static struct fontmap *curfont[10];     /*indexed by lang*/
166
167 typedef struct papersize {
168         char *name;             /* name of paper size */
169         int height, width;      /* height, width in points for LANDSCAPE */
170 } Paper;
171
172 static Paper papersizes[] = {
173         { "a3",         842, 1191 },    /* 29.7cm * 42cm */
174         { "a4",         595, 842 },     /* 21cm * 29.7cm */
175         { "a5",         421, 595 },     /* 14.85cm * 21cm */
176         { "b5",         516, 729 },     /* 18.2cm * 25.72cm */
177         { "A3",         842, 1191 },    /* 29.7cm * 42cm */
178         { "A4",         595, 842 },     /* 21cm * 29.7cm */
179         { "A5",         421, 595 },     /* 14.85cm * 21cm */
180         { "B5",         516, 729 },     /* 18.2cm * 25.72cm */
181         { "letter",     612, 792 },     /* 8.5in * 11in */
182         { "legal",      612, 1008 },    /* 8.5in * 14in */
183         { "ledger",     1224, 792 },    /* 17in * 11in */
184         { "tabloid",    792, 1224 },    /* 11in * 17in */
185         { "statement",  396, 612 },     /* 5.5in * 8.5in */
186         { "executive",  540, 720 },     /* 7.6in * 10in */
187         { "folio",      612, 936 },     /* 8.5in * 13in */
188         { "quarto",     610, 780 },     /* 8.5in * 10.83in */
189         { "10x14",      720, 1008 },    /* 10in * 14in */
190         { NULL, 0, 0 }
191 };
192
193 static const char *latin1def =
194 "[ /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
195 " /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
196 " /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
197 " /.notdef /.notdef /space /exclam /quotedbl /numbersign /dollar /percent /ampersand /quoteright\n"
198 " /parenleft /parenright /asterisk /plus /comma /hyphen /period /slash /zero /one\n"
199 " /two /three /four /five /six /seven /eight /nine /colon /semicolon\n"
200 " /less /equal /greater /question /at /A /B /C /D /E\n"
201 " /F /G /H /I /J /K /L /M /N /O\n"
202 " /P /Q /R /S /T /U /V /W /X /Y\n"
203 " /Z /bracketleft /backslash /bracketright /asciicircum /underscore /quoteleft /a /b /c\n"
204 " /d /e /f /g /h /i /j /k /l /m\n"
205 " /n /o /p /q /r /s /t /u /v /w\n"
206 " /x /y /z /braceleft /bar /braceright /asciitilde /.notdef /.notdef /.notdef\n"
207 " /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
208 " /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
209 " /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
210 " /space /exclamdown /cent /sterling /currency /yen /brokenbar /section /dieresis /copyright\n"
211 " /ordfeminine /guillemotleft /logicalnot /hyphen /registered /macron /degree /plusminus /twosuperior /threesuperior\n"
212 " /acute /mu /paragraph /periodcentered /cedilla /onesuperior /ordmasculine /guillemotright /onequarter /onehalf\n"
213 " /threequarters /questiondown /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla\n"
214 " /Egrave /Eacute /Ecircumflex /Edieresis /Igrave /Iacute /Icircumflex /Idieresis /Eth /Ntilde\n"
215 " /Ograve /Oacute /Ocircumflex /Otilde /Odieresis /multiply /Oslash /Ugrave /Uacute /Ucircumflex\n"
216 " /Udieresis /Yacute /Thorn /germandbls /agrave /aacute /acircumflex /atilde /adieresis /aring\n"
217 " /ae /ccedilla /egrave /eacute /ecircumflex /edieresis /igrave /iacute /icircumflex /idieresis\n"
218 " /eth /ntilde /ograve /oacute /ocircumflex /otilde /odieresis /divide /oslash /ugrave\n"
219 " /uacute /ucircumflex /udieresis /yacute /thorn /ydieresis] /isolatin1encoding exch def\n";
220
221 static const char *latin2def =
222 "[ /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
223 " /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
224 " /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
225 " /.notdef /.notdef /space /exclam /quotedbl /numbersign /dollar /percent /ampersand /quoteright\n"
226 " /parenleft /parenright /asterisk /plus /comma /minus /period /slash /zero /one\n"
227 " /two /three /four /five /six /seven /eight /nine /colon /semicolon\n"
228 " /less /equal /greater /question /at /A /B /C /D /E\n"
229 " /F /G /H /I /J /K /L /M /N /O\n"
230 " /P /Q /R /S /T /U /V /W /X /Y\n"
231 " /Z /bracketleft /backslash /bracketright /asciicircum /underscore /quoteleft /a /b /c\n"
232 " /d /e /f /g /h /i /j /k /l /m\n"
233 " /n /o /p /q /r /s /t /u /v /w\n"
234 " /x /y /z /braceleft /bar /braceright /asciitilde /.notdef /.notdef /.notdef\n"
235 " /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
236 " /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
237 " /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
238 " /space /Aogonek /breve /Lslash /currency /Lcaron /Sacute /section /dieresis /Scaron\n"
239 " /Scedilla /Tcaron /Zacute /hyphen /Zcaron /Zdotaccent /degree /aogonek /ogonek /lslash\n"
240 " /acute /lcaron /sacute /caron /cedilla /scaron /scedilla /tcaron /zacute /hungarumlaut\n"
241 " /zcaron /zdotaccent /Racute /Aacute /Acircumflex /Abreve /Adieresis /Lacute /Cacute /Ccedilla\n"
242 " /Ccaron /Eacute /Eogonek /Edieresis /Ecaron /Iacute /Icircumflex /Dcaron /Dbar /Nacute\n"
243 " /Ncaron /Oacute /Ocircumflex /Ohungarumlaut /Odieresis /multiply /Rcaron /Uring /Uacute /Uhungarumlaut\n"
244 " /Udieresis /Yacute /Tcedilla /germandbls /racute /aacute /acircumflex /abreve /adieresis /lacute\n"
245 " /cacute /ccedilla /ccaron /eacute /eogonek /edieresis /ecaron /iacute /icircumflex /dcaron\n"
246 " /dbar /nacute /ncaron /oacute /ocircumflex /ohungarumlaut /odieresis /divide /rcaron /uring\n"
247 " /uacute /uhungarumlaut /udieresis /yacute /tcedilla /dotaccent] /isolatin2encoding exch def\n";
248
249 static struct encoding {
250         char *name;
251         char *defstr;
252 } encodings[] = {
253         { "iso-8859-1", "isolatin1encoding", },
254         { "latin1",     "isolatin1encoding", },
255         { "iso-8859-2", "isolatin2encoding", },
256         { "latin2",     "isolatin2encoding", },
257         { NULL, NULL, },
258 };
259 struct encoding *encoding = NULL;
260
261 static Paper *paper;
262 static int w_width, w_height;
263 static int paper_xmargin = 10;
264 static int paper_ymargin = 5;
265
266 static Paper *findpaper(char *);
267 static void print_out(void);
268 static void scan_font(u_int);
269 static void print_page(u_int);
270 static void print_init(void);
271 static void print_pageinit(u_int);
272 static void process_direc_print(struct ctrl *cp);
273 static void scan_backcolor(u_int);
274 static void line_start(void);
275 static void line_end(void);
276 static void icon_output(struct textpool *);
277 static void line_skip(int, int);
278 static void print_bar(struct ctrl *);
279 static void print_icon(struct ctrl *);
280 static void print_line(char *, int);
281 static void print_string(char *, int);
282 static void print_fragment(u_char *, u_int, int, int);
283 static void text_remember(char *, int, int, int, int);
284 static void icon_remember(int, int, int, u_long);
285 static void image_remember(struct ctrl *, struct imagepool *);
286 static void image_load_print(char *, int, int, int, int, int, int);
287 static void print_usage(char *);
288 static void setpencolor(u_long);
289 static void print_full_image(XImage *, Visual *);
290 static void print_8_image(XImage *);
291 static void print_32_image(XImage *, Visual *);
292 static void print_eps(FILE *, char *, int, int, int, int, int);
293 static struct fontmap *findfont(int, int, char *);
294 static struct fontmap *findttfont(int, int, char *);
295 static char *fontstring(struct fontmap *);
296 static void loadfont(struct fontmap *, char *);
297 static int  count_pause(u_int page);   /* Added 23.07.2004 by Arnd Schmitter */
298
299 /* image/ *.[ch] */
300 extern char *Paths[];
301 extern int NumPaths;
302 extern char *expandPath(char *);
303
304 /*
305  * Paper size selection code is based on psutil.c by Angus J. C. Duggan
306  * but trivial
307  */
308 static Paper *
309 findpaper(name)
310         char *name;
311 {
312         Paper *pp;
313         for (pp = papersizes; pp->name; pp++) {
314                 if (strcmp(pp->name, name) == 0)
315                         return pp;
316         }
317         return (Paper *)NULL;
318 }
319
320 static void
321 print_out()
322 {
323         u_int   i;
324         u_int   width, height;
325
326         width  = window_width;
327         height = window_height;
328         window_width  = w_width;
329         window_height = w_height;
330
331         char_size[0] = window_height * DEFAULT_CHARSIZE / 100;
332         sup_off = DEFAULT_SUPOFF;
333         sub_off = DEFAULT_SUBOFF;
334         sup_scale = DEFAULT_SUPSCALE;
335
336         if (outputfile[0]) {
337                 if ((fp = fopen(outputfile, "w")) == NULL) {
338                         perror("fopen");
339                         exit(-1);
340                 }
341         } else
342                 fp = stdout;
343
344         print_init();
345         for (i = 1; i <= maxpage; i ++) {
346                 scan_font(i);
347         }
348         for (i = 1; i <= maxpage; i ++)
349           {
350             lg=0; /* Set the recursionlevel to 0 for each new page (Arnd Schmitter 23.07.2004) */
351             print_page(i);
352           }
353
354         fclose(fp);
355
356         window_width  = width;
357         window_height = height;
358 }
359
360 static void
361 scan_font(page)
362         u_int page;
363 {
364         u_int line;
365         struct ctrl *cp;
366         struct fontmap *font;
367         int code;
368
369         if (mgp_flag & FL_VERBOSE)
370                 fprintf(fp, "%% scan_font page %d\n", page);
371         for (line = 0;
372              line <= page_attribute[page].pg_linenum;
373              line++) {
374                 /* process normal control */
375                 for (cp = page_control[page][line]; cp; cp = cp->ct_next) {
376                         switch(cp->ct_op) {
377                         case CTL_PSFONT:
378                                 font = findfont(cp->ct_op,ASCII,cp->ctc_value);
379                                 if(font)
380                                         curfont[ASCII] = font;
381                                 break;
382
383                         case CTL_XFONT2:
384                                 if (strcmp(cp->ctc2_value2, "iso8859-1") == 0)
385                                         code = ASCII;
386                                 else if (strncmp(cp->ctc2_value2,
387                                                 "jisx0208", 8) == 0) {
388                                         code = KANJI;
389                                 } else {
390                                         fprintf(stderr,
391                                                 "unsupported XFONT registry %s\n",
392                                                 cp->ctc2_value2);
393                                         exit(1);
394                                 }
395                                 font = findfont(cp->ct_op, code,
396                                         cp->ctc2_value1);
397                                 if (font)
398                                         curfont[code] = font;
399                                 break;
400
401                         case CTL_XFONT:
402                                 fprintf(stderr, "obsolete directive XFONT\n");
403                                 exit(1);
404                         case CTL_TEXT:
405                                 if (strstr(cp->ctc_value, "\033$B")
406                                  || strstr(cp->ctc_value, "\033$@")) {
407                                         if (curfont[KANJI]) {
408                                                 loadfont(curfont[KANJI],
409                                                         curfont[KANJI]->font);
410                                         } else {
411                                                 fprintf(stderr,
412 "unable to find proper font for %s\n", "kanji");
413                                                 exit(1);
414                                         }
415                                 }
416                                 if (curfont[ASCII]) {
417                                         loadfont(curfont[ASCII],
418                                                 curfont[ASCII]->font);
419                                 } else {
420                                         fprintf(stderr,
421 "unable to find proper font for %s\n", "ascii");
422                                         exit(1);
423                                 }
424
425                         default:
426                                 break;
427                         }
428                 }
429         }
430
431         memset(curfont, 0, sizeof(curfont));
432 }
433
434 /*
435  * This Function counts the Number of Pause-Statements.
436  */
437 static int
438 count_pause(page)
439      u_int page;
440 {
441   int count=0;
442   u_int line;
443   struct ctrl*cp;
444   for (line = 0;
445        line <= page_attribute[page].pg_linenum;
446        line++) {
447     curlinenum = line;
448     /* process normal control */
449     for (cp = page_control[page][line]; cp; cp = cp->ct_next)
450       {
451         if(cp->ct_op == CTL_PAUSE)
452           {
453             count++;
454           }
455       }
456   }
457   return count;
458 }
459
460 static void
461 print_page(page)
462         u_int page;
463 {
464         u_int line;
465         struct ctrl *cp;
466
467         int ret=0;  /* A Pause Command was found */
468         int lc = 0; /* Counter to prevent infinite recursion loops at Pause-Statements */
469         int pcount; /* Stores the Number of Pause Statements for a Page */
470
471         /* Modified by Arnd Schmitter 23.07.2004:
472      * when in PauseMode for emulationg %pause in PS file (option "-m")
473      * this function is called recursively to print the beginning of
474      * the page again up to current %pause statement
475      */
476         /*curpagenum = page;*/
477         curpagenum++;
478         scan_backcolor(page);
479         print_pageinit(curpagenum);
480         /* End of Modification */
481
482         for (line = 0;
483              line <= page_attribute[page].pg_linenum;
484              line++) {
485                 curlinenum = line;
486                 /* process normal control */
487                 for (cp = page_control[page][line]; cp; cp = cp->ct_next)
488                   {
489                     if ((PauseMode) && (cp->ct_op == CTL_PAUSE))
490                       if (lc >= lg)
491                         ret=1;
492                       else
493                         (lc)++;
494                     else
495                       process_direc_print(cp);
496
497                     if (ret) goto pause; /* If a Pause has been found exit Loop immedeatly */
498                   }
499         }
500  pause:
501         fprintf(fp, "grestore\n\n");
502         fprintf(fp, "showpage\n\n");
503         /* If a Pause has been found -> Restart this Page */
504         if (ret)
505           {
506             lg++;
507             /* If we are in Pause-Mode check if we are called because of the last CTL_PAUSE at End of Page */
508             /*   At the Endo of the Last Page is no PAUSE Statemtent. So we have to use all Statements in the
509              Page */
510             pcount=count_pause(page);
511             if ((pcount != lg)||(page == (maxpage)))
512               print_page(page);
513           }
514 }
515
516 static void
517 print_init()
518 {
519         char **p;
520         char *aligns[] = { "center", "left", "right", NULL };
521
522         /* Added by Arnd Schmitter 23.07.2004 */
523         /*   If we split Pages with Pause Statements the number of absolute Pages gets greater then maxpage */
524         u_int i;
525         int absolute_pages = maxpage+1;
526         if (PauseMode)
527           {
528             for (i = 0; i < maxpage; i++)
529               {
530                 absolute_pages+=count_pause(i)-1;
531               }
532           }
533
534         /*fprintf(stderr,"Pages %d\n",absolute_pages);*/
535
536         fprintf(fp, "%%!PS-Adobe-2.0\n");
537         fprintf(fp, "%%%%Creator: mgp2ps\n");
538         fprintf(fp, "%%%%Title: %s\n", mgp_fname);
539         fprintf(fp, "%%%%Pages: %d\n", absolute_pages);
540         fprintf(fp, "%%%%BoundingBox: 0 0 %d %d\n", paper->height, paper->width);
541         fprintf(fp, "%%%%DocumentPaperSizes: %s\n", paper->name);
542         fprintf(fp, "%%%%Orientation: Landscape\n");
543         fprintf(fp, "%%%%EndComments\n");
544
545         /* define constants */
546         fprintf(fp, "/XMARGIN %d def /YMARGIN %d def "
547                 "/WIDTH %d def /HEIGHT %d def\n",
548                 paper_xmargin, paper_ymargin, window_width, window_height);
549         fprintf(fp, "/XBODY WIDTH XMARGIN 2 mul sub def\n");
550         fprintf(fp, "/vertgap %d def /horizgap %d def\n", vert_gap[0], horiz_gap[0]);
551
552         fprintf(fp, "/resety {/ymin 0 def /ymax 0 def} def\n");
553         fprintf(fp, "/setymax {dup ymax gt {dup /ymax exch def} if pop} def\n");
554         fprintf(fp, "/setymin {dup ymin lt {dup /ymin exch def} if pop} def\n");
555         fprintf(fp, "/calcy {dup ( ) eq\n"
556                 "  {0 setymax 0 setymin pop}\n"
557                 "  {pop charsize 0.7 mul setymax charsize -0.15 mul setymin}\n"
558                 "  ifelse\n"
559                 "} def\n");
560
561         fprintf(fp, "resety\n");
562
563         /* define writebox */
564         fprintf(fp, "/writebox {\n");
565         fprintf(fp, "  XMARGIN YMARGIN -1 mul moveto "
566                         "0 HEIGHT -1 mul rlineto\n");
567         fprintf(fp, "  WIDTH 0 rlineto 0 HEIGHT rlineto\n");
568         fprintf(fp, "  WIDTH -1 mul 0 rlineto stroke\n");
569         fprintf(fp, "} def\n");
570
571         /* define writeboxfill */
572         fprintf(fp, "/writeboxfill {\n");
573         fprintf(fp, "  newpath XMARGIN YMARGIN -1 mul moveto "
574                         "0 HEIGHT -1 mul rlineto\n");
575         fprintf(fp, "  WIDTH 0 rlineto 0 HEIGHT rlineto\n");
576         fprintf(fp, "  WIDTH -1 mul 0 rlineto closepath eofill stroke\n");
577         fprintf(fp, "} def\n");
578
579         /* ypos = ypos - (charsize * (1 + vert_gap / 100)) + little margin */
580         fprintf(fp, "/NL {\n");
581         fprintf(fp, "  charsize imgsize gt\n");
582         fprintf(fp, "   ymax ymin sub /csize exch def\n");
583         fprintf(fp, "   csize 0 eq {/csize charsize def} if\n");
584         fprintf(fp, "    { vertgap 100 div 1 add csize mul }\n");
585         fprintf(fp, "    { vertgap 100 div csize mul imgsize add }\n");
586         fprintf(fp, "  ifelse\n");
587         fprintf(fp, "  ypos exch sub /ypos exch def\n");
588         /* we can get similar results to xft2 by doing this */
589         if (!gaplevel)
590                 fprintf(fp, "  HEIGHT 90 div ypos exch sub /ypos exch def\n");
591         fprintf(fp, "} bind def\n");
592
593         /* show with line wrapping */
594         fprintf(fp, "/initcharsize { /charsize 0 def /imgsize 0 def resety} def\n");
595         fprintf(fp, "initcharsize\n");
596         fprintf(fp, "/setcharsize {\n");
597         fprintf(fp, "  dup charsize gt { dup /charsize exch def } if pop\n");
598         fprintf(fp, "} def\n");
599         fprintf(fp, "/setimgsize {\n");
600         fprintf(fp, "  dup imgsize gt { dup /imgsize exch def } if pop\n");
601         fprintf(fp, "} def\n");
602
603         fprintf(fp, "/updatetotlen {\n");
604         fprintf(fp, "  dup totlen exch sub /totlen exch def\n");
605         fprintf(fp, "} bind def\n");
606
607         fprintf(fp, "/updatefillzero {\n");
608         fprintf(fp, "  inmargin {\n");
609         fprintf(fp, "    currentpoint pop /fillzero exch def\n");
610         fprintf(fp, "    /inmargin false def\n");
611         fprintf(fp, "  } if\n");
612         fprintf(fp, "} bind def\n");
613
614         /* centering */
615         fprintf(fp, "/centerdefxpos {\n");
616         fprintf(fp, "  totlen XBODY gt\n");
617         fprintf(fp, "    { XMARGIN }\n");
618         fprintf(fp, "    { XBODY totlen sub 2 div XMARGIN add }\n");
619         fprintf(fp, "  ifelse /xpos exch def\n");
620         fprintf(fp, "} bind def\n");
621
622         /* leftfill */
623         fprintf(fp, "/leftdefxpos {\n");
624         fprintf(fp, "  /xpos fillzero def\n");
625         fprintf(fp, "} bind def\n");
626
627         /* rightfill */
628         fprintf(fp, "/rightdefxpos {\n");
629         fprintf(fp, "  totlen XBODY gt\n");
630         fprintf(fp, "    { XMARGIN }\n");
631         fprintf(fp, "    { XBODY totlen sub XMARGIN add }\n");
632         fprintf(fp, "  ifelse /xpos exch def\n");
633         fprintf(fp, "} bind def\n");
634
635         /* check newline */
636         for (p = aligns; *p; p++) {
637                 fprintf(fp, "/%snewlinecheck {\n", *p);
638                 fprintf(fp, "  currentpoint pop add XMARGIN XBODY add gt {\n");
639                 fprintf(fp, "    NL %sdefxpos xpos ypos charsize 2 div sub moveto\n",
640                         *p);
641                 fprintf(fp, "  } if\n");
642                 fprintf(fp, "} bind def\n");
643         }
644
645         /* a spell for EPS */
646         fprintf(fp, "%%\n");
647         fprintf(fp, "/BeginEPSF {%%def\n");
648         fprintf(fp, "  /b4_Inc_state save def\n");
649         fprintf(fp, "  /dict_count countdictstack def\n");
650         fprintf(fp, "  /op_count count 1 sub def\n");
651         fprintf(fp, "  userdict begin\n");
652         fprintf(fp, "  /showpage {}def\n");
653         fprintf(fp, "  0 setgray 0 setlinecap\n");
654         fprintf(fp, "  1 setlinewidth 0 setlinejoin\n");
655         fprintf(fp, "  10 setmiterlimit [] 0 setdash\n");
656         fprintf(fp, "  newpath\n");
657         fprintf(fp, "  /languagelevel where\n");
658         fprintf(fp, "  {pop languagelevel\n");
659         fprintf(fp, "  1 ne\n");
660         fprintf(fp, "    {false setstrokeadjust\n");
661         fprintf(fp, "     false setoverprint\n");
662         fprintf(fp, "    }if\n");
663         fprintf(fp, "  }if\n");
664         fprintf(fp, "}bind def\n");
665         fprintf(fp, "%%\n");
666         fprintf(fp, "/EndEPSF {%%def\n");
667         fprintf(fp, "  count op_count sub {pop}repeat\n");
668         fprintf(fp, "  countdictstack\n");
669         fprintf(fp, "  dict_count sub {end}repeat\n");
670         fprintf(fp, "  b4_Inc_state restore\n");
671         fprintf(fp, "}bind def\n");
672         fprintf(fp, "%%\n");
673
674         /* emit character encoding definition, if necessary */
675         if (encoding && strcmp(encoding->defstr, "isolatin1encoding") == 0)
676                 fprintf(fp, "%s", latin1def);
677         if (encoding && strcmp(encoding->defstr, "isolatin2encoding") == 0)
678                 fprintf(fp, "%s", latin2def);
679 }
680
681 static void
682 print_pageinit(page)
683         u_int page;
684 {
685
686         window_width  = paper->width - paper_xmargin * 2;
687         window_height = paper->height - paper_ymargin * 2;
688         fprintf(fp, "%%%%Page: %d %d\n", page, page);
689         fprintf(fp, "/ypos YMARGIN -1 mul 4 sub def\n");
690         fprintf(fp, "/xpos 0 def\n");
691         fprintf(fp, "initcharsize\n");
692         if (!colorps)
693                 fprintf(fp, "90 rotate newpath writebox\n");
694         else {
695                 setpencolor(back);
696                 fprintf(fp, "90 rotate newpath writeboxfill\n");
697         }
698         fprintf(fp, "gsave\n");
699 }
700
701 static void
702 process_direc_print(cp)
703         struct ctrl *cp;
704 {
705         struct fontmap *font;
706         int code;
707
708         switch(cp->ct_op) {
709         case CTL_SIZE:
710                 char_size[0] = window_height * cp->ctf_value / 100;
711                 fprintf(fp, "%d setcharsize\n", char_size[0]);
712                 break;
713
714         case CTL_PSFONT:
715                 font = findfont(cp->ct_op,ASCII,cp->ctc_value);
716                 if(font)
717                         curfont[ASCII] = font;
718                 break;
719
720         case CTL_XFONT2:
721                 if (strcmp(cp->ctc2_value2, "iso8859-1") == 0)
722                         code = ASCII;
723                 else if (strncmp(cp->ctc2_value2, "jisx0208", 8) == 0)
724                         code = KANJI;
725                 else {
726                         fprintf(stderr, "unsupported XFONT registry %s\n",
727                                 cp->ctc2_value2);
728                         exit(1);
729                 }
730                 font = findfont(cp->ct_op, code, cp->ctc2_value1);
731                 if (font)
732                         curfont[code] = font;
733                 break;
734
735         case CTL_XFONT:
736                 fprintf(stderr, "internal error: "
737                         "obsolete directive CTL_XFONT\n");
738                 exit(1);
739
740         case CTL_VGAP:
741                 vert_gap[0] = cp->cti_value;
742                 fprintf(fp, "/vertgap %d def\n", cp->cti_value);
743                 break;
744
745         case CTL_HGAP:
746                 horiz_gap[0] = cp->cti_value;
747                 fprintf(fp, "/horizgap %d def\n", cp->cti_value);
748                 break;
749
750         case CTL_GAP:
751                 vert_gap[0] = horiz_gap[0] = cp->cti_value;
752                 fprintf(fp, "/vertgap %d def ", cp->cti_value);
753                 fprintf(fp, "/horizgap %d def\n", cp->cti_value);
754                 break;
755
756         case CTL_CENTER:
757                 align = AL_CENTER;
758                 break;
759
760         case CTL_LEFT:
761                 align = AL_LEFT;
762                 break;
763
764         case CTL_LEFTFILL:
765                 align = AL_LEFTFILL0;
766                 break;
767
768         case CTL_RIGHT:
769                 align = AL_RIGHT;
770                 break;
771
772         case CTL_IMAGE:
773                 image_remember(cp, &imagepool[nimagepool]);
774                 line_skip(imagepool[nimagepool].xsiz,
775                         imagepool[nimagepool].ysiz);
776
777                 /* placeholder */
778                 textpool[ntextpool].pfx = 0;
779                 textpool[ntextpool].xoffset = 0;
780                 textpool[ntextpool].xsiz = imagepool[nimagepool].xsiz;
781                 textpool[ntextpool].size = imagepool[nimagepool].ysiz;
782                 textpool[ntextpool].font = 0;           /*image*/
783                 textpool[ntextpool].text = NULL;
784                 textpool[ntextpool].fore = fore;        /*XXX*/
785                 textpool[ntextpool].back = back;        /*XXX*/
786                 ntextpool++;
787
788                 nimagepool++;
789                 break;
790
791         case CTL_BAR:
792                 print_bar(cp);
793                 break;
794
795         case CTL_PREFIX:
796                 curprefix = cp->ctc_value;
797                 break;
798
799         case CTL_PREFIXN:
800                 xprefix = window_width * cp->ctf_value / 100;
801                 break;
802
803         case CTL_TABPREFIX:
804                 tabprefix = cp->ctc_value;
805                 break;
806
807         case CTL_TABPREFIXN:
808                 tabxprefix = window_width * cp->ctf_value / 100;
809                 break;
810
811         case CTL_PREFIXPOS:
812                 if (tabprefix)
813                         print_line(tabprefix, 1);
814                 else if (curprefix)
815                         print_line(curprefix, 1);
816                 break;
817
818         case CTL_TEXT:
819             {
820                 if (!cp->ctc_value)
821                         break;
822                 print_line(cp->ctc_value, 0);
823                 if (align == AL_LEFTFILL0)
824                         align = AL_LEFTFILL1;
825
826                 /* disable super/subscript for next line */
827                 if (char_off != 0)
828                 {
829                         char_size[0]=nonscaled_size[0];
830                         char_off=0;
831                 }
832                 break;
833             }
834
835         case CTL_ICON:
836                 print_icon(cp);
837                 break;
838
839         case CTL_LINESTART:
840                 line_start();
841                 break;
842
843         case CTL_LINEEND:
844                 line_end();
845                 if (align == AL_LEFTFILL1)
846                         align = AL_LEFTFILL0;
847                 break;
848
849         case CTL_FORE:
850                 fore = cp->ctl_value;
851                 break;
852
853 #if 0 /* it's not necessary */
854         case CTL_BACK:
855                 back = cp->ctl_value;
856                 break;
857 #endif
858
859         /*
860      * MARK and AGAIN processing by A.Ito, 14 Jul. 2000
861      */
862         case CTL_MARK:
863                 fprintf(fp,"/markx xpos def /marky ypos def\n");
864                 break;
865
866         case CTL_AGAIN:
867                 fprintf(fp,"markx marky moveto /xpos markx def /ypos marky def\n");
868                 break;
869
870         case CTL_VALIGN:
871                 valign = cp->cti_value;
872                 break;
873
874         case CTL_AREA:
875                 window_width = (paper->width - paper_xmargin * 2) * cp->ctar_width / 100;
876                 window_height = (paper->height - paper_ymargin * 2) * cp->ctar_height / 100;
877                 fprintf(fp, "grestore\ngsave\n");
878                 fprintf(fp, "%f dup scale\n", cp->ctar_height / 100.0);
879                 fprintf(fp, "WIDTH XMARGIN 2 mul sub %f mul 0 translate\n",
880                     (double)cp->ctar_xoff / cp->ctar_height);
881                 fprintf(fp, "/XBODY WIDTH XMARGIN 2 mul sub %f mul def\n",
882                     (double)cp->ctar_width / cp->ctar_height);
883                 fprintf(fp, "/ypos YMARGIN -1 mul 4 sub HEIGHT %f mul sub def\n",
884                     (double)cp->ctar_yoff / cp->ctar_height);
885                 fprintf(fp, "/xpos 0 def\n");
886                 break;
887         case CTL_OPAQUE:
888                 if (cp->cti_value > 100){
889                         fprintf(stderr, "%%opaque: value should be 0-100\n");
890                         cp->cti_value = 100;
891                 }
892                 fprintf(fp, "%f setgray\n", 1.0 - (float)cp->cti_value /100.0);
893                 break;
894
895         /* setup for super/subscript */
896         case CTL_SETSUP:
897                 if (cp->cti3_value1 > 100 || cp->cti3_value1 < 10){
898                         sup_off = DEFAULT_SUPOFF;
899                 } else {
900                         sup_off = cp->cti3_value1 / 100.;
901                 }
902                 if (cp->cti3_value2 > 100 || cp->cti3_value2 < 10){
903                         sub_off = DEFAULT_SUBOFF;
904                 } else {
905                         sub_off = cp->cti3_value2 / 100.;
906                 }
907                 if (cp->cti3_value3 > 100 || cp->cti3_value3 < 10){
908                         sup_scale = DEFAULT_SUPSCALE;
909                 } else {
910                         sup_scale = cp->cti3_value3 / 100.;
911                 }
912                 break;
913
914         /* subscript */
915         case CTL_SUB:
916                 /* save old size and set new one */
917                 nonscaled_size[0] = char_size[0];
918                 char_size[0] = char_size[0] * sup_scale;
919                 char_off = nonscaled_size[0] * (-sub_off);
920                 fprintf(fp, "%d setcharsize\n", char_size[0]);
921                 break;
922
923         /* superscript */
924         case CTL_SUP:
925                 /* save old size and set new one */
926                 nonscaled_size[0] = char_size[0];
927                 char_size[0] = char_size[0] * sup_scale;
928                 char_off = nonscaled_size[0] * sup_off;
929                 fprintf(fp, "%d setcharsize\n", char_size[0]);
930                 break;
931
932         default:
933           break;
934         }
935 }
936
937 static void
938 scan_backcolor(u_int page)
939 {
940   struct ctrl *cp;
941   u_int line;
942
943         for (line = 0; line <= page_attribute[page].pg_linenum; line++) {
944                 for (cp = page_control[page][line]; cp; cp = cp->ct_next)
945                         switch(cp->ct_op) {
946                                 case CTL_BACK:
947                                         back = cp->ctl_value;
948                                 break;
949                                 default:
950                                 break;
951                 }
952         }
953 }
954
955 static void
956 line_start()
957 {
958         linewidth = 0;
959         nimagepool = 0;
960         ntextpool = 0;
961 }
962
963 static void
964 line_end()
965 {
966         int i;
967         char *alignstr;
968
969         switch (align) {
970         case AL_CENTER:
971                 alignstr = "center";
972                 break;
973         case AL_LEFT:
974         case AL_LEFTFILL0:
975         case AL_LEFTFILL1:
976                 alignstr = "left";
977                 break;
978         case AL_RIGHT:
979                 alignstr = "right";
980                 break;
981         default:
982                 alignstr = "";
983                 break;
984         }
985
986         /*
987          * line output starts here
988          */
989         if (mgp_flag & FL_VERBOSE)
990                 fprintf(fp, "%% a line starts here\n");
991
992         /*
993          * if we have nothing on the line, skip it
994          */
995         if (!ntextpool && !nimagepool){
996                 fprintf(fp, "initcharsize %d setcharsize\n", char_size[0]);
997                 goto done;
998         }
999
1000         /*
1001          * push strings in reverse order.
1002          */
1003         fprintf(fp, "initcharsize\n");
1004         fprintf(fp, "0 %% sentinel for text width computation\n");
1005         fprintf(fp, "gsave newpath 0 0 moveto\n");
1006
1007         for (i = ntextpool - 1; 0 <= i; i--) {
1008                 if (!textpool[i].text) {
1009                         fprintf(fp, "%d add\n", textpool[i].xsiz);
1010                         continue;
1011                 }
1012                 fprintf(fp, "%d setcharsize %d %s %s calcy\n",
1013                         textpool[i].size, textpool[i].size,
1014                         fontstring(textpool[i].font),
1015                         textpool[i].text);
1016
1017                 fprintf(fp, "%d setcharsize %d %s %s "
1018                         "1 copy stringwidth pop 3 2 roll add\n",
1019                         textpool[i].size, textpool[i].size,
1020                         fontstring(textpool[i].font),
1021                         textpool[i].text);
1022         }
1023         fprintf(fp, "grestore\n");
1024
1025         if (mgp_flag & FL_VERBOSE) {
1026                 fprintf(fp, "%% stack should have: str3 str2 str1 width\n");
1027                 fprintf(fp, "%% alignment: %s\n", alignstr);
1028         }
1029
1030         /*
1031          * now show those chars with line wrapping. brief logic is:
1032          *
1033          *      position adjust;
1034          *      foreach i (item in textpool) {
1035          *              if (item exceeds the right edge) {
1036          *                      carriage return;
1037          *                      position adjust;
1038          *              }
1039          *              show;
1040          *      }
1041          */
1042         fprintf(fp, "/totlen exch def\n");
1043         fprintf(fp, "/totlen totlen %d add def\n", tabxprefix ? tabxprefix:xprefix);
1044         fprintf(fp, "/inmargin true def /fillzero XMARGIN def\n");
1045         fprintf(fp, "%sdefxpos ", alignstr);
1046
1047         /*
1048          * to determine text base line, we need to set imgsize first. pretty ugly..
1049          */
1050     {
1051         struct ctrl *cp1;
1052                 for (i = 0; i < nimagepool; i++) {
1053                         cp1 = imagepool[i].image;
1054                         if (cp1)
1055                                 fprintf(fp, "%d setimgsize\n", imagepool[i].ysiz);      /*XXX*/
1056                 }
1057         }
1058         fprintf(fp, "/yypos ypos charsize imgsize gt \n");
1059
1060         switch(valign){
1061         case VL_TOP:
1062                 fprintf(fp, " { 0 } { 0 } ifelse sub def\n");
1063                 break;
1064         case VL_BOTTOM:
1065                 fprintf(fp, " { 0 } { imgsize charsize sub } ifelse sub def\n");
1066                 break;
1067         case VL_CENTER:
1068                 fprintf(fp, " { 0 } { imgsize charsize sub 2 div } ifelse sub def\n");
1069                 break;
1070         }
1071         fprintf(fp, "/xpos xpos %d add def\n", tabxprefix ? tabxprefix:xprefix);
1072         fprintf(fp, "xpos yypos ymax sub moveto\n");
1073
1074         for (i = 0; i < ntextpool; i++) {
1075                 if (textpool[i].text) {
1076                         fprintf(fp, "%d %s 1 copy stringwidth pop ",
1077                                 textpool[i].size,
1078                                 fontstring(textpool[i].font));
1079                 } else
1080                         fprintf(fp, "%d ", textpool[i].xsiz);
1081                 fprintf(fp, "updatetotlen ");
1082                 if (textpool[i].text)
1083                         fprintf(fp, "%snewlinecheck ", alignstr);
1084                 else
1085                         fprintf(fp, "pop ");
1086
1087                 if (colorps
1088                  && (i == 0
1089                   || (textpool[i - 1].fore != textpool[i].fore)
1090                   || (textpool[i - 1].back != textpool[i].back))) {
1091                         fprintf(fp, "\n");
1092                         setpencolor(textpool[i].fore);
1093                 }
1094
1095                 if (textpool[i].text) {
1096                         if (!textpool[i].pfx)
1097                                 fprintf(fp, "updatefillzero ");
1098
1099                         /* for super/subscript: modify the current y-position */
1100                         if (textpool[i].yoffset != 0)
1101                                 fprintf(fp, "currentpoint %d add moveto ",
1102                                         textpool[i].yoffset);
1103                         fprintf(fp, "show\n");
1104
1105                         /* for super/subscript: reset the old y-position */
1106                         if (textpool[i].yoffset != 0)
1107                                 fprintf(fp, "currentpoint %d sub moveto ",
1108                                         textpool[i].yoffset);
1109                 } else {
1110                         fprintf(fp, "\n");
1111                         if (textpool[i].font) {
1112                                 /* icon */
1113                                 icon_output(&textpool[i]);
1114                         } else {
1115                                 /* image */
1116                                 fprintf(fp, "%d 0 rmoveto\n", textpool[i].xsiz);
1117                         }
1118                 }
1119                 fprintf(fp, "/xpos%d currentpoint pop def\n", i);
1120         }
1121
1122         ntextpool = 0;
1123
1124     {
1125         struct ctrl *cp1;
1126
1127         for (i = 0; i < nimagepool; i++) {
1128                 if (mgp_flag & FL_VERBOSE)
1129                         fprintf(fp, "%% emit the content of imagepool\n");
1130                 cp1 = imagepool[i].image;
1131                 if (cp1) {
1132                         image_load_print(cp1->ctm_fname, cp1->ctm_numcolor,
1133                                 cp1->ctm_ximagesize, cp1->ctm_yimagesize, 0,
1134                                 cp1->ctm_zoomflag, cp1->ctm_rotate);
1135                 }
1136                 fprintf(fp, "/xpos xpos%d def xpos ypos moveto\n",
1137                     imagepool[i].target_text);
1138
1139         }
1140         nimagepool = 0;
1141     }
1142
1143 done:
1144         fprintf(fp, "NL\n");
1145         tabprefix = NULL;
1146         tabxprefix = 0;
1147 }
1148
1149 static void
1150 icon_output(tp)
1151         struct textpool *tp;
1152 {
1153         int isize = tp->size;
1154         int csize = tp->xsiz;
1155         int ixoff, iyoff;
1156         int paintit;
1157
1158         iyoff = (csize - isize) / 6;    /*XXX*/
1159         ixoff = tp->xoffset + (csize - isize) / 2;  /* XXX */
1160
1161         paintit = (painticon || colorps);
1162
1163         switch ((size_t)tp->font) {     /*XXX*/
1164         case 0:
1165                 /* XXX: image is not supported yet */
1166                 break;
1167         case 1: /* this is box */
1168                 fprintf(fp, "currentpoint ");
1169                 if (paintit)
1170                         fprintf(fp, "currentpoint newpath moveto ");
1171                 fprintf(fp, "%d %d rmoveto ", ixoff, iyoff);
1172                 fprintf(fp, "0 %d rlineto ", isize);
1173                 fprintf(fp, "%d 0 rlineto ", isize);
1174                 fprintf(fp, "0 %d rlineto ", -isize);
1175                 fprintf(fp, "%d 0 rlineto ", -isize);
1176                 if (paintit)
1177                         fprintf(fp, "closepath eofill ");
1178                 fprintf(fp, "stroke moveto\n");
1179                 fprintf(fp, "%d 0 rmoveto\n", ixoff * 2 + isize);
1180                 break;
1181         case 2: /* this is arc */
1182                 fprintf(fp, "currentpoint ");
1183                 if (paintit)
1184                         fprintf(fp, "currentpoint newpath moveto ");
1185                 fprintf(fp, "%d %d rmoveto ", ixoff + isize, iyoff + isize/2);
1186                 fprintf(fp, "currentpoint exch %d add exch %d 0 360 arc ",
1187                         -isize/2, isize/2);
1188                 if (paintit)
1189                         fprintf(fp, "closepath eofill ");
1190                 fprintf(fp, "stroke moveto\n");
1191                 fprintf(fp, "%d 0 rmoveto\n", ixoff * 2 + isize);
1192                 break;
1193         case 3:
1194                 fprintf(fp, "currentpoint ");
1195                 if (paintit)
1196                         fprintf(fp, "currentpoint newpath moveto ");
1197                 fprintf(fp, "%d %d rmoveto ", ixoff, iyoff);
1198                 fprintf(fp, "%d 0 rlineto ", isize);
1199                 fprintf(fp, "%d %d rlineto ", -isize/2, isize);
1200                 fprintf(fp, "%d %d rlineto ", -isize/2, -isize);
1201                 if (paintit)
1202                         fprintf(fp, "closepath eofill ");
1203                 fprintf(fp, "stroke moveto\n");
1204                 fprintf(fp, "%d 0 rmoveto\n", ixoff * 2 + isize);
1205                 break;
1206         case 4:
1207                 fprintf(fp, "currentpoint ");
1208                 if (paintit)
1209                         fprintf(fp, "currentpoint newpath moveto ");
1210                 fprintf(fp, "%d %d rmoveto ", ixoff, iyoff + isize);
1211                 fprintf(fp, "%d 0 rlineto ", isize);
1212                 fprintf(fp, "%d %d rlineto ", -isize/2, -isize);
1213                 fprintf(fp, "%d %d rlineto ", -isize/2, isize);
1214                 if (paintit)
1215                         fprintf(fp, "closepath eofill ");
1216                 fprintf(fp, "stroke moveto\n");
1217                 fprintf(fp, "%d 0 rmoveto\n", ixoff * 2 + isize);
1218                 break;
1219         case 5:
1220                 fprintf(fp, "currentpoint ");
1221                 if (paintit)
1222                         fprintf(fp, "currentpoint newpath moveto ");
1223                 fprintf(fp, "%d %d rmoveto ", ixoff, iyoff);
1224                 fprintf(fp, "0 %d rlineto ", isize);
1225                 fprintf(fp, "%d %d rlineto ", isize, -isize/2);
1226                 fprintf(fp, "%d %d rlineto ", -isize, -isize/2);
1227                 if (paintit)
1228                         fprintf(fp, "closepath eofill ");
1229                 fprintf(fp, "stroke moveto\n");
1230                 fprintf(fp, "%d 0 rmoveto\n", ixoff * 2 + isize);
1231                 break;
1232         case 6:
1233                 fprintf(fp, "currentpoint ");
1234                 if (paintit)
1235                         fprintf(fp, "currentpoint newpath moveto ");
1236                 fprintf(fp, "%d %d rmoveto ", ixoff + isize, iyoff);
1237                 fprintf(fp, "0 %d rlineto ", isize);
1238                 fprintf(fp, "%d %d rlineto ", -isize, -isize/2);
1239                 fprintf(fp, "%d %d rlineto ", isize, -isize/2);
1240                 if (paintit)
1241                         fprintf(fp, "closepath eofill ");
1242                 fprintf(fp, "stroke moveto\n");
1243                 fprintf(fp, "%d 0 rmoveto\n", ixoff * 2 + isize);
1244                 break;
1245         case 7:
1246                 fprintf(fp, "currentpoint ");
1247                 if (paintit)
1248                         fprintf(fp, "currentpoint newpath moveto ");
1249                 fprintf(fp, "%d %d rmoveto ", ixoff, iyoff + isize/2);
1250                 fprintf(fp, "%d %d rlineto ",  isize/2,  isize/2);
1251                 fprintf(fp, "%d %d rlineto ",  isize/2, -isize/2);
1252                 fprintf(fp, "%d %d rlineto ", -isize/2, -isize/2);
1253                 fprintf(fp, "%d %d rlineto ", -isize/2,  isize/2);
1254                 if (paintit)
1255                         fprintf(fp, "closepath eofill ");
1256                 fprintf(fp, "stroke moveto\n");
1257                 fprintf(fp, "%d 0 rmoveto\n", ixoff * 2 + isize);
1258                 break;
1259         }
1260 }
1261
1262 static void
1263 line_skip(x, y)
1264         int x;
1265         int y;
1266 {
1267         linewidth += x;
1268         lineheight = (lineheight < y) ? y : lineheight;
1269 }
1270
1271 static void
1272 print_bar(cp)
1273         struct ctrl *cp;
1274 {
1275         struct ctrl_bar pbar;
1276
1277         pbar.ct_width = cp->ctb_width * w_height / 1000;
1278         pbar.ct_start = cp->ctb_start * w_width / 100;
1279         pbar.ct_length = cp->ctb_length * w_width / 100;
1280
1281         fprintf(fp, "%%bar color %d %d %d\n",
1282                 cp->ctb_width, cp->ctb_start, cp->ctb_length);
1283         fprintf(fp, "XMARGIN ypos moveto\n");
1284         fprintf(fp, "%d 0 rmoveto\n", pbar.ct_start);
1285         fprintf(fp, "%d %d rlineto\n", 0, pbar.ct_width * -1);
1286         fprintf(fp, "%d %d rlineto\n", pbar.ct_length, 0);
1287         fprintf(fp, "%d %d rlineto\n", 0, pbar.ct_width);
1288         fprintf(fp, "%d %d rlineto stroke\n", pbar.ct_length * -1, 0);
1289         fprintf(fp, "/ypos ypos %d sub def\n",
1290                 cp->ctb_width + VERT_GAP(char_size[0]) / 2);
1291         fprintf(fp, "xpos ypos moveto\n");
1292
1293         linewidth = 0;
1294 }
1295
1296 static void
1297 print_icon(cp)
1298         struct ctrl *cp;
1299 {
1300         int i;
1301         int itype, isize;
1302
1303         for (i = 0; icon_words[i].ctl_strlen != 0; i++) {
1304                 if (!strncasecmp(cp->ctic_value, icon_words[i].ctl_string,
1305                         strlen(cp->ctic_value)))
1306                                 break;
1307         }
1308         itype = icon_words[i].ctl_type;
1309         isize = char_size[0] * cp->ctic_size / 100;
1310         icon_remember(itype, isize, linewidth, cp->ctic_color);
1311         linewidth += char_size[0];
1312 }
1313
1314 static void
1315 print_line(data, pfx)
1316         char *data;
1317         int pfx;
1318 {
1319         if (data && *data)
1320                 print_string(data, pfx);
1321 }
1322
1323 static void
1324 print_string(data, pfx)
1325         char *data;
1326         int pfx;
1327 {
1328         u_char *p, *q;
1329         int kanji = 0;
1330         u_int code2;
1331
1332         p = (u_char *)data;
1333
1334         while (*p && *p != '\n') {
1335                 if (p[0] == 0x1b && p[1] == '$'
1336                  && (p[2] == 'B' || p[2] == '@')) {
1337                         kanji = 1;
1338                         p += 3;
1339                         continue;
1340                 }
1341                 if (p[0] == 0x1b && p[1] == '('
1342                  && (p[2] == 'B' || p[2] == 'J')) {
1343                         kanji = 0;
1344                         p += 3;
1345                         continue;
1346                 }
1347
1348                 if (kanji) {
1349                         for (q = p + 2; 0x21 <= q[0] && q[0] <= 0x7e; q += 2) {
1350                                 code2 = q[0] * 256 + q[1];
1351                                 if (!iskinsokuchar(code2))
1352                                         break;
1353                         }
1354                 } else {
1355                         q = p;
1356                         while (*q && isprint(*q) && !isspace(*q))
1357                                 q++;
1358                         if (q == p)
1359                                 q++;
1360                         else {
1361                                 /* append spaces to the end of the word. */
1362                                 while (*q && isspace(*q))
1363                                         q++;
1364                         }
1365                 }
1366
1367                 print_fragment(p, q - p, kanji, pfx);
1368
1369                 p = q;
1370         }
1371 }
1372
1373 static void
1374 print_fragment(data, len, kanjimode, pfx)
1375         u_char *data;
1376         u_int len;
1377         int kanjimode;
1378         int pfx;
1379 {
1380         u_char *p;
1381         char *q;
1382         char buf[4096];
1383         u_int code;
1384         int textstartpos = 0;
1385 #define OPENBRACE(kanji)        ((kanji) ? '<' : '(')
1386 #define CLOSEBRACE(kanji)       ((kanji) ? '>' : ')')
1387 #define DANGERLETTER(x) \
1388         ((x) == '(' || (x) == ')' || (x) == '\\')
1389
1390         p = data;
1391         if (kanjimode) {
1392                 q = &buf[1];
1393                 while (len) {
1394                         code = p[0] * 256 + p[1];
1395                         sprintf(q, "%04x ", code);
1396                         p += 2;
1397                         len -= 2;
1398                         q += 5;
1399                 }
1400                 buf[0] = OPENBRACE(kanjimode);
1401                 *q++ = CLOSEBRACE(kanjimode);
1402                 *q = '\0';
1403                 text_remember(buf, KANJI, char_size[0], textstartpos, pfx);
1404         } else {
1405                 /* must take care of escaping those "dangerous" letters */
1406                 q = &buf[0];
1407                 *q++ = OPENBRACE(kanjimode);
1408                 while (len) {
1409                         if (DANGERLETTER(p[0]))
1410                                 *q++ = '\\';
1411                         *q++ = *p++;
1412                         len--;
1413                 }
1414                 *q++ = CLOSEBRACE(kanjimode);
1415                 *q++ = '\0';
1416                 text_remember(buf, ASCII, char_size[0], textstartpos, pfx);
1417         }
1418         /* by A.Ito 14 Jul. 2000 */
1419         /* placeholder */
1420         imagepool[nimagepool].image = NULL;
1421         imagepool[nimagepool].target_text = ntextpool-1;
1422         nimagepool++;
1423 }
1424
1425 static char *
1426 checkeps(fname)
1427         char *fname;
1428 {
1429         static char epsfile[MAXPATHLEN];
1430         static char fullname[MAXPATHLEN];
1431         char *p;
1432
1433         /* rewrite file suffix, if it is not "ps" nor "eps". */
1434         strlcpy(epsfile, fname, sizeof(epsfile));
1435         p = strrchr(epsfile, '.');
1436         if (p) {
1437                 if (strcmp(p, ".ps") != 0 && strcmp(p, ".eps") != 0 &&
1438                         strcmp(p, ".idraw") != 0) {
1439                         /* try "basename.eps" */
1440                         memcpy(p, ".eps", 5);
1441                 }
1442         }
1443
1444         fullname[0] = '\0';
1445         if (findImage(epsfile, fullname) == 0)
1446                 return fullname;
1447         else
1448                 return NULL;
1449 }
1450
1451 static void
1452 text_remember(text, ctype, fontsize, offset, pfx)
1453         char *text;
1454         int ctype;
1455         int fontsize;
1456         int offset;
1457         int pfx;
1458 {
1459         /*XXX*/
1460         if (strcmp(text, "()") == 0)
1461                 return;
1462         if (!curfont[ctype]) {
1463                 fprintf(stderr, "cannot find proper font, skipping\n");
1464                 return;
1465         }
1466         textpool[ntextpool].pfx = pfx;
1467         textpool[ntextpool].xoffset = offset;
1468         textpool[ntextpool].yoffset = char_off;
1469         textpool[ntextpool].xsiz = linewidth - offset;
1470         textpool[ntextpool].size = fontsize;
1471         textpool[ntextpool].font = curfont[ctype];
1472         textpool[ntextpool].text = strdup(text);
1473         textpool[ntextpool].fore = fore;
1474         textpool[ntextpool].back = back;
1475         ntextpool++;
1476 }
1477
1478 static void
1479 icon_remember(icon, fontsize, offset, color)
1480         int icon;
1481         int fontsize;
1482         int offset;
1483         u_long color;
1484 {
1485         textpool[ntextpool].pfx = 1;
1486         textpool[ntextpool].xoffset = offset;
1487         textpool[ntextpool].xsiz = char_size[0];
1488         textpool[ntextpool].size = fontsize;
1489         textpool[ntextpool].font = (struct fontmap *)(size_t)icon;      /*XXX*/
1490         textpool[ntextpool].text = NULL;
1491         textpool[ntextpool].fore = color;
1492         textpool[ntextpool].back = back;        /*XXX*/
1493         ntextpool++;
1494 }
1495
1496 /* !TODO: move rotation code into some library */
1497 /* rotate image by 90 degrees (counter clockwise) */
1498 static void rotate_image_p90(image)
1499         Image *image;
1500 {
1501         unsigned int row, column, pl = image->pixlen;
1502         unsigned int new_height = image->width, new_width = image->height, new_linelen = new_width * pl;
1503         byte *src, *tgt, *col_head;
1504         Pixel d;
1505         /* allocate buffer for new image */
1506         byte *rot_data = lmalloc(new_linelen * new_height);
1507
1508         /* do the rotation */
1509         for (row = 0, src = image->data, col_head = rot_data + (new_height - 1) * new_linelen;
1510                         row < image->height;
1511                         row++, col_head += pl) {
1512                 for (column = 0, tgt = col_head;
1513                                 column < image->width;
1514                                 column++, src += pl, tgt -= new_linelen) {
1515                         d = memToVal(src, pl);
1516                         valToMem(d, tgt, pl);
1517                 }
1518         }
1519
1520         /* swap to rotated image, exchange height and width
1521            and point to rotated data */
1522         image->height = new_height;
1523         image->width = new_width;
1524         lfree(image->data);
1525         image->data = rot_data;
1526 }
1527
1528 /* rotate image by -90 degrees (clockwise) */
1529 static void rotate_image_m90(image)
1530 Image *image;
1531 {
1532         unsigned int row, column, pl = image->pixlen;
1533         unsigned int new_height = image->width, new_width = image->height, new_linelen = new_width * pl;
1534         byte *src, *tgt;
1535         Pixel d;
1536         /* allocate buffer for new image */
1537         byte *rot_data = lmalloc(new_linelen * new_height);
1538
1539         /* do the rotation */
1540         for (row = 0, src = image->data; row < image->height; row++) {
1541                 for (column = 0, tgt = rot_data + new_linelen - (row + 1) * pl;
1542                                 column < image->width;
1543                                 column++, src += pl, tgt += new_linelen) {
1544                         d = memToVal(src, pl);
1545                         valToMem(d, tgt, pl);
1546                 }
1547         }
1548
1549         /* swap to rotated image, exchange height and width
1550            and point to rotated data */
1551         image->height = new_height;
1552         image->width = new_width;
1553         lfree(image->data);
1554         image->data = rot_data;
1555
1556         return;
1557 }
1558
1559 /* rotate image by 180 degrees */
1560 static void rotate_image_180(image)
1561         Image *image;
1562 {
1563         unsigned int row, column, pl = image->pixlen;
1564         unsigned int new_height = image->height, new_width = image->width, new_linelen = new_width * pl;
1565         byte *src, *tgt;
1566         Pixel d;
1567         /* allocate buffer for new image */
1568         byte *rot_data = lmalloc(new_linelen * new_height);
1569
1570         /* do the rotation */
1571         for (row = 0, src = image->data; row < image->height; row++) {
1572                 for (column = 0, tgt = rot_data + (new_height - row) * new_linelen - pl;
1573                                 column < image->width;
1574                                 column++, src += pl, tgt -= pl) {
1575                         d = memToVal(src, pl);
1576                         valToMem(d, tgt, pl);
1577                 }
1578         }
1579
1580         /* swap to rotated image, exchange height and width
1581            and point to rotated data */
1582         image->height = new_height;
1583         image->width = new_width;
1584         lfree(image->data);
1585         image->data = rot_data;
1586
1587         return;
1588 }
1589
1590 static void
1591 image_remember(cp, pool)
1592         struct ctrl *cp;
1593         struct imagepool *pool;
1594 {
1595         char *epsname;
1596         Image *myimage;
1597         float xzoom, yzoom;
1598         int x1, y1, x2, y2, width, height, swidth, sheight;
1599         struct render_state state;
1600
1601         if ((epsname = checkeps(cp->ctm_fname))){
1602                 if (ps_boundingbox(epsname, &x1, &y1, &x2, &y2) < 0) goto noneps;
1603
1604                 width = x2 - x1;
1605                 height = y2 - y1;
1606         } else {
1607                 myimage = loadImage(cp->ctm_fname, mgp_flag & FL_VERBOSE);
1608                 if (!myimage) {
1609                         fprintf(stderr, "failed to open %s\n", cp->ctm_fname);
1610                         exit(1);
1611                 }
1612                 switch (cp->ctm_rotate) {
1613                         case 0:
1614                                 /* Do nothing */
1615                                 break;
1616
1617                         case -90:
1618                         case 270:
1619                                 rotate_image_m90(myimage);
1620                                 break;
1621
1622                         case 90:
1623                                 rotate_image_p90(myimage);
1624                                 break;
1625
1626                         case -180:
1627                         case 180:
1628                                 rotate_image_180(myimage);
1629                                 break;
1630
1631                         default:
1632                                 fprintf(stderr, "rotation by %d degrees not supported.\n", cp->ctm_rotate);
1633                                 cleanup(-1);
1634                 }
1635                 width = myimage->width;
1636                 height = myimage->height;
1637                 freeImage(myimage);
1638         }
1639                 xzoom = (!cp->ctm_ximagesize ? 100 : cp->ctm_ximagesize);
1640                 yzoom = (!cp->ctm_yimagesize ? 100 : cp->ctm_yimagesize);
1641
1642                 state.width = window_width;
1643                 state.height = window_height;
1644                 image_zoomratio(&state, &xzoom, &yzoom, cp->ctm_zoomflag,
1645                         width, height);
1646                 swidth = (int) width * xzoom / 100;
1647                 sheight = (int) height * yzoom / 100;
1648
1649                 pool->xsiz = swidth;
1650                 pool->ysiz = sheight;
1651                 pool->xoffset = linewidth;
1652                 pool->image = cp;
1653                 return;
1654
1655 noneps:
1656         myimage = loadImage(cp->ctm_fname, mgp_flag & FL_VERBOSE);
1657         if (!myimage) {
1658                 fprintf(stderr, "failed to open %s\n", cp->ctm_fname);
1659                 exit(1);
1660         }
1661         switch (cp->ctm_rotate) {
1662                 case 0:
1663                         /* Do nothing */
1664                         break;
1665
1666                 case -90:
1667                 case 270:
1668                         rotate_image_m90(myimage);
1669                         break;
1670
1671                 case 90:
1672                         rotate_image_p90(myimage);
1673                         break;
1674
1675                 case -180:
1676                 case 180:
1677                         rotate_image_180(myimage);
1678                         break;
1679
1680                 default:
1681                         fprintf(stderr, "rotation by %d degrees not supported.\n", cp->ctm_rotate);
1682                         cleanup(-1);
1683         }
1684         pool->xsiz = myimage->width;
1685         pool->ysiz = myimage->height;
1686         freeImage(myimage);
1687         pool->xoffset = linewidth;
1688         pool->image = cp;
1689 }
1690
1691 static void
1692 image_load_print(filename, numcolor, ximagesize, yimagesize, backflag, zoomflag, rotate)
1693         char *filename;
1694         int numcolor;
1695         int ximagesize;
1696         int yimagesize;
1697         int backflag;
1698         int zoomflag;
1699         int rotate;
1700 {
1701         Image *myimage, *image;
1702         Pixmap mypixmap;
1703         XImageInfo *ximageinfo;
1704         XImage  *print_image;
1705         int width, height;
1706         float xzoomrate, yzoomrate;
1707         static Cursor curs;
1708         u_int   print_width, print_height;
1709         struct render_state state;
1710         int xpos = 0;
1711
1712         if (zoomflag == 2)
1713                 ximagesize = yimagesize = 0;
1714
1715         /* hook for eps */
1716     {
1717         char *p;
1718         FILE *epsfp;
1719
1720         p = checkeps(filename);
1721         if (p) {
1722                 epsfp = fopen(p, "r");
1723                 print_eps(epsfp, p, numcolor, ximagesize, yimagesize,
1724                         backflag, zoomflag);
1725                 fclose(epsfp);
1726                 return;
1727         }
1728     }
1729
1730         if (!curs)
1731                 curs = XCreateFontCursor(display, XC_watch);
1732         XDefineCursor(display, window, curs); XFlush(display);
1733
1734         screen = DefaultScreen(display);
1735
1736         if ((myimage = loadImage(filename, verbose)) == NULL)
1737                 exit(-1);       /* fail to load image data */
1738         switch (rotate) {
1739                 case 0:
1740                         /* Do nothing */
1741                         break;
1742
1743                 case -90:
1744                 case 270:
1745                         rotate_image_m90(myimage);
1746                         break;
1747
1748                 case 90:
1749                         rotate_image_p90(myimage);
1750                         break;
1751
1752                 case -180:
1753                 case 180:
1754                         rotate_image_180(myimage);
1755                         break;
1756
1757                 default:
1758                         fprintf(stderr, "rotation by %d degrees not supported.\n", rotate);
1759                         cleanup(-1);
1760         }
1761         width = myimage->width;
1762         height = myimage->height;
1763
1764         if (numcolor)
1765                 myimage = reduce(myimage, numcolor, verbose);
1766
1767         xzoomrate = (float) ximagesize;
1768         yzoomrate = (float) yimagesize;
1769         state.width = window_width;
1770         state.height = window_height;
1771         image_zoomratio(&state, &xzoomrate, &yzoomrate, zoomflag,
1772                 width, height);
1773         image = myimage;
1774         myimage = zoom(image, xzoomrate, yzoomrate, verbose);
1775         freeImage(image);
1776         width = myimage->width;
1777         height = myimage->height;
1778
1779         if (! (ximageinfo= imageToXImage(display, screen, visual, depth,
1780                         myimage, 0, 0, 0, verbose))) {
1781                 fprintf(stderr, "Cannot convert Image to XImage\n");
1782                 exit(1);
1783         }
1784
1785         mypixmap = ximageToPixmap(display, RootWindow(display, 0), ximageinfo);
1786         if (!mypixmap) {
1787                 fprintf(stderr, "Cannot create image in server\n");
1788                 exit(1);
1789         }
1790
1791         switch (align) {
1792         case AL_LEFT:
1793         case AL_LEFTFILL0:
1794         case AL_LEFTFILL1:
1795                 xpos = 0;
1796                 break;
1797         case AL_CENTER:
1798                 xpos = (window_width - width) / 2;
1799                 break;
1800         case AL_RIGHT:
1801                 xpos = window_width - width;
1802                 break;
1803         }
1804
1805         print_width = myimage->width;
1806         print_height = myimage->height;
1807
1808         print_image =  XGetImage(display, mypixmap, 0, 0,
1809                                         print_width, print_height,
1810                                         AllPlanes, ZPixmap);
1811
1812         fprintf(fp, "gsave\n");
1813
1814         /* fixed by A.Ito */
1815         fprintf(fp, "xpos ypos %d sub translate\n",
1816                 print_height);
1817         fprintf(fp, "%d %d scale\n", print_width, print_height);
1818         fprintf(fp, "%d %d 8\n", print_width, print_height);
1819         fprintf(fp, "[%d 0 0 %d 0 %d]\n", print_width,
1820                         -1 * print_height, print_height);
1821         fprintf(fp, "{currentfile\n");
1822         fprintf(fp, "%d string readhexstring pop}\n", print_width * 3);
1823         fprintf(fp, "false 3\n");
1824         fprintf(fp, "colorimage\n");
1825
1826         /* XXX is there any generic way of doing this? */
1827         switch (print_image->bits_per_pixel) {
1828         case 8:
1829                 print_8_image(print_image);
1830                 break;
1831         case 16:
1832                 print_full_image(print_image, visual);
1833                 break;
1834         case 32:
1835                 print_32_image(print_image, visual);
1836                 break;
1837         default:
1838                 fprintf(stderr, "Sorry unsupported visual %d\n",
1839                         print_image->bits_per_pixel);
1840                 exit(-1);
1841         }
1842
1843         fprintf(fp, "grestore\n");
1844
1845         XFreePixmap(display, mypixmap);
1846         freeXImage(myimage, ximageinfo);
1847         freeImage(myimage);
1848         XUndefineCursor(display, window); XFlush(display);
1849 }
1850
1851 static void
1852 print_usage(name)
1853         char    *name;
1854 {
1855         fprintf(stderr, "Usage: %s [-cimPrv] [-e encoding] [-f psfile] "
1856             "[-g gap] [-p paper] [-x xmargin] [-y ymargin] mgpfile\n", name);
1857         exit(0);
1858 }
1859
1860 static void
1861 setpencolor(c)
1862         u_long c;
1863 {
1864         /*
1865          * update the color of the pen.
1866          * XXX background is ignored at this moment
1867          */
1868         XColor color;
1869
1870         color.pixel = c;
1871         XQueryColor(display, colormap, &color);
1872         fprintf(fp, "%f %f %f setrgbcolor %% #%08x depth %d\n",
1873                 color.red / 65535.0,
1874                 color.green / 65535.0,
1875                 color.blue / 65535.0,
1876                 (int) color.pixel, depth);
1877 }
1878
1879 static void
1880 print_full_image(print_image, visual)
1881         XImage  *print_image;
1882         Visual  *visual;
1883 {
1884         u_int   x, y;
1885         u_int   r, g, b;
1886         u_int   count = 0;
1887         u_int   width, height, byte_width;
1888         u_short *data;
1889
1890         data = (u_short *)print_image->data;
1891         width = print_image->width;
1892         height = print_image->height;
1893         byte_width = print_image->bytes_per_line / sizeof(u_short);
1894
1895         for (y = 0; y < height; y ++) {
1896                 for (x = 0; x < width; x ++) {
1897                         r = ((data[x + y * byte_width] & visual->red_mask) >> 11) & 0xff;
1898                         g = ((data[x + y * byte_width] & visual->green_mask) >> 5) & 0xff;
1899                         b = (data[x + y * byte_width] & visual->blue_mask) & 0xff;
1900
1901                         if (reverse)
1902                                 fprintf(fp, "%02x%02x%02x",
1903                                         ~(r << 3) & 0xff, ~(g << 2) & 0xff, ~(b << 3) & 0xff);
1904                         else
1905                                 fprintf(fp, "%02x%02x%02x", r << 3, g << 2, b << 3);
1906
1907                         count ++;
1908                         if (count == 10) {
1909                                 count = 0;
1910                                 fprintf(fp, "\n");
1911                         }
1912                 }
1913         }
1914 }
1915
1916 static void
1917 print_32_image(print_image, visual)
1918         XImage  *print_image;
1919         Visual  *visual;
1920 {
1921         u_int   x, y;
1922         u_int   r, g, b;
1923         u_int   count = 0;
1924         u_int   width, height;
1925         u_short *data;
1926
1927         data = (u_short *)print_image->data;
1928         width = print_image->width;
1929         height = print_image->height;
1930
1931         for (y = 0; y < height; y ++) {
1932                 for (x = 0; x < width; x ++) {
1933                         unsigned long pix;
1934                         pix = XGetPixel(print_image, x, y);
1935                         r = ((pix & visual->red_mask)   >> 16) & 0xff;
1936                         g = ((pix & visual->green_mask) >>  8) & 0xff;
1937                         b =   pix & visual->blue_mask          & 0xff;
1938
1939                         if (reverse)
1940                                 fprintf(fp, "%02x%02x%02x",
1941                                         ~r & 0xff, ~g & 0xff, ~b & 0xff);
1942                         else
1943                                 fprintf(fp, "%02x%02x%02x", r, g, b);
1944
1945                         count ++;
1946                         if (count == 10) {
1947                                 count = 0;
1948                                 fprintf(fp, "\n");
1949                         }
1950                 }
1951         }
1952 }
1953
1954 static void
1955 print_8_image(print_image)
1956         XImage  *print_image;
1957 {
1958         u_int   x, y;
1959         u_int   count = 0;
1960         u_char  *data;
1961         u_int   width, height, byte_width;
1962
1963         data = (u_char *)print_image->data;
1964         width = print_image->width;
1965         height = print_image->height;
1966         byte_width = print_image->bytes_per_line / sizeof(u_char);
1967
1968         for (y = 0; y < height; y ++) {
1969                 for (x = 0; x < width; x ++) {
1970                         if (reverse)
1971                                 fprintf(fp, "%02x%02x%02x",
1972                                         ~data[x + y * byte_width] & 0xff,
1973                                         ~data[x + y * byte_width] & 0xff,
1974                                         ~data[x + y * byte_width] & 0xff);
1975                         else
1976                                 fprintf(fp, "%02x%02x%02x",
1977                                         data[x + y * byte_width],
1978                                         data[x + y * byte_width],
1979                                         data[x + y * byte_width]);
1980
1981                         count ++;
1982                         if (count == 10) {
1983                                 count = 0;
1984                                 fprintf(fp, "\n");
1985                         }
1986                 }
1987         }
1988 }
1989
1990 static void
1991 print_eps(epsfp, filename, numcolor, ximagesize, yimagesize, backflag, zoomflag)
1992         FILE *epsfp;
1993         char *filename;
1994         int numcolor;
1995         int ximagesize;
1996         int yimagesize;
1997         int backflag;
1998         int zoomflag;
1999 {
2000         char line1[BUFSIZ];
2001         char line2[BUFSIZ];
2002         char line[BUFSIZ];
2003         int x1, y1, x2, y2, height, width, sheight, swidth;
2004         int xpos = 0;
2005         float xzoomrate, yzoomrate;
2006         double xscale, yscale;
2007         int noboundingbox;
2008         struct render_state state;
2009
2010         if (fgets(line1, sizeof(line1), epsfp) == NULL) {
2011                 fprintf(stderr, "no first line in %s.\n", filename);
2012                 exit(1);
2013         }
2014         if (strncmp(line1, "%!", 2) != 0) {
2015                 fprintf(stderr, "non eps file %s used as eps.\n", filename);
2016                 exit(1);
2017         }
2018
2019         noboundingbox = 1;
2020         while (1) {
2021                 if (fgets(line2, sizeof(line2), epsfp) == NULL)
2022                         break;
2023                 if (line2[0] != '%')
2024                         break;
2025                 if (strncmp(line2, "%%EndComments", 12) == 0)
2026                         break;
2027                 if (sscanf(line2, "%%%%BoundingBox: %d %d %d %d",
2028                                 &x1, &y1, &x2, &y2) == 4) {
2029                         noboundingbox = 0;
2030                         break;
2031                 }
2032         }
2033         if (noboundingbox) {
2034                 fprintf(stderr, "no bounding box in %s.\n", filename);
2035                 exit(1);
2036         }
2037
2038         /* width/height of original image */
2039         width = x2 - x1;
2040         height = y2 - y1;
2041
2042         ximagesize = (!ximagesize ? 100 : ximagesize);
2043         yimagesize = (!yimagesize ? 100 : yimagesize);
2044
2045         xzoomrate = (float) ximagesize;
2046         yzoomrate = (float) yimagesize;
2047         state.width = window_width;
2048         state.height = window_height;
2049         image_zoomratio(&state, &xzoomrate, &yzoomrate, zoomflag,
2050                 width, height);
2051         xscale = xzoomrate / 100.0;
2052         yscale = yzoomrate / 100.0;
2053
2054         /* scaled image size */
2055         swidth = (int)(xscale * width);
2056         sheight = (int)(yscale * height);
2057
2058         switch (align) {
2059         case AL_LEFT:
2060         case AL_LEFTFILL0:
2061         case AL_LEFTFILL1:
2062                 xpos = 0;
2063                 break;
2064         case AL_CENTER:
2065                 xpos = (window_width - swidth) / 2;
2066                 break;
2067         case AL_RIGHT:
2068                 xpos = window_width - swidth;
2069                 break;
2070         }
2071
2072         fprintf(fp, "BeginEPSF\n");
2073 /*
2074         fprintf(fp, "%d XMARGIN add ypos translate\n", xpos);
2075 */
2076         /* by A.Ito */
2077         fprintf(fp, "xpos ypos translate\n");
2078         fprintf(fp, "%f %f scale\n", xscale, yscale);
2079         fprintf(fp, "%d %d translate\n", -1 * x1, -1 * y2);
2080         fprintf(fp, "%%%%BeginDocument: %s\n", filename);
2081         fputs(line1, fp);
2082         fputs(line2, fp);
2083         while (fgets(line, sizeof(line), epsfp)) {
2084                 if (strncmp(line, "%%PageBoundingBox:", 18) == 0
2085                 ||  strncmp(line, "%%Trailer", 9) == 0)
2086                         line[1] = '#';
2087                 fputs(line, fp);
2088         }
2089         fprintf(fp, "%%%%EndDocument\n");
2090         fprintf(fp, "EndEPSF\n");
2091 }
2092
2093 /*------------------------------------------------------------*/
2094
2095 int
2096 main(argc, argv)
2097         int argc;
2098         char **argv;
2099 {
2100         u_int opt;
2101         extern char *optarg;
2102         extern int optind;
2103         char *progname;
2104         static char pathbuf[MAXPATHLEN];
2105
2106         setlocale(LC_CTYPE, "");
2107
2108         progname = argv[0];
2109
2110         /* set default paper size */
2111         paper = findpaper(DEFAULT_PAPER_SIZE);
2112
2113         while ((opt = getopt(argc, argv, "ce:f:g:imPp:rvx:y:")) != -1) {
2114                 switch (opt) {
2115                 case 'c':
2116                         colorps++;
2117                         break;
2118
2119                 case 'e':
2120                         for (encoding = &encodings[0];
2121                              encoding->name;
2122                              encoding++) {
2123                                 if (strcmp(encoding->name, optarg) == 0)
2124                                         break;
2125                         }
2126                         if (!encoding->name) {
2127                                 fprintf(stderr, "unknown encoding %s\n", optarg);
2128                                 exit(1);
2129                         }
2130                         break;
2131
2132                 case 'f':
2133                         strlcpy(outputfile, optarg, sizeof(outputfile));
2134                         break;
2135
2136                 case 'g':
2137                         gaplevel = atoi(optarg);
2138                         break;
2139
2140                 case 'i':
2141                         painticon++;
2142                         break;
2143
2144                 case 'm':       /* Added by Arnd Schmitter 23.07.2004 */
2145                         PauseMode=1;
2146                         break;
2147
2148                 case 'P':
2149                         parse_debug++;
2150                         break;
2151
2152                 case 'p':
2153                         paper = findpaper(optarg);
2154                         if (!paper) {
2155                                 fprintf(stderr,"Paper size '%s' not recognised. Using %s instead.\n",
2156                                     optarg, DEFAULT_PAPER_SIZE);
2157                                 paper = findpaper(DEFAULT_PAPER_SIZE);
2158                         }
2159                         break;
2160
2161                 case 'r':
2162                         reverse = 1;
2163                         break;
2164
2165                 case 'v':
2166                         mgp_flag |= FL_VERBOSE;
2167                         break;
2168
2169                 case 'x':
2170                         paper_xmargin = atoi(optarg);
2171                         break;
2172
2173                 case 'y':
2174                         paper_ymargin = atoi(optarg);
2175                         break;
2176
2177                 default:
2178                         print_usage(progname);
2179                         /*NOTREACHED*/
2180                 }
2181         }
2182
2183         w_width  = paper->width - paper_xmargin * 2;
2184         w_height = paper->height - paper_ymargin * 2;
2185
2186         argc -= optind;
2187         argv += optind;
2188
2189         if (argc != 1) {
2190                 print_usage(progname);
2191                 /*NOTREACHED*/
2192         }
2193
2194         mgp_fname = argv[0];
2195
2196         /* setting up the search path. */
2197     {
2198         char *p;
2199         loadPathsAndExts();
2200         strlcpy(pathbuf, mgp_fname, sizeof(pathbuf));
2201         if ((p = strrchr(pathbuf, '/'))) {
2202                 *p = '\0';
2203                 Paths[NumPaths++]= expandPath(pathbuf);
2204         }
2205     }
2206
2207         init_win1(NULL);
2208         load_file(mgp_fname);
2209         init_win2();
2210         fore = 0UL;
2211         back = (1UL << depth) - 1;
2212         print_out();
2213
2214         exit(0);
2215 }
2216
2217 static struct fontmap *
2218 findfont(ctrl, lang, font)
2219         int ctrl;
2220         int lang;
2221         char *font;
2222 {
2223         struct fontmap *p, *q;
2224         char *star;
2225
2226         if (!font[0])
2227                 return NULL;
2228
2229         for (p = fontmap; 0 <= p->ctrl; p++) {
2230                 if (p->ctrl != ctrl || p->lang != lang)
2231                         continue;
2232                 star = strchr(p->font, '*');
2233                 if (!star && strcmp(p->font, font) == 0)
2234                         goto found;
2235                 if (star && strncmp(p->font, font, star - p->font) == 0)
2236                 {
2237                         if(strcmp(font,"k14")==0)
2238                                 goto found;
2239                         if(ctrl ==CTL_PSFONT)
2240                                 fprintf(stderr,"PSFONT: %s  not found\n",font);
2241                         goto found;
2242                 }
2243         }
2244         return NULL;
2245
2246 found:
2247         if (p->fontid)
2248                 return p;
2249
2250         p->fontid = ++maxfontid;
2251
2252         if (mgp_flag & FL_VERBOSE) {
2253                 char fonttype;
2254
2255                 switch (ctrl) {
2256                 case CTL_XFONT2: fonttype = 'x'; break;
2257
2258                 case CTL_PSFONT: fonttype = 'p'; break;
2259                 default:        fonttype = '?'; break;
2260                 }
2261                 fprintf(fp, "%% %cfont \"%s\" seen, mapped to ps font \"%s\"\n",
2262                         fonttype, font, p->psfont);
2263                 if (strcmp(font, p->font) != 0) {
2264                         fprintf(fp, "%%\t(wildcard match against \"%s\")\n",
2265                                 p->font);
2266                 }
2267         }
2268         /* use the same font index for same PS font names */
2269         for (q = fontmap; 0 <= q->ctrl; q++) {
2270                 if (strcmp(p->psfont, q->psfont) == 0)
2271                         q->fontid = maxfontid;
2272         }
2273
2274         return p;
2275 }
2276
2277 static char *
2278 fontstring(font)
2279         struct fontmap *font;
2280 {
2281         static char fontname[10];
2282
2283         sprintf(fontname, "F%03d", font->fontid);
2284         return fontname;
2285 }
2286
2287 static void
2288 loadfont(font, name)
2289         struct fontmap *font;
2290         char *name;
2291 {
2292         if (!font) {
2293                 fprintf(stderr, "unable to find proper font for %s\n", name);
2294                 exit(1);
2295         }
2296
2297         if (font->loaded)
2298                 return;
2299
2300         /* define font calling sequence */
2301         if (mgp_flag & FL_VERBOSE) {
2302                 fprintf(fp, "%% loading font \"%s\" for %s\n",
2303                         font->psfont, font->font);
2304         }
2305         if (font->lang == ASCII && encoding) {
2306                 /*
2307                  * Symbol font does not need latin1-encoding
2308                  */
2309                 if (strcmp(font->psfont, "Symbol") == 0) {
2310                         fprintf(fp,
2311                                 "/%s%s\n"
2312                                 "       /%s findfont\n"
2313                                 "               dup length dict begin\n"
2314                                 "               {1 index /FID ne {def} {pop "
2315                                 "pop} ifelse} forall\n"
2316                                 "       currentdict end\n"
2317                                 "definefont pop\n",
2318                                 fontstring(font), "t", font->psfont);
2319                 } else {
2320                         fprintf(fp,
2321 "/%s%s\n"
2322 "       /%s findfont\n"
2323 "               dup length dict begin\n"
2324 "               {1 index /FID ne {def} {pop pop} ifelse} forall\n"
2325 "               /Encoding %s def\n"
2326 "       currentdict end\n"
2327 "definefont pop\n",
2328                         fontstring(font), "t", font->psfont, encoding->defstr);
2329                 }
2330
2331                 fprintf(fp, "/%s {/%s%s findfont exch scalefont setfont} def\n",
2332                         fontstring(font), fontstring(font), "t");
2333         } else {
2334                 fprintf(fp, "/%s {/%s findfont exch scalefont setfont} def\n",
2335                         fontstring(font), font->psfont);
2336         }
2337         font->loaded = 1;
2338 }
2339
2340 void
2341 cleanup(int sig)
2342 {
2343         /* dummy */
2344 }