1 /**
2  *
3  * $Id: gra2ps.c,v 1.16 2009/04/03 14:07:43 isizaka Exp isizaka $
4  *
5  * This is free software; you can redistribute it and/or modify it.
6  *
7  * Original author: Satoshi ISHIZAKA
8  *                  isizaka@msa.biglobe.ne.jp
9  **/
10 
11 /**
12  *
13  * $Log: gra2ps.c,v $
14  * Revision 1.16  2009/04/03 14:07:43  isizaka
15  * add viewc
16  *
17  * Revision 1.15  2003/08/15 12:04:26  isizaka
18  * 2.03.17
19  *
20  * Revision 1.13  2000/10/17 14:43:28  isizaka
21  * add '-r', '-p', '-l' option
22  *
23  * Revision 1.12  2000/10/16 13:41:03  isizaka
24  * bug fix about undefined current point.
25  *
26  * Revision 1.11  1999/10/15 15:31:11  isizaka
27  * Encoding is changed to ISOLatin1.
28  *
29  * Revision 1.10  1999/08/26 14:30:39  isizaka
30  * charwidth is changed
31  *
32  *
33  * Revision 1.6  1999/04/15 12:16:39  isizaka
34  * 99/04/15
35  *
36  * Revision 1.5  1999/04/11 06:10:15  isizaka
37  * *** empty log message ***
38  *
39  * Revision 1.4  1999/03/22 05:33:59  isizaka
40  * check time stamp for 'Ngraph.ini'
41  *
42  * Revision 1.3  1999/03/21 16:11:11  isizaka
43  * hyphen for Windows and X11
44  *
45  * Revision 1.2  1999/03/18 11:31:50  isizaka
46  * add 'setcp' flag to avoid "nocurrentpoint" error.
47  *
48  * Revision 1.1  1999/03/17 13:36:29  isizaka
49  * Initial revision
50  *
51  *
52  **/
53 
54 #include <sys/stat.h>
55 #include <stdio.h>
56 #include <stdlib.h>
57 #include <time.h>
58 #include <ctype.h>
59 #include <limits.h>
60 #include <math.h>
61 #include <string.h>
62 #include <stdarg.h>
63 #include <errno.h>
64 #ifdef WINDOWS
65 #include <io.h>
66 #include <dir.h>
67 #else
68 #include <unistd.h>
69 #endif
70 
71 #define MPI 3.1415926535897932385
72 
73 #define GRAF "%Ngraph GRAF"
74 #ifndef LIBDIR
75 #define LIBDIR "/usr/local/lib/Ngraph"
76 #endif
77 #define CONF "gra2ps.ini"
78 #define GRA2CONF "[gra2ps]"
79 #define DIRSEP '/'
80 #define CONFSEP "/"
81 #define NSTRLEN 256
82 #define LINETOLIMIT 500
83 #define VERSION "2.03.20"
84 
85 #define TRUE  1
86 #define FALSE 0
87 
88 enum {A3=0,A4,B4,A5,B5,LETTER,LEGAL};
89 enum {NORMAL=0,BOLD,ITALIC,BOLDITALIC};
90 
91 struct fontmap;
92 struct fontmap {
93   char *fontalias;
94   char *fontname;
95   int type;
96   int used;
97   struct fontmap *next;
98 } *fmap=NULL;
99 
100 char *outfilename;
101 FILE *outfp;
102 char *libdir,*homedir;
103 char *includefile=NULL;
104 int include=FALSE;
105 int epsf=FALSE;
106 int color=FALSE;
107 int landscape=FALSE;
108 int paper=A4;
109 int rotate=FALSE;
110 int bottom=29700;
111 int sjis=FALSE;
112 int font_slant=12;
113 
printfstderr(char * fmt,...)114 int printfstderr(char *fmt,...)
115 {
116   int len;
117   va_list ap;
118 
119   va_start(ap,fmt);
120   len=vfprintf(stderr,fmt,ap);
121   va_end(ap);
122   return len;
123 }
124 
niskanji(unsigned int code)125 int niskanji(unsigned int code)
126 {
127   if (((0x81<=code) && (code<=0x9f))
128    || ((0xe0<=code) && (code<=0xff))) return TRUE;
129   return FALSE;
130 }
131 
njms2jis(unsigned int code)132 unsigned int njms2jis(unsigned int code)
133 {
134   unsigned char dh,dl;
135 
136   dh=code >> 8;
137   dl=code & 0xff;
138   if (dh<=0x9f) dh-=0x70;
139   else dh-=0xb0;
140   dh=dh<<1;
141   if (dl>=0x9f) dl-=0x7e;
142   else {
143     dh--;
144     if (dl>=0x80) dl-=0x20;
145     else dl-=0x1f;
146   }
147   return ((unsigned int)(dh << 8))+dl;
148 }
149 
nstrnew(void)150 char *nstrnew(void)
151 {
152   char *po;
153 
154   po=malloc(NSTRLEN);
155   po[0]='\0';
156   return po;
157 }
158 
nstrccat(char * po,char ch)159 char *nstrccat(char *po,char ch)
160 {
161   size_t len,num;
162 
163   if (po==NULL) return NULL;
164   len=strlen(po);
165   num=len/NSTRLEN;
166   if (len%NSTRLEN==NSTRLEN-1) po=realloc(po,NSTRLEN*(num+2));
167   po[len]=ch;
168   po[len+1]='\0';
169   return po;
170 }
171 
fgetline(FILE * fp,char ** buf)172 int fgetline(FILE *fp,char **buf)
173 {
174   char *s;
175   int ch;
176 
177   *buf=NULL;
178   ch=fgetc(fp);
179   if (ch==EOF) return 1;
180   s=nstrnew();
181   while (TRUE) {
182     if ((ch=='\0') || (ch=='\n') || (ch==EOF)) {
183       *buf=s;
184       return 0;
185     }
186     if (ch!='\r') s=nstrccat(s,ch);
187     ch=fgetc(fp);
188   }
189 }
190 
openconfig(char * section)191 FILE *openconfig(char *section)
192 {
193   char *s,*buf,*homeconf,*libconf;
194   FILE *fp;
195   struct stat homestat,libstat;
196 
197   homeconf=(char *)malloc(strlen(homedir)+strlen(CONFSEP)+strlen(CONF)+1);
198   strcpy(homeconf,homedir);
199   if ((strlen(homedir)>0) && (homeconf[strlen(homedir)-1]=='/'))
200     homeconf[strlen(homedir)-1]='\0';
201   strcat(homeconf,CONFSEP);
202   strcat(homeconf,CONF);
203   libconf=(char *)malloc(strlen(libdir)+strlen(CONFSEP)+strlen(CONF)+1);
204   strcpy(libconf,libdir);
205   if ((strlen(libdir)>0) && (libconf[strlen(libdir)-1]=='/'))
206     libconf[strlen(libdir)-1]='\0';
207   strcat(libconf,CONFSEP);
208   strcat(libconf,CONF);
209   if (access(homeconf,04)==0) {
210     if (stat(homeconf,&homestat)!=0) {
211       free(homeconf);
212       homeconf=NULL;
213     }
214   } else {
215     free(homeconf);
216     homeconf=NULL;
217   }
218   if (access(libconf,04)==0) {
219     if (stat(libconf,&libstat)!=0) {
220       free(libconf);
221       libconf=NULL;
222     }
223   } else {
224     free(libconf);
225     libconf=NULL;
226   }
227   if (homeconf!=NULL) {
228     if (libconf==NULL) s=homeconf;
229     else if (homestat.st_mtime>=libstat.st_mtime) {
230       s=homeconf;
231       free(libconf);
232     } else {
233       s=libconf;
234       free(homeconf);
235     }
236   } else if (libconf!=NULL) s=libconf;
237   else return NULL;
238   if ((fp=fopen(s,"rt"))==NULL) return NULL;
239   free(s);
240   while (fgetline(fp,&buf)==0) {
241     if (strcmp(buf,section)==0) {
242       free(buf);
243       return fp;
244     }
245     free(buf);
246   }
247   fclose(fp);
248   return NULL;
249 }
250 
getitok(char ** s,int * len,char * ifs)251 char *getitok(char **s,int *len,char *ifs)
252 {
253   char *po,*spo;
254   int i;
255 
256   if (*s==NULL) return NULL;
257   po=*s;
258   for (i=0;(po[i]!='\0') && (strchr(ifs,po[i])!=NULL);i++);
259   if (po[i]=='\0') {
260     *len=0;
261     return NULL;
262   }
263   spo=po+i;
264   for (;(po[i]!='\0') && (strchr(ifs,po[i])==NULL);i++);
265   *s+=i;
266   *len=*s-spo;
267   return spo;
268 }
269 
getitok2(char ** s,int * len,char * ifs)270 char *getitok2(char **s,int *len,char *ifs)
271 {
272   char *po,*s2;
273 
274   if ((s2=getitok(s,len,ifs))==NULL) return NULL;
275   po=malloc(*len+1);
276   strncpy(po,s2,*len);
277   po[*len]='\0';
278   return po;
279 }
280 
getconfig(FILE * fp,char ** val)281 char *getconfig(FILE *fp,char **val)
282 {
283   char *s,*tok,*buf;
284   int len;
285 
286   while (TRUE) {
287     if (fgetline(fp,&buf)!=0) return NULL;
288     else {
289       if (buf[0]=='[') {
290         free(buf);
291         return NULL;
292       } else {
293         s=buf;
294         if ((tok=getitok2(&s,&len," \t=,"))!=NULL) {
295           for (;(s[0]!='\0') && (strchr(" \t=,",s[0])!=NULL);s++);
296           *val=malloc(strlen(s)+1);
297           strcpy(*val,s);
298           free(buf);
299           return tok;
300         }
301         free(buf);
302         free(tok);
303       }
304     }
305   }
306 }
307 
closeconfig(FILE * fp)308 void closeconfig(FILE *fp)
309 {
310   fclose(fp);
311 }
312 
getintpar(char * s,int num,int cpar[])313 int getintpar(char *s,int num,int cpar[])
314 {
315   int i,pos1,pos2;
316   char s2[256];
317   char *endptr;
318 
319   pos1=0;
320   for (i=0;i<num;i++) {
321     while ((s[pos1]!='\0') && (strchr(" \t,",s[pos1])!=NULL)) pos1++;
322     if (s[pos1]=='\0') return FALSE;
323     pos2=0;
324     while ((s[pos1]!='\0') && (strchr(" \t,",s[pos1])==NULL)) {
325     s2[pos2]=s[pos1];
326     pos2++;
327     pos1++;
328   }
329   s2[pos2]='\0';
330   cpar[i]=strtol(s2,&endptr,10);
331   if (endptr[0]!='\0') return FALSE;
332   }
333   return TRUE;
334 }
335 
GRAinput(char * s,void (* draw)(char code,int * cpar,char * cstr))336 int GRAinput(char *s,void (*draw)(char code,int *cpar,char *cstr))
337 {
338   int pos,i;
339   int num;
340   char code;
341   int *cpar;
342   char *cstr;
343 
344   code='\0';
345   cpar=NULL;
346   cstr=NULL;
347   for (i=0;s[i]!='\0';i++)
348     if (strchr("\n\r",s[i])!=NULL) {
349       s[i]='\0';
350       break;
351     }
352   pos=0;
353   while ((s[pos]==' ') || (s[pos]=='\t')) pos++;
354   if (s[pos]=='\0') return TRUE;
355   if (strchr("IE%VAGOMNLTCBPRDFHSK",s[pos])==NULL) return FALSE;
356   code=s[pos];
357   if (strchr("%FSK",code)==NULL) {
358     if (!getintpar(s+pos+1,1,&num)) return FALSE;
359     num++;
360     cpar=malloc(sizeof(int)*num);
361     if (!getintpar(s+pos+1,num,cpar)) goto errexit;
362   } else {
363     cpar=malloc(sizeof(int));
364     cpar[0]=-1;
365     cstr=malloc(strlen(s)-pos);
366     strcpy(cstr,s+pos+1);
367   }
368   draw(code,cpar,cstr);
369   free(cpar);
370   free(cstr);
371   return TRUE;
372 
373 errexit:
374   free(cpar);
375   free(cstr);
376   return FALSE;
377 }
378 
putstdout(char * s)379 void putstdout(char *s)
380 {
381   fputs(s,outfp);
382   fputs("\n",outfp);
383 }
384 
printfstdout(char * fmt,...)385 void printfstdout(char *fmt,...)
386 {
387   va_list ap;
388 
389   va_start(ap,fmt);
390   vfprintf(outfp,fmt,ap);
391   va_end(ap);
392 }
393 
394 char *fontalias=NULL;
395 double fontsize=2000;
396 int fonttype=NORMAL;
397 char textspace[256];
398 int loadfont=FALSE;
399 int setcp=FALSE;
400 int cpx=0;
401 int cpy=0;
402 int lineto=FALSE;
403 int linetonum=0;
404 
405 int HelveticaSet[256]={
406 278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,
407 278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,
408 278,278,355,556,556,889,667,222,333,333,389,584,278,584,278,278,
409 556,556,556,556,556,556,556,556,556,556,278,278,584,584,584,556,
410 1015,667,667,722,722,667,611,778,722,278,500,667,556,833,722,778,
411 667,778,722,667,611,722,667,944,667,667,611,278,278,278,469,556,
412 222,556,556,500,556,556,278,556,556,222,222,500,222,833,556,556,
413 556,556,333,500,278,556,500,722,500,500,500,334,260,334,584,278,
414 278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,
415 278,333,333,333,333,333,333,333,333,278,333,333,278,333,333,333,
416 278,333,556,556,556,556,260,556,333,737,370,556,584,333,737,333,
417 400,584,333,333,333,556,537,278,333,333,365,556,834,834,834,611,
418 667,667,667,667,667,667,1000,722,667,667,667,667,278,278,278,278,
419 722,722,778,778,778,778,778,584,778,722,722,722,722,667,667,611,
420 556,556,556,556,556,556,889,500,556,556,556,556,278,278,278,278,
421 556,556,556,556,556,556,556,584,611,556,556,556,556,500,556,500};
422 
423 int HelveticaBoldSet[256]={
424 278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,
425 278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,
426 278,333,474,556,556,889,722,278,333,333,389,584,278,584,278,278,
427 556,556,556,556,556,556,556,556,556,556,333,333,584,584,584,611,
428 975,722,722,722,722,667,611,778,722,278,556,722,611,833,722,778,
429 667,778,722,667,611,722,667,944,667,667,611,333,278,333,584,556,
430 278,556,611,556,611,556,333,611,611,278,278,556,278,889,611,611,
431 611,611,389,556,333,611,556,778,556,556,500,389,280,389,584,278,
432 278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,
433 278,333,333,333,333,333,333,333,333,278,333,333,278,333,333,333,
434 278,333,556,556,556,556,280,556,333,737,370,556,584,333,737,333,
435 400,584,333,333,333,611,556,278,333,333,365,556,834,834,834,611,
436 722,722,722,722,722,722,1000,722,667,667,667,667,278,278,278,278,
437 722,722,778,778,778,778,778,584,778,722,722,722,722,667,667,611,
438 556,556,556,556,556,556,889,556,556,556,556,556,278,278,278,278,
439 611,611,611,611,611,611,611,584,611,611,611,611,611,556,611,556};
440 
441 int TimesRomanSet[256]={
442 250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,
443 250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,
444 250,333,408,500,500,833,778,333,333,333,500,564,250,564,250,278,
445 500,500,500,500,500,500,500,500,500,500,278,278,564,564,564,444,
446 921,722,667,667,722,611,556,722,722,333,389,722,611,889,722,722,
447 556,722,667,556,611,722,722,944,722,722,611,333,278,333,469,500,
448 333,444,500,444,500,444,333,500,500,278,278,500,278,778,500,500,
449 500,500,333,389,278,500,500,722,500,500,444,480,200,480,541,250,
450 250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,
451 278,333,333,333,333,333,333,333,333,250,333,333,250,333,333,333,
452 250,333,500,500,500,500,200,500,333,760,276,500,564,333,760,333,
453 400,564,300,300,333,500,453,250,333,300,310,500,750,750,750,444,
454 722,722,722,722,722,722,889,667,611,611,611,611,333,333,333,333,
455 722,722,722,722,722,722,722,564,722,722,722,722,722,722,556,500,
456 444,444,444,444,444,444,667,444,444,444,444,444,278,278,278,278,
457 500,500,500,500,500,500,500,564,500,500,500,500,500,500,500,500};
458 
459 int TimesBoldSet[256]={
460 250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,
461 250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,
462 250,333,555,500,500,1000,833,333,333,333,500,570,250,570,250,278,
463 500,500,500,500,500,500,500,500,500,500,333,333,570,570,570,500,
464 930,722,667,722,722,667,611,778,778,389,500,778,667,944,722,778,
465 611,778,722,556,667,722,722,1000,722,722,667,333,278,333,581,500,
466 333,500,556,444,556,444,333,500,556,278,333,556,278,833,556,500,
467 556,556,444,389,333,556,500,722,500,500,444,394,220,394,520,250,
468 250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,
469 278,333,333,333,333,333,333,333,333,250,333,333,250,333,333,333,
470 250,333,500,500,500,500,220,500,333,747,300,500,570,333,747,333,
471 400,570,300,300,333,556,540,250,333,300,330,500,750,750,750,500,
472 722,722,722,722,722,722,1000,722,667,667,667,667,389,389,389,389,
473 722,722,778,778,778,778,778,570,778,722,722,722,722,722,611,556,
474 500,500,500,500,500,500,722,444,444,444,444,444,278,278,278,278,
475 500,556,500,500,500,500,500,570,500,556,556,556,556,500,556,500};
476 
477 int TimesItalicSet[256]={
478 250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,
479 250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,
480 250,333,420,500,500,833,778,333,333,333,500,675,250,675,250,278,
481 500,500,500,500,500,500,500,500,500,500,333,333,675,675,675,500,
482 920,611,611,667,722,611,611,722,722,333,444,667,556,833,667,722,
483 611,722,611,500,556,722,611,833,611,556,556,389,278,389,422,500,
484 333,500,500,444,500,444,278,500,500,278,278,444,278,722,500,500,
485 500,500,389,389,278,500,444,667,444,444,389,400,275,400,541,250,
486 250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,
487 278,333,333,333,333,333,333,333,333,250,333,333,250,333,333,333,
488 250,389,500,500,500,500,275,500,333,760,276,500,675,333,760,333,
489 400,675,300,300,333,500,523,250,333,300,310,500,750,750,750,500,
490 611,611,611,611,611,611,889,667,611,611,611,611,333,333,333,333,
491 722,667,722,722,722,722,722,675,722,722,722,722,722,556,611,500,
492 500,500,500,500,500,500,667,444,444,444,444,444,278,278,278,278,
493 500,500,500,500,500,500,500,675,500,500,500,500,500,444,500,444};
494 
495 int TimesBoldItalicSet[256]={
496 250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,
497 250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,
498 250,389,555,500,500,833,778,333,333,333,500,570,250,606,250,278,
499 500,500,500,500,500,500,500,500,500,500,333,333,570,570,570,500,
500 832,667,667,667,722,667,667,722,778,389,500,667,611,889,722,722,
501 611,722,667,556,611,722,667,889,667,611,611,333,278,333,570,500,
502 333,500,500,444,500,444,333,500,556,278,278,500,278,778,556,500,
503 500,500,389,389,278,556,444,667,500,444,389,348,220,348,570,250,
504 250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,
505 278,333,333,333,333,333,333,333,333,250,333,333,250,333,333,333,
506 250,389,500,500,500,500,220,500,333,747,266,500,606,333,747,333,
507 400,570,300,300,333,576,500,250,333,300,300,500,750,750,750,500,
508 667,667,667,667,667,667,944,667,667,667,667,667,389,389,389,389,
509 722,722,722,722,722,722,722,570,722,722,722,722,722,611,611,500,
510 500,500,500,500,500,500,722,444,444,444,444,444,278,278,278,278,
511 500,556,500,500,500,500,500,570,500,556,556,556,556,444,500,444};
512 
513 int SymbolSet[256]={
514 250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,
515 250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,
516 250,333,713,500,549,833,778,439,333,333,500,549,250,549,250,278,
517 500,500,500,500,500,500,500,500,500,500,278,278,549,549,549,444,
518 549,722,667,722,612,611,763,603,722,333,631,722,686,889,722,722,
519 768,741,556,592,611,690,439,768,645,795,611,333,863,333,658,500,
520 500,631,549,549,494,439,521,411,603,329,603,549,549,576,521,549,
521 549,521,549,603,439,576,713,686,493,686,494,480,200,480,549,250,
522 250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,
523 250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,
524 250,620,247,549,167,713,500,753,753,753,753,1042,987,603,987,603,
525 400,549,411,549,549,713,494,460,549,549,549,549,1000,603,1000,658,
526 823,686,795,987,768,768,823,768,768,713,713,713,713,713,713,713,
527 768,713,790,790,890,823,549,250,713,603,603,1042,987,603,987,603,
528 494,329,790,790,786,713,384,384,384,384,384,384,494,494,494,494,
529 250,329,274,686,686,686,384,384,384,384,384,384,494,494,494,250};
530 
531 
charwidth(unsigned int ch,char * font,int size)532 int charwidth(unsigned int ch, char *font,int size)
533 {
534   if ((strcmp(font,"Times")==0) || (strcmp(font,"Tim")==0))
535     return (int )(25.4/72000.0*size*TimesRomanSet[ch]);
536   else if ((strcmp(font,"TimesBold")==0) || (strcmp(font,"TimB")==0))
537     return (int )(25.4/72000.0*size*TimesBoldSet[ch]);
538   else if ((strcmp(font,"TimesItalic")==0) || (strcmp(font,"TimI")==0))
539     return (int )(25.4/72000.0*size*TimesItalicSet[ch]);
540   else if ((strcmp(font,"TimesBoldItalic")==0) || (strcmp(font,"TimBI")==0))
541     return (int )(25.4/72000.0*size*TimesBoldItalicSet[ch]);
542   else if ((strcmp(font,"Helvetica")==0) || (strcmp(font,"Helv")==0)
543         || (strcmp(font,"HelveticaOblique")==0) || (strcmp(font,"HelvO")==0)
544         || (strcmp(font,"HelveticaItalic")==0) || (strcmp(font,"HelvI")==0))
545     return (int )(25.4/72000.0*size*HelveticaSet[ch]);
546   else if ((strcmp(font,"HelveticaBold")==0) || (strcmp(font,"HelvB")==0)
547       || (strcmp(font,"HelveticaBoldOblique")==0) || (strcmp(font,"HelvBO")==0)
548       || (strcmp(font,"HelveticaBoldItalic")==0) || (strcmp(font,"HelvBI")==0))
549     return (int )(25.4/72000.0*size*HelveticaBoldSet[ch]);
550   else if ((strcmp(font,"Symbol")==0) || (strcmp(font,"Sym")==0)
551         || (strcmp(font,"SymbolBold")==0) || (strcmp(font,"SymB")==0)
552         || (strcmp(font,"SymbolItalic")==0) || (strcmp(font,"SymI")==0)
553         || (strcmp(font,"SymbolBoldItalic")==0) || (strcmp(font,"SymBI")==0))
554     return (int )(25.4/72000.0*size*SymbolSet[ch]);
555   else if ((strcmp(font,"Gothic")==0) || (strcmp(font,"Goth")==0)
556         || (strcmp(font,"GothicBold")==0) || (strcmp(font,"GothB")==0)
557         || (strcmp(font,"GothicItalic")==0) || (strcmp(font,"GothI")==0)
558         || (strcmp(font,"GothicBoldItalic")==0) || (strcmp(font,"GothBI")==0)
559         || (strcmp(font,"Mincho")==0) || (strcmp(font,"Min")==0)
560         || (strcmp(font,"MinchoBold")==0) || (strcmp(font,"MinB")==0)
561         || (strcmp(font,"MinchoItalic")==0) || (strcmp(font,"MinI")==0)
562         || (strcmp(font,"MinchoBoldItalic")==0) || (strcmp(font,"MinBI")==0))
563     return (int )(25.4/72000.0*size*1000);
564   else return (int )(25.4/72000.0*size*600);
565 }
566 
charheight(char * font,int size)567 int charheight(char *font,int size)
568 {
569   if ((strcmp(font,"Times")==0) || (strcmp(font,"Tim")==0))
570     return (int )(25.4/72000.0*size*662);
571   else if ((strcmp(font,"TimesBold")==0) || (strcmp(font,"TimB")==0))
572     return (int )(25.4/72000.0*size*676);
573   else if ((strcmp(font,"TimesItalic")==0) || (strcmp(font,"TimI")==0))
574     return (int )(25.4/72000.0*size*653);
575   else if ((strcmp(font,"TimesBoldItalic")==0) || (strcmp(font,"TimBI")==0))
576     return (int )(25.4/72000.0*size*669);
577   else if ((strcmp(font,"Helvetica")==0) || (strcmp(font,"Helv")==0)
578         || (strcmp(font,"HelveticaOblique")==0) || (strcmp(font,"HelvO")==0)
579         || (strcmp(font,"HelveticaItalic")==0) || (strcmp(font,"HelvI")==0))
580     return (int )(25.4/72000.0*size*718);
581   else if ((strcmp(font,"HelveticaBold")==0) || (strcmp(font,"HelvB")==0)
582      || (strcmp(font,"HelveticaBoldOblique")==0) || (strcmp(font,"HelvBO")==0)
583      || (strcmp(font,"HelveticaBoldItalic")==0) || (strcmp(font,"HelvBI")==0))
584     return (int )(25.4/72000.0*size*718);
585   else if ((strcmp(font,"Symbol")==0) || (strcmp(font,"Sym")==0)
586         || (strcmp(font,"SymbolBold")==0) || (strcmp(font,"SymB")==0)
587         || (strcmp(font,"SymbolItalic")==0) || (strcmp(font,"SymI")==0)
588         || (strcmp(font,"SymbolBoldItalic")==0) || (strcmp(font,"SymBI")==0))
589     return (int )(25.4/72000.0*size*673);
590   else if ((strcmp(font,"CourierBold")==0) || (strcmp(font,"CourB")==0)
591         || (strcmp(font,"CourierBoldOblique")==0) || (strcmp(font,"CourBO")==0)
592         || (strcmp(font,"CourierBoldItalic")==0) || (strcmp(font,"CourBI")==0))
593     return (int )(25.4/72000.0*size*562);
594   else if ((strcmp(font,"Gothic")==0) || (strcmp(font,"Goth")==0)
595         || (strcmp(font,"GothicBold")==0) || (strcmp(font,"GothB")==0)
596         || (strcmp(font,"GothicItalic")==0) || (strcmp(font,"GothI")==0)
597         || (strcmp(font,"GothicBoldItalic")==0) || (strcmp(font,"GothBI")==0))
598     return (int )(25.4/72000.0*size*791);
599   else if ((strcmp(font,"Mincho")==0) || (strcmp(font,"Min")==0)
600         || (strcmp(font,"MinchoBold")==0) || (strcmp(font,"MinB")==0)
601         || (strcmp(font,"MinchoItalic")==0) || (strcmp(font,"MinI")==0)
602         || (strcmp(font,"MinchoBoldItalic")==0) || (strcmp(font,"MinBI")==0))
603     return (int )(25.4/72000.0*size*807);
604   else return (int )(25.4/72000.0*size*562);
605 }
606 
chardescent(char * font,int size)607 int chardescent(char *font,int size)
608 {
609   return (int )(25.4/72000.0*size*250);
610 }
611 
612 
613 char *bfontalias=NULL;
614 int bloadfont=FALSE;
615 int boffsetx=0;
616 int boffsety=0;
617 int bminx=INT_MAX;
618 int bminy=INT_MAX;
619 int bmaxx=INT_MIN;
620 int bmaxy=INT_MIN;
621 int bposx=0;
622 int bposy=0;
623 int bpt=0;
624 int bspc=0;
625 int bdir=0;
626 int blinew=0;
627 int bclip=TRUE;
628 int bclipsizex=21000;
629 int bclipsizey=29700;
630 
setbbminmax(int x1,int y1,int x2,int y2,int lw)631 void setbbminmax(int x1,int y1,int x2,int y2,int lw)
632 {
633   int x,y;
634 
635   if (x1>x2) {
636     x=x1; x1=x2; x2=x;
637   }
638   if (y1>y2) {
639     y=y1; y1=y2; y2=y;
640   }
641   if (lw) {
642     x1-=blinew;
643     y1-=blinew;
644     x2+=blinew;
645     y2+=blinew;
646   }
647   if (!bclip || !((x2<0) || (y2<0) || (x1>bclipsizex) || (y1>bclipsizey))) {
648     if (bclip) {
649       if (x1<0) x1=0;
650       if (y1<0) y1=0;
651       if (x2>bclipsizex) x2=bclipsizex;
652       if (y2>bclipsizey) y1=bclipsizey;
653     }
654     x1+=boffsetx;
655     x2+=boffsetx;
656     y1+=boffsety;
657     y2+=boffsety;
658     if (x1<bminx) bminx=x1;
659     if (y1<bminy) bminy=y1;
660     if (x2>bmaxx) bmaxx=x2;
661     if (y2>bmaxy) bmaxy=y2;
662   }
663 }
664 
665 
getboundingbox(char code,int * cpar,char * cstr)666 void getboundingbox(char code,int *cpar,char *cstr)
667 {
668   int i,lw;
669   double x,y,csin,ccos;
670   int w,h,d,x1,y1,x2,y2,x3,y3,x4,y4;
671   int c1,c2;
672   char ch;
673 
674   switch (code) {
675   case 'X': case 'I': case 'E': case '%': case 'G':
676     break;
677   case 'V':
678     boffsetx=cpar[1];
679     boffsety=cpar[2];
680     bposx=0;
681     bposy=0;
682     if (cpar[5]==1) bclip=TRUE;
683     else bclip=FALSE;
684     bclipsizex=cpar[3]-cpar[1];
685     bclipsizey=cpar[4]-cpar[2];
686     break;
687   case 'A':
688     blinew=cpar[2]/2;
689     break;
690   case 'M':
691     bposx=cpar[1];
692     bposy=cpar[2];
693     break;
694   case 'N':
695     bposx+=cpar[1];
696     bposy+=cpar[2];
697     break;
698   case 'L':
699     setbbminmax(cpar[1],cpar[2],cpar[3],cpar[4],TRUE);
700     break;
701   case 'T':
702     setbbminmax(bposx,bposy,cpar[1],cpar[2],TRUE);
703     bposx=cpar[1];
704     bposy=cpar[2];
705     break;
706   case 'C':
707     if (cpar[7]==0) lw=TRUE;
708     else lw=FALSE;
709     if (cpar[7]==1) setbbminmax(cpar[1],cpar[2],cpar[1],cpar[2],lw);
710     setbbminmax(cpar[1]+(int )(cpar[3]*cos(MPI*cpar[5]/18000.0)),
711                 cpar[2]-(int )(cpar[4]*sin(MPI*cpar[5]/18000.0)),
712                 cpar[1]+(int )(cpar[3]*cos((MPI*cpar[5]+cpar[6])/18000.0)),
713                 cpar[2]-(int )(cpar[4]*sin((MPI*cpar[5]+cpar[6])/18000.0)),lw);
714     cpar[6]+=cpar[5];
715     cpar[5]-=9000;
716     cpar[6]-=9000;
717     if ((cpar[5]<0) && (cpar[6]>0))
718       setbbminmax(cpar[1],cpar[2]-cpar[4],cpar[1],cpar[2]-cpar[4],lw);
719     cpar[5]-=9000;
720     cpar[6]-=9000;
721     if ((cpar[5]<0) && (cpar[6]>0))
722       setbbminmax(cpar[1]-cpar[3],cpar[2],cpar[1]-cpar[3],cpar[2],lw);
723     cpar[5]-=9000;
724     cpar[6]-=9000;
725     if ((cpar[5]<0) && (cpar[6]>0))
726       setbbminmax(cpar[1],cpar[2]+cpar[4],cpar[1],cpar[2]+cpar[4],lw);
727     cpar[5]-=9000;
728     cpar[6]-=9000;
729     if ((cpar[5]<0) && (cpar[6]>0))
730       setbbminmax(cpar[1]+cpar[3],cpar[2],cpar[1]+cpar[3],cpar[2],lw);
731     break;
732   case 'B':
733     if (cpar[5]==1) lw=FALSE;
734     else lw=TRUE;
735     setbbminmax(cpar[1],cpar[2],cpar[3],cpar[4],lw);
736     break;
737   case 'P':
738     setbbminmax(cpar[1],cpar[2],cpar[1],cpar[2],FALSE);
739     break;
740   case 'R':
741     for (i=0;i<(cpar[1]-1);i++)
742       setbbminmax(cpar[i*2+2],cpar[i*2+3],cpar[i*2+4],cpar[i*2+5],lw);
743     break;
744   case 'D':
745     if (cpar[2]==0) lw=TRUE;
746     else lw=FALSE;
747     for (i=0;i<(cpar[1]-1);i++)
748       setbbminmax(cpar[i*2+3],cpar[i*2+4],cpar[i*2+5],cpar[i*2+6],lw);
749     break;
750   case 'F':
751     free(bfontalias);
752     bfontalias=malloc(strlen(cstr)+1);
753     strcpy(bfontalias,cstr);
754     break;
755   case 'H':
756     bpt=cpar[1];
757     bspc=cpar[2];
758     bdir=cpar[3];
759     bloadfont=TRUE;
760     break;
761   case 'S':
762     if (!bloadfont) break;
763     csin=sin(MPI*bdir/18000.0);
764     ccos=cos(MPI*bdir/18000.0);
765     i=0;
766     while (i<strlen(cstr)) {
767       ch=0;
768       if (cstr[i]=='\\') {
769         if (cstr[i+1]=='x') {
770           if (tolower(cstr[i+2])>='a') c1=tolower(cstr[i+2])-'a'+10;
771           else c1=tolower(cstr[i+2])-'0';
772           if (tolower(cstr[i+3])>='a') c2=tolower(cstr[i+3])-'a'+10;
773           else c2=tolower(cstr[i+3])-'0';
774           ch=c1*16+c2;
775           i+=4;
776         } else if (cstr[i+1]=='\\') {
777           ch=cstr[i];
778           i+=2;
779         } else i++;
780       } else {
781        switch (cstr[i]) {
782        case '\\':
783          ch='\\';
784          break;
785        case ')':
786          ch=')';
787          break;
788        case '(':
789          ch='(';
790          break;
791        default:
792          if (cstr[i]&0x80) {
793            c1=((unsigned char)cstr[i])>>4;
794            c2=((unsigned char)cstr[i]) & 0xF;
795            ch=c1*16+c2;
796          } else ch=cstr[i];
797          break;
798        }
799        i++;
800       }
801       w=charwidth((unsigned char)ch,bfontalias,bpt);
802       h=charheight(bfontalias,bpt);
803       d=chardescent(bfontalias,bpt);
804       x=0;
805       y=d;
806       x1=(int )(bposx+(x*ccos+y*csin));
807       y1=(int )(bposy+(-x*csin+y*ccos));
808       x=0;
809       y=-h;
810       x2=(int )(bposx+(x*ccos+y*csin));
811       y2=(int )(bposy+(-x*csin+y*ccos));
812       x=w;
813       y=d;
814       x3=(int )(bposx+(x*ccos+y*csin));
815       y3=(int )(bposy+(-x*csin+y*ccos));
816       x=w;
817       y=-h;
818       x4=(int )(bposx+(int )(x*ccos+y*csin));
819       y4=(int )(bposy+(int )(-x*csin+y*ccos));
820       setbbminmax(x1,y1,x4,y4,FALSE);
821       setbbminmax(x2,y2,x3,y3,FALSE);
822       bposx+=(int )((w+bspc*25.4/72)*ccos);
823       bposy-=(int )((w+bspc*25.4/72)*csin);
824     }
825     break;
826   case 'K':
827     if (!bloadfont) break;
828     csin=sin(MPI*bdir/18000.0);
829     ccos=cos(MPI*bdir/18000.0);
830     i=0;
831     while (i<strlen(cstr)) {
832       if (niskanji((unsigned char)cstr[i]) && (cstr[i+1]!='\0')) {
833         w=charwidth(cstr[i],bfontalias,bpt);
834         h=charheight(bfontalias,bpt);
835         d=chardescent(bfontalias,bpt);
836         x=0;
837         y=d;
838         x1=(int )(bposx+(x*ccos+y*csin));
839         y1=(int )(bposy+(-x*csin+y*ccos));
840         x=0;
841         y=-h;
842         x2=(int )(bposx+(x*ccos+y*csin));
843         y2=(int )(bposy+(-x*csin+y*ccos));
844         x=w;
845         y=d;
846         x3=(int )(bposx+(x*ccos+y*csin));
847         y3=(int )(bposy+(-x*csin+y*ccos));
848         x=w;
849         y=-h;
850         x4=(int )(bposx+(int )(x*ccos+y*csin));
851         y4=(int )(bposy+(int )(-x*csin+y*ccos));
852         setbbminmax(x1,y1,x4,y4,FALSE);
853         setbbminmax(x2,y2,x3,y3,FALSE);
854         bposx+=(int )((w+bspc*25.4/72)*ccos);
855         bposy-=(int )((w+bspc*25.4/72)*csin);
856         i+=2;
857       } else i++;
858     }
859     break;
860   }
861 }
862 
draw(char code,int * cpar,char * cstr)863 void draw(char code,int *cpar,char *cstr)
864 {
865   time_t t;
866   struct tm *ltime;
867   char *buf,*fontname;
868   FILE *fp;
869   int i,a;
870   struct fontmap *fcur;
871   unsigned int jis,R,G,B;
872   int c1,c2,sx,sy;
873   double d,ftan;
874 
875   if (lineto) {
876     if (code!='T') {
877       putstdout("st");
878       setcp=FALSE;
879       lineto=FALSE;
880       linetonum=0;
881     } else if (linetonum>LINETOLIMIT) {
882       putstdout("st");
883       printfstdout("%d %d mto\n",cpx,cpy);
884       lineto=FALSE;
885       linetonum=1;
886     }
887   }
888   switch (code) {
889   case 'X':
890     printfstdout("%s",cstr);
891     break;
892   case 'I':
893     printfstderr("Include (%s)\n",includefile);
894     if ((fp=fopen(includefile,"rt"))==NULL) {
895       printfstderr("Error: no include file %s\n",includefile);
896       exit(1);
897     }
898     while (fgetline(fp,&buf)!=1) {
899       if (strcmp(buf,"%%Creator:")==0) {
900         printfstdout("%s GRA2PS %s\n",buf,VERSION);
901       } else if (strcmp(buf,"%%CreationDate:")==0) {
902         t=time(NULL);
903         ltime=localtime(&t);
904         printfstdout("%s %d-%d-%d %d:%d\n",buf,
905                      ltime->tm_mon+1,ltime->tm_mday,1900+ltime->tm_year,
906 					 ltime->tm_hour,ltime->tm_min);
907 	  } else if (strcmp(buf,"%%Pages:")==0) {
908         printfstdout("%s %d\n",buf,1);
909       } else if (strcmp(buf,"%%BoundingBox:")==0) {
910         if (epsf) {
911           if (bminx>bmaxx) {
912             bminx=0;
913             bmaxx=0;
914           }
915           if (bminy>bmaxy) {
916             bminy=bottom;
917             bmaxy=bottom;
918           }
919           sx=(bmaxx-bminx)/100;
920           sy=(bmaxy-bminy)/100;
921           bminx-=sx;
922           bminy-=sy;
923           bmaxx+=sx;
924           bmaxy+=sy;
925           if (rotate)
926             printfstdout("%s %d %d %d %d\n",buf,
927                         (int )(bminy/2540.0*72),
928                         (int )(bminx/2540.0*72),
929                         (int )(bmaxy/2540.0*72),
930                         (int )(bmaxx/2540.0*72));
931           else
932             printfstdout("%s %d %d %d %d\n",buf,
933                         (int )(bminx/2540.0*72),
934                         (int )((bottom-bmaxy)/2540.0*72),
935                         (int )(bmaxx/2540.0*72),
936                         (int )((bottom-bminy)/2540.0*72));
937         } else {
938           if (rotate)
939             printfstdout("%s %d %d %d %d\n",buf,
940                         (int )(0),
941                         (int )(0),
942                         (int )(cpar[4]/2540.0*72),
943                         (int )(cpar[3]/2540.0*72));
944           else
945             printfstdout("%s %d %d %d %d\n",buf,
946                         (int )(0),
947                         (int )((bottom-cpar[4])/2540.0*72),
948                         (int )(cpar[3]/2540.0*72),
949                         (int )(bottom/2540.0*72));
950         }
951       } else if ((strcmp(buf,"%%EndComments")==0) && (epsf)) {
952         putstdout(buf);
953       } else {
954         putstdout(buf);
955       }
956       free(buf);
957     }
958     fclose(fp);
959     putstdout("%%Page: Figure 1");
960     putstdout("%%BeginPageSetup");
961     if (rotate) printfstdout("/ANGLE %d def\n",-90);
962     else printfstdout("/ANGLE %d def\n",0);
963     printfstdout("/bottom %d def\n",-bottom);
964     putstdout("NgraphDict begin");
965     putstdout("PageSave");
966     putstdout("BeginPage");
967     putstdout("%%EndPageSetup");
968     include=TRUE;
969     break;
970   case 'E':
971     putstdout("EndPage");
972     putstdout("PageRestore");
973     putstdout("showpage");
974     putstdout("end");
975     putstdout("%%Trailer");
976     putstdout("%%DocumentNeededResources: ");
977     fcur=fmap;
978     while (fcur!=NULL) {
979       if (fcur->used)
980         printfstdout("%% font %s\n",fcur->fontname);
981       fcur=fcur->next;
982     }
983     putstdout("%%EOF");
984     break;
985   case '%':
986     if (include) printfstdout("%c%s\n",'%',cstr);
987     printfstderr("%c%s\n",'%',cstr);
988     break;
989   case 'V':
990     if (color)
991       printfstdout("%d %d %d %d %d viewc\n",
992       cpar[1],cpar[2],cpar[3]-cpar[1],cpar[4]-cpar[2],cpar[5]);
993     else
994       printfstdout("%d %d %d %d %d view\n",
995       cpar[1],cpar[2],cpar[3]-cpar[1],cpar[4]-cpar[2],cpar[5]);
996     break;
997   case 'A':
998     if (cpar[1]==0) printfstdout("[] 0 ");
999     else {
1000       printfstdout("[");
1001       for (i=0;i<cpar[1];i++) printfstdout("%d ",cpar[i+6]);
1002       printfstdout("] 0 ");
1003     }
1004     printfstdout("%d %d %d %g lsty\n",cpar[2],cpar[3],cpar[4],cpar[5]/100.0);
1005     break;
1006   case 'G':
1007     R=cpar[1];
1008     G=cpar[2];
1009     B=cpar[3];
1010     if (color)
1011       printfstdout(
1012       "%d 255 div %d 255 div %d 255 div setrgbcolor\n",R,G,B);
1013     else {
1014       d=0.3*R+0.59*G+0.11*B;
1015       a=(int )d;
1016       if (d-a>=0.5) a++;
1017       printfstdout("%d 255 div setgray\n",a);
1018     }
1019     break;
1020   case 'M':
1021     printfstdout("%d %d mto\n",cpar[1],cpar[2]);
1022     cpx=cpar[1];
1023     cpy=cpar[2];
1024     setcp=TRUE;
1025     break;
1026   case 'N':
1027     printfstdout("%d %d rmto\n",cpar[1],cpar[2]);
1028     cpx+=cpar[1];
1029     cpy+=cpar[2];
1030     setcp=TRUE;
1031     break;
1032   case 'L':
1033     printfstdout("%d %d %d %d l\n",cpar[1],cpar[2],cpar[3],cpar[4]);
1034     setcp=FALSE;
1035     break;
1036   case 'T':
1037     if (!setcp) printfstdout("%d %d mto\n",cpx,cpy);
1038     printfstdout("%d %d lto\n",cpar[1],cpar[2]);
1039     cpx=cpar[1];
1040     cpy=cpar[2];
1041     lineto=TRUE;
1042     linetonum++;
1043     setcp=TRUE;
1044     break;
1045   case 'C':
1046 	if (cpar[7]==0)
1047 	  printfstdout("%d %d %d %d %d %d e\n",
1048         -cpar[5]-cpar[6],-cpar[5],cpar[3],cpar[4],cpar[1],cpar[2]);
1049     else if (cpar[7]==1)
1050       printfstdout("%d %d %d %d %d %d fe\n",
1051         -cpar[5]-cpar[6],-cpar[5],cpar[3],cpar[4],cpar[1],cpar[2]);
1052     else
1053       printfstdout("%d %d %d %d %d %d ae\n",
1054         -cpar[5]-cpar[6],-cpar[5],cpar[3],cpar[4],cpar[1],cpar[2]);
1055     setcp=FALSE;
1056     break;
1057   case 'B':
1058     if (cpar[5]==0)
1059       printfstdout("%d %d %d %d rec\n",
1060                    cpar[3]-cpar[1],cpar[4]-cpar[2],cpar[1],cpar[2]);
1061     else
1062       printfstdout("%d %d %d %d bar\n",
1063                    cpar[3]-cpar[1],cpar[4]-cpar[2],cpar[1],cpar[2]);
1064     setcp=FALSE;
1065     break;
1066   case 'P':
1067     printfstdout("%d %d pix\n",cpar[1],cpar[2]);
1068     break;
1069   case 'R':
1070     for (i=0;i<cpar[1];i++)
1071       printfstdout("%d %d ",cpar[i*2+2],cpar[i*2+3]);
1072     printfstdout("%d ",cpar[1]);
1073     putstdout("rpo");
1074     setcp=FALSE;
1075     break;
1076   case 'D':
1077     for (i=0;i<cpar[1];i++)
1078       printfstdout("%d %d ",cpar[i*2+3],cpar[i*2+4]);
1079     printfstdout("%d ",cpar[1]);
1080     if (cpar[2]==0) putstdout("dpo");
1081     else if (cpar[2]==1) putstdout("epo");
1082     else putstdout("fpo");
1083     setcp=FALSE;
1084     break;
1085   case 'F':
1086     free(fontalias);
1087     fontalias=malloc(strlen(cstr)+1);
1088     strcpy(fontalias,cstr);
1089     break;
1090   case 'H':
1091     fontname=NULL;
1092     if (fontalias==NULL) {
1093       loadfont=FALSE;
1094       break;
1095     }
1096     fcur=fmap;
1097     while (fcur!=NULL) {
1098       if (strcmp(fontalias,fcur->fontalias)==0) {
1099         fontname=fcur->fontname;
1100         fonttype=fcur->type;
1101         if (!(fcur->used))
1102           printfstdout("%%IncludeResource: font %s\n",fcur->fontname);
1103         fcur->used=TRUE;
1104         break;
1105       }
1106       fcur=fcur->next;
1107     }
1108     if (fontname==NULL) {
1109       loadfont=FALSE;
1110       break;
1111     }
1112     fontsize=cpar[1]/72.0*25.4;
1113     sprintf(textspace,"%g %g",cpar[2]*cos(MPI*cpar[3]/18000.0)*25.4/72,
1114                              -cpar[2]*sin(MPI*cpar[3]/18000.0)*25.4/72);
1115     if ((fonttype==ITALIC) || (fonttype==BOLDITALIC)) {
1116       ftan=tan(font_slant*MPI/180.0);
1117       printfstdout("[%g %g %g %g 0 0] ",
1118          cpar[1]*cos(MPI*cpar[3]/18000.0)*25.4/72,
1119         -cpar[1]*sin(MPI*cpar[3]/18000.0)*25.4/72,
1120         -cpar[1]*(sin(MPI*cpar[3]/18000.0)
1121          -ftan*cos(MPI*cpar[3]/18000.0))*25.4/72,
1122         -cpar[1]*(cos(MPI*cpar[3]/18000.0)
1123          +ftan*sin(MPI*cpar[3]/18000.0))*25.4/72);
1124     } else {
1125       printfstdout("[%g %g %g %g 0 0] ",
1126          cpar[1]*cos(MPI*cpar[3]/18000.0)*25.4/72,
1127         -cpar[1]*sin(MPI*cpar[3]/18000.0)*25.4/72,
1128         -cpar[1]*sin(MPI*cpar[3]/18000.0)*25.4/72,
1129         -cpar[1]*cos(MPI*cpar[3]/18000.0)*25.4/72);
1130     }
1131     printfstdout("%s F\n",fontname);
1132     loadfont=TRUE;
1133     break;
1134   case 'S':
1135     if (!loadfont) break;
1136     if ((fonttype==BOLD) || (fonttype==BOLDITALIC)) {
1137       printfstdout("/BOLDS %g def\n",fontsize*0.018);
1138     }
1139     printfstdout("%s (",textspace);
1140     i=0;
1141     while (i<strlen(cstr)) {
1142       if (cstr[i]=='\\') {
1143         if (cstr[i+1]=='x') {
1144           if (tolower(cstr[i+2])>='a') c1=tolower(cstr[i+2])-'a'+10;
1145           else c1=tolower(cstr[i+2])-'0';
1146           if (tolower(cstr[i+3])>='a') c2=tolower(cstr[i+3])-'a'+10;
1147           else c2=tolower(cstr[i+3])-'0';
1148           printfstdout("\\%c%c%c",c1/4+'0',(c1%4)*2+c2/8+'0',c2%8+'0');
1149           i+=4;
1150         } else if (cstr[i+1]=='\\') {
1151           printfstdout("\\\\");
1152           i+=2;
1153         } else i++;
1154       } else {
1155         switch (cstr[i]) {
1156         case '\\':
1157           printfstdout("\\\\");
1158           break;
1159         case ')':
1160           printfstdout("\\)");
1161           break;
1162         case '(':
1163           printfstdout("\\(");
1164           break;
1165         default:
1166           if (cstr[i]&0x80) {
1167             c1=((unsigned char)cstr[i])>>4;
1168             c2=((unsigned char)cstr[i]) & 0xF;
1169             printfstdout("\\%c%c%c",c1/4+'0',(c1%4)*2+c2/8+'0',c2%8+'0');
1170           } else printfstdout("%c",cstr[i]);
1171           break;
1172         }
1173         i++;
1174       }
1175     }
1176     if ((fonttype==BOLD) || (fonttype==BOLDITALIC)) {
1177       printfstdout(") ashowB\n");
1178     } else {
1179       printfstdout(") ashow\n");
1180     }
1181     break;
1182   case 'K':
1183     if (!loadfont) break;
1184     if ((fonttype==BOLD) || (fonttype==BOLDITALIC)) {
1185       printfstdout("/BOLDS %g def\n",fontsize*0.018);
1186     }
1187     printfstdout("%s <",textspace);
1188     i=0;
1189     while (i<strlen(cstr)) {
1190       if (niskanji((unsigned char)cstr[i]) && (cstr[i+1]!='\0')) {
1191         if (!sjis)
1192           jis=njms2jis(((unsigned char)cstr[i] << 8)+(unsigned char)cstr[i+1]);
1193         else
1194           jis=((unsigned char)cstr[i] << 8)+(unsigned char)cstr[i+1];
1195         printfstdout(" %2hx%2hx",jis>>8,jis &0xff);
1196         i+=2;
1197       } else i++;
1198     }
1199     if ((fonttype==BOLD) || (fonttype==BOLDITALIC)) {
1200       printfstdout("> ashowB\n");
1201     } else {
1202       printfstdout("> ashow\n");
1203     }
1204     break;
1205   }
1206 }
1207 
loadconfig(void)1208 void loadconfig(void)
1209 {
1210   FILE *fp;
1211   char *tok,*str,*s2;
1212   char *f1,*f2,*f3;
1213   struct fontmap *fcur,*fnew;
1214   int val;
1215   char *endptr;
1216   int len;
1217 
1218   if ((fp=openconfig(GRA2CONF))==NULL) {
1219     printfstderr("Error: configuration file (%s) is not found.\n",CONF);
1220     exit(1);
1221   }
1222   fcur=NULL;
1223   while ((tok=getconfig(fp,&str))!=NULL) {
1224     s2=str;
1225     if (strcmp(tok,"font_map")==0) {
1226       f1=getitok2(&s2,&len," \t,");
1227       f2=getitok2(&s2,&len," \t,");
1228       f3=getitok2(&s2,&len," \t,");
1229       if ((f1!=NULL) && (f2!=NULL) && (f3!=NULL)) {
1230         fnew=malloc(sizeof(struct fontmap));
1231         if (fcur==NULL) fmap=fnew;
1232         else fcur->next=fnew;
1233         fcur=fnew;
1234         fcur->next=NULL;
1235         fcur->fontalias=f1;
1236         if (strcmp(f2,"bold")==0) fcur->type=BOLD;
1237         else if (strcmp(f2,"italic")==0) fcur->type=ITALIC;
1238         else if (strcmp(f2,"bold_italic")==0) fcur->type=BOLDITALIC;
1239         else fcur->type=NORMAL;
1240         fcur->fontname=f3;
1241         fcur->used=FALSE;
1242         free(f2);
1243       } else {
1244         free(f1);
1245         free(f2);
1246         free(f3);
1247       }
1248     } else if (strcmp(tok,"include")==0) {
1249       includefile=getitok2(&s2,&len,"");
1250     } else if (strcmp(tok,"color")==0) {
1251       f1=getitok2(&s2,&len," \t,");
1252       val=strtol(f1,&endptr,10);
1253       if (endptr[0]=='\0') {
1254         if (val==0) color=FALSE;
1255         else color=TRUE;
1256       }
1257       free(f1);
1258     } else if (strcmp(tok,"sjis")==0) {
1259       f1=getitok2(&s2,&len," \t,");
1260       val=strtol(f1,&endptr,10);
1261       if (endptr[0]=='\0') {
1262         if (val==0) sjis=FALSE;
1263         else sjis=TRUE;
1264       }
1265       free(f1);
1266     }
1267     free(tok);
1268     free(str);
1269   }
1270   closeconfig(fp);
1271 }
1272 
main(int argc,char ** argv)1273 int main(int argc,char **argv)
1274 {
1275   int i;
1276   char *filename;
1277   FILE *fp;
1278   char *buf;
1279   char *lib,*home;
1280   char *tmpname;
1281   int ch;
1282   char *endptr;
1283   int a;
1284 
1285   printfstderr("Ngraph - PostScript(R) Printer Driver version: "VERSION"\n");
1286 
1287 #ifndef WINDOWS
1288   if ((lib=getenv("NGRAPHLIB"))!=NULL) {
1289     if ((libdir=(char *)malloc(strlen(lib)+1))==NULL) exit(1);
1290     strcpy(libdir,lib);
1291   } else {
1292     if ((libdir=(char *)malloc(strlen(LIBDIR)+1))==NULL) exit(1);
1293     strcpy(libdir,LIBDIR);
1294   }
1295   if ((home=getenv("NGRAPHHOME"))!=NULL) {
1296     if ((homedir=(char *)malloc(strlen(home)+1))==NULL) exit(1);
1297     strcpy(homedir,home);
1298   } else if ((home=getenv("HOME"))!=NULL) {
1299     if ((homedir=(char *)malloc(strlen(home)+1))==NULL) exit(1);
1300     strcpy(homedir,home);
1301   } else if ((home=getenv("Home"))!=NULL) {
1302     if ((homedir=(char *)malloc(strlen(home)+1))==NULL) exit(1);
1303     strcpy(homedir,home);
1304   } else {
1305     if ((homedir=(char *)malloc(strlen(libdir)+1))==NULL) exit(1);
1306     strcpy(homedir,libdir);
1307   }
1308 #else
1309   if ((lib=getenv("NGRAPHLIB"))!=NULL) {
1310     if ((libdir=(char *)malloc(strlen(lib)+1))==NULL) exit(1);
1311     strcpy(libdir,lib);
1312   } else {
1313     for (i=strlen(argv[0]);(argv[0][i]!='\\') && (i>0);i--);
1314     if ((libdir=(char *)malloc(i+1))==NULL) exit(1);
1315     strncpy(libdir,argv[0],i);
1316     libdir[i]='\0';
1317   }
1318   if ((home=getenv("NGRAPHHOME"))!=NULL) {
1319     if ((homedir=(char *)malloc(strlen(home)+1))==NULL) exit(1);
1320     strcpy(homedir,home);
1321   } else if ((home=getenv("HOME"))!=NULL) {
1322     if ((homedir=(char *)malloc(strlen(home)+1))==NULL) exit(1);
1323     strcpy(homedir,home);
1324   } else {
1325     if ((homedir=(char *)malloc(strlen(libdir)+1))==NULL) exit(1);
1326     strcpy(homedir,libdir);
1327   }
1328 #endif
1329   includefile=malloc(strlen(libdir)+11);
1330   strcpy(includefile,libdir);
1331   strcat(includefile,"/Ngraph.ps");
1332 
1333   loadconfig();
1334 
1335   outfilename=NULL;
1336   for (i=1;(i<argc) && (argv[i][0]=='-') && (argv[i][1]!='\0');i++) {
1337     switch (argv[i][1]) {
1338     case 'o':
1339       if (((i+1)<argc) && (argv[i+1][0]!='-')) {
1340         outfilename=argv[i+1];
1341         i++;
1342       }
1343       break;
1344     case 'i':
1345       if (((i+1)<argc) && (argv[i+1][0]!='-')) {
1346         free(includefile);
1347         if ((includefile=malloc(strlen(argv[i+1])+1))!=NULL)
1348           strcpy(includefile,argv[i+1]);
1349         i++;
1350       }
1351       break;
1352     case 'c':
1353       color=TRUE;
1354       break;
1355     case 'e':
1356       epsf=TRUE;
1357       break;
1358     case 'p':
1359       if (((i+1)<argc) && (argv[i+1][0]!='-')) {
1360         if ((strcmp(argv[i+1],"A3")==0) || (strcmp(argv[i+1],"a3")==0))
1361           paper=A3;
1362         else if ((strcmp(argv[i+1],"A4")==0) || (strcmp(argv[i+1],"a4")==0))
1363           paper=A4;
1364         else if ((strcmp(argv[i+1],"B4")==0) || (strcmp(argv[i+1],"b4")==0))
1365           paper=B4;
1366         else if ((strcmp(argv[i+1],"A5")==0) || (strcmp(argv[i+1],"a5")==0))
1367           paper=A5;
1368         else if ((strcmp(argv[i+1],"B5")==0) || (strcmp(argv[i+1],"b5")==0))
1369           paper=B5;
1370         else if ((strcmp(argv[i+1],"LETTER")==0)
1371         || (strcmp(argv[i+1],"letter")==0))
1372           paper=LETTER;
1373         else if ((strcmp(argv[i+1],"LEGAL")==0)
1374         || (strcmp(argv[i+1],"legal")==0))
1375           paper=LEGAL;
1376         i++;
1377       }
1378       break;
1379     case 'l':
1380       landscape=TRUE;
1381       break;
1382     case 'r':
1383       rotate=TRUE;
1384       break;
1385     case 's':
1386       if ((i+1)<argc) {
1387         a=strtol(argv[i+1],&endptr,10);
1388         if ((endptr[0]=='\0') && (0<=a) && (a<=60)) font_slant=a;
1389         i++;
1390       }
1391       break;
1392     default:
1393       printfstderr("unknown option `%s'.\n",argv[i]);
1394       free(includefile);
1395       free(libdir);
1396       free(homedir);
1397       exit(1);
1398     }
1399   }
1400 
1401   if (i>=argc) {
1402     printfstderr("Usage: gra2ps [options] grafile\n");
1403     printfstderr("Options:\n");
1404     printfstderr(" -o file                        : output file\n");
1405     printfstderr(" -i file                        : include file\n");
1406     printfstderr(" -c                             : color output\n");
1407     printfstderr(" -e                             : EPSF output\n");
1408     printfstderr(" -p a3|a4|b4|a5|b5|letter|legal : paper\n");
1409     printfstderr(" -l                             : landscape\n");
1410     printfstderr(" -r                             : rotate by 90 degree\n");
1411     printfstderr(" -s theta                       : slant angle (degree)\n");
1412     free(includefile);
1413     free(libdir);
1414     free(homedir);
1415     exit(1);
1416   }
1417 
1418   if (!rotate) {
1419     switch (paper) {
1420     case A3:
1421       if (landscape) bottom=29700;
1422       else bottom=42000;
1423       break;
1424     case A4:
1425       if (landscape) bottom=21000;
1426       else bottom=29700;
1427       break;
1428     case B4:
1429       if (landscape) bottom=25700;
1430       else bottom=36400;
1431       break;
1432     case B5:
1433       if (landscape) bottom=18200;
1434       else bottom=25700;
1435       break;
1436     case LETTER:
1437       if (landscape) bottom=21590;
1438       else bottom=27940;
1439       break;
1440     case LEGAL:
1441       if (landscape) bottom=21590;
1442       else bottom=35560;
1443       break;
1444     }
1445   } else bottom=0;
1446 
1447   if (outfilename!=NULL) {
1448     if ((outfp=fopen(outfilename,"wt"))==NULL) {
1449       fprintf(stderr,"error: file open `%s'.\n",outfilename);
1450       free(includefile);
1451       free(libdir);
1452       free(homedir);
1453       exit(1);
1454     }
1455   } else outfp=stdout;
1456 
1457   filename=argv[i];
1458   tmpname=NULL;
1459   if (epsf && (filename[0]=='-') && (filename[1]=='\0')) {
1460 	if ((tmpname=tempnam(NULL,"GR2PS"))==NULL) exit(1);
1461     if ((fp=fopen(tmpname,"wt"))==NULL) exit(1);
1462     while ((ch=fgetc(stdin))!=EOF) fputc(ch,fp);
1463     fclose(fp);
1464     filename=tmpname;
1465   }
1466   if (epsf) {
1467     if ((fp=fopen(filename,"rt"))==NULL) {
1468       printfstderr("error: file not found `%s'.\n",filename);
1469       goto errexit;
1470     }
1471     if (fgetline(fp,&buf)==1) {
1472       printfstderr("error: illegal GRA format.\n");
1473       goto errexit;
1474     }
1475     if (strcmp(buf,GRAF)!=0) {
1476       printfstderr("error: illegal GRA format.\n");
1477       goto errexit;
1478     }
1479     free(buf);
1480     while (fgetline(fp,&buf)!=1) {
1481       if (!GRAinput(buf,getboundingbox)) {
1482         printfstderr("error: illegal GRA format.\n");
1483         goto errexit;
1484       }
1485       free(buf);
1486     }
1487     fclose(fp);
1488   }
1489   if ((filename[0]=='-') && (filename[1]=='\0')) fp=stdin;
1490   else {
1491     if ((fp=fopen(filename,"rt"))==NULL) {
1492       printfstderr("error: file not found `%s'.\n",filename);
1493       goto errexit;
1494     }
1495   }
1496   if (fgetline(fp,&buf)==1) {
1497     printfstderr("error: illegal GRA format.\n");
1498     goto errexit;
1499   }
1500   if (strcmp(buf,GRAF)!=0) {
1501     printfstderr("error: illegal GRA format.\n");
1502     goto errexit;
1503   }
1504   free(buf);
1505   while (fgetline(fp,&buf)!=1) {
1506     if (!GRAinput(buf,draw)) {
1507       printfstderr("error: illegal GRA format.\n");
1508       goto errexit;
1509     }
1510     free(buf);
1511   }
1512   fclose(outfp);
1513   fclose(fp);
1514   if (tmpname!=NULL) {
1515     unlink(tmpname);
1516     free(tmpname);
1517   }
1518   free(includefile);
1519   free(libdir);
1520   free(homedir);
1521   return 0;
1522 errexit:
1523   if (tmpname!=NULL) {
1524     unlink(tmpname);
1525     free(tmpname);
1526   }
1527   free(includefile);
1528   free(libdir);
1529   free(homedir);
1530   return 1;
1531 }
1532