1 /* **************************************************
2  * CNPRINT.C For CNPRINT Version 3.30b (VMS & UNIX) *
3  * **************************************************
4   Copyright YIDAO CAI (~{2LR@5@~}), 1992-2001
5   All Rights Reserved.
6   Free for non-commercial and personal use only.
7 
8   The source code, or part of it, original or modified, may not be
9   included in any other software, without permission from the author.
10   See "Author" section of the help file for details.
11 
12 Disclaimer: Posting CNPRINT on any FTP site does not imply the author's
13 	endorsement of the beliefs of the organization who owns the FTP site.
14 
15 CNPRINT, a utility to print Chinese/Japanese/Korean text (or convert to
16 	PostScript) under DOS, VMS and UNIX systems.  It works just as
17 	a print command on your system.  Currently GB, Hz, zW, BIG-5,
18 	JIS (new-, old-, NEC-), EUC, shifted-JIS, KSC, UTF16, UTF8 and
19 	UTF7 are supported.
20 
21 *** PLEASE read CNPRINT.HELP first EVEN if you have used CNPRINT before ***
22 
23 YIDAO CAI  cai@neurophys.wisc.edu
24 MAY-11-2001
25 **************************************************** */
26 
27 /*#define STAT*/
28 /*#define CNS_SUPPORT*/
29 #define PSPRINT
30 #define TIME
31 
32 #ifdef VMS
33 
34 #else
35 # ifdef unix
36  /* */
37 # else
38 #  define unix
39 # endif
40 /* for multi-users on unix */
41 # define MUSER
42 #endif
43 
44 #include <stdio.h>
45 #include <time.h>
46 #include <ctype.h>
47 #include <stdlib.h>
48 #include <string.h>
49 #ifdef MUSER
50 #include <unistd.h>
51 #endif
52 
53 #define GBstr "_gb"
54 #define B5str "_b5"
55 #define PSstr "_ps"
56 #define HZstr "_hz"
57 #define JISstr "_jis"
58 #define Version "CNPRINT V3.30b (VMS & UNIX) MAY-11-2001"
59 #define EOL '\n'
60 #define CR  13
61 #define FF  12
62 #define LF  10
63 #define ESC 0x1B
64 #define CTRLD 4
65 #define IN 1
66 #define OUT 0
67 #define R 1
68 #define L 2
69 #define RMXY 11 /* rotate and move */
70 #define RMX  12
71 #define RMY  13
72 #define NT 0
73 #define EQ 0
74 #define T 3
75 #define B 4
76 #define RMIRROR 5
77 
78 #define RINIT 999 /* re-init */
79 
80 /* code types */
81 #define UNKNOWN 0
82 #define ASCII  1
83 #define ZW     2
84 #define HZ     3
85 #define GB     4
86 #define GBORB5 5
87 #define B5     6
88 #define CNS    7
89 #define GBK    8	/* extended (kuozhan) GB */
90 #define B5P    9	/* Big5 plus */
91 #define JIS    11	/* JIS-0208, Japanese */
92 #define SJIS   12
93 #define EUC    13
94 #define EUCORSJIS   14
95 #define KSC    16       /* KSC-5601-1987, Korean */
96 #define UTF    17       /* 2-byte unicode, also UTF16BE */
97 #define UTF7   18       /* 7-bit unicode */
98 #define UTF8   19       /* 8-bit unicode */
99 #define UTF16  20       /* 16-bit unicode, particularly 16LE */
100 
101 static char *codename[]={"Unknown", "ASCII", "zW", "Hz", "GB",
102 	"GB or BIG5", "BIG5", "CNS", "GBK", "Big5+", "",
103 	"JIS", "Shift-JIS", "EUC", "EUC or Shift-JIS", "",
104 	"KSC", "UTF", "UTF7", "UTF8", "UTF16LE", "", ""};
105 
106 /* conversion codes */
107 #define HZGB 1
108 #define GBHZ 2
109 #define FILT 3
110 #define ZWGB 4
111 #define JIS8 5          /* 7-bit JIS to 8-bit JIS */
112 #define JISRP 6         /* repair damaged JIS file */
113 #define JISCVT 7        /* convert EUC etc to 7-bit JIS */
114 #define HZPGB 8
115 #define HZPB5 9
116 #define KSC8 10         /* 7-bit KSC to 8-bit KSC */
117 #define UTF7TOUNI 11    /* convert to escaped 2-byte */
118 #define UTF8TOUNI 12
119 #define UTF16BETOUNI 13
120 #define UTF16LETOUNI 14
121 #define CNSB5 15        /* CNS planes 1/2 to Big5 */
122 #define GBB5  16        /* GB to B5 */
123 #define HZB5  17
124 #define B5GB  18
125 #define B5HZ  19
126 #define TOSHORTPS 20
127 #define PAGEPRINT 21
128 #define MIMEQP 22	/* decoding mime quoted printable */
129 #define MIME64 23	/* decoding mime base64 */
130 #define ADDLBAS	24	/* filter input file, add sender's address */
131 #define UNIGB	25	/* unicode to GB */
132 #define UNIB5	26
133 #define UNIKSC	27
134 #define UNIJIS	28
135 #define UTF8CJK	29	/* unicode type to CJK */
136 #define UTF7CJK	30
137 #define UTF16CJK 31	/* BE */
138 #define UTF16LECJK 32
139 #define GBUNI	33	/* GB to unicode */
140 #define B5UNI	34
141 #define KSCUNI	35
142 #define JISUNI	36
143 #define CJKUTF8	37	/* CJK to unicode type */
144 #define CJKUTF7	38
145 #define CJKUTF16 39	/* BE */
146 #define CJKUTF16LE 40
147 #define STATS 41	/* statistics output */
148 
149 #ifdef PSPRINT
150 #define isbreaka(c) (c==' ' || c=='(' || c=='{')
151 #define isbreakb(c) (c=='}' || c==')')
152 #define MAXLENGTHA 20
153 #define MAXLENGTH 72
154 #define MAXLENGTHB 99
155 #endif
156 
157 /* paper sizes */
158 #define LETTER 1
159 #define LEGAL  2
160 #define A3     3
161 #define A4     4
162 
163 #define BUFSIZE 8192
164 #define MAXBUFSZ 60000
165 #define SBUFSIZE 256
166 
167 
168 int     LM, RM, TM, BM, CSP, CLP, CIP, H, V;
169 int	indentL=0, indentR=0;	/* left or right indent in dots */
170 int	BMover=8;		/* allow to exceed BM by this amount in dots */
171 float   XX=0.0, YY;             /* actual paper size in inch, e.g. 8.5x11 */
172 int     Xw, Yh, Xa, Ya;         /*  "" in dots, Xa (lm), Ya (tm) */
173 float   pts, defpts;		/* 1 pts = 1/72 inch */
174 float   ppd = -1;    /* pts per dot, default .24, assume device res 300dpi */
175 static float Cw=0.72;           /* char width/line space */
176 float   Ci, Ca, defCi, defCa;   /* space between lines, characters */
177     /* Additional char spacing for font, FontCa >= -5 must be set in HBF/HTF */
178 float	FontCa;
179 float	FontptsScale ;		/* scale a char in both x and y */
180 float   Casc=0.5;               /* ASC_width / CH_width */
181 int     nCN=2048, copies=1;     /* # of entries in CNdict */
182 int     nHzline=9999;           /* # of chars per Hz/JIS line, default 70 */
183 char    prntcmd[80];
184 
185 char    PSfile[100], EPSHDfile[80], KWfile[80], G2Bfileb[80], tempfile[80];
186 char    DictExt[2];             /* CNdict extension for EPS */
187 int     ptspc, defptsi;		/* currently used pts, defpsti=INT(defpts+.5) */
188 int     mx, my, CHsize;  /* bitmap mx by my, string length CHsize */
189 int     inCH=100, newpos=1;
190 int     filecount=1, fprntfile=1;
191 int	input_file_layer=0;	/* control deletion of intermediate files */
192 int     fputnpage=6;            /* page number position 1-6 */
193 int     pgpd=0;                 /* physical pages actually printed */
194 int     pgcount=1, pgcount_bak;
195 int	bp=0, ep=0;  /* page numbers to begin/end printing */
196 int     Prntpage, odd=0;   /* page-print: 0/1/2, print all/odd/even pages */
197 int     twoside=0;              /* two-sided format */
198 int     booklet=0;              /* output booklet format */
199 int     frl=NT;                 /* right-left */
200 int     fnewline=1;
201 int     cnsp=0;                 /* special CH char */
202 
203     /* gray level: 0=black, 1=white; by default, use color mode if rgb>0 */
204 struct ColorGrayStr { float gray, red, green, blue; } color;
205 int	linewidth=1, deflinewidth=1;
206 float   Cx=1., Cy=1., defCx, defCy;
207 int     stdinput=0, stdoutput=0; /* use stdin/stdout */
208 int     code=UNKNOWN, defcode=UNKNOWN, convcode=NT;
209 int	codecmd, convcodecmd;
210 int     big5=0, lcode;  /* language code (GB, B5, JIS, KSC) */
211 int     pausqm=0;       /* pause at every (pause) pages */
212 int     landscape=0, EPS=0, IncEPS=0;   /* generate EPS, EPS file included */
213 int     vertical=0, Rotate=0, vgb=0;
214 int     suppress=0, mute=0, keepPS=0;   /* mute menu or map .,:; to CH */
215 int     manualfeed=0, envelope=0;
216 int     adjust=1;       /* adjust spaces between punctuation marks */
217 int     alnumadjust=0;  /* adjust alnum from CH to English */
218 int     timestat=0;     /* suppress time / statistics about document */
219 int     AdjAtEndDoc=1;  /* BM adjust at end of document if multicolumn */
220 int     cmdlinehbf=0;   /* hbf filename supplied in command-line */
221 int     cgap=0;         /* gap between columns in pts, use default if zero */
222 int	vgap=0;	/* vertical gap when column # changes (def. 1.5 line spacing) */
223 int     tabascii=0;     /* set tab width according to CH (0) or ASCII(1)
224 			   default 0 (1 if ASCII file selected) */
225 
226 /* mode for printing address labels */
227 #define LBASMAX 512     /* max # of chars for sender's address */
228 int	addrlabel=0;
229 int	lbn=0, lbnx=2, lbny=5;
230 int	lb_eat_EOL=1;	/* EOL after @[LBAS], @[LB] or @[LB##] is ignored */
231 float	lbxp=.5, lbyp=1.0, lbxinc=4.25, lbyinc=2.0;
232 void addLBAS(FILE *);
233 
234 /* special effect */
235 int     fshade=0;
236 struct  {int x; int f;} UDline; /* underline */
237 
238 /* for central adjust; */
239 int     centraladj=0, spaceH;	/* spaceH: H value of 1st non-space char */
240 int     startline=1;            /* previous line ended with EOL */
241 
242 /* ASC font */
243 int     nEF = -1, defnEF, *nEFs;
244 int     euro=0;         /* European chars, def: auto-detect; -1, disable */
245 float   Wasc[129];       /* width of ASC char re Courier */
246 char	**EFontnames, **EFmetricfiles;
247 int	nEFmax=40, nEFfamily=10;	/* default in old version */
248 char	*zerolenstr="";
249 static char *EFname[]={"AvantGarde-Book", "", "Courier", "Helvetica", "", "",
250   "Palatino-Roman", "Times-Roman", "ZapfChancery-MediumItalic", "ZapfDingbats",
251 "AvantGarde-BookOblique", "", "Courier-Oblique", "Helvetica-Oblique",
252   "", "", "Palatino-Italic", "Times-Italic", "", "",
253 "AvantGarde-Demi", "", "Courier-Bold", "Helvetica-Bold", "", "",
254   "Palatino-Bold", "Times-Bold", "", "",
255 "AvantGarde-DemiOblique", "", "Courier-BoldOblique", "Helvetica-BoldOblique",
256   "", "", "Palatino-BoldItalic", "Times-BoldItalic", "", "Symbol"};
257 
258 void getEfontdata(int);
259 int getEfontlist(void);
260 int isASCfont(char *);
261 
262 /*  for search  */
263 #define MAXLINES 350    /* max # of lines, affect multiple column options */
264 #define ASCBUFSIZE 300
265 int     PCN, SCN;
266 int     cTM, cBM, cLM, cRM, Ha;
267 int     pline=0, pcolumn=1;
268 int     sline=0, column=1, defcolumn;  /* defcolumn is the one set for doc */
269 int     lineclp[MAXLINES], linedif[MAXLINES], linecip[MAXLINES];
270 
271 struct {unsigned char s[ASCBUFSIZE]; int p, pp, Hp;} ascbuf;
272 
273 /* for efficient multiple font/language handling */
274 int	PreScanMode=1;
275 struct FontTag {
276 	char	FontName[100]; /* HBF/TTF/HTF */
277 	int	FontID;	/* numerical */
278 	int	ttf_font;
279 	int	lcode;	/* needed only for multiple language */
280 	int	mx, my;
281 	unsigned int    *fstring, *fdict, nchar, cspace, b1l, b2l;
282 	unsigned int	b2h_range1, b2gap, b2span;
283 	unsigned int	ndchar, nCN, k;
284 	unsigned char   **ptstring;
285 	struct FontTag *p;
286  } *Fonts, *CurrentFont;
287 unsigned int    *fstring, *fdict, nchar;
288 unsigned int    cspace, b1l, b2l;    /* space char, lowerest byte-1(2) */
289 unsigned int	b2h_range1, b2gap, b2span;
290 
291 unsigned char   **ptstring, *array;
292 
293 /* for HBF */
294 char    HBFname[80], defHBFname[80];
295 struct  Roots {char *s; struct Roots *p;} *root;
296 struct  Bytes {int l; int h; int a;} *b2;
297 struct  HBFrange {
298 		unsigned int l; unsigned int h; long offset;
299 		char bmfname[50]; FILE *fp;
300  } *seg;
301 int     nb2, nseg, GR=0;        /* GL(GR=0): 7-bit form */
302 
303 int HBFopen(void);
304 void HBFclose(void);
305 int HBFgetBitmap(unsigned int);
306 void construct_fontname(char *);
307 
308 /* for TTF font support */
309 int	ttf_font=0;	/* will auto detect */
310 char	TTFfile[120];
311 int	PSLlevel=1;	/* language level, if 2, use Base85 compression */
312 unsigned char dummy[2];
313 FILE	*fpTTF;
314 int	UnicodeTTF=0;	/* can be used by all lcode through mapping */
315 unsigned short **UNItablemap;
316 
317 void loadUNImappingtable(int, int);
318 void mapToUnicode(unsigned char *, unsigned char *);
319 	/* defined in ttfb.c */
320 void TTFclose(FILE *);
321 void TTFgen_PSproc(FILE *, unsigned int, unsigned int);
322 
323 /* repairs */
324 int     ignorespace=0, fix=0, ignoreEOL=0;  /* fix/repair */
325 int     breakfile=0; /* break big file into small (>12k, def: 64k) ones;
326 	    or (when multi-input), in -fpg# start a new page for
327 	    each input (optional) if within # (<=9) lines to bottom,
328 	    or (when multi-input) multiple output (>10) */
329 long    fnchar=0;               /* char count in small file */
330 char    newshd='>';             /* initial char for news replys */
331 unsigned char sbuf[SBUFSIZE];
332 int     sbufp=0;                /* pointer to sbuf */
333 int     bmpshift=0, bmpshift_dir=NT;  /* shift bitmap of a char */
334 unsigned int bmpshift_ch, bmpshift_ch2;
335 
336 /* for utf & utf7: convert to two-byte unicode or CJK */
337 static unsigned char   base64[] =
338 	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
339 static unsigned char   safe[] = "'(),-.:?";
340 static unsigned char   optional[] = "!\"#$%&*;<=>@[]^_`{|}";
341 static unsigned char   space[] = " \t\n\r";
342 #define NUMBYTES 256
343 #define BASE64  0x01
344 #define SAFE    0x02
345 #define OPTIONAL 0x04
346 #define SPACE   0x08
347 #define CODE_ERROR 0x80
348 static  char    inv_base64[128];
349 static  char    char_type[NUMBYTES];
350 static  int     utf_initzd;
351 static  int     in_base64;
352 static  unsigned long   bit_buffer;
353 static  int     nbits;
354 /* should use chars that are rarely used (control chars) and not
355  the high-byte of CJK */
356 #define U2ESC   0x28    /* ESCs for 2-byte unicode */
357 #define U2ESC2  0x29    /* 0x2828 = 0x28, 0x2829 () = 0x00 */
358 #define isUnicodeASCII(c1, c2) ((c1) == 0x00 && (c2) <= 0x7E)
359 
360 void unicodepreproc(void);
361 int DetectUnicodeType(void);
362 void to2byte_unicode(FILE *);
363 void u2byte(int);
364 void utf16to2byte_unicode(FILE *);
365 void unicode2cjk(FILE *);
366 void unicode2cjk16(FILE *);
367 void cjk2unicode(FILE *);
368 long utf16_getc(FILE *);/* utf16 to 2-byte unicode (escaped) */
369 long utf8_getc(FILE *);	/* utf8 to 2-byte unicode */
370 long utf7_getc(FILE *);	/* utf7 to 2-byte unicode */
371 static void invert(void);
372 int unicode_isfs(unsigned char *, int);
373 
374 /* -----------------------------*/
375 void RegisterFont(void);
376 void UnRegisterFont(struct FontTag *);
377 
378 int columnWidth(void);
379 void charsize(float);
380 float getnew(float, int);
381 void newline(int, int);
382 void endpage(int);
383 void outputToStdout(char *);
384 void outputToDev(void);
385 void trailer(int);
386 void pagesetup(void);
387 void putnpagetime(void);
388 void header(void);
389 void putBitmap(unsigned char *);
390 void putBitmap85(unsigned char *, int);
391 void PSctrl(void);
392 
393 void CNdict(int, int);
394 unsigned int Addr(int, int);
395 
396 /* char level handling --- page layout related */
397 int isrlasc(int);
398 int isrlch(unsigned char, unsigned char);
399 unsigned char tovhb5(unsigned char);
400 int vchange(unsigned char *, unsigned char *);
401 int rtch(unsigned char, unsigned char);
402 int isfs(unsigned char *, int);
403 int issfs(unsigned char, unsigned char, unsigned char);
404 int putASC(int, int, int);
405 int putCH(unsigned char, unsigned char, int);
406 
407 void shade(void);
408 void underline(void);
409 void endAC(int);
410 void clearascbuf(int, int);
411 
412 int span(int);
413 int CheckLineLen(void);
414 
415 /* stat */
416 int     charstat=1;     /* char/word statistics */
417 void statistics(unsigned int, unsigned int);
418 extern void statinit(void);
419 void stat_prescan(void);
420 void wordstat(unsigned int);
421 
422 /* non-printing related */
423 void CharBMPshift(void); /* bitmap shift for char */
424 int CharBitmapShift(FILE *, long, unsigned char *);
425 
426 void Addchar(int, int);
427 void sbufprint(int);
428 void convertEOL(unsigned char *, int *);
429 void GetCharUsage(void);
430 int print_range_check(int);
431 
432 void set_doc_defaults(void);
433 void style(int);
434 int filter(unsigned char, unsigned char, unsigned char *, int);
435 int OIOU(int);
436 unsigned char *doAC(unsigned char *, int);
437 unsigned char *doAC_unicode(unsigned char *, int);
438 
439 /* code detection, conversion, etc */
440 int	convt_and_print=0;
441 void CodeConversion(void);
442 void convers(int);
443 void nullfilter(FILE *);
444 
445     /* JIS-related */
446 #define SS2         142
447 #define SJIS1(A)    ((A >= 129 && A <= 159) || (A >= 224 && A <= 239))
448 #define SJIS2(A)    (A >= 64 && A <= 252)
449 #define HANKATA(A)  (A >= 161 && A <= 223)
450 #define ISEUC(A)    (A >= 161 && A <= 254)
451 #define ISMARU(A)   (A >= 202 && A <= 206)
452 #define ISNIGORI(A) \
453 	((A >= 182 && A <= 196) || (A >= 202 && A <= 206) || (A == 179))
454 
455 void jispreproc(void);    /* convert to 7-bit, then to 8-bit */
456 void jis2jis8(FILE *);       /* 0x21-0x7E --> 0xA1-0xFE */
457 int SkipESCSeq(FILE *, int, int *);
458 int DetectJPCodeType(void);
459 void han2zen(FILE *, int *, int *, int);
460 void sjis2jis(int *, int *);
461 void shift2seven(FILE *, char *, char *);
462 void euc2seven(FILE *, char *, char *);
463 void seven2seven(FILE *, char *, char *);
464 void jisrepair(void);
465 
466     /* KSC */
467 void kscpreproc(void);
468 
469     /* GB/HZ, B5 */
470 #define isvgb(c) (c==0x21 || c==0x2c || c==0x3A || c==0x3B || c==0x3F)
471 #define MSBoff(c)   (c & 0x7f)
472 #define MSBon(c)    (c | 0x80)
473 #define GBPOS(a, b) (((a)-0xa1)*94 + ((b)-0xa1))
474 #define GBB1(n)     ((n)/94 + 0xa1)
475 #define GBB2(n)     ((n)%94 + 0xa1)
476 #define B5POS(a, b) (((a)-0xa1)*157 + (b) - ((b)>=0xa1 ?(0xa1-63):0x40))
477 #define B5B1(n)     (((n)/157) + 0xa1)
478 #define B5B2(n)     ((n)%157 + (((n)%157)<63 ? 0x40 : (0xa1-63)))
479 #define GBbox   85  /* index postion of 0xA1F5 */
480 #define B5box   27  /* 0xA1BC */
481 unsigned int *gbb5_fstr;
482 unsigned char **gbb5_ptstr;
483 
484 void gbb5preproc(void);
485 int DetectCNCodeType(void);
486 void hz2gb(FILE *);
487 void gb2hz(FILE *);
488 void zw2gb(FILE *);
489 void cns2b5(FILE *, FILE *);
490 void gbb5convinit(int);
491 void gbb5conv(FILE *, int);
492 void gbb5tableinit(int, FILE *);
493 
494     /* MIME type */
495 int mimeqp_hex(int);
496 int DetectMIMEType(void);
497 void mimeqpdecode(FILE *);
498 
499 
500 /* general, init, file handling, time, etc */
501 void	opnfile(int);
502 FILE	*Rfopen(char *, char *);
503 int	sgetc(FILE *);
504 int	sungetc(int);
505 void	bell(void);
506 void	signature(void);
507 void	usage(int);
508 void	MemExit(void);
509 void	getroot(void);
510 void	FName(char *, char *);
511 void	RE_name(char *, char *);
512 int	yes(int);
513 void	cleanup(int);
514 void	init(int, char **);
515 char	*readstr(char **v, char *s);
516 float	readfv(char **v, char *s);
517 int	isstr(char *s, char **v);
518 int	num(char **v, int n);
519 int	getdata(int);
520 
521 void	header(void), PSctrl(void);
522 void	charsize(float);
523 void	endpage(int);
524 void	putBitmap(unsigned char *);
525 
526 /* ============================= */
527 /* functions */
528 
529 float hex2float1(char, char);
530 int int3pts2dot(unsigned char *);
531 
532 void	insertEOL(void);
533 int	IncludeEPS(char *);
534 char	*gets_stdin(char *, int);
535 void	pageprint(FILE *);
536 int	copypage(int, int, int, FILE *, long *);
537 int	strfilecmp(char *, FILE *);
538 void	RegisterFont(void);
539 void tobooklet(void);
540 void toshortline(FILE *);
541 
542 struct  INfiles {char *s; char *t; FILE *fp; struct INfiles *p;}
543 	*Rinf, *inf, *mRinf;
544 
545 struct  WordFreqstr {unsigned char *s; int *addrs; int j; int freq;
546 		struct WordFreqstr *p;} *WordFreq;
547 
548 int     extraEOL = 0;   /* before error message */
549 FILE    *out, *HBF, *errout, *msgout;
550 
551 
552 #ifdef CNS_SUPPORT  /* begin CNS support */
553 /*
554 #include "cnsb5.h"
555 */
556 #else  /* no CNS support */
557 
cns2b5(FILE * in,FILE * out)558 void cns2b5(FILE *in, FILE *out)  /* CNS to Big5 convertion */
559 {
560 	fprintf(stderr,
561 "No CNS subroutines, please follow instructions in file cns2b5.c\n\
562 (available by ftp at ftp.neurophys.wisc.edu:/pub/cn,\n\
563 use \"anonymous\" as user name)\n");
564 }
565 #endif  /* CNS support */
566 
gets_stdin(char * s,int n)567 char *gets_stdin(char *s, int n)
568 {
569 	int	k;
570 	fgets(s, n, stdin);
571 	k = strlen(s);
572 	if (s[k-1]=='\n') s[k-1] = '\0';
573 	return s;
574 }
575 
insertEOL()576 void insertEOL()
577 /* print an EOL, to put message between page numbers */
578 {
579 	if (extraEOL) fputc('\n', errout);
580 	extraEOL = 0;
581 }
582 
IncludeEPS(char * s)583 int IncludeEPS(char *s)
584 {
585 	char    feps[80], cst[256];
586 	int     llx, lly, urx, ury;
587 	FILE    *fp;
588 
589 	if (!inCH) endAC(1);
590 	if (s[0]!='\0') strcpy (feps, s);
591 	else if (!stdinput) {
592 		insertEOL();
593 		fprintf(stderr,
594 "Please enter full name of EPS file to be included:\n");
595 		gets_stdin(feps, 79);
596 	}
597 	if ((fp=fopen(feps, "r"))==NULL) {
598 		insertEOL();
599 		fprintf(stderr,
600 "Can't open EPS file -> %s\n", feps);
601 		bell(); return 0;
602 	}
603 	while (fgets(cst, 255, fp)!=NULL)
604 		if (strncmp(cst, "%%BoundingBox", 13)==0) break;
605 	sscanf(cst, "%*s%d%d%d%d", &llx, &lly, &urx, &ury);
606 	fprintf(out,
607 "\nBeginEPSF\ncpx cpy translate dpi 72 div dup scale %d %d translate\n\
608 %%%%BeginDocument: %s\n", 0-llx, 0-lly, feps);
609 	rewind(fp);
610 	while(fgets(cst, 255, fp)!=NULL) fprintf(out, "%s", cst);
611 	fprintf(out, "\n%%%%EndDocument\nEndEPSF\n");
612 	fclose(fp);
613 	IncEPS++;
614 	return 1;
615 }
616 
HBFopen()617 int HBFopen()
618 /* open HBF file, set segment and byte-2-ranges, open bitmap files */
619 {
620 	int     j, m;
621 	char    cst[120];
622 	extern FILE *TTFopen_init(char *);
623 
624 	if ((HBF=Rfopen(HBFname, "r"))==NULL) {
625 		insertEOL();
626 		fprintf(stderr,
627 "Can't open HBF or TTF header file -> %s\n\
628 Please check if the path/directory/filename is correct\n\
629 and see Part VI of the help file\n\
630 about the name convention for HBF files: cn*##.hbf\n", HBFname);
631 		bell();
632 		if (*defHBFname==0) exit(-1);
633 		else return 0;
634 	}
635 /*
636  * check if it is HBF, HTF (header file for TTF), or TTF font itself
637  * the default is TTF font itself
638  * HTF contains the first line as "TTF_FILE: name_of_ttf_file"
639  * and possibly some comment lines
640 **** optionally, it can have a line to specify additional char spacing, e.g.
641 **** "_AddCharSpacing:  .5 " sets FontCa=0.5 (1=standard, 8% char
642 **** width, def=0, range < 20, > -5)
643 **** "_CharSizeScaling: 1.02" scales the whole char (note: very sensitive).
644 **** These lines can also be put in the HBF file after all regular
645 **** HBF property lines but before the line "HBF_END_FONT"
646 ****
647  */
648 
649 
650 	FontCa=0.;	/* reset font-specific parameters */
651 	FontptsScale=1.;
652 	while (fgets(cst, 119, HBF) != NULL) {
653 	    if (strncmp(cst, "COMMENT", 7) == EQ) continue;
654 	    else if (strncmp(cst, "HBF_START", 9) != EQ) {
655 		if (strncmp(cst, "TTF_FILE", 8)==EQ) {
656 		    sscanf(cst, "%*s%s", &TTFfile);
657 		    while (fgets(cst, 119, HBF) != NULL) {
658 			if (strncmp(cst, "_AddCharSpacing", 15) == EQ)
659 				sscanf(cst, "%*s%f", &FontCa);
660 			else if (strncmp(cst, "_CharSizeScaling", 16) == EQ)
661 				sscanf(cst, "%*s%f", &FontptsScale);
662 		    }
663 		}
664 		else strcpy(TTFfile, HBFname);
665 		fclose(HBF);
666 		ttf_font = 1;
667 		if ( (fpTTF=TTFopen_init(TTFfile)) == NULL) {
668 			ttf_font = 0;
669 			if (*defHBFname==0) exit(-3);
670 			else return 0;
671 		}
672 			/* mx, my: use those of load_cmap (ymax or EM) */
673 		if (mx < my) mx=my; my=mx;
674 		if (PSLlevel < 2) {
675 			PSLlevel=2;
676 			fprintf(stderr,
677 "TTF font requires PostScript language level 2, this PS file may not work.\n\
678 Please use -level option on command line\n");
679 		}
680 		RegisterFont();
681 		if (UnicodeTTF && lcode != UTF) loadUNImappingtable(lcode, 1);
682 		return 1;
683 	    }
684 	/* else: YES, found HBF */
685 	    break;
686 	}
687 
688 /* HBF file */
689 	GR=0;
690 	while (fgets(cst, 119, HBF)!=NULL)
691 		if (strncmp(cst, "HBF_BITMAP_BOUNDING_BOX", 23)==0) break;
692 	sscanf(cst, "%*s%d%d", &mx, &my);
693 	CHsize=my*((mx+7)/8);
694 	if (array!=NULL) free(array);
695 	array = (unsigned char *) calloc(CHsize+1, sizeof(unsigned char));
696 	if (array==NULL) MemExit();
697 
698 	while (fgets(cst, 119, HBF)!=NULL)
699 		if (strncmp(cst, "HBF_START_BYTE_2_RANGES", 23)==0) break;
700 	sscanf(cst, "%*s%d", &nb2);
701 	b2 = (struct Bytes *) calloc(nb2, sizeof(struct Bytes));
702 	if (b2==NULL) MemExit();
703 	for (j=0; j<nb2; j++) {
704 		while (fgets(cst, 119, HBF)!=NULL)
705 			if (strncmp(cst, "HBF_BYTE_2_RANGE", 16)==0) break;
706 		sscanf(cst, "%*s%i-%i", &(b2[j].l), &(b2[j].h));
707 		b2[j].a = b2[j].h - b2[j].l +1;
708 		if (b2[j].h >= 0xa1) GR=1; /* GL: 7-bit form */
709 		if (b2[j].a==1) {
710 			fprintf(stderr,
711 "Your system is special, please run hbfhx2d.c on all your HBF files\n\
712  (ftp: ftp.neurophys.wisc.edu:/pub/cn)\n");
713 			exit(0);
714 		}
715 	}
716 
717 	while (fgets(cst, 119, HBF)!=NULL)
718 		if (strncmp(cst, "HBF_START_CODE_RANGES", 21)==0) break;
719 	sscanf(cst, "%*s%d", &nseg);
720 	seg = (struct HBFrange *) calloc(nseg, sizeof(struct HBFrange));
721 	if (seg==NULL) MemExit();
722 	for (j=0; j<nseg; j++) {
723 		while (fgets(cst, 119, HBF)!=NULL)
724 			if (strncmp(cst, "HBF_CODE_RANGE", 14)==0) break;
725 		sscanf(cst, "%*s%i-%i%s%li", &(seg[j].l), &(seg[j].h),
726 			seg[j].bmfname, &(seg[j].offset));
727 		if (j>0) {
728 		    for (m=0; m<j; m++)
729 			if (strcmp(seg[m].bmfname, seg[j].bmfname)==0)
730 				seg[j].fp=seg[m].fp;
731 		}
732 		if (seg[j].fp==NULL) {
733 		    if ((seg[j].fp = Rfopen(seg[j].bmfname, (char *)
734 				( (bmpshift)? "rb+" : "rb" ) ))==NULL) {
735 			insertEOL();
736 			fprintf(stderr,
737 "Can't open bitmap font file -> %s\n\
738 Please make sure the path/directory/filename is correct\n\
739 and the HBF file is properly written\n", seg[j].bmfname);
740 			bell();
741 			if (*defHBFname==0) exit(-2);
742 			else return 0;
743 		    }
744 		}
745 	}
746 /* this is an extended HBF property only for cnprint, put it at the
747  * after all regular HBF property lines, but before the HBF_END_FONT line
748  * this line sets additional char spacing FontCa
749  */
750 	while (fgets(cst, 119, HBF) != NULL) {
751 		if (strncmp(cst, "_AddCharSpacing", 15) == EQ)
752 			sscanf(cst, "%*s%f", &FontCa);
753 		else if (strncmp(cst, "_CharSizeScaling", 16) == EQ)
754 			sscanf(cst, "%*s%f", &FontptsScale);
755 	}
756 	RegisterFont();
757 	return 1;
758 }
759 
HBFclose()760 void HBFclose()
761 /*
762  * Reset segment and byte-2-ranges, close bitmap files and HBF file
763  */
764 {
765 	int j;
766 
767 	if (ttf_font) {
768 		TTFclose(fpTTF);
769 		ttf_font=0;
770 		if (UnicodeTTF && lcode != UTF) {
771 		    for (j=0; j<=0xFF-b1l; j++) free(UNItablemap[j]);
772 		    free(UNItablemap);
773 		    UnicodeTTF=0;
774 		}
775 		return;
776 	}
777 
778 	for (j=0; j<nseg; j++) {
779 		if (seg[j].fp != NULL) fclose(seg[j].fp);
780 		seg[j].fp=NULL;
781 	}
782 	free(seg); free(b2);
783 	fclose(HBF);
784 }
785 
HBFgetBitmap(unsigned int ch)786 int HBFgetBitmap(unsigned int ch)
787 /*
788  * get bitmap string according to segment and byte-2-ranges
789  * or return 0 for out-of-range char
790  */
791 {
792 	unsigned int i, j, k, off;
793 	long    addr;
794 	if (!GR) ch -= 0x8080;  /* if 7-bit, ch must be in GR */
795 	for (i=0; i<nseg; i++) {
796 	    if (ch >= seg[i].l && ch <= seg[i].h) {
797 	/* treat as if segment starts at lowest byte 2, then compensate */
798 		off = seg[i].l%256 - b2[0].l;
799 		k = ch - seg[i].l + off;
800 		j = k%256; k /= 256;
801 		if (nb2==1)
802 		    addr = k*b2[0].a + j - off;
803 		else if (nb2==2) {
804 		    addr = k*(b2[0].a + b2[1].a) + j - off;
805 		    if (j > b2[0].a) addr -= (b2[1].l-b2[0].h-1);
806 		    if (off > b2[0].a) addr += (b2[1].l-b2[0].h-1);
807 		}
808 		else
809 	/* can't handle yet, but it seems enough for now */
810 		    return -5;
811 		addr = addr*CHsize + seg[i].offset;
812 		fseek(seg[i].fp, addr, 0);
813 		k = (int) fread(array, CHsize, 1, seg[i].fp);
814 		if (bmpshift_dir) {
815 		    if (bmpshift_dir != RMIRROR)
816 			fprintf(errout, "R%d  ", k);
817 		    CharBitmapShift(seg[i].fp, addr, array);
818 		}
819 		return k;
820 	    }
821 	}
822 	insertEOL();
823 	if (!mute) fprintf(errout, "Out of Range Char: %04X\n", ch);
824 	for (j=0; j<CHsize; j++) array[j]=0;
825 	return 0;
826 }
827 
828 
num(char ** v,int n)829 int num(char **v, int n)
830 {
831 	int     m=0;
832 	while (n-- && strlen(v[0])) {
833 		m *= 10;
834 		if (isdigit(*++v[0])) m += (*v[0]-'0');
835 		else {
836 			v[0]--; m /= 10; break;
837 		}
838 	}
839 	return m;
840 }
841 
isstr(char * s,char ** v)842 int isstr(char *s, char **v)
843 {
844 	int     j;
845 	j = strlen(s);
846 	if (j > strlen(v[0])) return 0;
847 	if (strncmp(s, v[0], j)==0) {
848 		v[0] += j-1;
849 		return 1;
850 	}
851 	else if (s[j-1]=='=' && v[0][j-1]=='/') {
852 		if (strncmp(s, v[0], j-1)==0) {
853 			v[0] += j-1;
854 			return 1;
855 		}
856 		else return 0;
857 	}
858 	return 0;
859 }
860 
readstr(char ** v,char * s)861 char *readstr(char **v, char *s)
862 {
863 	v[0]++; sscanf(*v, "%s", s);
864 	v[0] += (strlen(s)-1);
865 	return s;
866 }
867 
readfv(char ** v,char * s)868 float readfv(char **v, char *s)
869 {
870 	float   x;
871 	sscanf(readstr(v, s), "%f", &x);
872 	return x;
873 }
874 
initinputfile(char * cst)875 int initinputfile(char *cst)
876 {
877 	char    *s;
878 #ifdef VMS
879 	char    s2[80], sd[70], s3[40];
880 	int     n, wc=0;
881 	FILE    *tmp;
882 
883 	s = cst;
884 	while (*s!='\0') {
885 	   if (*s=='*' || *s=='?') wc++;
886 	   s++;
887 	}
888 	if (wc) {
889 	    n = strlen(cst);
890 	    while(n--) if (cst[n]==']') break;
891 	    sd[0]='\0';
892 	    if (n>0) {
893 		strcpy(sd, cst); sd[n+1]='\0';
894 	    }
895 	    strcpy(s2, "dir/output=dir.tmp ");
896 	    strcat(s2, cst);
897 	    system (s2);
898 	    tmp=fopen("dir.tmp", "r");
899 	    fgets(s2, 79, tmp);
900 	    while (fgets(s2, 79, tmp)!=NULL) {
901 		if (strncmp(s2, "Directory", 9)==0 || strlen(s2)<=2)
902 			continue;
903 		if (strncmp(s2, "Total of", 8)==0) break;
904 		s2[strlen(s2)-1]='\0';
905 		if (!mute) fprintf(errout, "%s  (Y/N)?", s2);
906 		if (mute || yes(1)) {
907 		    sscanf(s2, "%s", s3);
908 		    strcpy(s2, sd); strcat(s2, s3);
909 		    initinputfile(s2);
910 		}
911 	    }
912 	    system("del dir.tmp;");
913 	    return 1;
914 	}
915 #endif
916 	if (inf->fp == stdin) {
917 		inf->t = (char *) calloc(strlen(cst) + 10, sizeof(char));
918 		if (inf->t == NULL) MemExit();
919 		strcpy(inf->t, cst);
920 	}
921 	if (inf->s != NULL) {
922 inf->p = (struct INfiles *) calloc(1, sizeof(struct INfiles));
923 		if (inf->p == NULL) MemExit();
924 		inf = inf->p;
925 	}
926 	inf->s = (char *) calloc (strlen(cst) + 20, sizeof(char));
927 	if (inf->s == NULL) MemExit();
928 	strcpy(inf->s, cst);
929 	opnfile(IN);
930 	return 1;
931 }
932 
init(int argc,char ** v)933 void init(int argc, char **v)
934 {
935 	char    c, cst[100];
936 	int     m, j=0, ASCfile=0;
937 	float   ptscmd, Cxcmd, Cycmd, Cicmd, Cacmd, Casccmd;
938 	float   rmcmd, lmcmd, tmcmd, bmcmd;
939 	int     columncmd=0, eurocmd=0, fputnpagecmd = -2;
940 	int     papersize=UNKNOWN;
941 
942 	if (argc==RINIT) goto B5INIT;
943 	prntcmd[0]='\0'; EPSHDfile[0]='\0'; KWfile[0]='\0'; tempfile[0]='\0';
944 	*HBFname=0; *defHBFname=0; *PSfile=0; *G2Bfileb=0;
945 	Fonts=NULL;
946 	errout = stderr;
947 
948 	ptscmd=Cxcmd=Cycmd=0.;
949 	Cicmd=Cacmd=Casccmd=0.;
950 	rmcmd=lmcmd=tmcmd=bmcmd=0.;
951 
952 	color.gray = color.red = color.green = color.blue = 0.0;
953 
954 	Rinf = (struct INfiles *) calloc(1, sizeof(struct INfiles));
955 	if (Rinf == NULL) MemExit();
956 	inf = Rinf; inf->fp = stdin;    /* for unix pipeline */
957 
958 	while (--argc>0) if (*(++v)[0] == '-') {
959 	    if (*(v[0]+1)=='\0') stdinput=mute=1;
960 	    while (c = *++v[0]) {
961 		switch (c) {
962 		    case '5': code=B5; big5++; break;
963 		    case 'a':
964 			if (isstr("aa", v)) ASCfile++;
965 			else if (isstr("a3", v)) papersize=A3;
966 			else if (isstr("a4", v)) papersize=A4;
967 			else alnumadjust++;
968 			break;
969 		    case 'b':
970 			if (isstr("b52gb", v)) convcode=B5GB;
971 			else if (isstr("b52hz", v)) convcode=B5HZ;
972 			else if (isstr("b52uni", v)) convcode=B5UNI;
973 			else if (isstr("big5p", v)) code=B5P;
974 			else if (isstr("big5", v)) {
975 			    code=B5; big5++;
976 			}
977 			else if (isstr("bmps", v)) {
978 			    if ((bmpshift=num(v, 2)) > 0) {
979 				argc--; v++; v[0]--;
980 				sscanf(readstr(v, cst), "%x", &bmpshift_ch);
981 				v++;
982 				if (**v == '0') {
983 				    argc--; v[0]--;
984 				    sscanf(readstr(v, cst),
985 					"%x", &bmpshift_ch2);
986 				}
987 				else {
988 				    v--; bmpshift_ch2 = bmpshift_ch;
989 				}
990 			    }
991 			}
992 			else if (isstr("bm=", v)) bmcmd = readfv(v, cst);
993 			else if (isstr("bk", v)) {
994 				booklet = num(v, 1);
995 				if (booklet==0) booklet=2;
996 			}
997 			else if (bmpshift) bmpshift_dir=B;
998 			else {
999 				m=num(v, 3);
1000 				if (*++v[0]=='e') {
1001 					bp=m; ep=num(v, 3);
1002 				}
1003 				else {
1004 					v[0]--; pgcount=m;
1005 				}
1006 			}
1007 			break;
1008 		    case 'c':
1009 			if (isstr("cns", v)) {
1010 			    code=CNS; break;
1011 			}
1012 			else if (isstr("cgap=", v)) cgap = (int) readfv(v, cst);
1013 			else if ((m=num(v, 1)) < 1) break;
1014 			else columncmd=m;
1015 			if ((m=num(v, 2)) >= 10) cgap=m;
1016 			else if (m && m<10) v[0]--;
1017 			break;
1018 		    case 'd':
1019 			adjust=0; Casc=0.5;
1020 			break;
1021 		    case 'e':
1022 			if (isstr("euc", v)) code=EUC;
1023 			else if (isstr("even", v)) odd += 2;
1024 			else if (isstr("extr", v)) convcode=PAGEPRINT;
1025 			else if (isstr("euro", v)) eurocmd++;
1026 			else if (isstr("envs", v)) {
1027 			    envelope = 2;	/* small size */
1028 			    Casccmd = 0.6;
1029 			}
1030 			else if (isstr("env", v)) {
1031 			    envelope = 1;
1032 			    Casccmd = 0.6;
1033 			}
1034 			else if (isstr("epsheader=", v)) {
1035 				strcpy(EPSHDfile, readstr(v, cst));
1036 				IncEPS=1;
1037 			}
1038 			else if (m=num(v, 3)) {
1039 				Casccmd = m/10.;
1040 				if (m>=10) Casccmd /= 10.;
1041 			}
1042 			else {
1043 				isstr("eps", v); 	/* def: eps */
1044 				EPS=1; fputnpage=0; keepPS=1;
1045 				if (isstr("ms", v)) EPS++;
1046 			}
1047 			break;
1048 		    case 'f':
1049 			if (isstr("fpg", v)) breakfile = 1 + num(v, 1);
1050 			else if (isstr("f=", v)) {
1051 			    strcpy(HBFname, readstr(v, cst));
1052 			    cmdlinehbf=1;
1053 			}
1054 			else twoside=1;
1055 			break;
1056 		    case 'g':
1057 			if (isstr("gb2hz", v)) convcode=GBHZ;
1058 			else if (isstr("gb2b5", v)) convcode=GBB5;
1059 			else if (isstr("gb2uni", v)) convcode=GBUNI;
1060 			else if (isstr("gbk", v)) code=GBK;
1061 			else if (isstr("gb", v)) code=GB;
1062 			break;
1063 		    case 'h':
1064 			if (isstr("hz2gb", v)) convcode=HZGB;
1065 			else if (isstr("hz2b5", v)) convcode=HZB5;
1066 			else if (isstr("hz", v)) code=HZ;
1067 			else if ((m=num(v, 2)) > 0) nEF=m;
1068 			else {
1069 				usage(2); exit(0);
1070 			}
1071 			break;
1072 		    case 'i':
1073 			stdinput=mute=1;
1074 			if (isstr("io", v)) stdoutput=1;
1075 			break;
1076 		    case 'j':
1077 			if (isstr("jis8", v)) code=SJIS;
1078 			else if (isstr("jis2uni", v)) convcode=JISUNI;
1079 			else if (isstr("jis", v)) code=JIS;
1080 			else AdjAtEndDoc=0;
1081 			break;
1082 		    case 'k':
1083 			if (isstr("ksc2uni", v)) convcode=KSCUNI;
1084 			else if (isstr("ksc", v)) code=KSC;
1085 			else if (isstr("keeptempfile", v))
1086 				input_file_layer = -99;
1087 			else if ((m=num(v, 3)) > 0) breakfile=m;
1088 			else if (isstr("k=", v))
1089 				strcpy(KWfile, readstr(v, cst));
1090 			else breakfile = 64;
1091 			break;
1092 		    case 'l':
1093 			if (isstr("lm=", v)) lmcmd = readfv(v, cst);
1094 			else if (isstr("letter", v)) papersize=LETTER;
1095 			else if (isstr("legal", v)) papersize=LEGAL;
1096 			else if (isstr("label", v)) {
1097 				if ((m=num(v, 3)) > 0) addrlabel=m;
1098 				else addrlabel=1;
1099 			}
1100 			else if (isstr("level", v)) PSLlevel = num(v, 2);
1101 			else if (bmpshift) bmpshift_dir=L;
1102 			else {
1103 			    landscape = 1+num(v,1);
1104 			    column = 2;
1105 			}
1106 			break;
1107 		    case 'm':
1108 			if (isstr("mfeed", v)) manualfeed = (manualfeed)? 0:1;
1109 			else if (isstr("mimeqp", v)) convcode=MIMEQP;
1110 			else {
1111 				m=num(v,3);
1112 				if (!m) mute = (mute)? 0:1;
1113 				else copies=m;
1114 			}
1115 			break;
1116 		    case 'n':
1117 			m=num(v, 4);
1118 			if (m) nHzline=m;
1119 			else if (isstr("nopage", v)) fputnpagecmd=0;
1120 			else if (isstr("n=", v)) {
1121 				m=num(v, 4);
1122 				if ( m>=0 && m<=6000) nCN=m;
1123 			}
1124 			break;
1125 		    case 'o':
1126 			if (isstr("o=", v)) {
1127 				strcpy(PSfile, readstr(v, cst));
1128 				keepPS++;
1129 			}
1130 			else if (isstr("out", v)) stdoutput++;
1131 			else if (isstr("odd", v)) odd++;
1132 			else odd++;
1133 			break;
1134 		    case 'p':
1135 			if (isstr("print", v)) {
1136 				convt_and_print=1; break;
1137 			}
1138 			pausqm=4;
1139 			if (m=num(v,1)) pausqm=m;
1140 			break;
1141 		    case 'q':
1142 			if (isstr("q=", v))
1143 				strcpy(prntcmd, readstr(v, cst));
1144 			break;
1145 		    case 'r':
1146 			if (isstr("rm=", v)) rmcmd = readfv(v, cst);
1147 			else if ( (m=num(v, 1)) == 5) {
1148 				bmpshift_dir = RMIRROR; v[0]--;
1149 			}
1150 			else if (m) { convcode=FILT; fix=m;}
1151 			else if (!isstr("r=", v))
1152 				bmpshift_dir = (bmpshift)? R : RMIRROR;
1153 			else if ( (m=num(v, 4)) > 30) ppd=72./m;
1154 			break;
1155 		    case 's':
1156 			if (isstr("size=", v)) ptscmd = readfv(v, cst);
1157 			else if (isstr("short", v)) convcode=TOSHORTPS;
1158 			else suppress = (num(v, 1) > 1)? 2:1; break;
1159 		    case 't':
1160 			if (isstr("tab", v)) tabascii++;
1161 			else if (isstr("tm=", v)) tmcmd = readfv(v, cst);
1162 			else if (bmpshift) bmpshift_dir=T;
1163 			else {
1164 				timestat++;
1165 				if (fix && isalnum(*(v[0]+1)))
1166 					newshd = *++v[0];
1167 			}
1168 			break;
1169 		    case 'v':
1170 			if (isstr("vgap=", v)) vgap = (int) readfv(v, cst);
1171 			else {
1172 				vertical++; Rotate=1; /*adjust=0;*/ fputnpage=4;
1173 			}
1174 			break;
1175 		    case 'w': fprntfile=0; break;
1176 		    case 'x': case 'y':
1177 			if (m=num(v, 1)) {
1178 				if (c=='x') Cxcmd += (m/10.);
1179 				else Cycmd += (m/10.);
1180 			}
1181 			break;
1182 		    case 'z':
1183 			if (isstr("zw", v)) code=ZW;
1184 			else convcode++;
1185 			break;
1186 		    case 'u':
1187 			if (isstr("utf8", v)) code=UTF8;
1188 			else if (isstr("utf7", v)) code=UTF7;
1189 			else if (isstr("utf16le", v)) code=UTF16;
1190 			else if (isstr("utf16", v)) code=UTF;
1191 			else if (isstr("utf", v)) code=UTF;
1192 			else if (isstr("uni2gb", v)) convcode=UNIGB;
1193 			else if (isstr("uni2b5", v)) convcode=UNIB5;
1194 			else if (isstr("uni2ksc", v)) convcode=UNIKSC;
1195 			else if (isstr("uni2jis", v)) convcode=UNIJIS;
1196 			else {
1197 				mute=1; errout=fopen("log.1", "w");
1198 			}
1199 			break;
1200 		    default:
1201 			fprintf(stderr, "Problem option: -%c\n", c);
1202 			usage(11); exit(0); break;
1203 		}
1204 	    }
1205 	}
1206 	else if (argc!=RINIT) initinputfile(*v);
1207 /* end while-if */
1208 
1209 	getroot();
1210 /* get default code type, ppd, tempfile */
1211 	if (getdata(4)==0) defcode=GB;
1212 	if (ppd<0.) ppd=.24;
1213 	if (strlen(tempfile)<2) strcpy(tempfile, "CNPRINT.TMP");
1214 #ifdef MUSER
1215     /* use pid instead of time */
1216 	sprintf(cst, "%d", (int) getpid());
1217 	strcat(tempfile, cst);
1218 #endif
1219 
1220 	if (Rinf->fp == stdin && !bmpshift) {
1221 #ifdef VMS
1222 	    usage(0); exit(1);
1223 #else
1224 	    if (stdinput) {
1225 		/*fprintf(errout, "CNPRINT: use standard input\n");*/
1226 # ifdef MUSER
1227 		sprintf(cst, "/tmp/cnpstdin%d", (int) getpid());
1228 # else
1229 		strcpy(cst, "cnpstdin.tmp");
1230 # endif
1231 		opnfile(OUT);
1232 		while ( (c=fgetc(stdin)) != EOF) fputc(c, out);
1233 		fclose(out); out=NULL;
1234 		RE_name(tempfile, cst);
1235 		initinputfile(cst);
1236 	    }
1237 	    else {
1238 		usage(0); exit(1);
1239 	    }
1240 #endif
1241 	}
1242 
1243 	opnfile(OUT);
1244 	if (!mute) fprintf(errout, "%s\n\n", Version);
1245 /* prepare for multiple output */
1246 	codecmd=code;
1247 	convcodecmd=convcode;
1248 
1249 B5INIT: if (argc==RINIT) {
1250 		lcode=UNKNOWN;
1251 		UnRegisterFont(Fonts);
1252 		HBFclose();
1253 		Fonts=NULL;
1254 		/*fstring=NULL; ptstring=NULL;*/
1255 		if (!cmdlinehbf) *HBFname=0;
1256 	}
1257 	if (code>=ZW && code<=GB) lcode=GB;
1258 	else if (code==B5 || code==CNS) lcode=B5;
1259 	else if (code>=JIS && code<=EUC) lcode=JIS;
1260 	else if (code>=UTF && code<=UTF16) lcode=UTF;
1261 	else if (code==KSC || code==GBK || code==B5P) lcode=code;
1262 	else lcode=defcode;
1263 	/* else use default */
1264 	if ( (convcode==GBB5 || convcode==B5GB || convcode==HZB5)
1265 			&& convt_and_print)
1266 		lcode=code= (convcode==B5GB)? GB:B5;
1267 	if (vertical>1 && lcode==GB) vertical=vgb=1;
1268 
1269 	if (*HBFname==0) getdata(2);
1270 	if (*HBFname==0) {
1271 	    if (lcode!=GB) {
1272 		fprintf(stderr,
1273 "No HBF file specified for %s in either cnprint.cmd or command line\n\
1274 Please read Part IV of the help file\n\
1275 on how to specify font file for %s documents.\n",
1276 			codename[lcode], codename[lcode]);
1277 		bell(); exit(7);
1278 	    }
1279 	    else strcpy(HBFname, "cnj24.hbf");
1280 	}
1281 	j=strlen(HBFname);
1282 	if ((j==3 || j==4) && isdigit(HBFname[1]) && isdigit(HBFname[2])) {
1283 			/* if j24, k256 or alike, construct HBFname */
1284 		strcpy(cst, HBFname);
1285 		strcat(cst, ".hbf");
1286 		construct_fontname(cst);
1287 	}
1288 	strcpy(defHBFname, HBFname);
1289 
1290 	if (convcode==GBHZ || convcode==B5HZ) return;
1291 	else if (convcode==UNIGB || convcode==UNIB5
1292 		|| convcode==UNIKSC || convcode==UNIJIS) return;
1293 	else if (convcode==GBUNI || convcode==B5UNI
1294 			|| convcode==KSCUNI || convcode==JISUNI) {
1295 		if (code==defcode && code!=UTF) code=UTF;
1296 		return;
1297 	}
1298 	else if ((convcode==GBB5 || convcode==B5GB || convcode==HZB5)
1299 		&& !convt_and_print) return;
1300 	if (!HBFopen()) exit(0);
1301 /*      if (lcode==KSC) adjust=0;   */
1302 	if (argc==RINIT || bmpshift) return;
1303 
1304 	if (papersize != UNKNOWN)
1305 	    switch (papersize) {
1306 		case LETTER:    XX=8.5; YY=11.; break;
1307 		case LEGAL:     XX=8.5; YY=13.5; break;
1308 		case A3:        XX=11.69; YY=16.54; break;
1309 		case A4:        XX=8.27; YY=11.69; break;
1310 		default: break;
1311 	    }
1312 
1313 	if (!getdata(3)) {
1314 		XX=8.5; YY=11.;
1315 		pts = ((landscape)? 11.6 : 13.6)/(Cx+Cy-1);
1316 		Ca=1.;
1317 		Ci=Cy+(Cx-1.)/2.;
1318 		LM=261; RM=219; TM=252; BM=275; /* mm*10 */
1319 		if (landscape) {
1320 			LM=153; RM=152; TM=200; BM=220;
1321 		}
1322 	}
1323 	if (prntcmd[0]=='\0') fprntfile=0;
1324 	if (booklet) {
1325 		column = booklet; LM=RM=100;
1326 		landscape = 1;
1327 	}
1328 	if (landscape>1) {
1329 		LM=153; RM=152; TM=200; BM=220;
1330 		switch (landscape) {
1331 		    case 2: Cy=1.2; Ci=1.1; pts=11.6; break;
1332 		    case 3: pts=11.6; break;
1333 		    case 4: Cy=1.2; Ci=1.1; pts=11.3; break;
1334 		    case 5: pts=11.3; break;
1335 		    default: break;
1336 		}
1337 	}
1338 	if (ASCfile) {
1339 		Ci=0.5; Casc=0.6;
1340 		TM=180; BM=180; /* mm*10 */
1341 		LM-=20;
1342 		tabascii = (tabascii)? 0:1;
1343 	}
1344 
1345 	ascbuf.p=ascbuf.pp=0;
1346 /* command line values have top priority */
1347 	if (envelope) {
1348 		landscape=1;
1349 		TM=(XX>8.4)? 700 : 640; BM = TM - 40;
1350 		RM=120; LM=(YY>11.2)? 823 : 648;
1351 		if (envelope==2) LM += 750;
1352 		fputnpage=0;
1353 		manualfeed++;
1354 		Ci=.5; Casc=.6;
1355 		if (nEF<0) nEF=3;
1356 	}
1357 	if (addrlabel) {
1358 		LM=RM=TM=BM=25;		/* 2.54 mm, 0.1 inch */
1359 		fputnpage=0;
1360 		manualfeed++;
1361 		Ci=.5; Casc=.6;
1362 		if (nEF<0) nEF=3;
1363 		column=lbnx;
1364 	}
1365 	if (columncmd>0) column=columncmd;
1366 	if (Cxcmd>0.01) Cx=Cxcmd; if (Cycmd>0.01) Cy=Cycmd;
1367 	if (Cicmd>0.01) Ci=Cicmd; if (Cacmd>0.001) Ca=Cacmd;
1368 	if (rmcmd>0.01) RM=(int)(rmcmd*10);
1369 	if (lmcmd>0.01) LM=(int)(lmcmd*10);
1370 	if (tmcmd>0.01) TM=(int)(tmcmd*10);
1371 	if (bmcmd>0.01) BM=(int)(bmcmd*10);
1372 	if (Casccmd>0.01) Casc=Casccmd;
1373 	if (ptscmd>1.) pts=ptscmd;
1374 	if (eurocmd) euro = (euro>=0)? -1 : 1;
1375 	if (fputnpagecmd >= 0) fputnpage=fputnpagecmd;
1376 
1377 	if (nEF<0) nEF=2; /* def: Courier */
1378 
1379 	if (!getEfontlist()) {
1380 		EFontnames = EFname;
1381 		EFmetricfiles = NULL;
1382 	}
1383 	nEFs = (int *) calloc(nEFmax+1, sizeof(int));
1384 	if (nEFs == NULL) MemExit();
1385 	getEfontdata(1); /* make it the last one */
1386 }
1387 
construct_fontname(char * str)1388 void construct_fontname(char *str)
1389 {
1390 	if (lcode==UTF) sprintf(HBFname, "cnu%s", str);
1391 	else if (lcode==GBK) sprintf(HBFname, "cng%s", str);
1392 	else if (lcode==B5P) sprintf(HBFname, "cnp%s", str);
1393 	else sprintf(HBFname, "cn%s%s",
1394 ((lcode==B5)? "5" : ((lcode==JIS) ? "j" : ( (lcode==KSC)? "k" : ""))), str);
1395 }
1396 
RegisterFont()1397 void RegisterFont()
1398 {
1399 	struct FontTag *F;
1400 	int	j, k;
1401 
1402 	CurrentFont = NULL;
1403 	if (Fonts!=NULL) {
1404 	    for (F = Fonts; F != NULL; F = F->p) {
1405 		if (strcmp(HBFname, F->FontName) == EQ) {
1406 			CurrentFont = F; break;
1407 		}
1408 		else if (F->p==NULL) break;
1409 	    }
1410 	}
1411 	if (CurrentFont != NULL) {	/* not a new font */
1412 		if (PreScanMode) {
1413 		/* copy lcode related properties, but not needed for now */
1414 			;
1415 		}
1416 		fstring = CurrentFont->fstring;
1417 		ptstring = CurrentFont->ptstring;
1418 		mx = CurrentFont->mx;
1419 		my = CurrentFont->my;
1420 		ttf_font = CurrentFont->ttf_font;
1421 		return;
1422 	}
1423 
1424 /* new font */
1425 	CurrentFont = (struct FontTag *) calloc(1, sizeof(struct FontTag));
1426 	if (CurrentFont == NULL) MemExit();
1427 	CurrentFont->p = NULL;
1428 
1429 	if (Fonts==NULL) {
1430 		Fonts = CurrentFont;
1431 		CurrentFont->FontID = 1;
1432 	}
1433 	else { /* add to the chain: F is the last one on the chain */
1434 		F->p = CurrentFont;
1435 		CurrentFont->FontID = F->FontID + 1;
1436 	}
1437 	F = CurrentFont;
1438 	strcpy(F->FontName, HBFname);
1439 	F->mx = mx; F->my = my;
1440 	F->ttf_font = ttf_font;
1441 
1442 	switch (lcode) {
1443 	    case UTF:
1444 		cspace = 0x3000;
1445 		b2span = 256;
1446 		b2gap = 0;
1447 	/* b1l should be 0x01 or 0x00, not 0x30 */
1448 		b1l=0x00; b2l=0x00; b2h_range1=0xFF;
1449 		nchar = (unsigned int) 61440; /* 240*256 */
1450 		break;
1451 	    case B5:
1452 		cspace = 0xA140;
1453 		b2span = 157;
1454 		b2gap = 34;
1455 		b1l=0xA1; b2l=0x40; b2h_range1=0x7E;
1456 		nchar = 13973; /* (63+94)*89 */
1457 		break;
1458 	    case GBK: case B5P:
1459 		cspace = (lcode==GBK)? 0xA1A1 : 0xA140;
1460 		b2span = 190;
1461 		b2gap = 1;
1462 		b1l=0x81; b2l=0x40; b2h_range1=0x7E;
1463 		nchar = 23940;
1464 		break;
1465 	    default:   /* GB, KSC, JIS */
1466 		cspace = 0xA1A1;
1467 		b2span = 94;
1468 		b2gap = 0;
1469 		b1l=0xA1; b2l=0xA1; b2h_range1=0xFE;
1470 		nchar = (lcode==GB)? 8178 : 7876; /* 94*87 or 94*84 */
1471 		break;
1472 	}
1473 
1474 	k=0;
1475 	if (!ttf_font) {
1476 		for (j=0; j<nb2; j++) k += b2[j].a;
1477 		k *= (seg[nseg-1].h/256 - seg[0].l/256 + 1);
1478 	}
1479 	if (nchar < k) nchar = k;
1480 
1481 	fstring = (unsigned int *) calloc(nchar + 1, sizeof(unsigned int));
1482 	ptstring = (unsigned char **)calloc(nchar + 1, sizeof(unsigned char *));
1483 	if (fstring==NULL || ptstring==NULL) MemExit();
1484 
1485 	F->nchar = nchar;
1486 	F->lcode = lcode;
1487 	F->cspace = cspace;
1488 	F->b1l = b1l;
1489 	F->b2l = b2l;
1490 	F->b2h_range1 = b2h_range1;
1491 	F->b2gap = b2gap;
1492 	F->b2span = b2span;
1493 	F->fstring = fstring;
1494 	F->ptstring = ptstring;
1495 
1496 
1497 }
1498 
UnRegisterFont(struct FontTag * F)1499 void UnRegisterFont(struct FontTag *F)
1500 {
1501 	int	j;
1502 
1503 	if (F==NULL) return ;
1504 
1505 	UnRegisterFont(F->p);
1506 	if (F->fdict != NULL) free(F->fdict);
1507 	if (F->fstring != NULL) free(F->fstring);
1508 	if (F->ptstring != NULL) {
1509 	    if (F->nchar > 0)
1510 		for (j=0; j < F->nchar; j++)
1511 		    if (F->ptstring[j] != NULL && F->ptstring[j] != dummy)
1512 			free(F->ptstring[j]);
1513 	    free(F->ptstring);
1514 	}
1515 	free(F);
1516 }
1517 
getdata(int n)1518 int getdata(int n)
1519 {
1520 	char    t[100], str[20], *s;
1521 	int     j, k, m[10];
1522 	float   x1, x2, x3, x4;
1523 	FILE    *cmd;
1524 
1525 	if ((cmd=Rfopen("cnprint.cmd", "r"))==NULL) {
1526 		if (n>0) fprintf(errout,
1527 "Can't open file cnprint.cmd\n\
1528 Please check if it exists or if the path is correct\n\
1529 and/or read the help file for information on cnprint.cmd\n");
1530 		return 0;
1531 	}
1532 	switch(n) {
1533 	    case 1:     /* get metric data for ASCII fonts */
1534 		if (strlen(EFontnames[nEF])<=2) return 0;
1535 		while (fgets(t, 98, cmd)!=NULL) {
1536 		    if (strncmp(EFontnames[nEF], t, strlen(EFontnames[nEF]))==0)
1537 			break;
1538 		}
1539 		k=0;
1540 		while (fgets(t, 98, cmd)!=NULL) {
1541 		    if (!strncmp(t, "DATA", 4)) {
1542 			sscanf(t, "%*s%d%d%d%d%d%d%d%d%d%d",
1543 			    &m[0], &m[1], &m[2], &m[3], &m[4], &m[5],
1544 			    &m[6], &m[7], &m[8], &m[9]);
1545 			j=0;
1546 			while(k<129) {
1547 				Wasc[k++]=m[j++]/10000.;
1548 				if (j==10) break;
1549 			}
1550 		    }
1551 		    if (k>=129) break;
1552 		}
1553 		if (k<129) {
1554 		    fclose(cmd); return 0;
1555 		}
1556 		break;
1557 	    case 2:     /* Default BIG5/JIS/KSC fonts */
1558 		if (lcode==B5P) strcpy(str, "BIG5PLUS_FONT");
1559 		else if (lcode==GBK) strcpy(str, "GBK_FONT");
1560 		else strcpy(str, (lcode==B5)? "BIG5FONT" :
1561 			((lcode==JIS)? "JIS_FONT" :
1562 			((lcode==KSC)? "KSC_FONT" :
1563 			((lcode==UTF)? "UTF_FONT" : "GB_FONT"))));
1564 		while(fgets(t, 98, cmd)!=NULL) {
1565 		    if (strncmp(t, "DEFAULT_", 8)) continue;
1566 		    if (strncmp((t+8), str, strlen(str)) != EQ) continue;
1567 		    sscanf(t, "%*s%s", HBFname);
1568 		    break;
1569 		}
1570 		break;
1571 	    case 3:     /* PS print command, paper size, margins, etc */
1572 		x1=x2=0.;
1573 		if (XX < 1.0) {
1574 		    while(fgets(t, 98, cmd)!=NULL) {
1575 			if (strncmp(t, "DEFAULT_PAPERSIZE", 17)) continue;
1576 			sscanf(t, "%*s%f%f", &x1, &x2);
1577 			break;
1578 		    }
1579 		    if (x1<1. || x2<1.) {XX=8.5; YY=11.;}
1580 		    else {XX=x1; YY=x2;}
1581 		    rewind(cmd);
1582 		}
1583 
1584 		if (fprntfile) while(fgets(t, 98, cmd)!=NULL) {
1585 		    if (strncmp(t, "PS_PRINT_COMMAND", 16)) continue;
1586 		    s = &t[j=17];
1587 		    while(s[0]==' ') s = &t[++j];
1588 		    j=0;
1589 		    while(s[j]) if (s[j++]==EOL) s[j-1] = '\0';
1590 		    if (!strlen(prntcmd)) strcpy(prntcmd, s);
1591 		    break;
1592 		}
1593 		rewind(cmd);
1594 
1595 		while(fgets(t, 98, cmd)!=NULL) {
1596 		    if (strncmp(t, "POSTSCRIPT_LANGUAGE_LEVEL", 25)) continue;
1597 		    if (sscanf(t, "%*s%d", &k) == 1) {
1598 			if (k>=1 && k<=30) PSLlevel=k;
1599 		    }
1600 		    break;
1601 		}
1602 		rewind(cmd);
1603 
1604 		x1=x2=x3=x4=0.;
1605 		while(fgets(t, 98, cmd)!=NULL) {
1606 		    if (strncmp(t, "PAPER_MARGINS", 13)) continue;
1607 			/* margin: R L T B */
1608 		    if (!landscape)
1609 			sscanf(t, "%*s%f%f%f%f", &x1, &x2, &x3, &x4);
1610 		    else sscanf(t,
1611 			"%*s%*f%*f%*f%*f%f%f%f%f", &x1, &x2, &x3, &x4);
1612 		    break;
1613 		}
1614 		if (x1<2.9 || x2<2.9 || x3<2.9 || x4<2.9) {
1615 		    LM=261; RM=219; TM=252; BM=275; /* mm*10 */
1616 		    if (landscape) {
1617 			LM=153; RM=152; TM=200; BM=220;
1618 		    }
1619 		}
1620 		else {
1621 			LM = (int) (x1*10);
1622 			RM = (int) (x2*10);
1623 			TM = (int) (x3*10);
1624 			BM = (int) (x4*10);
1625 		}
1626 		rewind(cmd);
1627 
1628 		x1=x2=x3=x4=0.;
1629 		while(fgets(t, 98, cmd)!=NULL) {
1630 		    if (strncmp(t, "SIZE_SPACE", 10)) continue;
1631 			/* Ppts, Lpts, char & line space */
1632 		    sscanf(t, "%*s%f%f%f%f", &x1, &x2, &x3, &x4);
1633 		    break;
1634 		}
1635 		if (x1<2. || x2<2. || x3<.01 || x4<.01) {
1636 		    pts = ((landscape)? 11.6 : 13.6)/(Cx+Cy-1);
1637 		    Ca=1.;
1638 		    Ci=Cy+(Cx-1.)/2.;
1639 		}
1640 		else {
1641 		    pts = (landscape)? x2 : x1;
1642 		    Ca=x3;
1643 		    Ci = (x4>.99 && x4<1.01)? (Cy+(Cx-1.)/2.) : x4;
1644 		}
1645 		rewind(cmd);
1646 
1647 		x1=x2=0.;
1648 		while(fgets(t, 98, cmd)!=NULL) {
1649 		    if (strncmp(t, "WIDTH-HEIGHT", 12)) continue;
1650 			/* Cx, Cy */
1651 		    sscanf(t, "%*s%f%f", &x1, &x2);
1652 		    break;
1653 		}
1654 		if (x1>=1.0) Cx=x1;
1655 		if (x2>=1.0) Cy=x2;
1656 		if (Cx>1.01 && Cy>1.01) Cy=1.;
1657 		rewind(cmd);
1658 		x1 = .5;  /* default: euro = 0 (auto detect) */
1659 		while(fgets(t, 98, cmd)!=NULL) {
1660 		    if (strncmp(t, "EUROPEAN-LANGUAGE", 17)) continue;
1661 		    sscanf(t, "%*s%f", &x1);
1662 		    break;
1663 		}
1664 		if (x1 < -.2) euro = -1;        /* disable auto detect */
1665 		else if (x1 > .8) euro = 1;
1666 		rewind(cmd);
1667 
1668 		k = -1; /* default page number position: H, V */
1669 		while(fgets(t, 98, cmd)!=NULL) {
1670 		    if (strncmp(t, "PAGE_NUMBER_POSITION", 20)) continue;
1671 		    sscanf(t, (vertical)? "%*s%*s%d":"%*s%d", &k);
1672 		    if (k>=0 && k<=6) fputnpage=k;
1673 		    break;
1674 		}
1675 		rewind(cmd);
1676 
1677 		/* address label data */
1678 		while(fgets(t, 98, cmd)!=NULL) {
1679 		    if (strncmp(t, "ADDRESS_LABEL", 13) != EQ) continue;
1680 		    sscanf(t, "%*s%d%d %f%f%f%f %d",
1681 			&j, &k, &x1, &x2, &x3, &x4, &lb_eat_EOL);
1682 		    lbnx=j; lbny=k;
1683 		    lbxp=x1; lbyp=x2;
1684 		    lbxinc=x3; lbyinc=x4;
1685 		    break;
1686 		}
1687 		break;
1688 	    case 4:     /* default encoding, tempfile & device res */
1689 		while(fgets(t, 98, cmd)!=NULL) {
1690 			if (strncmp(t, "DEFAULT_ENCODING", 16)) continue;
1691 			sscanf(t, "%*s%s", tempfile);
1692 			break;
1693 		}
1694 		if (strncmp(tempfile, "JIS", 3)==0) defcode=JIS;
1695 		else if (strncmp(tempfile, "KSC", 3)==0) defcode=KSC;
1696 		else if (strncmp(tempfile, "BIG5P", 5)==0) defcode=B5P;
1697 		else if (strncmp(tempfile, "BIG5", 4)==0) defcode=B5;
1698 		else if (strncmp(tempfile, "GBK", 3)==0) defcode=GBK;
1699 		else if (strncmp(tempfile, "UNICODE", 7)==0) {
1700 			defcode=UTF; lcode=UTF;
1701 		}
1702 		else defcode=GB;
1703 		if (code==UNKNOWN) lcode=defcode;
1704 		tempfile[0]='\0';
1705 		rewind(cmd);
1706 
1707 		while(fgets(t, 98, cmd)!=NULL) {
1708 		    if (strncmp(t, "TEMPFILE", 8)) continue;
1709 		    sscanf(t, "%*s%s", tempfile);
1710 		    break;
1711 		}
1712 		rewind(cmd);
1713 		x1=0.;
1714 		while(fgets(t, 98, cmd)!=NULL) {
1715 		    if (strncmp(t, "DEVICERES", 9)) continue;
1716 		    sscanf(t, "%*s%f", &x1);
1717 		    if (x1>30. && ppd<0.) ppd=72./x1;
1718 		    break;
1719 		}
1720 		break;
1721 	    case 5:     /* default GB<->B5 table file */
1722 		while(fgets(t, 98, cmd)!=NULL) {
1723 			if (strncmp(t, "DEFAULT_GBB5_TABLEFILE", 22))
1724 				continue;
1725 			sscanf(t, "%*s%s%s", KWfile, G2Bfileb);
1726 			break;
1727 		}
1728 		break;
1729 	    default: break;
1730 	}
1731 	fclose(cmd);
1732 	return 1;
1733 }
1734 
opnfile(int n)1735 void opnfile(int n)
1736 {
1737 	if (n==IN) {
1738 		if ((inf->fp = fopen(inf->s, "r")) == NULL) {
1739 		    insertEOL();
1740 		    fprintf(errout, "Can't open input file -> %s\n", inf->s);
1741 		    bell(); exit (-3);
1742 		}
1743 	}
1744 	else if ((out=fopen(tempfile, "w"))==NULL) {
1745 		insertEOL();
1746 		fprintf(errout, "Can't open output file\n");
1747 		bell(); exit (-4);
1748 	}
1749 }
1750 
style(int menu)1751 void style(int menu)
1752 {
1753     int     a, b, j, k;
1754     float   lm, rm, tm, bm, x, pr, pb, os=0., gap;
1755     float   Ck;     /* ~~~ mm/dot ~~~ */
1756     char    s[100], cst[100];
1757     static char *npagepos[]={"No Page Number", "Upper Left", "Upper Middle",
1758 	    "Upper Right", "Lower Left", "Lower Middle", "Lower Right"};
1759 
1760     Ck = ppd*25.4/72;  /* mm/dot */
1761     Xw = (int) (XX*72/ppd);
1762     Yh = (int) (YY*72/ppd);
1763     pr = (int) (Xw*Ck);
1764     pb = (int) (Yh*Ck);
1765     if (landscape) {
1766 	x=pr; pr=pb; pb=x;
1767     }
1768     lm = LM/10.; rm = RM/10.;  /* mm*10 --> mm */
1769     tm = TM/10.; bm = BM/10.;
1770     gap = (cgap)? cgap : 2.5*Cw*pts;
1771     gap *= 25.4/72;     /* pts --> mm */
1772 
1773     if (menu) do {
1774 	charsize(pts);
1775 	if (booklet) rm=lm=(rm+lm)/2.;
1776 	if (fputnpage) fprintf(errout,
1777 "    N: Page Numbering.    %s.   Starting page number: %d\n",
1778 		npagepos[fputnpage], pgcount);
1779 	else fprintf(errout,
1780 "    N: Page Numbering.          No.\n");
1781 	x = (Cx>Cy)? Cx : 1./Cy;
1782 	fprintf(errout,
1783 "    X: Character Width/Height. %5.2f (Y: H/W. %5.2f)\n", x, 1./x);
1784 	fprintf(errout,
1785 "    L: Left Margin.   %6.1f mm    S: Character Size. %6.2f mm (%4.1f pts)\n\
1786     R: Right Margin.  %6.1f mm    A: Character Space.%6.2f (1=standard)\n\
1787     T: Top Margin.    %6.1f mm    I: Line Space.     %6.2f (1=standard)\n\
1788     B: Bottom Margin. %6.1f mm    H: English Font.     %s.\n",
1789 		lm, CSP*Ck, pts, rm, Ca, tm, Ci, bm, EFontnames[nEF]);
1790 	fprintf(errout,
1791 "    F: Two-Sided.        %s.\t   U: Envelope.         %s.\n",
1792 		((twoside)? "Yes" : "No"), (envelope ? "Yes" : "No"));
1793 	fprintf(errout,
1794 "    V: Vertical Mode.    %s.\t   E: EPS Output.       %s.\n",
1795 		(vertical ? "Yes" : "No"), (EPS ? "Yes" : "No"));
1796 	fprintf(errout,
1797 "    C: Page Column(s).   %d \t   D: EPS Page Header.  %s.\n",
1798 		column, strlen(EPSHDfile)? EPSHDfile : "None");
1799 	fprintf(errout,
1800 "    M: Manual Feed.      %s.\t   O: Orientation.      %s.\n",
1801 	    (manualfeed ? "Yes":"No"), (landscape ? "Landscape":"Portrait"));
1802 	fprintf(errout,
1803 "    P: Print PS file.    %s.\t   Q: Quit.\n\n", (fprntfile ? "Yes":"No"));
1804 	/*a = 10.*(pb-bm-tm + (1-Cw)*CLP*Ck)/(CLP*Ck);*/
1805 	a = (int) (10.*(pb-bm-tm + (CLP-CIP)*Ck)/(CLP*Ck));
1806 	if (booklet) b = (int) (10.*(pr-rm*(column+2))/(CSP*Ck)/column);
1807 	else {
1808 		b = (int) (10.*(pr-rm-lm-gap*(column-1)) / (CSP*Ck)/column);
1809 	}
1810 	fprintf(errout,
1811 " There are about %g lines in a page and %g words in a line\n\n\
1812 \tN, P, S, A, I, L, R, T, B, H, E, F, ..., Q\n\n\
1813  Type one of the above to change, or press RETURN key to continue\n",
1814 a/10.0, b/10.0);
1815 	gets_stdin(cst, 99);
1816 /*fprintf(stderr, "cst = :%s:\n", cst);*/
1817 	if (cst[0] != '\0') switch (toupper(cst[0])) {
1818 	    case 'X':
1819 		x = (Cx>Cy)? Cx : 1./Cy;
1820 		fprintf(errout,
1821 "\tX: Character Width/Height.    Current:   %5.2f\n", x);
1822 		Cx=getnew(Cx, 5); Cy=1.;
1823 		break;
1824 	    case 'Y':
1825 		x = (Cx>Cy)? Cx : 1./Cy;
1826 		fprintf(errout,
1827 "\tY: Character Height/Width.    Current:   %5.2f\n", 1./x);
1828 		Cy=getnew(Cy, 5); Cx=1.;
1829 		break;
1830 	    case 'V':
1831 		vertical = (vertical)? 0 : 1;
1832 		if (fputnpage) fputnpage = (vertical)? 4:6;
1833 		break;
1834 	    case 'C':
1835 		fprintf(errout,
1836 "\tC: Page Column(s).    Current:   %d\n", column);
1837 		column = (int) getnew(column+0.1, 4);
1838 		break;
1839 	    case 'E':
1840 		EPS = (EPS)? 0 : 1;
1841 		break;
1842 	    case 'M':
1843 		manualfeed = (manualfeed)? 0 : 1;
1844 		break;
1845 	    case 'O':
1846 		landscape=(landscape)? 0:1;
1847 		x=pr; pr=pb; pb=x;
1848 		break;
1849 	    case 'U':
1850 		envelope=1;
1851 		if (!landscape) {
1852 			landscape=1;
1853 			x=pr; pr=pb; pb=x;
1854 		}
1855 		fputnpage=0;
1856 		bm=tm=(XX>8.4)? 70. : 64.;
1857 		rm=25.4; lm=(YY>11.2)? 82.3 : 64.8;
1858 		break;
1859 	    case 'F':
1860 		twoside=(twoside)? 0:1;
1861 		break;
1862 	    case 'D':
1863 		fprintf(errout,
1864 "Please enter full name of the EPS file to be used as page header:\n");
1865 		gets_stdin(EPSHDfile, 79);
1866 		fprintf(errout,
1867 "Page header on the first page (Y/N)?\n");
1868 		gets_stdin(s, 99);
1869 		if (toupper(s[0]) != 'N') IncEPS=1;
1870 		break;
1871 	    case 'N':
1872 		if (fputnpage) fprintf(errout,
1873 "\tN: Page Numbering.  Current:  %s.  Starting page number: %d\n",
1874 			npagepos[fputnpage], pgcount);
1875 		else fprintf(errout,
1876 "\tN: Page Numbering.  Current:   No.\n");
1877 		fprintf(errout,
1878 "\nEnter any number to change/select starting page number,\n\
1879 \tN: no page numbering\n\tP: change page number position\n\
1880 or press RETURN to continue\n");
1881 		gets_stdin(s, 99);
1882 		switch (toupper(s[0])) {
1883 		    case 'N': fputnpage=0; break;
1884 		    case 'P':
1885 			for (j=0; j<7; j++)
1886 			    fprintf(errout, "\t%d:  %s\n", j, npagepos[j]);
1887 			fprintf(errout,
1888 "Please select one, or press RETURN to continue\n");
1889 			gets_stdin(s, 99);
1890 			if (isdigit(s[0]) && s[0] <= '6')
1891 				fputnpage = s[0]-'0';
1892 			break;
1893 		    case '\0': break;
1894 		    default:
1895 			if (toupper(s[0])!='Y') sscanf(s,"%d", &a);
1896 			else a=pgcount;
1897 			if (bp && a>bp) {
1898 			    fprintf(errout,
1899 "Input greater than %d, the page to begin printing, OK?!\n", bp);
1900 			    bell(); gets_stdin(s, 99);
1901 			}
1902 			else {
1903 			    pgcount=a;
1904 			    if (!fputnpage) fputnpage = (vertical)? 4:6;
1905 			}
1906 			break;
1907 		}
1908 		break;
1909 	    case 'P':
1910 		fprntfile=(fprntfile)? 0:1;
1911 		if (fprntfile && strlen(prntcmd)<=2) {
1912 			fprintf(errout,
1913 "Print command invalid/not found, please enter new one:\n");
1914 			bell(); gets_stdin(s, 99);
1915 			sscanf(s, "%s", prntcmd);
1916 			if (strlen(prntcmd)<=2) fprntfile=0;
1917 		}
1918 		break;
1919 	    case 'S':
1920 		fprintf(errout,
1921 "\tCharacter Size. Current: %7.2f mm (%4.1f pts)\n\
1922 \t\t****** 1 pts = 3.556 mm ******\n", CSP*Ck, pts);
1923 		pts=getnew(pts,0);
1924 		break;
1925 	    case 'A':
1926 		fprintf(errout,
1927 "Standard is 8%% of the size of a Chinese character\n\
1928 \tA: Character Space. Current: %7.3f (1=standard)\n", Ca);
1929 		Ca=getnew(Ca,2);
1930 		break;
1931 	    case 'I':
1932 		fprintf(errout,
1933 "Standard is 50%% of the size of a Chinese character\n\
1934 \tI: Line Space.      Current: %7.3f (1=standard)\n", Ci);
1935 		Ci=getnew(Ci,2);
1936 		break;
1937 	    case 'L':
1938 		fprintf(errout,
1939 "\tLeft Margin.    Current: %6.1f mm\n\n", lm);
1940 		lm=getnew(lm,1);
1941 		if (booklet) rm=lm;
1942 		break;
1943 	    case 'R':
1944 		fprintf(errout,
1945 "\tRight Margin.   Current: %6.1f mm\n\n", rm);
1946 		rm=getnew (rm,1);
1947 		if (booklet) lm=rm;
1948 		break;
1949 	    case 'T':
1950 		fprintf(errout,
1951 "\tTop Margin.     Current: %6.1f mm\n\n", tm);
1952 		tm=getnew (tm,1);
1953 		break;
1954 	    case 'B':
1955 		fprintf(errout,
1956 "\tBottom Margin.  Current: %6.1f mm\n\n", bm);
1957 		bm=getnew (bm,1);
1958 		break;
1959 	    case 'H':
1960 		fprintf(errout,
1961 "\tH: English Font.    Current: %s\n\n", EFontnames[nEF]);
1962 		for (j=0; j<nEFfamily; j++)
1963 		    if (strlen(EFontnames[j]) >= 2)
1964 			fprintf(errout, "%4d:  %s\n", j, EFontnames[j]);
1965 		fprintf(errout,
1966 "0-%d: Normal  %d-%d: Oblique/Italic  %d-%d: Bold  %d-%d: Bold & Oblique\n",
1967 nEFfamily-1,
1968 nEFfamily, 2*nEFfamily-1,
1969 2*nEFfamily, 3*nEFfamily-1,
1970 3*nEFfamily, 4*nEFfamily-1);
1971 		j = nEF;
1972 		k = nEF = (int) getnew(nEF+0.1, 3);
1973 		if (k==j) break;
1974 		getEfontdata(0);
1975 	/* fall back to original if selection not available */
1976 		if (nEF != k) {
1977 			fprintf(errout,
1978 "Metric data not available for selected font, keep original font\n");
1979 			nEF = j;
1980 			getEfontdata(0);
1981 		}
1982 		break;
1983 	    case 'Q':
1984 		cleanup(1);
1985 		exit(0);
1986 	    default: break;
1987 	}
1988     } while (cst[0] != '\0');
1989 
1990     if ( (lm+rm) > XX*25. || (tm+bm) > YY*25.) {
1991 	fprintf(stderr, "Supplied paper margins out of range.\n"); exit(0);
1992     }
1993     charsize(pts);
1994     defpts=pts;
1995     defptsi = ptspc = (int) (defpts+0.5);
1996     defCa=Ca; defCi=Ci; defcolumn=column;
1997     defCx=Cx; defCy=Cy; defnEF=nEF;
1998     cgap = (int) (gap/Ck);
1999     if (vgap==0) vgap = (int) (1.5*(CLP-CIP));
2000     else vgap = (int) (vgap/ppd);
2001 
2002     if (booklet) {
2003 	j = (int) ((pr - rm*(column+2))/Ck/CSP/column + 0.5);
2004 	RM = j*CSP;     /* width of each "column" */
2005 /* margins applies to all, except central one for staping, twice as wide */
2006 	LM = (int) ((pr/Ck-column*RM)/(column+2));
2007 	RM += LM;
2008 	booklet = column; /* in case it is changed */
2009 	column = 1;
2010     }
2011     else {
2012 	LM = (int) (lm/Ck);
2013 	RM = (int) ((pr - rm)/Ck);
2014 
2015     }
2016     TM = (int) ((tm + os)/Ck);
2017     BM = (int) ((pb - bm - os)/Ck);
2018     BM = (BM - TM + (CLP-CIP) + CLP/2) / CLP * CLP + TM;
2019     x = (RM - LM - cgap*(column-1)) / (float) CSP / column;
2020     j = (int) x;
2021     if (column>1) {     /* & not booklet */
2022 	if (x-j > 0.65) {
2023 		x = (1 - x + j++) * CSP*column;
2024 		RM += (int) (x*0.45);
2025 		LM -= (int) (x*0.15);
2026 	}
2027 	else if ((x=(x-j)*CSP*column) > 0.3*cgap*(column-1)) {
2028 		RM -= (int) (x*0.45);
2029 		LM += (int) (x*0.15);
2030 	}
2031 	cgap = (RM - LM - j*CSP*column)/(column-1);
2032     }
2033     else if (!booklet) {   /* & column = 1 */
2034 	if (x-j > 0.50) {
2035 		x = (1 - x + j++) * CSP;
2036 		RM += (int) (x*0.651);
2037 		LM -= (int) (x*0.35);
2038 	}
2039 	else {
2040 		x = (x - j) * CSP;
2041 		RM -= (int) (x*0.65);
2042 		LM += (int) (x*0.35);
2043 	}
2044     }
2045  /*fprintf(stderr, "cgap = %d  j = %d, CSP = %d\n", cgap, j, CSP);*/
2046 
2047     if (menu) fprintf(errout,
2048 " There are %d lines in a page and %d words in a line\n\n", (BM-TM)/CLP, j);
2049     RM -= LM; BM -= TM; Xa = LM; Ya = TM;
2050     LM=TM=0;
2051     nEFs[nEF]++;
2052     pgcount_bak = pgcount;
2053     if (bp < pgcount) bp=pgcount;
2054     if (ep && ep<bp) ep=0;  /* error, print to file end instead */
2055 }
2056 
getEfontdata(int displaymessage)2057 void getEfontdata(int displaymessage)
2058 {
2059 	int	j, k, nEF0, m[10];
2060 	char	cst[100];
2061 	FILE    *fp;
2062 
2063 	nEF0 = nEF;
2064 	if (strlen(EFontnames[nEF]) < 3) nEF=2;
2065 	if (nEF%nEFfamily != 2) {
2066 		/* get metric data from metric file */
2067 	    if (EFmetricfiles != NULL && EFmetricfiles[nEF] != NULL
2068 			&& (fp=Rfopen(EFmetricfiles[nEF], "r")) != NULL) {
2069 		while (fgets(cst, 98, fp) != NULL) {
2070 		    if (!strncmp(cst, "DATA", 4)) {
2071 			sscanf(cst, "%*s%d%d%d%d%d%d%d%d%d%d",
2072 			    &m[0], &m[1], &m[2], &m[3], &m[4], &m[5],
2073 			    &m[6], &m[7], &m[8], &m[9]);
2074 			j=0;
2075 			while(k<129) {
2076 				Wasc[k++]=m[j++]/10000.;
2077 				if (j==10) break;
2078 			}
2079 		    }
2080 		    if (k>=129) {
2081 			fclose(fp);
2082 			return;
2083 		    }
2084 		}
2085 		fclose(fp);
2086 	    }
2087 		/* no metric file or data not complete, try "cnprint.cmd" */
2088 	    if (!getdata(1)) nEF=2;
2089 	}
2090 	if ((nEF%nEFfamily)==2) for (j=0; j<129; j++) Wasc[j]=1.;
2091 	if (nEF!=nEF0 && displaymessage) {
2092 		insertEOL(); bell();
2093 		fprintf(errout,
2094 "No metric data available for selected font, use Courier\n");
2095 	}
2096 }
2097 
columnWidth()2098 int columnWidth()
2099 
2100 {
2101 /*	int     n;
2102 	float   x;
2103 	if (column==1) return (RM-LM);
2104 	x = (cgap)? cgap :
2105 		(2.*pts*(Cw*Cx + (Ca+FontCa-1.)/25.)*25./24./ppd +.65);
2106 	n = (RM-LM-x*(column-1))/column;
2107 	return (ptspc==defptsi)? ((n/CSP)*CSP) : n;
2108 */
2109 		/* use doc default: do not use current char size based */
2110 	return (RM-LM-cgap*(column-1))/column;
2111 }
2112 
charsize(float x)2113 void charsize(float x)
2114 {
2115 	CSP = (int) (x*(Cw*Cx + (Ca+FontCa-1.)/25.)*25./24./ppd +.65);
2116 	pts = CSP/((Cw*Cx + (Ca+FontCa-1.)/25.)*25./24./ppd);
2117 	CLP = (int) (pts*(Cw*Cy - 1./25. + (1.0 - Cw + 1./25.)*Ci)*25./24./ppd);
2118 	CIP = (int) (pts*Cw*Cy/ppd); /* an estimate */
2119 
2120 }
2121 
getnew(float y,int n)2122 float getnew(float y, int n)
2123 {
2124 	float   x = -1.;
2125 	char    s[40];
2126 	fprintf(errout,
2127 " Please enter your desired value, or press RETURN to continue\n");
2128 	if (n==0)
2129 fprintf(errout, " ~~~~~~ ONLY VALUE IN --pts-- IS ACCEPTABLE ~~~~~~\n");
2130 	else if (n==1)
2131 fprintf(errout, " ~~~~~~  inch OR mm  ~~~~~~\n");
2132 	gets_stdin(s, 39);
2133 	if (s[0]=='\0') return y;
2134 	sscanf(s,"%f",&x);
2135 	if (x<=5. && n==1) x *= 25.4;
2136 		/* 5mm < Margin <= 127 mm (5 in) */
2137 	if (n==0 && x<100. && x>=1.) return x;
2138 	else if (n==1 && x<=200. && x>=5.) return x;
2139 	else if (n==2 && x<=20. && x>=0.01) return x;
2140 	else if (n==3 && x<nEFmax && x>= -1e-8) return x+0.1;
2141 	else if (n==4 && x<20. && x>= 0.9) return x+0.11;
2142 	else if (n==5 && x<11. && x>= .1) return x;
2143 	else {
2144 		fprintf(errout,
2145 "WARNING: input value out of range, ignored !\n\n");
2146 		bell(); return y;
2147 	}
2148 }
2149 
cleanup(int deltempfile)2150 void cleanup(int deltempfile)
2151 {
2152 	inf=Rinf;
2153 	while (inf != NULL) {
2154 		if (inf->fp != NULL) fclose(inf->fp);
2155 		inf = inf->p;
2156 	}
2157 	HBFclose();
2158 	if (deltempfile) {
2159 		fclose(out); remove(tempfile);
2160 	}
2161 }
2162 
newline(int pr,int ret)2163 void newline(int pr, int ret)
2164 {
2165 	int     x;
2166 
2167 /* search */
2168 	if (!pr) {
2169 		fnewline=1; Ha=0; endAC(0); inCH=100;
2170 		if (++sline > MAXLINES) {
2171 		    bell();
2172 		    fprintf(stderr,
2173 			"MAXLINES (%d) exceeded, abort\n", MAXLINES);
2174 		    exit(0);
2175 		}
2176 		lineclp[1+sline]=CLP;
2177 		linecip[1+sline]=CIP;
2178 		linedif[sline] = (H<cRM && H>=0)? (cRM-H):0;
2179 		if (ret && centraladj /*&& startline*/) {
2180 			linedif[sline] = (cRM - LM - (H-spaceH))/(-2);
2181 
2182 		}
2183 		H = LM + indentL;
2184 		cnsp=0; spaceH = -1;
2185 		return;
2186 	}
2187 /* print */
2188 	/*ascbuf.p=0;*/
2189 	if (fshade) shade();
2190 	else endAC(pr);
2191 	spaceH = -1;
2192 	V += lineclp[++pline]; H = cLM + indentL;
2193 	if (V > cBM+BMover || pline > sline) {
2194 	    /*pline--;*/
2195 	    x = columnWidth();
2196 	    if (++pcolumn <= column) {
2197 		V = cTM + linecip[pline];
2198 		cLM=LM+(x+(RM-LM-x*column)/(column-1))*(pcolumn-1);
2199 		H = cLM + indentL;
2200 
2201 	    }
2202 	    else if (V > BM+BMover) {
2203 		endpage(0);
2204 		V=cTM=TM; cLM=LM;
2205 		H = cLM + indentL;
2206 		PCN=SCN=1;              /* see isfs, PCN=2 */
2207 		pline=1; sline=0;       /* force to search */
2208 		pcolumn=1;
2209 	    }
2210 	    cRM = cLM + x;
2211 	}
2212 	fnewline=1; Ha=0;
2213 	if (fshade) ;
2214 	if (UDline.f) UDline.x = H;
2215 	cnsp=0;
2216 }
2217 
endpage(int endDoc)2218 void endpage(int endDoc)
2219 {
2220 	char    s[80];
2221 	int     pp, j, k;
2222 
2223 	if (Prntpage && !PreScanMode) {
2224 		if (pgpd++==0) bell();
2225 		if (!mute) fprintf(errout,
2226 			(pgpd%5 == 0 || endDoc)? "%5d\n" : "%5d", pgcount);
2227 		extraEOL = 1;
2228 		putnpagetime();
2229 		fprintf(out, "EP SP\n");
2230 		fprintf(out, "end  %% CN31%sDict\n", DictExt);
2231 	}
2232 	pgcount++;
2233 	pp = (pausqm)? pausqm:1;
2234 	Prntpage = print_range_check(pgcount);
2235 	if (twoside) {
2236 		j = (landscape)? Yh:Xw;
2237 		k = Xa; Xa = j-RM-Xa;
2238 		RM = j-Xa-k;
2239 	}
2240 	if (PreScanMode) return;
2241 
2242 	if (endDoc || (pausqm && !(pgpd%pp)) ) {
2243 		insertEOL();
2244 		trailer(0);
2245 		if (ferror(out)) {
2246 			fprintf(stderr,
2247 "WARNING: PS file %s write error, possibly out of memory/disk space.\n\
2248 Suggestion: delete PS file and run CNPRINT again, use the -b#e# option\n\
2249 	 to print fewer pages at a time\n", tempfile);
2250 			bell(); exit(-5);
2251 		}
2252 		fclose(out);
2253 		if (!booklet) outputToDev();
2254 		if (pausqm && !fprntfile) {
2255 			fprintf(errout,"Please press RETURN to continue");
2256 			bell(); gets_stdin(s, 79);
2257 		}
2258 		filecount++;
2259 		if (!endDoc) {
2260 			opnfile(OUT); header(); pgpd=0;
2261 		}
2262 	}
2263 	else if (Prntpage) pagesetup();
2264 }
2265 
outputToStdout(char * fn)2266 void outputToStdout(char *fn)
2267 {
2268 	char    s[100];
2269 	FILE	*in;
2270 
2271 	if ((in=fopen(fn, "r"))==NULL)
2272 		fprintf(stderr, "CNPRINT File open error: %s", fn);
2273 	else {
2274 		while(fgets(s, 99, in)!=NULL) printf("%s", s);
2275 		fclose(in);
2276 	}
2277 }
2278 
outputToDev()2279 void outputToDev()
2280 {
2281 	char    s[100], fn[100];
2282 
2283 	if (stdoutput) outputToStdout(tempfile);
2284 	else if (fprntfile) {
2285 		sprintf(s, "%s %s", prntcmd, tempfile);
2286 #ifdef VMS
2287 		if (!keepPS) sprintf(s, "%s/delete %s", prntcmd, tempfile);
2288 #endif
2289 		system(s); bell();
2290 #ifdef VMS
2291 			;
2292 #else
2293                 if (!mute) {
2294 		    fprintf(errout,
2295 "Job has been sent to the printer\n\
2296 Please press RETURN after the print job is finished");
2297 		    gets_stdin(s, 79);
2298 		}
2299 		if (!keepPS) remove(tempfile);
2300 #endif
2301 	}
2302 	if (keepPS || (!fprntfile && !stdoutput)) {
2303 		strcpy(fn, PSfile);
2304 		if (pausqm) {
2305 			sprintf(s, "%d", filecount); FName(fn, s);
2306 		}
2307 		RE_name(tempfile, fn);
2308 		fprintf(errout, "PS File: %s\n", fn);
2309 	}
2310 }
2311 
trailer(int Nppg)2312 void trailer(int Nppg)
2313 /* # of pages (booklet), use pgpd if 0 (regular) */
2314 {
2315 	int     j;
2316 	struct FontTag *F;
2317 
2318 	fprintf(out, "%%%%Trailer\n");
2319 	if (!EPS) fprintf(out, "%%%%Pages: %d\n", (Nppg==0)? pgpd : Nppg);
2320 	j=0;
2321 	while (j<nEFmax) if (nEFs[j++]>0) {
2322 		fprintf(out,
2323 "%%%%DocumentNeededResources: font %s\n", EFontnames[j-1]);
2324 		break;
2325 	    }
2326 	while (j<nEFmax) if (nEFs[j++]>0)
2327 		fprintf(out, "%%%%+: font %s\n", EFontnames[j-1]);
2328 	fprintf(out,
2329 "%%%%DocumentSuppliedResources: procset CN31%sDict\n", DictExt);
2330 	for (F=Fonts; F!=NULL; F=F->p) {
2331 	    if (F->nCN>0) for (j=1; j<=(1+(F->nCN-1)/256); j++)
2332 		fprintf(out, "%%%%+: font CN%df%d%d%s\n",
2333 			F->FontID, F->mx, j, DictExt);
2334 	}
2335 	fprintf(out, "%%%%EOF\n");
2336 	if (Nppg) return;
2337 	if (EPS) {
2338 		fprintf(errout,
2339 "Be sure to adjust the BoundingBox in the EPS file,\n\
2340 otherwise the EPS file may be placed outside the display/print area\n");
2341 		if (pgpd>1) {
2342 			bell();
2343 			fprintf(errout,
2344 "WARNING: PS file does NOT comform to EPSF format: more than 1 page\n");
2345 		}
2346 	}
2347 	if (IncEPS) fprintf(errout,
2348 "If the included EPS image is not printed/displayed,\n\
2349 most likely you forgot to adjust the BoundingBox in the EPS file\n");
2350 }
2351 
pagesetup()2352 void pagesetup()
2353 {
2354 	if (!EPS) fprintf(out, "\n%%%%Page: %d %d\n", pgcount, pgpd+1);
2355 	if (!EPS && !booklet) fprintf(out, "%%%%BeginPageSetup\n");
2356 	fprintf(out, "CN31%sDict begin\n", DictExt);
2357 	if (landscape) fprintf(out,
2358 "BP -%d LRT %d %d translate\n", Xw, Xa, Xw-BM-Ya);
2359 	else fprintf(out, "BP %d %d translate\n", Xa, Yh-BM-Ya);
2360 	PSctrl();
2361 	if (!EPS && !booklet) fprintf(out, "%%%%EndPageSetup\n");
2362 	if (strlen(EPSHDfile)) {
2363 		if (pgcount==1 && !IncEPS) return;
2364 		fprintf(out, "%d 0 Q\n", BM);
2365 		IncludeEPS(EPSHDfile);
2366 	}
2367 }
2368 
putnpagetime()2369 void putnpagetime()
2370 {
2371 
2372 
2373 	struct  tm *time_str;
2374 	int     i=0, pnp, px, py, tx, ty;
2375 	time_t  time_val;
2376 	char    s1[120], s2[40];
2377 	float	BSO = 7.2/ppd;	/* 0.1 inch */
2378 
2379 	endAC(1);
2380 	if (!fputnpage) return;
2381 	pnp=fputnpage;
2382 	if ((twoside || booklet==2) && !(pgcount%2)) {
2383 		if (pnp==1 || pnp==4) pnp += 2;
2384 		else if (pnp==3 || pnp==6) pnp -= 2;
2385 	}
2386 	if (vertical) {
2387 		px = tx = (pnp>3)? (int) (RM+4.5*BSO) : (int) (LM-4*BSO);
2388 		if (pnp==1 || pnp==4) {  /* left */
2389 			py = (int) (BM-4*BSO); ty = (int) (TM + 4*BSO);
2390 		}
2391 		else if (pnp==2 || pnp==5) { /*middle */
2392 			ty = py = (int) ((BM-TM+3*BSO)/2);
2393 			tx = (pnp<3)? (int) (RM+4.5*BSO) : (int) (LM-4*BSO);
2394 		}
2395 		else { /*right */
2396 			py = (int) (TM + 4*BSO);
2397 			ty = (int) (BM - 4*BSO);
2398 		}
2399 	}
2400 	else {
2401 		py = ty = (pnp>3)? (int) (BM+4.5*BSO) : (int) (TM-4*BSO);
2402 		if (pnp==1 || pnp==4) {  /* left */
2403 			px = LM; tx = RM;
2404 		}
2405 		else if (pnp==2 || pnp==5) { /*middle */
2406 			tx = px = (int) ((RM-LM-3*BSO)/2);
2407 			ty = (pnp<3)? (int) (BM+4.5*BSO) : (int) (TM-4*BSO);
2408 		}
2409 		else { /*right */
2410 			px = (int) (RM - 6*BSO);
2411 			tx = LM;
2412 		}
2413 	}
2414 
2415 /* use document default font/size for page number */
2416 	i = (int) (0.8338*(defpts*Cw*defCx/ppd)*20.*Casc);
2417 	fprintf(out,
2418 "/%s [%g 0 0 %d 0 0] SF\n",
2419 EFontnames[defnEF], i/10.0, (int) (defpts*0.75*defCy/ppd) );
2420 	fprintf(out, (vertical)?
2421 "%d %d p add Qa gctr (%5d.) S grestore\n" :
2422 "%d %d Qa (%5d.) S\n", BM-py, px, pgcount);
2423 	if (timestat==1) return;
2424 #ifdef TIME
2425 	time(&time_val);
2426 	time_str = localtime(&time_val);
2427 	strftime(s2, 39, "%a %d-%b-%Y %H:%M:%S %Z", time_str);
2428 	for (i=0; i<40 && (s2[i]=toupper(s2[i])) != '\0'; i++) ;
2429 	if (timestat != 2)
2430 		strcpy(s1, "CNPRINT");
2431 	else {
2432 		char *fns;
2433 		fns = (inf==Rinf)? inf->t : inf->s;
2434 		if (strlen(fns) <= 119) strcpy(s1, fns);
2435 		else strncpy(s1, fns, 119);
2436 	}
2437 	s1[119]=s2[39]='\0';
2438 	i = (int) ((strlen(s1)+strlen(s2))*3.6/ppd);
2439 	if (pnp==2 || pnp==5) i /= 2;
2440 	else if (pnp==3 || pnp==6) i=0;
2441 	if (vertical) ty += i;
2442 	else tx -= i;
2443 	fprintf(out, (vertical)?
2444 "/Courier %d SF %d %d p add Qa gctr (%s %s) S grestore\n" :
2445 "/Courier %d SF %d %d Qa (%s %s) S\n", (int) (6./ppd), BM-ty, tx, s1, s2);
2446 #endif
2447 }
2448 
header()2449 void header()
2450 {
2451 	int     j, n, urx, ury;
2452 	time_t  time_val;
2453 	struct FontTag *F;
2454 
2455 	if (EPS > 1) fprintf(out, "%c", CTRLD);	/* ctrl-D: MS EPS */
2456 	fprintf(out,
2457 "%%!PS-Adobe-3.0 %s\n\
2458 %%%%Creator: %s CYD UW-Madison WI USA\n\
2459 %%%%Title: IN %s PS %s\n", (EPS)? "EPSF-3.0": "", Version, Rinf->t, PSfile);
2460 	time(&time_val);
2461 	DictExt[1]=DictExt[0]='\0';
2462 	if (EPS) {
2463 		n = (int) time_val%62;
2464 		if (n<10) DictExt[0] = n + '0';
2465 		else if (n<36) DictExt[0] = n - 10  + 'A';
2466 		else DictExt[0] = n - 36  + 'a';
2467 	}
2468 	fprintf(out, "%%%%CreationDate: %s", ctime(&time_val));
2469 	j = (int) ((Yh-(Ya+BM+2*CLP))*ppd); if (j<=0) j=0;
2470 	urx = Xw-RM-Xa; n=Xa;
2471 	if (twoside) { n=(urx<Xa)? urx : Xa; urx=n; }
2472 	n = (int) ((n-CSP)*ppd);
2473 	urx =(int) ((Xw-urx+3*CSP/2)*ppd);
2474 	ury =(int) ((Yh-Ya+3*CLP/2)*ppd);
2475 	fprintf(out,
2476 "%%%%BoundingBox: %d %d %d %d\n", n, j, urx, ury);
2477 	if (!EPS) fprintf(out, "%%%%Pages: (atend)\n");
2478 	fprintf(out,
2479 "%%%%DocumentNeededResources: (atend)\n\
2480 %%%%DocumentSuppliedResources: (atend)\n\
2481 %%%%Orientation: %s\n\
2482 %%%%EndComments\n", (landscape)? "Landscape":"Portrait");
2483 	fprintf(out,
2484 "%%%%BeginProlog\n\
2485 %%%%BeginResource: procset CN31%sDict 19200 6400\n", DictExt);
2486 	fprintf(out,
2487 "/CN31%sDict 150 dict def CN31%sDict begin %% Jan 24, 2001\n", DictExt, DictExt);
2488 	fprintf(out,
2489 "/B {bind def} bind def\n\
2490 /*SF{ exch findfont exch dup type /arraytype eq {makefont}{scalefont}\n\
2491  ifelse setfont}B\n\
2492 /*RF{ gsave newpath 4 -2 roll moveto dup 0 exch rlineto exch 0 rlineto\n\
2493  neg 0 exch rlineto closepath fill grestore}B\n\
2494 /languagelevel where {pop languagelevel}{1} ifelse 2 lt {/SF /*SF load def\n\
2495  /RF /*RF load def}{/SF /selectfont load def /RF /rectfill load def} ifelse\n\
2496 /LRT{90 rotate 0 exch translate}B\n\
2497 /BP{/pagelevel save def 72 dpi div dup scale}B\n\
2498 /EP{pagelevel restore}B\n\
2499 /SP{showpage}B\n");
2500 	fprintf(out,
2501 "/S{show 0 p 9 div neg rmoveto}B\n\
2502 /Q{exch moveto}B\n\
2503 /q{p add Q}B\n\
2504 /Qa{exch p 9 div add moveto}B\n\
2505 /gct{gsave currentpoint translate}B\n\
2506 /gctr{gct 90 rotate}B\n");
2507 	fprintf(out,
2508 "/a{mx my true [1 0 0 -1 0 my]}B\n\
2509 /LL{mx my true [mx 0 0 my neg 0 mx]}B\n");
2510 	fprintf(out,
2511 "/T{gct scl LL}B\n\
2512 /t{gctr scl LL}B\n\
2513 /Z{gct tLL}B\n\
2514 /z{gctr tLL}B\n\
2515 /W{show p 0 rmoveto}B\n\
2516 /w{gctr show grestore p 0 rmoveto}B\n\
2517 /M{imagemask grestore p 0 rmoveto}B\n\
2518 /m/imagemask load def\n");
2519 	if (PSLlevel>=2) fprintf(out,
2520 "/U{uappend fill}B\n\
2521 /V{U grestore p 0 rmoveto}B\n");
2522 	fprintf(out,
2523 "/BeginEPSF{currentpoint /cpy exch def /cpx exch def\n\
2524  /b4_Inc_state save def /dict_count countdictstack def\n\
2525  /op_count count 1 sub def userdict begin /showpage{}def\n\
2526  0 setgray 0 setlinecap 1 setlinewidth 0 setlinejoin 10 setmiterlimit\n\
2527  [] 0 setdash newpath /languagelevel where {pop languagelevel 1 ne\n\
2528  {false setstrokeadjust false setoverprint}if}if}B\n\
2529 /EndEPSF {count op_count sub {pop} repeat countdictstack\n\
2530  dict_count sub {end} repeat b4_Inc_state restore }B\n");
2531 	fprintf(out, "/Shade{setgray RF setgray}B\n");
2532 	fprintf (out,           /* redefine font using ISOLatin1 */
2533 "/ILE {findfont dup length dict begin\n\
2534  {1 index /FID ne {def}{pop pop} ifelse}forall\n\
2535  /Encoding ISOLatin1Encoding def currentdict end\n\
2536  /ILfont exch definefont pop /ILfont}B\n\
2537 /linedraw {gsave moveto lineto stroke grestore}B\n\
2538 /UDline {gsave moveto 0 rlineto setlinewidth 1 eq\n\
2539  {[p 2.5 div dpi 300 div mul dup .7 mul]} {[]} ifelse\n\
2540  0 setdash stroke grestore}B\n");
2541 	fprintf(out,
2542 "/RD{ gsave newpath 4 -2 roll moveto dup 0 exch rlineto exch 0 rlineto\n\
2543  neg 0 exch rlineto closepath stroke grestore}B\n");
2544 	fprintf(out,
2545 "/code 256 array def /str 3 string def /s00 (00) def\n\
2546  code 0 [0 1 255 {dup 16 str cvrs exch 16 lt\n\
2547  {s00 exch 1 exch putinterval s00} if cvn} for] putinterval\n");
2548 	fprintf(out, "end %% CN31%sDict\n", DictExt);
2549 	fprintf(out,
2550 "%%%%EndResource\n\
2551 %%%%EndProlog\n\
2552 %%%%BeginSetup\n");
2553 	fprintf(out,
2554 "%sstatusdict begin /manualfeed true def end\n", (manualfeed)? "":"% ");
2555 	fprintf(out, "CN31%sDict begin\n", DictExt);
2556 	fprintf(out, "/dpi %d def\n", (int) (72./ppd+.2));
2557 	if (copies>1 && !EPS) fprintf(out, "/#copies %d def\n", copies);
2558 	for (F=Fonts; F!=NULL; F=F->p) {
2559 		if (strcmp(HBFname, F->FontName) != EQ) {
2560 			HBFclose();
2561 			strcpy(HBFname, F->FontName);
2562 			HBFopen();
2563 		}
2564 		fdict = F->fdict;
2565 		j = nCN; nCN = F->nCN;
2566 /*		if (nCN) fprintf(out,
2567 "/a{%d %d true [1 0 0 -1 0 %d]}B\n", mx, my, my);*/
2568 		n=0;
2569 		while (nCN > 256*n) CNdict(++n, F->FontID);
2570 		if (nCN>0 && !pausqm) {
2571 		    free(fdict); F->fdict=NULL;
2572 		}
2573 		nCN = j;
2574 	}
2575 	fprintf(out, "end %% CN31%sDict\n", DictExt);
2576 	fprintf(out, "%%%%EndSetup\n");
2577 	if (strcmp(HBFname, defHBFname) != EQ) {
2578 		HBFclose();
2579 		strcpy(HBFname, defHBFname);
2580 		HBFopen();
2581 	}
2582 	if (Prntpage) pagesetup();
2583 }
2584 
CNdict(int n,int FontID)2585 void CNdict(int n, int FontID)
2586 /* Fonts for frequently used characters with nCN entries */
2587 {
2588 	unsigned int i, m;
2589 	unsigned char c1, c2;
2590 	int	nch;
2591 	long	jn;
2592 	float   x;
2593 
2594 	/*jn = (mx/24.)*/
2595 	jn = (long) ( (my/24.)*1.4 * ((nCN>=n*256)? 256:(nCN%256)) );
2596 	if (ttf_font) jn /= 6;
2597 	/* j = (mx*my/24./24.)*(358./256.)*k; k = j*(344./358.);*/
2598 	x = mx; /*25./24.;*/
2599 	fprintf(out,
2600 "%%%%BeginResource: font /CN%df%d%d%s %ld00 %ld00\n",
2601 		FontID, mx, n, DictExt, jn+1, (long) (jn*0.961+1));
2602 	fprintf(out,
2603 "8 dict begin\n\
2604 /FontType 3 def\n\
2605 /FontMatrix [%8.6f 0 0 %8.6f 0 0] def\n\
2606 /FontBBox [0 0 %6.3f %6.3f] def\n", 1./x, 1./x, x, x);
2607 	fprintf(out,
2608 "/BuildGlyph{0 0 0 0 %d %d setcachedevice\n\
2609  exch /CharProcs%d get exch 2 copy known not {pop /.notdef} if get exec}B\n\
2610 /BuildChar{1 index /Encoding get exch get 1 index /BuildGlyph get exec}B\n",
2611 mx, my, n);
2612 	fprintf(out,
2613 "/Encoding 256 array def\n\
2614 Encoding 0 code putinterval\n");
2615 	if (nCN < n*256) fprintf(out,
2616 "%d 1 255 {Encoding exch /.notdef put} for\n", nCN%256);
2617 	fprintf(out,
2618 "/CharProcs%d %d dict def\n\
2619 CharProcs%d begin\n/.notdef {} def\n", n, (nCN>=n*256)? 257:(nCN%256+1), n);
2620 
2621 	nch = (nCN < n*256)? nCN : n*256;
2622 	for (i=(n-1)*256; i<nch; i++) {
2623 	    m=fdict[i];
2624 	    c1 = m/b2span + b1l;
2625 	    c2 = m%b2span + b2l;
2626 	    if (c2 > b2h_range1) c2 += b2gap;
2627 	    if (ttf_font) {
2628 		fprintf(out, "/%02X{", i%256);
2629 		if (UnicodeTTF && lcode != UTF) mapToUnicode(&c1, &c2);
2630 		TTFgen_PSproc(fpTTF, c1, c2);
2631 		fprintf(out, "U}B\n");
2632 		ptstring[m] = dummy; /* provide a dummy address */
2633 	    }
2634 	    else {
2635 		fprintf(out, "/%02X {a{<", i%256);
2636 		HBFgetBitmap(c1*256+c2);
2637 		putBitmap(array);
2638 		fprintf(out, ">}m}B\n");
2639 		ptstring[m] = array;
2640 	    }
2641 	}
2642 	fprintf(out,
2643 "end currentdict end\n/CN%df%d%d%s exch definefont pop\n\
2644 %%%%EndResource\n", FontID, mx, n, DictExt);
2645 }
2646 
putBitmap(unsigned char * a)2647 void putBitmap(unsigned char *a)
2648 {
2649 	int j;
2650 	if (PSLlevel>=2) { putBitmap85(a, CHsize); return; }
2651 	for (j=0; j<CHsize; ++j)
2652 		fprintf(out, (!((j+4)%40))? "\n%02x" : "%02x", a[j]);
2653 }
2654 
putBitmap85(unsigned char * a,int arraylen)2655 void putBitmap85(unsigned char *a, int arraylen)
2656 /*
2657  * ASCII base 85 encoder
2658  */
2659 {
2660 	int	j, kb, mlen, char_on_line;
2661 	unsigned long base256;
2662 	unsigned long divarray[5] = { 1UL, 85UL, 7225UL, 614125UL, 52200625UL };
2663 
2664 	fprintf(out, "~");
2665 	char_on_line = 10;
2666 	for (j=0; j<arraylen; j+=4) {
2667 		mlen = arraylen - j;
2668 		if (mlen > 4) mlen = 4;
2669 		base256 = 0;
2670 		for (kb=0; kb<mlen; kb++) {
2671 			base256 += ((unsigned long) a[j+kb]) << (8 * (3-kb));
2672 		}
2673 		if (base256==0 && mlen==4) {
2674 			fprintf(out, "z");
2675 			char_on_line++;
2676 		}
2677 		else for (kb = 4; kb >= 4-mlen; kb--) {
2678 			putc((base256 / divarray[kb] + '!'), out);
2679 			base256 = base256 % divarray[kb];
2680 			char_on_line++;
2681 		}
2682 		if (char_on_line >= 75) {
2683 			fprintf(out, "\n"); char_on_line=0;
2684 		}
2685 	}
2686 	fprintf(out, "~");
2687 }
2688 
PSctrl()2689 void PSctrl()
2690 /* should not be called when in SEARCH mode */
2691 {
2692 	float   z, ns, nsx, nsy;
2693 	int     j, nx, ny;
2694 
2695 /* now allow @[xx] or @[xxx] for font size: 999 max */
2696 	if (ptspc <= 0 || ptspc >= 1000) ptspc=defptsi;
2697 	z = (ptspc==defptsi)? defpts : ptspc;
2698 
2699 	charsize(z);
2700 	ns = FontptsScale * z * Cw/ppd;
2701 	j = (int) (ns*Cx*10); nsx = j/10.;
2702 	j = (int) (ns*Cy*10); nsy = j/10.;
2703 	nx = (int) ((0.8338*CSP)*2.*Casc*10);
2704 	ny = (int) (z*0.75*Cy/ppd);
2705 
2706 	clearascbuf(1, 1); endAC(1); inCH=100;
2707 	if (!Prntpage || PreScanMode) return;
2708 	fprintf(out,
2709 "/p %d def /mx %d def /my %d def\n\
2710 /scl{%g %g scale}B\n",
2711 CSP, mx, my, nsx, nsy);
2712 /*	fprintf(out,
2713 "/p %d def\n/LL {%d %d %d %d scale true [%d 0 0 -%d 0 %d]} B\n",
2714 CSP, mx, my, nsx, nsy, mx, my, mx);*/
2715 	fprintf(out,
2716 "/tLL{%g %g scale}B\n", ns*Cx/mx, ns*Cy/my);
2717 	if (CurrentFont->nCN>0)
2718 	    for (j=1; j<=(CurrentFont->nCN+255)/256; j++) {
2719 		if (nsx!=nsy) fprintf(out,
2720 "/z%d{/CN%df%d%d%s [%g 0 0 %g 0 0] SF}B\n",
2721 j, CurrentFont->FontID, mx, j, DictExt, nsx, nsy);
2722 		else fprintf(out,
2723 "/z%d{/CN%df%d%d%s %g SF}B\n", j, CurrentFont->FontID, mx, j, DictExt, nsx);
2724 	    }
2725 	fprintf(out,
2726 "/fa{/%s%s [%d.%d 0 0 %d 0 0] SF}B\n", EFontnames[nEF],
2727 		(euro>=1)? " ILE":"", nx/10, nx%10, ny);
2728 	if (color.red + color.green + color.blue > 0.001) fprintf(out,
2729 		"%g %g %g setrgbcolor\n", color.red, color.green, color.blue);
2730 	else fprintf(out, "%g setgray\n", color.gray);
2731 }
2732 
isrlasc(int c)2733 int isrlasc(int c)
2734 /* L=left; R=right; NT=none */
2735 {
2736 	if (!adjust) return NT;
2737 	switch (c) {
2738 		case 40 : case 60 : case 91 : case 123 :
2739 			return L;
2740 		case 33 : case 41 : case 44 : case 46 : case 58 :
2741 		case 59 : case 62 : case 63 : case 93 : case 125 :
2742 		case '-':
2743 			return R;
2744 		default: return NT;
2745 	}
2746 }
2747 
isrlch(unsigned char c1,unsigned char c2)2748 int isrlch(unsigned char c1, unsigned char c2)
2749 /* L=left; R=right; NT=none */
2750 {
2751     switch(lcode) {
2752 	case B5: case B5P:
2753 		if (c1!=0xA1) return NT;/* A145-A149, A150-A154, a1a9-a1ac */
2754 		if ((c2>=0x41 && c2<=0x44)||(c2>=0x4D && c2<=0x4F)) return R;
2755 		else if (c2>=0x5D && c2<=0xA8) return (c2%2)? R : L;
2756 		else return NT;
2757 	case JIS:
2758 		if (c1 > 0xA1) return NT;
2759 		if (c2>=0xC6 && c2<=0xDB) return (c2%2)? R : L;
2760 		else if (vertical) {
2761 			if (c2>=0xA2 && c2<=0xA4) return R;
2762 			else return NT;
2763 		}
2764 		else { /* A1A9, A1AA ? */
2765 			if ((c2>=0xA2 && c2<=0xA8) || (c2>=0xEB && c2<=0xED))
2766 				 return R;
2767 			else return NT;
2768 		}
2769 	case KSC:
2770 		if (c1==0xA3) {
2771 		    switch (c2) {
2772 			case 0xA8 : case 0xDB : case 0xFB :
2773 				return L;
2774 			/*case 0xA1 : case 0xA7 : case 0xBF : */
2775 			case 0xAE : case 0xBA :
2776 			case 0xBB : case 0xDF :
2777 				return (vertical)? NT:R;
2778 			case 0xA9 : case 0xAC : case 0xDD : case 0xFD :
2779 				return R;
2780 			default: return NT;
2781 		    }
2782 		}
2783 		else if (c1!=0xA1) return NT;
2784 		/*if (c2>=0xA2 && c2<=0xA3) return R;
2785 		else */
2786 		if (c2>=0xAE && c2>=0xBD) return (c2%2)? R : L;
2787 		else return NT;
2788 	case GB: case GBK:
2789 	    switch (c1) {
2790 		case 0xA1:
2791 		    if (c2>=0xAE && c2<=0xBF) c2%=2;
2792 		    switch (c2) {
2793 			case 0: return L;
2794 			case 1: case 0xA2 : case 0xA3 : /*case 0xC3 :*/
2795 				return R;
2796 			case 0xE3 : case 0xE4 : case 0xE5 :
2797 				return (vertical)? NT:R;
2798 			default: return NT;
2799 		    }
2800 		case 0xA3:
2801 		    switch (c2) {
2802 			case 0xA8 : case 0xDB : case 0xFB :
2803 				return L;
2804 			case 0xE0 :
2805 				return (vertical)? NT:L;
2806 			case 0xA1 : case 0xA7 : case 0xAE : case 0xBA :
2807 			case 0xBB : case 0xBF : case 0xDF :
2808 				return (vertical)? NT:R;
2809 			case 0xA9 : case 0xAC : case 0xDD : case 0xFD :
2810 				return R;
2811 			default: return NT;
2812 		    }
2813 		default: return NT;
2814 	    }
2815 	case UTF:      /* unicode */
2816 		/* this will never be true
2817 		  if (isUnicodeASCII(c1, c2)) return isrlasc(c2); */
2818 		if (c1 != 0x30) return NT;
2819 		switch (c2) {
2820 		    case 0x08 : case 0x0A : case 0x0C : case 0x0E :
2821 		    case 0x10 : case 0x14 : case 0x16 : case 0x1D :
2822 			return L;
2823 		    case 0x09 : case 0x0B : case 0x0D : case 0x0F :
2824 		    case 0x11 : case 0x15 : case 0x17 : case 0x1E :
2825 		    case 0x1F : case 0x01 : case 0x02 :
2826 			return R;
2827 		    default: return NT;
2828 		}
2829 	    break;
2830 	default: break;
2831     }
2832     return NT;
2833 }
2834 
tovhb5(unsigned char c)2835 unsigned char tovhb5(unsigned char c)
2836 /*
2837  * convert vertical big5 punctuations to horizontal ones or vice versa
2838  */
2839 {
2840 	int j;
2841 	if (c<0x5D || c>0x7D) return c;
2842 	j = (c-0x5D)%4;
2843 	if (j<2 && vertical) return (c+2);
2844 	if (j>=2 && !vertical) return (c-2);
2845 	return c;
2846 }
2847 
vchange(unsigned char * c1,unsigned char * c2)2848 int vchange(unsigned char *c1, unsigned char *c2)
2849 /*
2850  * substitutions under vertical mode
2851  */
2852 {
2853     switch(lcode) {
2854 	case JIS:
2855 	    if (*c1==0xA1) switch (*c2) {
2856 		case 0xC6: case 0xC7: case 0xC8: case 0xC9:
2857 			*c2 += 0x10; break;
2858 		default: break;
2859 	    }
2860 	    break;
2861 	case B5: case B5P:
2862 	    if (*c1==0xA1) switch (*c2) {
2863 		/*case 0x43: *c1 = 0xA2; *c2 = 0x58; break;
2864 		case 0x4D: *c2 = 0xA6; break;
2865 		case 0x4E: *c2 = 0xAB; break;*/
2866 		case 0xA5: *c2 = 0x77; break;
2867 		case 0xA6: *c2 = 0x78; break;
2868 		case 0xA7: *c2 = 0x7B; break;
2869 		case 0xA8: *c2 = 0x7C; break;
2870 		default: break;
2871 	    }
2872 	    break;
2873 	case GB: case GBK:
2874 	    if (*c1==0xA1) switch (*c2) {      /* GB: default c1=0xA1 */
2875 		/*case 0xA2: *c2 = 0xE4; break;
2876 		case 0xA3: *c2 = 0xE3; break;*/
2877 		case 0xAE: case 0xAF: case 0xB0: case 0xB1:
2878 			*c2 += 0x0A; break;
2879 		default: break;
2880 	    }
2881 /* problem: A1A3 is a comma, */
2882 	    break;
2883 	case KSC:
2884 	    if (*c1==0xA1) switch (*c2) {
2885 		case 0xAE: case 0xAF: case 0xB0: case 0xB1:
2886 			*c2 += 0x0A; break;
2887 		default: break;
2888 	    }
2889 	    break;
2890 	case UTF:   /* unicode */
2891 	    break;
2892 	default: break;
2893     }
2894     return 1;
2895 }
2896 
rtch(unsigned char c1,unsigned char c2)2897 int rtch(unsigned char c1, unsigned char c2)
2898 /* R=rotate */
2899 {
2900     switch(lcode) {
2901 	case JIS:
2902 	    switch (c1) {
2903 		case 0xA1:
2904 			if (c2>=0xA2 && c2<=0xA4) return RMXY;
2905 			else return (c2>=0xC2)? NT : R;
2906 		case 0xA2: return (c2<=0xEF)? NT : R;
2907 		case 0xA3: return (c2<=0xD4)? NT : R;
2908 		case 0xA6: return NT;
2909 		case 0xA7: return (c2<=0xCF)? NT : R;
2910 		default: return R;
2911 	    }
2912 	case B5: case B5P: /* B5P should be compatible with B5 */
2913 	    switch (c1) {
2914 		case 0xA1:
2915 		    if (c2>=0x41 && c2<=0x43) return RMXY;
2916 		    else if (c2>=0x4D && c2<=0x4F) return RMXY;
2917 		    else if (c2>=0x5D && c2<=0x7C)
2918 			return ((c2-0x5D)%4 <= 1)? R:NT;
2919 		    else return (c2>=0x7D && c2<=0xFE && c2!=0xC0)? NT : R;
2920 		case 0xA2:
2921 		    if (c2>=0x40 && c2<=0x58) return NT;
2922 		    else if (c2>=0x62 && c2<=0xC2) return NT;
2923 		    else if (c2>=0xCF && c2<=0xFE) return NT;
2924 		    else return R;
2925 		case 0xA3:
2926 		    return (c2>=0x40 && c2<=0x73)? NT : R;
2927 		case 0xC8:
2928 		    return (c2>=0x41 && c2<=0x78)? NT : R;
2929 		default: return R;
2930 	    }
2931 	case GB: case GBK: /* hopefully GBK is compatible with GB */
2932 	    switch (c1) {
2933 		case 0xA1:
2934 		    switch (c2) {
2935 			case 0xA2: case 0xA3: return RMXY;
2936 			case 0xA9: return R;
2937 			default: return NT;
2938 		    }
2939 		case 0xA3:
2940 		    switch (c2) {
2941 			case 0xA1: case 0xBF: case 0xBA: case 0xBB:
2942 				return RMX; /* ! ? : ; */
2943 			case 0xAC: return RMXY;  /* , */
2944 			default: return NT;
2945 		    }
2946 		case 0xA6: case 0xA7: case 0xA9: return NT;
2947 		case 0xA8:
2948 		    if (c2==0xE7) return NT;
2949 		    else return (c2 <= 0xC4)? NT : R;
2950 		default: return R;
2951 	    }
2952 	case KSC:  /* needs work */
2953 	    switch (c1) {
2954 		case 0xA1:
2955 		    switch (c2) {
2956 			default: return NT;
2957 		    }
2958 		case 0xA3:
2959 		    switch (c2) {
2960 			case 0xA1: case 0xBA: case 0xBF: return R;
2961 			case 0xAC: return RMXY;
2962 			default: return NT;
2963 		    }
2964 		default: return R;
2965 	    }
2966 	case UTF:
2967 	    if (c1 != 0x30) return R;
2968 	    if (c2 >= 0x08 && c2 <= 0x11 || c2 >= 0x14 && c2 <= 0x1B)
2969 		return NT;
2970 	    else return R;
2971 	default: break;
2972     }
2973     return NT;
2974 }
2975 
putASC(int c,int c2,int pr)2976 int putASC(int c, int c2, int pr)
2977 {
2978 	int     p, k, ASP, rl, rr=0;
2979 	float   x;
2980 	static int map[] = {    /* map some European chars, 128-160 */
2981 		0xC7, 0xFC, 0xE9, 0xE2, 0xE4, 0xE0, 0xE5, 0xE7,
2982 		0xEA, 0xEB, 0xE8, 0xEF, 0xEE, 0xEC, 0xC4, 0xC5,
2983 		0xC9, 0xE6, 0xC6, 0xF4, 0xF6, 0xF2, 0xFB, 0xF9,
2984 		0xFF, 0xD6, 0xDC, 0xA2, 0xA3, 0xA5, 0xDF, 0x83, 0xE1};
2985 
2986 	cnsp=0; frl=NT;
2987 	if (c==LF || c==FF) {
2988 		clearascbuf(pr, 1);
2989 		if (c==FF && pr) {  /* a quick and dirty way */
2990 			V = BM; pcolumn = column;
2991 		}
2992 		newline(pr, 1);
2993 		return 0;
2994 	}
2995 	if (c=='\t') {
2996 		clearascbuf(pr, 1);
2997 		endAC(pr);
2998 		x = (H-cLM)/(CSP*((tabascii)? Casc: 0.5));
2999 		k = (int) (x + 8.5);  k = (int) ((k/8)*8);
3000 		H += (int) ( (k-x)*CSP*((tabascii)? Casc: 0.5) );
3001 		return 0;
3002 	}
3003 	k = (c>=' ' && c<=160)? (c-' ') : 0;  /* change 126 to 160 */
3004 	ASP = (int) (CSP*Casc*Wasc[k]*10.);
3005 	Ha += (ASP%10); ASP /= 10;
3006 	if (c>=128 && c<=160) {
3007 		c=map[c-128];
3008 		if (euro==0 && pr) { /* auto detect feature: end previous line
3009 			with clearascbuf(1, 1) and endAC(1) in PSctrl() */
3010 			euro=1; PSctrl();
3011 		}
3012 	}
3013 	if (c!=' ') {
3014 		rl=isrlasc(c);
3015 	/* left-end char */
3016 		if (H > cRM-indentR-ASP*3/2 && rl==L && adjust) {
3017 		    clearascbuf(pr, 1);
3018 		    newline(pr, 0);
3019 		    return 1;
3020 		}
3021 		else if (H > cRM-indentR-ASP/2) {
3022 		    if (!adjust || H > cRM-indentR+2*CSP*Casc) {
3023 			    clearascbuf(pr, 1);
3024 			    newline(pr, 0);
3025 			    return 1;
3026 		    }
3027 		    else if (c2==LF /*|| c2==CR*/)  /* no need for a new line */
3028 			rr=4;
3029 	    /*  "abc ": include space in the current line, rr=3, treat
3030 		as if H<<cRM; but if " a " or " I ", move them to next line */
3031 		    else if (c2==' ') {
3032 			rr=3;
3033 			if ((c=='a' || c=='I') && ascbuf.p>0) {
3034 			    if (ascbuf.s[ascbuf.p-1]==' ') {
3035 				clearascbuf(pr, 1);
3036 				newline(pr, 0);
3037 				return 1;
3038 			    }
3039 			}
3040 		    }
3041 	    /*  do not break digits like 108.9, does not work if 108.92 */
3042 		    else if (rl==R && (c!='.' || !isdigit(c2)))
3043 			rr=2;
3044 	    /*  c2 is ascii and not left-end, here b1l=0xa1 or 0x30(utf),
3045 		but ascbuf.p > 40% line, or last word > 15 chars */
3046 		    else if (c2<b1l && isrlasc(c2)!=L &&
3047 			(ascbuf.p-ascbuf.pp>15 ||
3048 			H-ascbuf.Hp >(cRM-indentR-cLM)*.3)) {
3049 			    clearascbuf(pr, 1);
3050 			    newline(pr, 0);
3051 			    return 1;
3052 		    }
3053 		    else if (ascbuf.p) {
3054 			    p = ascbuf.p-ascbuf.pp;
3055 			    clearascbuf(pr, 0);
3056 			    newline(pr, 0);
3057 			/* push un-used chars back to major buffer, safe in
3058 			   most of cases: but not for unicode !!! */
3059 			    return 1+p;
3060 		    }
3061 		    else newline(pr, 0);
3062 		    if (rr<2) return 1;
3063 			/* rr<2: do not use char c; rr=2: use c & add newline;
3064 			   rr>2: use char c only */
3065 		}
3066 		if (pr) {
3067 		    if (centraladj && spaceH == -1) {
3068 			H -= linedif[pline];
3069 			spaceH = 1;
3070 		    }
3071 		    if (inCH && Prntpage && !PreScanMode)
3072 			fprintf(out, "%d %d Qa fa\n(", BM-V, H);
3073 		}
3074 		else if (centraladj && spaceH == -1) spaceH = H;
3075 		ascbuf.s[(ascbuf.p)++]=c;
3076 		if (ascbuf.p==1) {
3077 			ascbuf.Hp=H; ascbuf.pp=0;
3078 		}
3079 		inCH=OUT;
3080 		if (rr==2) {
3081 			clearascbuf(pr, 1);
3082 			newline(pr, 0);
3083 			return 0;
3084 		}
3085 	}
3086 	else {
3087 	    if (inCH) newpos = 1;
3088 	    if (ascbuf.p) ascbuf.s[(ascbuf.p)++]=c;
3089 	    ascbuf.pp=ascbuf.p;
3090 	    ascbuf.Hp=H+ASP;	/* introduces error (~Ha) */
3091 	    if (centraladj) {
3092 		if (centraladj==2 && spaceH == -1) {
3093 		    if (pr) {
3094 			H -= linedif[pline]; spaceH=1;
3095 		    }
3096 		    else spaceH = H;
3097 		}
3098 		else if (pr && spaceH != 1) H -= ASP;
3099 	    }
3100 	}
3101 	H += ASP;
3102 	if (Ha>=10) { H++; Ha -= 10; }
3103 	return 0;
3104 }
3105 
Addr(int c1,int c2)3106 unsigned int Addr(int c1, int c2)
3107 {
3108 	unsigned int a = (c1-b1l)*b2span + c2-b2l;
3109 	if (c2 > b2h_range1) a -= b2gap;
3110 	/*if (lcode==UTF) a = (c1-b1l)*256 + c2;
3111 	else a = (lcode!=B5)? ((c1-0xA1)*94+c2-0xA1) :
3112 		( (c1-0xA1)*157 + ( (c2>=0xA1)? (63+c2-0xA1):(c2-0x40) ) );
3113 	*/
3114 	return (a>nchar)? nchar : a;
3115 }
3116 
putCH(unsigned char c1,unsigned char c2,int pr)3117 int putCH(unsigned char c1, unsigned char c2, int pr)
3118 {
3119 	int     j, rl, rt, newl=0;
3120 	unsigned int ch, addr;
3121 
3122 	rl=rt=NT;
3123 	if (lcode==B5)
3124 		if ((big5>1 || vertical) && c1==0xA1) c2=tovhb5(c2);
3125 	if (vertical) {
3126 		vchange(&c1, &c2);
3127 		rt = rtch(c1, c2);
3128 		if (rt != NT) Rotate=1;
3129 	}
3130 	/*else rt=NT;*/
3131 	if (c1>=0xA4) cnsp=0;
3132 	else if (adjust) {
3133 /* such adjustment should also be allowed for vertical printing, except
3134  * for some like : ;
3135  */
3136     /*      if (lcode==B5 || lcode==JIS) {
3137 		cnsp=0; rl=isrlch(c1, c2);
3138 		if (rl==L && H > cRM-indentR-CSP*3/2) newl=1;
3139 	    }
3140 	    else if (lcode==GB) {
3141 */              cnsp++;
3142 		if ( (rl=isrlch(c1, c2))==NT ) cnsp=0;
3143 		else if (rl==L) {
3144 		    if (H > cRM-indentR-2*CSP) {
3145 			cnsp=1; newpos=1;
3146 			if (H < cRM-indentR-CSP*5/4) {
3147 				H -= ((frl==R)? CSP: CSP/2);
3148 				if (frl==R) frl=NT;
3149 				if (H < cRM-indentR-2*CSP) H=cRM-indentR-2*CSP;
3150 			}
3151 			else if (H < cRM-indentR-CSP*3/4 && frl==R) {
3152 				H -= CSP;
3153 				if (H < cRM-indentR-2*CSP) H=cRM-indentR-2*CSP;
3154 			}
3155 			else newl=1;
3156 		    }
3157 		}
3158 		else if (rl==R && frl==L) cnsp=1;
3159 	   /* } */
3160 	}
3161 	if (!inCH) {
3162 	    if (ascbuf.p) clearascbuf(pr, 1);
3163 	    endAC(pr);	/* also set newpos=1, inCH=100, ascbuf.p=0 */
3164 	}
3165 	ch = (c1*256) + c2;
3166 	if (ch != cspace) {
3167 	    if (adjust) {
3168 		if (frl==R && H > cRM-indentR-CSP
3169 				&& H <=cRM-indentR-CSP/4 && !cnsp) {
3170 			newpos=1;
3171 			H = (H > cRM-indentR-CSP/2)?
3172 				(H-CSP/2) : (cRM-indentR-CSP);
3173 		}
3174 		else if (newl || (H>cRM-indentR-CSP*2/3 && rl!=R)
3175 				|| H>cRM-indentR+1.5*CSP) {
3176 			newline(pr, 0);
3177 			return 2;
3178 		}
3179 		if (cnsp >= 2) {
3180 		    if (!pr) H -= (CSP/2);
3181 		    else {      /* take care of 'half' CN */
3182 			if (linedif[pline] > CSP/2)
3183 				linedif[pline] -= (CSP/2);
3184 			else if (linedif[pline] > 0) {
3185 				H -= (CSP/2-linedif[pline]);
3186 				linedif[pline]=0; newpos=1;
3187 			}
3188 			else {
3189 				H -= (CSP/2); newpos=1;
3190 			}
3191 		    }
3192 		}
3193 	    }
3194 	    else if (H > cRM - indentR - CSP*2/3) {
3195 		newline(pr, 0);
3196 		return 2;
3197 	    }
3198 
3199 	    if (!pr) {
3200 		inCH=100;
3201 		if (centraladj && spaceH == -1) spaceH = H;
3202 	    }
3203 	    else {
3204 		if (centraladj && spaceH == -1) {
3205 			H -= linedif[pline]; spaceH=1;
3206 
3207 		}
3208 		addr=Addr(c1, c2);
3209 		if (PreScanMode && Prntpage)
3210 			fstring[addr]++;
3211 		else if (Prntpage) {
3212 
3213 		    if (vertical && rt != NT && rt != R) { /* rotate & move */
3214 			fprintf(out, "%d %d q ",
3215 				BM-V + CSP/ (rt==RMY ? 6:2),
3216 				H - CSP/ (rt==RMX ? 6:2) );
3217 			newpos=1; /* next char must re-define position */
3218 		    }
3219 		    else if (newpos || (rt==NT && Rotate) ) {
3220 			if (newpos==1 || rt==R || (rt==NT && Rotate) )
3221 			    fprintf(out, (vertical && rt==R)?
3222 				"%d %d q\n":"%d %d Q\n", BM-V, H);
3223 			newpos=0;
3224 			if (vertical && rt==NT) {Rotate=0; newpos=2;}
3225 		    }
3226 /* possible problem here for unicode */
3227 		    if (fstring[addr]>=60000) {
3228 			j = fstring[addr] - 60000;
3229 			if (inCH != (j>>8) +1)
3230 			    fprintf(out, "z%d ", (inCH = (j>>8) +1));
3231 			j%=256;
3232 fprintf(out, (j>='~' || j<' ' || j=='(' || j==')' || j==92)?
3233 			"<%02x>%c\n" : "(%c)%c\n", j, ((rt==NT)? 'W':'w'));
3234 		    }
3235 		    else if (ttf_font) {
3236 			fprintf(out, (rt==NT)? "Z" : "z");
3237 			if (UnicodeTTF && lcode != UTF)
3238 				mapToUnicode(&c1, &c2);
3239 			TTFgen_PSproc(fpTTF, c1, c2);
3240 			fprintf(out, "V\n");
3241 		    }
3242 		    else {
3243 			fprintf(out, (rt==NT)? "T {<" : "t {<");
3244 			HBFgetBitmap(ch);
3245 			putBitmap(array);
3246 			/*putBitmap(ptstring[addr]);*/
3247 			fprintf(out, ">}M\n");
3248 		    }
3249 		    if (fstring[addr]>0 && fstring[addr]<60000
3250 				&& --fstring[addr]==100) {
3251 			if (CurrentFont->ptstring[addr] != NULL)
3252 				free(CurrentFont->ptstring[addr]);
3253 			ptstring[addr]=CurrentFont->ptstring[addr]=NULL;
3254 		    }
3255 		}
3256 	    }
3257 	}
3258 	else {
3259 	    if (centraladj) {
3260 		if (centraladj==2 && spaceH == -1) {
3261 		    if (pr) {
3262 			H -= linedif[pline]; spaceH=1;
3263 		    }
3264 		    else spaceH = H;
3265 		}
3266 		else if (pr && spaceH != 1) H -= CSP;
3267 	    }
3268 	    newpos=1;
3269 	}
3270 	H+=CSP;
3271 	frl=rl;
3272 	return 0;
3273 }
3274 
signature()3275 void signature()
3276 {
3277 	time_t  time_val;
3278 	char    *msg[]={"\nHave a nice day !\n", "", "", "", "",
3279 		"\nThank you for using CNPRINT !\n", "", "", ""};
3280 	if (mute) return ;
3281 	time(&time_val);
3282 	if (time_val%287 == 2) fprintf(errout,
3283 "\nThis version of CNPRINT is about to expire, please contact author.\n");
3284 	else if (time_val%131 == 2) fprintf(errout,
3285 "\nThank you for using CNPRINT.  Please consider contribution to\n\
3286 CNPRINT educational fund, to help kids in rural China get five-\n\
3287 years' basic education.  See \"Author\" section of the help file\n\
3288 for details.\n");
3289 	else fprintf(errout, "%s", msg[(int)(time_val%8)]);
3290 }
3291 
usage(int n)3292 void usage(int n)
3293 {
3294 /* unlisted: -keeptempfile */
3295 	if (n>10) bell();
3296 	fprintf(errout, "%s\n\n", Version);
3297 	fprintf(errout,
3298 "USAGE: cnprint [-h] [-wvlc2x3...] [-f=font] [file1 [file2]...] \
3299 [-o=outfile]\n\n\
3300 	-big5(gb)(hz)(zw)(cns)(jis)(euc)(jis8)(ksc)(utf)(utf8)(utf7)(utf16)\n\
3301 	 	(utf16le): Specify input code type.\n\
3302 	-v(-vv): Vertical printing mode.\n\
3303 	-c3:    Divide one page into 3 Columns.\n\
3304 	-w:     Generate PS file Without printing it.\n\
3305 	-l:     Paper orientation Landscape.\n\
3306 	-i(out)(io): Use standard input (output) (both).\n\
3307 	-f=j16 (f24, k24, or full HBF name): Select font.\n");
3308 	fprintf(errout,
3309 "	-x2:	Character width/height 1.2 (-y3: h/w 1.3).\n\
3310 	-e56:   ASCII width = 0.56 CJK width.\n\
3311 	-gb2b5(hz2b5)(b52gb)(b52hz)(hz2gb)(gb2hz): code conversion only.\n\
3312 	-print: use with gb2b5 etc, also print or generate PS file.\n\
3313 	-uni2gb(-gb2uni)(b5)(ksc)(jis): unicode<->CJK (utf type: -utf16 etc)\n\
3314 	-m:     Disable/enable Menu (-m5: print 5 copies).\n\
3315 	-aa:    Special mode for pure ASCII text file.\n\
3316 	-b20e34: Print pages 20-34 (-odd, -even: odd or even-numbered pages).\n\
3317 	-b18:   Set the starting page number as 18.\n");
3318 	if (n!=2) {
3319 		fprintf(errout,
3320 "Use -h option for more on-line help.  See help file for details.\n");
3321 	       /*       signature(); */
3322 		return;
3323 	}
3324 	fprintf(errout, "Press RETURN key to continue\n");
3325 	n=getchar();
3326 	fprintf(errout,
3327 "	-q=laserps: : System PS print command = 'laserps'.\n");
3328 	fprintf(errout,
3329 "	-t(-tt): Do NOT print time (-tt: print time and input filename).\n\
3330 	-55:    BIG5 input, adjust horizontal/vertical punctuations.\n\
3331 	-c320:  3 Columns on one page with 20 pts space between columns.\n\
3332 	-cgap=15: Space between columns (in pts, def: 2.5 char width).\n\
3333 	-vgap=15: Vertical space at place of column number change\n\
3334 		(in pts, def: 1.5 of document line spacing).\n\
3335 	-l#:    Special landscape modes for printing HXWZ (#: 1-4) (*).\n\
3336 	-a:     Print double-byte letters, digits as English ones.\n\
3337 	-d:     NO special treatment of punctuation marks.\n\
3338 	-e(-eps): EPS output (-ems or -epsms: MS format EPS).\n\
3339 	-epsheader=EPSfile: specify EPS header file\n\
3340 	-s:     Suppress the effects of functional sequences @[**] (*).\n\
3341 	-k:	When multiple inputs, produce multiple outputs.\n\
3342 	-mfeed:	Manual feed paper.\n\
3343 	-nopage: Do not print page number and date.\n\
3344 	-h23:	Set English font as Helvetica-Bold (def: Courier, see menu).\n\
3345 	-size=14.5: Char size 14.5 points.\n\
3346 	-rm(lm)(tm)(bm)=12.3: Paper margin (right, left, top, bottom) \
3347 12.3mm\n\
3348 	-a4(letter)(legal)(a3): Paper size A4 (Letter)(Legal)(A3).\n");
3349 
3350 	fprintf(errout, "Press RETURN key to continue\n");
3351 	n=getchar();
3352 	fprintf(errout,
3353 "	-env:	Envelope mode (-envs: small size envelope) (*).\n\
3354 	-label: Print address label, also set manual feed (*).\n\
3355 	-bk(4): Booklet format with 2 (4) columns.\n\
3356 	-fpg(5): Start new page for new input file (if 5 lines to bottom).\n\
3357 	-j:     Adjust bottom margin if more than one column (*).\n\
3358 	-p4:    Print/convert 4 pages at a time.\n\
3359 	-tab:   TAB mode: 4 CJKs <-> 8 ASCIIs, default CJK (ASCII if -aa)\n\
3360 	-f:	Two-sided format (but does not print on both sides!)\n\
3361 	-short: Convert PS file, long lines to short lines\n\
3362 	-extr:  Extract/print selected pages in a PS file\n\
3363 	-mimeqp: Decode mime quoted printables (=A8=D3=C5 like text)\n\
3364 	-euro:  Disable <-> enable ability of printing European chars.\n\
3365 	-n74:   Chars per line N 74 (Hz<->GB, JIS/KSC pre-processing *).\n\
3366 	-bmps4 0xa1a2 (0xa1a5) -r/l/t/b: Shift bitmap to right/left/\
3367 top/bottom\n\
3368 		by 4 pixels for char 0xa1a2 (to 0xa1a5) (*).\n\
3369 	-n=256: # of chars in CNdict (default 2048) (*).\n\
3370 	-r=600: Device resolution 600 dpi (default 300).\n\
3371 	-level1(2): PostScript level (def: level 2, use compression).\n\
3372 	-ttt:   Word freq statistics excluding \
3373 (-tttt: including) symbols.\n");
3374 	fprintf(errout, "Press RETURN key to continue\n");
3375 	n=getchar();
3376 	fprintf(errout,
3377 "  Repair functions:\n\
3378 	-zzz:   Filter out functional sequence like @[**].\n\
3379 	-r1:    -zzz + ignore EOL when # of char per line > N and < M.\n\
3380 	-r2:    -zzz + ignore EOL when # of char per line <= N.\n\
3381 	-n68(-m120): set N=68 or M=120 (default: N auto-select, M 100).\n\
3382 	-r6:    -r1 + ignore one of two consecutive EOLs (newline char).\n\
3383 	-r7(-r8): -zzz + add (del) space before Chinese char (for CStar).\n\
3384 	-r3:    -zzz + make # of spaces at beginning of a line to be 4.\n\
3385 	-r4:    -r3, even there was no space there.\n\
3386 	-s:     (when r1, r2, r6) also ignore Space\n\
3387 	-p:     (when r1, r2, r6) match quotation marks.\n\
3388 	-m:     (when r1, r2, r6) map .,:;?! etc to CJK ones.\n\
3389 	-a:     Map double-byte letters, digits to English ones.\n\
3390 	-t(-tx): (when r1, r2, r6) ignore 'x' (default: '>') in news reply.\n\
3391 	-e:     (when r1, r2, r6) do NOT ignore EOL.\n\
3392 	-k(-k90): (when -zzz or -r#) break big file into ~64K (90K) ones.\n\
3393 	* See help file for details.\n");
3394 	fprintf(errout,
3395 "\n%s\nCopyright Yidao CAI 1992-2001, All Rights Reserved\n\
3396 cai@neurophys.wisc.edu\n", Version);
3397 }
3398 
isfs(unsigned char * s,int pr)3399 int isfs(unsigned char *s, int pr)
3400 {
3401 	int	j, k;
3402 	float	x;
3403 	unsigned char c1, c2, c3, st0[100];
3404 	unsigned char *t;
3405 	int	seqlen;
3406 
3407 	t=s; seqlen=1;
3408 	while (*t && *t!=']' && seqlen<51) {seqlen++; t++;}
3409 		/* ignore string too short or too long: "[xx]" is minimum */
3410 	if (seqlen < 4 || s[seqlen-1]!=']') return 0;
3411 	c1=s[1]; c2=s[2], c3=s[3];
3412 
3413 
3414 
3415 	if (suppress) return (suppress>=2)? 0 : seqlen;
3416 
3417 	switch(c1) {
3418 /* RGB */
3419 	    case 'R':
3420 		if (c2!='G' || c3!='B' || seqlen!=11) return 0;
3421 		for (j=4; j<=9; j++) if (!isxdigit(s[j])) return 0;
3422 		color.red = hex2float1(s[4], s[5]);
3423 		color.green = hex2float1(s[6], s[7]);
3424 		color.blue = hex2float1(s[8], s[9]);
3425 		if (color.red + color.green + color.blue > 0.001) {
3426 			color.gray = 0.0;
3427 			if (pr && Prntpage && !PreScanMode) {
3428 		    		fprintf(out, "%g %g %g setrgbcolor\n",
3429 					color.red, color.green, color.blue);
3430 			}
3431 		}
3432 		return 11;
3433 /* move to */
3434 	    case 'M':
3435 		if (c2!='V' || seqlen!=10) return 0;
3436 		for (j=3; j<=8; j++) if (!isdigit(s[j])) return 0;
3437 		j = 100*(s[3]-'0') + 10*(s[4]-'0') + (s[5]-'0');
3438 		k = 100*(s[6]-'0') + 10*(s[7]-'0') + (s[8]-'0');
3439 		endAC(pr);
3440 			/* V position is one line off */
3441 		if (pr && k!=1) V = (int) (k/ppd + linecip[1]);
3442 		if (j!=1) H = (int) (j/ppd);
3443 		return 10;
3444 
3445 /* line break and BOX draw/fill */
3446 	    case 'B':
3447 		if (c2!='O' && c3!='X' && seqlen > 4) return 0;
3448 		if (c2=='R') {
3449 			clearascbuf(pr, 1);
3450 			newline(pr, 1);
3451 			return 4;
3452 		}
3453 	/* BOXDRAW/FILL: def fill */
3454 		for (j=8; j<seqlen-1; j++) if (!isdigit(s[j])) return 0;
3455 		if (pr && Prntpage && !PreScanMode) {
3456 			fprintf(out, "%d %d %d %d %s\n",
3457 				int3pts2dot(s+8), BM-int3pts2dot(s+11),
3458 				int3pts2dot(s+14), int3pts2dot(s+17),
3459 				(strncmp((char *) s, "[BOXDRAW", 8)
3460 					==EQ)? "RD\n" : "RF");
3461 		}
3462 		return 21;
3463 
3464 /* C: column number */
3465 	    case 'C':
3466 		if (c2=='B' || c2=='b' || c2=='E') {
3467     /* Central adjust Begin/End */
3468 			if (c2=='E' && s[4]==LF) {  /* safe: seqlen>=4 */
3469 				clearascbuf(pr, 1);
3470 				newline(pr, 1);
3471 				centraladj = 0;
3472 				return 5;
3473 			}
3474 			else if (c2=='E') centraladj = 0;
3475 			else centraladj = (c2=='B')? 1:2;
3476 			return 4;
3477 		}
3478 
3479 		if (!pr) return issfs(c1, c2, c3);
3480 		if (!isdigit(c2)) return 0;
3481 		k = (c2=='0')? defcolumn : (c2-'0');
3482 		PCN++;
3483 		if (PCN==1) /* do nothing */
3484 			/*fprintf(stderr, "PCN = 1\n")*/ ;
3485 		else {
3486 
3487 			column = k;      /* set search mode for next one */
3488 
3489 			V -= lineclp[pline];
3490 		/* a safety measure, in case V go beyond cBM */
3491 			if (V < cBM) V = cBM;
3492 			cBM = BM;
3493 			V = cTM = V + vgap;
3494 
3495 			H = cLM = LM;
3496 			cRM = LM + columnWidth();
3497 			sline = 0;  pline = 1; fnewline = 1; /* force search */
3498 			SCN = PCN = 1;
3499 			if (cTM > BM) {
3500 				endpage(0);
3501 				V=cTM=TM;
3502 				pcolumn=1;
3503 			}
3504 		}
3505 		return 4;
3506 
3507 /* DF: use default settings for font, size, line and char spaces... */
3508 	    case 'D':
3509 		if (c2 != 'F') return 0;
3510 		strcpy((char *) st0, "[F0]"); isfs(st0, pr);
3511 		strcpy((char *) st0, "[00]"); isfs(st0, pr);
3512 			/* Cx, Cy: changes Ci! so XY must be before I0 */
3513 		strcpy((char *) st0, "[XY]"); isfs(st0, pr);
3514 		strcpy((char *) st0, "[I0]"); isfs(st0, pr);
3515 		strcpy((char *) st0, "[A0]"); isfs(st0, pr);
3516 		return 4;
3517 
3518 /* ASC font by number */
3519 
3520 	    case 'h': case 'H': case 'q': case 'Q':
3521 		if (!isdigit(c2)) return 0;
3522 		k=nEF;
3523 		nEF=c2-'0';
3524 		if (isdigit(c3)) {
3525 			nEF=nEF*10 + (c3-'0');
3526 			if (c1=='h' && isdigit(s[4])) nEF=nEF*10 + (s[4]-'0');
3527 		}
3528 		if (c1=='H' || c1=='Q') nEF += 2*nEFfamily;
3529 		if (c1=='q' || c1=='Q') nEF += nEFfamily;
3530 		if (nEF != k) {
3531 			getEfontdata(pr && !PreScanMode);
3532 			nEFs[nEF]++;
3533 			if (pr /*&& nEF!=k*/) PSctrl();
3534 		}
3535 		return seqlen;
3536 
3537 /* CH font: or ASC font by name (F) */
3538 	    case 'f': case 'F': case 'v': case 'V': case 'T':
3539 		if (seqlen==4 && !isalpha(c2) && c2!='0') return 0;
3540 		if (seqlen!=5 && c1=='T') return 0; /* only @[Txx] is valid */
3541 		if (seqlen==5 && c1=='F') return 0; /* @[Fxx] not valid */
3542 
3543 	/* not correct!!! as font may affect CSP, leave as it is for now */
3544 		if (!pr) return seqlen;
3545 
3546 	/* @[Fxxx]: specify full hbf/htf/ttf/ASCfont name */
3547 		if (c1=='F' && seqlen >= 6) {
3548 		    t = s+2;
3549 		    strncpy((char *) st0, (char *) t, seqlen-3);
3550 		    st0[seqlen-3] = '\0';
3551 
3552 		    k=nEF;
3553 		    if ((nEF = isASCfont((char *) st0)) >= 0) {
3554 
3555 			if (nEF != k) {
3556 				getEfontdata(pr && !PreScanMode);
3557 				nEFs[nEF]++;
3558 				if (pr /*&& nEF!=k*/) PSctrl();
3559 			}
3560 			return seqlen;
3561 		    }
3562 		    else {
3563 
3564 			nEF = k;
3565 			strcpy(HBFname, (char *) st0);
3566 		    }
3567 		}
3568 	/* true type fonts: @[Txx] */
3569 		else if (c1=='T') {
3570 			sprintf((char *) st0, "%c%c.htf", c2, c3);
3571 			construct_fontname((char *) st0);
3572 		}
3573 	/* old @[Fx], @[Vx] format */
3574 		else {
3575 		    if (c2 == '0') {
3576 			strcpy(HBFname, defHBFname);
3577 			HBFclose(); HBFopen();
3578 			PSctrl();
3579 			return 4;
3580 		    }
3581 		    k = (isupper(c1))? 1:0;
3582 		    k += (isupper(c2))? 1:0;
3583 		    switch(k) {
3584 			case 0: j = (toupper(c1)=='F')? 16:40; break;
3585 			case 1: j = (toupper(c1)=='F')? 24:56; break;
3586 			case 2: j = (toupper(c1)=='F')? 48:64; break;
3587 			default: break;
3588 		    }
3589 		    sprintf((char *) st0, "%c%d.hbf", tolower(c2), j);
3590 		    construct_fontname((char *) st0);
3591 		}
3592 
3593 		HBFclose();
3594 		if (!HBFopen()) {
3595 			strcpy(HBFname, defHBFname);
3596 			insertEOL();
3597 			if (pr && !PreScanMode)
3598 				fprintf(errout, "Default font used\n\n");
3599 			HBFopen();
3600 		}
3601 		PSctrl();
3602 		return seqlen;
3603 
3604 /* shading */
3605 	    case 'S':
3606 		if (!isdigit(c2)) return 0;
3607 		if (!pr) return 4;
3608 		if (fshade) shade();
3609 		fshade=(c2=='0')? 0:1;
3610 		return 4;
3611 /* gray */
3612 	    case 'G':
3613 		if (seqlen==4) {
3614 			if (isdigit(c2)) color.gray = (c2-'0')/10.;
3615 			else return 0;
3616 		}
3617 		else if (strncmp((char *) s, "[GRAY", 5)==EQ) {
3618 			if (sscanf((char *) s, "[GRAY%f]", &x) != 1) return 0;
3619 			if (x>=0.0 && x<=1.0) color.gray = x;
3620 		}
3621 		else return 0;
3622 		color.red = color.green = color.blue = 0.0;
3623 		endAC(pr);
3624 		if (pr && Prntpage && !PreScanMode)
3625 			fprintf(out, "%g setgray\n", color.gray);
3626 		return seqlen;
3627 
3628 /* X, Y expansion */
3629 	    case 'X': case 'Y':
3630 		if (!isdigit(c2)) {
3631 			if (c1=='X' && c2=='Y') {/* [XY], use default */
3632 				Cx = defCx; Cy = defCy;
3633 			}
3634 			else return 0;
3635 		}
3636 		else {
3637 			if (seqlen==4) {
3638 				x = 1.0 + (c2-'0')/10.0;
3639 			}
3640 			else {	/* allow [X1.32] format  */
3641 			    if (sscanf((char *) s, "[%c%f]", &x) != 1) return 0;
3642 			}
3643 			if (x==0.0) { /* use default */
3644 				Cx = defCx; Cy = defCy;
3645 			}
3646 			else if (c1=='X') {
3647 				Cx = x; Cy=1.0;
3648 			}
3649 			else {
3650 				Cy = x; Cx=1.0;
3651 			}
3652 		}
3653 		Ci = (Cx+Cy < 2.01)? defCi: (Cy+(Cx-1.)/2.);
3654 		if (!pr) return (ptspc<=99) ?
3655 			issfs('0'+ptspc/10, '0'+ptspc%10, ']') :
3656 			issfs('0'+ptspc/100, '0'+(ptspc/10)%10, '0'+ptspc%10);
3657 		PSctrl();
3658 		return seqlen;
3659 
3660 /* E: ASC width, line and char space; EP: EPS */
3661 	    case 'E':
3662 		if (!isdigit(c2) && c2!='P') return 0;
3663 		if (isdigit(c2)) {
3664 		    Casc = (c2=='0')? Casc : (c2-'0')/10.;
3665 		    if (!pr) return (ptspc<=99) ?
3666 			issfs('0'+ptspc/10, '0'+ptspc%10, ']') :
3667 			issfs('0'+ptspc/100, '0'+(ptspc/10)%10, '0'+ptspc%10);
3668 		    PSctrl();
3669 		    return 4;
3670 		}
3671 		else if (c2=='P') { /* EP or EPS */
3672 
3673 		    endAC((int) (pr && Prntpage));
3674 		    if (pr && Prntpage && !PreScanMode) {
3675 			fprintf(out,"%d %d Q ", BM-V, H);
3676 			if (c3=='S' && seqlen>7) {
3677 				strncpy((char *) st0, (char *) (s+4), seqlen-5);
3678 				st0[seqlen-5] = '\0';
3679 				IncludeEPS((char *) st0);
3680 			}
3681 			else IncludeEPS("");
3682 			PSctrl();
3683 		    }
3684 		    return seqlen;
3685 		}
3686 		else return 0;
3687 
3688 /* line spaces, indent */
3689 	    case 'I':
3690 		if (c1=='I' && c2=='N' && c3=='D') { /* INDL/R/E */
3691 		    if (s[4]=='E') {
3692 			if (H==indentL) H -= indentL;
3693 			indentL=indentR=0;  /* end */
3694 		    }
3695 		    else if (seqlen>6) {
3696 			if (sscanf((char *) s, "[IND%*c%d]", &k) != 1) return 0;
3697 			k = (int) (k/ppd);
3698 			if (s[4]=='R') indentR = k;
3699 			else {
3700 				indentL = k;
3701 				if (H==0) H += indentL;
3702 			}
3703 		    }
3704 		    else return 0;
3705 		    return seqlen;
3706 		}
3707 		else {
3708 		    Ci = (c2=='0')? defCi :
3709 			(isdigit(c2)? (c2-'0')/10. : (c2-'a'+1) );
3710 		    if (!pr) return (ptspc<=99) ?
3711 			issfs('0'+ptspc/10, '0'+ptspc%10, ']') :
3712 			issfs('0'+ptspc/100, '0'+(ptspc/10)%10, '0'+ptspc%10);
3713 		    PSctrl();
3714 		    return 4;
3715 		}
3716 
3717 /* char space, envelope address */
3718 	    case 'A':
3719 		if (!isxdigit(c2)) {
3720 		    if (c1=='A' && (c2=='S' || c2=='R')) {
3721 		/* Envelope, S/R addresses of sender and receiver, move left
3722 		   margin to right by 3.25/2 inch if AR, restore if AS */
3723 			if (pr) return 4;
3724 			j = (int) ( ((envelope==2)? 2 : 3.25) * 72./ppd );
3725 			if (c2=='R') {
3726 			    LM += j; V = (int) (1.25*72/ppd);
3727 			}
3728 			else if (LM>=j) LM -= j;
3729 			H = cLM = LM;
3730 			return 4;
3731 		    }
3732 		    else return 0;
3733 		}
3734 		else {
3735 		    Ca = (c2=='0')? defCa : (isdigit(c2)? (c2-'0') : c2-'a'+10);
3736 		    if (!pr) return (ptspc<=99) ?
3737 			issfs('0'+ptspc/10, '0'+ptspc%10, ']') :
3738 			issfs('0'+ptspc/100, '0'+(ptspc/10)%10, '0'+ptspc%10);
3739 		    PSctrl();
3740 		    return 4;
3741 		}
3742 
3743 	    case 'P':
3744 		if (!isdigit(c2)) return 0;
3745 		if (!pr) return 4;
3746 		j = c2-'0';
3747 		if (!j || (BM-V)/CLP<=j) {
3748 			V=BM; pline--; newline(1, 0);
3749 		}
3750 		return 4;
3751 
3752 	    case 'L':  /* LBAS is used in preprocessing only (addLBAS) */
3753 	/* Linedraw */
3754 		if (strncmp((char *) s, "[LINEDRAW", 9) == EQ) {
3755 		    for (j=9; j<seqlen-1; j++) if (!isdigit(s[j])) return 0;
3756 		    if (pr && Prntpage && !PreScanMode) {
3757 			fprintf(out, "%d %d %d %d linedraw\n",
3758 				int3pts2dot(s+9), BM-int3pts2dot(s+12),
3759 				int3pts2dot(s+15), BM-int3pts2dot(s+18));
3760 		    }
3761 		    return 22;
3762 		}
3763 		if (strncmp((char *) s, "[LINEWIDTH", 10) == EQ) {
3764 		    if (sscanf((char *) s, "[LINEWIDTH%d]", &k) != 1) return 0;
3765 		    linewidth = (k==0)? deflinewidth : k;
3766 		    if (pr && Prntpage && !PreScanMode)
3767 			fprintf(out, "%d setlinewidth\n", linewidth);
3768 		    return seqlen;
3769 		}
3770 		if (c2!='B') return 0;
3771 		j=0;
3772 		if (s[3] != ']') j=2;	/* @[LB] or @[LBxx] */
3773 		if (pr) {
3774 			if (s[3]==']') lbn++;
3775 			else lbn = (s[3]-'0')*10 + (s[4]-'0');
3776 			if (lbn > (k=lbnx*lbny)) {
3777 				lbn -= (k+1);
3778 				V=BM; /*pline--;*/ pcolumn=column;
3779 				newline(1, 0);  /* force a new page */
3780 	/* also push back '@', potential problem here, esp. with unicode */
3781 				return -1;
3782 			}
3783 			k = lbn-1;
3784 			H=cLM = (int) ( ((k/lbny)*lbxinc + lbxp - .1)*72/ppd );
3785 			V = (int) ( ((k%lbny)*lbyinc + lbyp - .1)*72/ppd );
3786 		}
3787 		cRM = (int) ( cLM + (lbxinc - lbxp - 0.1)*72/ppd );
3788 		return 4+j;
3789 /* underline */
3790 	    case 'U': case 'u':
3791 		if (c2!='B' && c2!='E') return 0;
3792 		if (!pr) return 4;
3793 		if (c2=='B') {
3794 			UDline.x = H; UDline.f = 1;
3795 			if (c1=='u') UDline.f = 2;     /* broken line 10:7 */
3796 		}
3797 		else {
3798 			endAC(pr);
3799 			UDline.f = 0;
3800 		}
3801 		return 4;
3802 	    case '+': case '-':
3803 /* char size increment/decrement */
3804 		if (!isdigit(c2)) return 0;
3805 		k = c2-'0';
3806 		if (isdigit(c3)) k = k*10 + (c3-'0');
3807 		if (c1 == '+') k = defptsi + k;
3808 		else k = defptsi - k;
3809 /*fprintf(stderr, "%c%c%c: k = %d \n", c1, c2, c3, k);*/
3810 		if (k <= 0 || k > 999) k = defptsi;
3811 		if (pr) {
3812 			ptspc=k; PSctrl();
3813 /*fprintf(stderr, "ptspc = %d\n", ptspc);*/
3814 		}
3815 		else j = (k <= 99)? issfs('0'+k/10, '0'+k%10, ']') :
3816 			issfs('0'+k/100, '0'+(k/10)%10, '0'+k%10);
3817 		return (c3==']')? 4 : 5;
3818 	    default:
3819 		if (!isdigit(c1) || !isdigit(c2)) return 0;
3820 /* char size */
3821 		if (!pr) return issfs(c1, c2, c3);
3822 		ptspc = (c1-'0')*10 + (c2-'0');
3823 		if (isdigit(c3)) ptspc = ptspc*10 + (c3-'0');
3824 		PSctrl();
3825 		return (c3==']')? 4 : 5;
3826 	}
3827 }
3828 
issfs(unsigned char c1,unsigned char c2,unsigned char c3)3829 int issfs(unsigned char c1, unsigned char c2, unsigned char c3)
3830 {
3831 /* now accept @[xx] or @[xxx] for char size */
3832 	int	k;
3833 	float	y;
3834 	switch(c1) {
3835 /* C: column number */
3836 	    case 'C':
3837 		if (!isdigit(c2)) return 0;
3838 		k = (c2=='0')? defcolumn : (c2-'0');
3839 
3840 		if (H > cLM) ;
3841 		if (sline==0) PCN=SCN=0; /* often happens at start of doc */
3842 		SCN++;
3843 		if (SCN==1) {
3844 			column = k;
3845 			cTM = V;
3846 			cRM = LM + columnWidth();
3847 
3848 		}
3849 		else {
3850 
3851 			cBM=span(1);
3852 			cLM  = LM;
3853 			pcolumn = 1;
3854 		}
3855 		return 4;
3856 	    default:
3857 		if (!isdigit(c1) || !isdigit(c2)) return 0;
3858 /* char size */
3859 		k = (c1-'0')*10 + (c2-'0');
3860 		if (c3 != ']') k = k*10 + (c3-'0');
3861 		if (k>=1000 || k<=0) { y=defpts; ptspc=defptsi;}
3862 		else y=ptspc=k;   /* ptspc for print has been saved */
3863 		charsize(y);
3864 		  /* size ctrl at the beginning of a line, take it */
3865 /* New approach:  no adjustment of V here  */
3866 		if (H==LM || CLP > 1.1*lineclp[sline+1])
3867 			lineclp[sline+1] = CLP;
3868 		if (H==LM || CIP > linecip[sline+1])
3869 			linecip[sline+1] = CIP;
3870 		return 4;
3871 	}
3872 }
3873 
shade()3874 void shade()
3875 {
3876 	endAC(0); ;
3877 }
3878 
underline()3879 void underline()
3880 {
3881 	int y;
3882 
3883 	if (vertical) {
3884 		y = (int) ( ((ptspc==defptsi)? defpts : ptspc)*Cy*Cw/ppd + .1 );
3885 		y += BM-V+CLP/9;
3886 	}
3887 	else y = BM-V-CLP/9;
3888 	fprintf(out, "%d %4.1f %d %d %d UDline\n",
3889 		UDline.f-1, pts/4, H-UDline.x, UDline.x, y);
3890 	UDline.x = H;
3891 }
3892 
endAC(int pr)3893 void endAC(int pr)
3894 {
3895 	if (!inCH) {
3896 	    if (pr && Prntpage && !PreScanMode) {
3897 		clearascbuf(1, 0);
3898 		fprintf(out,") S\n");
3899 	    }
3900 	    inCH=100;
3901 	}
3902 	if (UDline.f && pr && Prntpage) underline();
3903 	newpos=1; ascbuf.p=0;
3904 }
3905 
clearascbuf(int pr,int clearall)3906 void clearascbuf(int pr, int clearall)
3907 {
3908 	int j, k, n=0, c;
3909 
3910 	k = clearall? ascbuf.p : ascbuf.pp;
3911 	if (ascbuf.p<ascbuf.pp) k=0;
3912 	if (pr && Prntpage && k>0 && !PreScanMode) {
3913 	    for (j=0; j<k; j++) {
3914 		c=ascbuf.s[j];
3915 		if (c<' ' || c>=128) {
3916 		    n+=3; fprintf(out, "\\%03o", c);
3917 		}
3918 		if (c=='(' || c==')' || c==92) {
3919 		    n++; fprintf(out, "\\%c", c);
3920 		}
3921 		else fprintf(out, "%c", c);
3922 		n++;
3923 		if (n>75 && c==' ' || n>78) {
3924 		    n=0; fprintf(out, "\\\n"); /* break line */
3925 		}
3926 	    }
3927 	}
3928 	if (!clearall && ascbuf.p != ascbuf.pp && ascbuf.p)
3929 	    for (j=ascbuf.pp; j<ascbuf.p; j++)
3930 		ascbuf.s[j-ascbuf.pp] = ascbuf.s[j];
3931 	ascbuf.p = 0;
3932 }
3933 
convers(int convOnly)3934 void convers(int convOnly)
3935 {
3936 	static char *st1[]={
3937 		"", "Hz --> GB", "GB --> Hz", "", "zW --> GB",
3938 		"", "Trying to repair", "JIS Pre-Processing",
3939 		"HZ+ --> GB", "HZ+ -->B5",
3940 		"KSC7 --> KSC8", "UTF7 --> 2-byte unicode",
3941 		"UTF8 --> 2-byte unicode", "UTF-16BE --> CJK",
3942 		"UTF-16LE --> CJK",
3943 		"CNS --> BIG5", "GB --> BIG5", "", "BIG5 --> GB", "",
3944 		"Long lines --> short lines", "Print/extract selected pages",
3945 		"MIME quoted printable --> 8 bit", "MIME base64 --> 8 bit",
3946 		"Add sender's address",
3947 		"unicode --> GB", "unicode --> Big5", "unicode --> KSC",
3948 		"unicode --> JIS", "UTF-8 --> CJK",
3949 		"UTF-7 --> CJK", "UTF-16 --> CJK", "", "", "",
3950 		"", "", "", "", "",
3951 		"", "Stat", ""};
3952 	static char *st2[]={"", "GB", "Hz", "Filtered/Repaired", "GB",
3953 		"8-bit", "Repaired", "7-bit JIS", "GB", "BIG5",
3954 		"8-bit", "2-byte", "2-byte", "2-byte", "2-byte",
3955 		"BIG5", "BIG5", "", "GB", "",
3956 		"Short version", "Selected pages", "8 bit", "8 bit", "",
3957 		"GB", "Big5", "KSC", "JIS", "CJK",
3958 		"CJK", "CJK", "CJK", "", "",
3959 		"", "", "", "", "",
3960 		"", "Statistic output", ""};
3961 	static char ki[]="$B", ko[]="(B";
3962 	char    st[20], s[80];
3963 	FILE    *in;
3964 
3965 	if (convcode==FILT) {
3966 		strcpy(st, "NEW");
3967 		if (breakfile) sprintf(st, "%d", filecount++);
3968 	}
3969 	else if (convcode==STATS) {
3970 		strcpy(st, "stt");
3971 	}
3972 /* GB/B5/JIS-->GB/B5/JIS */
3973 	else {
3974 	    fprintf(errout, "%s ...\n", st1[convcode]);
3975 	    inf=Rinf; sbufp=0;
3976 	    while ((in = inf->fp) != NULL) {
3977 		if (inf != Rinf) fputc(EOL, out);
3978 		switch (convcode) {
3979 		    case HZGB: case HZPGB: case HZPB5:
3980 			hz2gb(in);
3981 			strcpy(st, (convcode==HZPB5)? B5str : GBstr);
3982 			break;
3983 		    case GBHZ:
3984 			gb2hz(in); strcpy(st, HZstr); break;
3985 		    case ZWGB:
3986 			zw2gb(in); strcpy(st, GBstr); break;
3987 		    case CNSB5:
3988 			cns2b5(in, out); strcpy(st, B5str); break;
3989 		    case B5GB:
3990 			gbb5conv(in, B5GB); strcpy(st, GBstr);
3991 			break;
3992 		    case GBB5:
3993 			gbb5conv(in, GBB5); strcpy(st, B5str);
3994 			break;
3995 		    case JIS8:
3996 			jis2jis8(in); strcpy(st, "JS8"); break;
3997 		    /*case KSC8: ksc2ksc8(in);strcpy(st, "KS8"); break;*/
3998 		    case JISRP:
3999 			/*jisrepair(in);*/ strcpy(st, "RP");break;
4000 		    case JISCVT:
4001 			switch (code) {
4002 				case JIS:  seven2seven(in, ki, ko); break;
4003 				case EUC:  euc2seven(in, ki, ko);   break;
4004 				case SJIS: shift2seven(in, ki, ko); break;
4005 				default: break;
4006 			}
4007 			strcpy(st, "JS7");
4008 			break;
4009 		    case UTF8TOUNI:
4010 		    case UTF7TOUNI:
4011 			to2byte_unicode(in); strcpy(st, "uni");
4012 			break;
4013 		    case UTF16BETOUNI:
4014 		    case UTF16LETOUNI:
4015 			utf16to2byte_unicode(in); strcpy(st, "uni");
4016 			break;
4017 		    case CJKUTF8:
4018 		    case CJKUTF7:
4019 		    case CJKUTF16:
4020 		    case CJKUTF16LE:
4021 			cjk2unicode(in); strcpy(st, "uni"); break;
4022 		    case UTF8CJK:
4023 		    case UTF7CJK:
4024 			unicode2cjk(in); strcpy(st, "cjk"); break;
4025 		    case UTF16CJK:
4026 		    case UTF16LECJK:
4027 			unicode2cjk16(in); strcpy(st, "cjk"); break;
4028 		    case UNIGB:
4029 			nullfilter(in); strcpy(st, "gb"); break;
4030 		    case UNIB5:
4031 			nullfilter(in); strcpy(st, "b5"); break;
4032 		    case UNIKSC:
4033 			nullfilter(in); strcpy(st, "ksc"); break;
4034 		    case UNIJIS:
4035 			nullfilter(in); strcpy(st, "jis"); break;
4036 		    case MIMEQP:
4037 			mimeqpdecode(in); strcpy(st, "8b"); break;
4038 		    case ADDLBAS:
4039 			addLBAS(in); strcpy(st, "lb"); break;
4040 #ifdef PSPRINT
4041 		    case TOSHORTPS:
4042 			toshortline(in); strcpy(st, "sht"); break;
4043 		    case PAGEPRINT:
4044 			pageprint(in); strcpy(st, "pps"); break;
4045 #endif
4046 		    default: break;
4047 		}
4048 		fclose(in);
4049 		inf->fp=NULL;
4050 		if ((inf=inf->p) == NULL) break;
4051 	    }
4052 	    inf=Rinf;
4053 	}
4054 	if (ferror(out)) {
4055 		fprintf(stderr, "%s version write error: %s\n",
4056 			st2[convcode], tempfile);
4057 		bell(); exit(-5);
4058 	}
4059 	fclose(out);
4060 	if (convOnly) {
4061 	    strcpy(s, PSfile);
4062 	    if (*PSfile==0) {
4063 		strcpy(PSfile, Rinf->s); FName(PSfile, st);
4064 	    }
4065 	    else if (breakfile) FName(PSfile, st);
4066 	    if (convOnly==10) {	/* PSPRINT functions */
4067 		outputToDev();
4068 	    }
4069 	    else {
4070 		if (stdoutput) outputToStdout(tempfile);
4071 		else {
4072 			RE_name(tempfile, PSfile);
4073 			fprintf(errout, "%s version: %s\n",
4074 				st2[convcode], PSfile);
4075 		}
4076 		if (breakfile && convOnly==100) {
4077 			opnfile(OUT); strcpy(PSfile, s);
4078 		}
4079 	    }
4080 	}
4081 	else {
4082 		if (input_file_layer > 0) remove(Rinf->s);
4083 		else input_file_layer++;
4084 		FName(Rinf->s, st);
4085 		RE_name(tempfile, Rinf->s);
4086 		opnfile(IN); opnfile(OUT);
4087 	}
4088 }
4089 
nullfilter(FILE * in)4090 void nullfilter(FILE *in)
4091 {
4092 	int	c;
4093 	while ((c=fgetc(in)) != EOF) fputc(c, out);
4094 }
4095 
unicode2cjk(FILE * in)4096 void unicode2cjk(FILE *in)
4097 {
4098 	unsigned short  uni, cjk;
4099 	for (;;) {
4100 		uni = (convcode==UTF7CJK)? utf7_getc(in) : utf8_getc(in);
4101 		if (uni == (unsigned short) EOF) break; /* not good ! */
4102 		if (uni <= 0x007F) {
4103 			fputc(uni, out); /* ASCII */
4104 			continue;
4105 		}
4106 		cjk= UNItablemap[(int)(uni/256)][(int)(uni%256)];
4107 		fputc((int)(cjk/256), out);
4108 		fputc((int)(cjk%256), out);
4109 	}
4110 }
4111 
cjk2unicode(FILE * in)4112 void cjk2unicode(FILE *in)
4113 
4114 {
4115 	unsigned short uni;
4116 	int	c1, c2;
4117 
4118 	if (convcode==CJKUTF8) {
4119 		fputc(0xEF, out);
4120 		fputc(0xBB, out);
4121 		fputc(0xBF, out);
4122 	}
4123 	else if (convcode==CJKUTF16LE) {
4124 		fputc(0xFF, out);
4125 		fputc(0xFE, out);
4126 	}
4127 	else {
4128 		fputc(0xFE, out);
4129 		fputc(0xFF, out);
4130 	}
4131 	for (;;) {
4132 		if ((c1= fgetc(in)) == EOF) break;
4133 		if (c1 < b1l) {
4134 			c2=c1; c1=0x00;  /* 0x80 */
4135 		}
4136 		else {
4137 			c2 = fgetc(in);
4138 			if (c2==EOF) break;
4139 			uni = UNItablemap[c1-b1l][c2-b2l];
4140 			c1 = (unsigned char) (uni/256);
4141 			c2 = (unsigned char) (uni%256);
4142 		}
4143 		switch (convcode) {
4144 		    case CJKUTF16LE:
4145 			fputc(c2, out); fputc(c1, out);
4146 			break;
4147 		    case CJKUTF8:
4148 			/* utf_fputc(c1, c2, out) */
4149 			break;
4150 		    default:
4151 			fputc(c1, out); fputc(c2, out);
4152 			break;
4153 		}
4154 	}
4155 }
4156 
unicode2cjk16(FILE * in)4157 void unicode2cjk16(FILE *in)
4158 /* 16 bit only */
4159 {
4160 	unsigned short cjk;
4161 	int	c1, c2, c3;
4162 
4163 	for (;;) {
4164 		c1 = fgetc(in); c2 = fgetc(in);
4165 		if (c1==EOF || c2==EOF) break;
4166 		if (convcode==UTF16LECJK) {
4167 			c3=c1; c1=c2; c2=c3;
4168 		}
4169 		if (isUnicodeASCII(c1, c2)) {
4170 			fputc(c2, out); /* ASCII */
4171 			continue;
4172 		}
4173 		cjk= UNItablemap[c1][c2];
4174 		fputc((int)(cjk/256), out);
4175 		fputc((int)(cjk%256), out);
4176 	}
4177 }
4178 
to2byte_unicode(FILE * in)4179 void to2byte_unicode(FILE *in)
4180 {
4181 	long	uni;
4182 	int	c1, c2, c3;
4183 
4184  /* UTF-8: EF BB BF */
4185 	sbufp = 0;
4186 	c1 = sgetc(in);
4187 	c2 = sgetc(in);
4188 	c3 = sgetc(in);
4189 	if (c1 != 0xEF || c2 != 0xBB || c3 != 0xBF) {
4190 		sungetc(c3); sungetc(c2); sungetc(c1);
4191 	}
4192 	while ((uni = (convcode==UTF7TOUNI)? utf7_getc(in) : utf8_getc(in) )
4193 			!= EOF) {
4194 		u2byte((int)(uni/256));
4195 		u2byte((int)(uni%256));
4196 	}
4197 }
4198 
utf16to2byte_unicode(FILE * in)4199 void utf16to2byte_unicode(FILE *in)
4200 {
4201 	int	c1, c2;
4202 
4203 	sbufp = 0;
4204 	c1 = sgetc(in);
4205 	c2 = sgetc(in);
4206 	if (c1+c2 != 0x01FD) {
4207 		sungetc(c2); sungetc(c1);
4208 	}
4209 	while ((c1=sgetc(in)) != EOF) {
4210 		c2 = sgetc(in);
4211 		if (c2==EOF) break;
4212 		if (convcode==UTF16LETOUNI) {
4213 			u2byte(c2); u2byte(c1);
4214 		}
4215 		else {
4216 			u2byte(c1); u2byte(c2);
4217 		}
4218 	}
4219 }
4220 
u2byte(int ch)4221 void u2byte(int ch)
4222 /*
4223  * output "escaped" u2 byte
4224  *#define U2ESC 0x4D, U2ESC2 0x21, ESCs for 2-byte unicode:
4225  */
4226 {               /*      4D4D = 4D, 4D21 = 00 */
4227 	switch (ch) {
4228 	    case 0x00:
4229 		fputc(U2ESC, out); fputc(U2ESC2, out);
4230 		break;
4231 	    case U2ESC:
4232 		fputc(U2ESC, out); fputc(ch, out);
4233 		break;
4234 	    default: fputc(ch, out); break;
4235 	}
4236 }
4237 
jis2jis8(FILE * in)4238 void jis2jis8(FILE *in)       /* 0x21-0x7E --> 0xA1-0xFE */
4239 {
4240 	int state, c1, c2, k=0;
4241 
4242 	state = OUT;
4243 	sbufp=0;
4244 	while ((c1=sgetc(in)) != EOF) {
4245 	    if (c1 == ESC) {
4246 		c2 = sgetc(in);
4247 /* ESC$B <ESC$@>, ESC(B for New & old JIS */
4248 		if (c2 == '$' || c2 == '(') {
4249 		    c1 = sgetc(in); k+=3;
4250 		    if (c1=='B') state = (c2=='$')? IN : OUT;
4251 		    else {
4252 			sungetc(c1); sungetc(c2); k-=2;
4253 			if (state==OUT) {       /* else eat ESC */
4254 			    fputc(ESC, out);
4255 			}
4256 		    }
4257 		}
4258 		else {  /* if IN, bad ESC, ignore */
4259 			sungetc(c2); k++;
4260 			if (state==OUT) fputc(ESC, out);
4261 		}
4262 	    }
4263 	    else if (state==IN) {
4264 		c2 = sgetc(in);
4265 		fprintf(out,"%c%c", c1+128, c2+128);
4266 		k+=2;
4267 	    }
4268 	    else if (k<nHzline-2 || c1!=EOL) {
4269 		k++; fputc(c1, out);
4270 		if (c1==EOL) k=0;
4271 	    }
4272 	    else k=0;
4273 	}
4274 }
4275 
hz2gb(FILE * in)4276 void hz2gb(FILE *in)
4277 {
4278 	int state, c1, c2, k=0;
4279 
4280 	state = OUT;
4281 	sbufp=0;
4282 	while ( (c1=sgetc(in)) != EOF) {
4283 	    if (c1=='~') {
4284 		k+=2;
4285 		if ( (c2=sgetc(in)) == '{') state = IN;
4286 		else if (c2 == '}') state = OUT;
4287 		else if (c2 == '~') fputc(c2, out);
4288 		else if (c2==EOL) {
4289 			state=OUT; k=0;
4290 		}
4291 		else if (state==OUT) {
4292 			fprintf(out, "%c", c1);
4293 			k--; sungetc(c2);
4294 		}
4295 		else {  /* may be more likely to be '~}' ? */
4296 			if (!mute) fprintf(errout,
4297 				"Bad code : 0x%02X%02X\n", c1, c2);
4298 			fprintf(out, "%c%c", MSBon(c1), MSBon(c2));
4299 		}
4300 	    }
4301 	    else {
4302 		if (state >= IN && c1 != EOL) {
4303 		    c2 = sgetc(in);
4304 		    if (c2==EOL) {	/* bad code, turn c1 to 7-bit */
4305 			if (!mute) fprintf(errout,
4306 				"Bad code: 0x%02X%02X\n", c1, c2);
4307 			fprintf(out, "%c", MSBoff(c1));
4308 			state=OUT; k=0;
4309 		    }
4310 		    else if (c2=='~') {
4311 			/* "#~{" or "#~}": since '{' or '}' is not valid
4312 			    first byte, more likely to be "~{" or "##~{".
4313 			    this correction is optional */
4314 			c2=sgetc(in); sungetc(c2);
4315 			if (c2=='{' || c2=='}') {
4316 			    sungetc('~');
4317 			    fprintf(out, "%c", c1);
4318 			}
4319 			else {
4320 			    fprintf(out, "%c%c", MSBon(c1), MSBon('~'));
4321 			    k+=2;
4322 			}
4323 		    }
4324 		    else {
4325 			fprintf(out, "%c%c", MSBon(c1), MSBon(c2));
4326 			k+=2;
4327 		    }
4328 		}
4329 		else if (k<nHzline-2 || c1!=EOL) {
4330 		    /* do not set MSB off, euro or pure GB? */
4331 			fputc(c1, out);
4332 			k++;
4333 			if (c1==EOL) {
4334 			    state=OUT; k=0;
4335 			}
4336 		}
4337 		else k=0;  /* eat this EOL */
4338 	    }
4339 	}
4340 }
4341 
gb2hz(FILE * in)4342 void gb2hz(FILE *in)
4343 {
4344 	int state, c1, c2, k=0, nGB=0;
4345 
4346 	if (nHzline>100) nHzline=76;
4347 	state = OUT;
4348 	while ((c1=fgetc(in))!=EOF) {
4349 /* GB1 */   if (c1>=0xA1) {
4350 		if ((c2=fgetc(in))==EOF) break;
4351 /* GB2 */       else if (c2>=0xA1) {
4352 		    nGB++;
4353 		    if (state==OUT) {
4354 			if (k >= nHzline-2) { fprintf(out, "~\n"); k=0; }
4355 			fprintf(out, "~{"); state=IN; k+=2;
4356 		    }
4357 		    else if (k >= nHzline-4) {fprintf(out, "~}~\n~{"); k=2;}
4358 		    fprintf(out, "%c%c", MSBoff(c1), MSBoff(c2));
4359 		    k+=2;
4360 		}
4361 		else {
4362 /* keep bad code as it is */
4363 		    if (!mute) fprintf(errout,
4364 			"Probably bad code: %02X%02X\n", c1, c2);
4365 		    if (state==IN) {
4366 			fprintf(out, "~}"); state=OUT; k+=2;
4367 		    }
4368 		    if (k >= nHzline-1 && c1!=EOL && c2!=EOL)
4369 			{ fprintf(out, "~\n"); k=0; }
4370 		    fprintf(out, "%c%c", c1, c2);
4371 		    k+=2;
4372 		    if (c1==EOL) k=1;
4373 		    if (c2==EOL) k=0;
4374 		}
4375 	    }
4376 	    else {
4377 /* ASCII */     /*  may also be euro char */
4378 		if (c1>=0x80) fprintf(errout, "Probably bad code: %02X\n",c1);
4379 		if (state==IN) {
4380 			fprintf(out, "~}"); state=OUT; k+=2;
4381 		}
4382 		if (k >= nHzline-1 && c1!=EOL) { fprintf(out, "~\n"); k=0; }
4383 		fputc(c1, out);
4384 		if (c1==EOL) k=0;
4385 		else if (c1=='\t') { k/=8; k = (k+1)*8; }
4386 		else k++;
4387 	    }
4388 	}
4389 	if (state==IN) fprintf(out, "~}");
4390 	if (!nGB) fprintf(errout, "Input may not be a GB file\n");
4391 }
4392 
zw2gb(FILE * in)4393 void zw2gb(FILE *in)
4394 {
4395 	int c1, c2, zW=0, Newline=1;
4396 
4397 	while ((c1=fgetc(in)) != EOF)
4398 	    if (!zW) {
4399 		if (c1==EOL) {
4400 		    fputc(EOL, out);
4401 		    Newline=1;
4402 		}
4403 		else if (Newline && c1=='z') {
4404 		    if ((c2=fgetc(in)) == EOF) {
4405 			 fputc(c1, out); break;
4406 		    }
4407 		    else if (c2=='W') zW=1;
4408 		    else fprintf(out, "%c%c", c1, c2);
4409 		    Newline = 0;
4410 		}
4411 		else {
4412 		    fputc(c1, out);
4413 		    Newline = 0;
4414 		}
4415 	    }
4416 	    else if (c1=='\n') {
4417 		zW=0; Newline=1; /* soft CR */
4418 	    }
4419 	    else { /* zW mode */
4420 		if ((c2=fgetc(in)) == EOF) {
4421 		    fputc(MSBon(c1), out);
4422 		    break;
4423 		}
4424 		else if (c2=='\n') {
4425 		    zW=0; Newline=1;
4426 		    if (c1=='#') fputc(EOL, out);
4427 		    else fprintf(out, "%c\n", MSBon(c1)); /*invalid zW seq.*/
4428 		}
4429 		else if (c1=='#' && c2==' ') fputc(' ', out);
4430 		else if (c1==' ') fputc(c2, out);
4431 		else fprintf(out, "%c%c", MSBon(c1), MSBon(c2));
4432 	    }
4433 }
4434 
span(int mode)4435 int span(int mode)
4436 /*
4437  * vertical column gap is uniform, only need to take care of 1st line image
4438  */
4439 {
4440 	int x, y, n, j, kc=1;
4441 	int cip0;
4442 
4443 	if (mode==0) {
4444 	    if (sline < column) return 0;
4445 	    x = BM-cTM;
4446 	    y = linecip[1]-lineclp[1];
4447 	    n = 1;
4448 	    cip0 = linecip[1];
4449 	    for (j=1; j<=sline; j++) {
4450 		y += lineclp[j];
4451 		if (y > x+BMover) {
4452 	    		y = linecip[j]-lineclp[j];
4453 			if (cip0 < linecip[j]) cip0 = linecip[j];
4454 			if (j != n) j--;
4455 			n = j+1; kc++;
4456 		}
4457 	    }
4458 	    linecip[0] = cip0;
4459 	    return (kc>column)? 1:0;
4460 	}
4461 	else if (mode==10 && AdjAtEndDoc) { /* end of document */
4462 		linecip[0] = linecip[1];
4463 		return BM;
4464 	}
4465 	else {
4466 	    n=0;
4467 	    do {
4468 		x=0; n++;
4469 		if (column==1) n=sline;
4470 		y = x = linecip[1]-lineclp[1];
4471 		linecip[0] = cip0 = linecip[1];
4472 		for (j=1; j <= n; j++) x += lineclp[j];
4473 		if (x+cTM >= BM) return BM;
4474 		else if (column==1) return (x+cTM);
4475 		kc=1;
4476 		for (j=1; j<=sline; j++) {
4477 
4478 		    y += lineclp[j];
4479 		    if (y > x + BMover) {
4480 			y = linecip[j]-lineclp[j];
4481 			if (cip0 < linecip[j]) cip0 = linecip[j];
4482 			j--; kc++;
4483 			if (kc>column) break;
4484 		    }
4485 		}
4486 		linecip[0] = cip0;
4487 		if (kc <= column && y <= x+BMover)
4488 			return (cTM+x > BM)? BM : (cTM+x);
4489 	    } while (kc>column);
4490 	}
4491 }
4492 
CheckLineLen()4493 int CheckLineLen()
4494 {
4495 	int	c1, c2, Hz;
4496 	unsigned int j, k, m=0, N=0;
4497 	int	i;
4498 	FILE	*in;
4499 
4500 	if (nHzline < 9999) return nHzline;
4501 	else if (nHzline==9999) nHzline=10000;
4502 	inf=Rinf; sbufp=0;
4503 	for (j=0; j<=150; j++) linedif[j]=0;
4504 	while ((in = inf->fp) != NULL) {
4505 	    if (!mute || convcode==FILT) fprintf(errout, " %s\n", inf->s);
4506 	    while ((c1=sgetc(in))!=EOF) {
4507 		if (c1==EOL) { /* used to determine nHzline */
4508 		    linedif[(m<150)?m:150]++;
4509 		    N += m; m=0;
4510 		}
4511 		else if (c1=='~' && lcode<JIS) {
4512 		    c2=sgetc(in);
4513 		    if (c2==EOL && nHzline>=10000) nHzline++;
4514 		    else if (c2=='{' || c2=='}') {
4515 			Hz++; m+=2;
4516 		    }
4517 		    else {
4518 			sungetc(c2); m++;
4519 		    }
4520 		}
4521 		else m++;
4522 	    }
4523 	    rewind(in);
4524 	    if (inf->p == NULL) break;
4525 	    else inf = inf->p;
4526 	}
4527 	inf=Rinf;
4528 
4529 	if (nHzline<9999) return nHzline;
4530 	if (Hz && convcode==HZGB) { /* 1% lines has ~\n */
4531 	    if ((nHzline-10000.)*200./Hz >= 2) return nHzline;
4532 	}
4533 	m=0;
4534 	for (j=0; j<=150; j++) m += linedif[j];
4535 /* long lines: # of lines < # of chars/100 or 20% lines have 150+ chars */
4536 	if (m < N/100 || m < linedif[150]*5) return 9999;
4537 		/* if 25% lines are N to N+3 chars long, set it */
4538 	for (j=0; j<=40; j++) {
4539 	    for (i = -1; i<=1; i+=2) {
4540 		N = 75 + j*i;
4541 		if ((linedif[N]+linedif[N+1]+linedif[N+2]+linedif[N+3]) > m/4)
4542 			return ( N - (1 - i) );
4543 	    }
4544 	}
4545 	return 9999;
4546 }
4547 
4548 
yes(int n)4549 int yes(int n)
4550 {
4551 	char s[40];
4552 	if (stdinput) return n; /* can't read from keyboard, use default */
4553 	do {
4554 		if (n>1) bell(); gets_stdin(s, 39);
4555 		if ((toupper(s[0]))=='Y') return 1;
4556 		else if ((toupper(s[0]))=='N') return 0;
4557 		else if (n<=1) return n;
4558 		else s[0]='\0';
4559 		fprintf(errout, "(Y/N) ?\n");
4560 	} while (s[0]=='\0');
4561 }
4562 
4563 
4564 #ifdef STAT   /* start STAT functions */
4565 /*
4566 #include "cnstat.h"
4567 */
4568 #else  /* No STAT functions */
4569 
statinit()4570 void statinit()
4571 {
4572 	fprintf(stderr,
4573 "Functions supported by enhanced version only\n\
4574 Please contact author\n");
4575 	cleanup(1); exit(0);
4576 }
4577 
wordstat(unsigned int d)4578 void wordstat(unsigned int d)
4579 {
4580 	return ;
4581 }
4582 
statistics(unsigned int Nchars,unsigned int NcharAll)4583 void statistics(unsigned int Nchars, unsigned int NcharAll)
4584 {
4585 	return ;
4586 }
4587 
stat_scan_output()4588 void stat_scan_output()
4589 {
4590 	return;
4591 }
4592 
4593 #endif  /* end STAT functions */
4594 
4595 
CharBMPshift()4596 void CharBMPshift() /* bitmap shift for char */
4597 {
4598 	unsigned int chl;
4599 
4600 	if (mx%8 > 0)
4601 	    fprintf(errout, "Width %d pixels not supported\n", mx);
4602 	else if (bmpshift >= mx)
4603 	    fprintf(errout,
4604 		"Request shift %d >= char width %d\n", bmpshift, mx);
4605 	else {
4606 	    fprintf(errout,
4607 "Please make a COPY of the original bitmap file(s)\n\
4608 Bitmap shift: %d pixels, %d (1-4, R/L/T/B) 0X%04X-0X%04X\n\
4609 Continue (Y/N)?\n",
4610 		bmpshift, bmpshift_dir, bmpshift_ch, bmpshift_ch2);
4611 	    if (yes(0)) {
4612 		for (chl=bmpshift_ch; chl<=bmpshift_ch2; chl++) {
4613 			fprintf(errout, "0X%04X:  ", chl);
4614 			HBFgetBitmap(chl);
4615 		}
4616 	    }
4617 	    else fprintf(errout, "Aborted\n");
4618 	}
4619 	cleanup(1); exit(0);
4620 }
4621 
CharBitmapShift(FILE * fp,long addr,unsigned char * a)4622 int CharBitmapShift(FILE *fp, long addr, unsigned char *a)
4623 {
4624 	unsigned char *c, ON[8];
4625 	int     j, k, n;
4626 
4627 	ON[0]=128;
4628 	for (j=1; j<8; j++) ON[j]=ON[j-1]/2;
4629 	c = (unsigned char *) calloc(CHsize+1, sizeof(unsigned char));
4630 	if (c==NULL) MemExit();
4631 
4632 	for (j=0; j<CHsize; j++) c[j]=0;
4633 	switch (bmpshift_dir) {
4634 	    case T: case B:
4635 		n = bmpshift * (mx/8);  /* rows to be shifted */
4636 		for (j=0; j<CHsize; j++) {      /* circular */
4637 		    if ((k=j+n) >= CHsize) k -= CHsize;
4638 		    if (bmpshift_dir==T) c[j] = a[k];
4639 		    else c[k] = a[j];
4640 		}
4641 	    /* for (j=n; j<CHsize; j++)   simple shift out
4642 		    if (bmpshift_dir==T) c[j-n]=b[j];
4643 		    else c[j]=b[j-n]; */
4644 		break;
4645 	    case R: case L:
4646 		n = mx*my;
4647 		for (j=0; j<n; j++) {
4648 		    if (bmpshift_dir==L) {
4649 		      if ((k=j+bmpshift) >= n) k -= n;
4650 		    }
4651 		    else if ((k=j-bmpshift) < 0) k += n;
4652 		    if (a[k/8] & ON[k%8]) c[j/8] += ON[j%8];
4653 		}
4654 		break;
4655 	    case RMIRROR:     /* rotate a mirror bitmap:
4656 				 matrix transpose, Cij = Aji */
4657 		for (j=0; j<CHsize; j++) {
4658 			c[j]=0;
4659 			for (k=0; k<8; k++) {
4660 			    n = k*mx +j*my*8; n = n/(mx*my) + n%(mx*my);
4661 			    if (a[n/8] & ON[n%8]) c[j] += ON[k];
4662 			}
4663 		}
4664 		for (j=0; j<CHsize; j++) a[j]=c[j];
4665 		break;
4666 	    default: break;
4667 	}
4668 	if (bmpshift_dir != RMIRROR) {
4669 	    fseek(fp, addr, 0);
4670 	    k = (int) fwrite(c, CHsize, 1, fp);
4671 	    fprintf(errout, "W%d\n", k);
4672 	}
4673 	free(c);
4674 	return 0;
4675 }
4676 
gbb5convinit(int dirc)4677 void gbb5convinit(int dirc)
4678 /* dirc: GBB5 or B5GB */
4679 {
4680 	FILE    *in;
4681 	int     j;
4682 	unsigned int gbb5_nchar;
4683 
4684 	gbb5_nchar = (dirc==GBB5)? 8178: 13973;      /* 'standard' GB/B5 only */
4685 /*
4686 	gbb5_cspace = (dirc==GBB5) ? 0xA140 : 0xA1A1;
4687 	gbb5_b1l = gbb5_cspace/256;
4688 */
4689 
4690 
4691 	gbb5_fstr = (unsigned int *) calloc(gbb5_nchar+1, sizeof(unsigned int));
4692 	gbb5_ptstr= (unsigned char **)
4693 		calloc(gbb5_nchar+1, sizeof(unsigned char *));
4694 	if (gbb5_fstr==NULL || gbb5_ptstr==NULL) MemExit();
4695 	for (j=0; j<gbb5_nchar; j++) {
4696 	    gbb5_fstr[j] = 30000;
4697 	    gbb5_ptstr[j] = NULL;
4698 	}
4699 
4700 /* read in conversion table */
4701 	j=0;
4702 	if (strlen(KWfile)==0) getdata(5);
4703 	if (KWfile[0] != '\0') {
4704 	    if ((in=Rfopen(KWfile, "r")) == NULL) j++;
4705 	    else gbb5tableinit(dirc, in);
4706 	}
4707 	if (G2Bfileb[0] != '\0') {
4708 	    if ((in=Rfopen(G2Bfileb, "r")) == NULL) j++;
4709 	    else gbb5tableinit(dirc, in);
4710 	}
4711 	if (j==2) {
4712 	    fprintf(errout, "Can't open GB<->B5 table file -> %s\n", KWfile);
4713 	    exit(0);
4714 	}
4715 }
4716 
gbb5tableinit(int dirc,FILE * in)4717 void gbb5tableinit(int dirc, FILE *in)
4718 /* dirc: GBB5 or B5GB */
4719 {
4720 	unsigned char   *p, *t, cst[120];
4721 	int     j, k1, k2, wordmap;
4722 
4723 	while (fgets((char *) cst, 118, in)!=NULL) {
4724 		/* MSB set for both GB and Big5, minimum line "GBB5\n" */
4725 	    if (cst[0] < 0xA1 || strlen((char *) cst) < 5) continue;
4726 	    p = &cst[0];
4727 	    wordmap=0;  /* def: char mapping */
4728 	    k1 = GBPOS(p[0], p[1]);
4729 	    k2 = B5POS(p[2], p[3]);
4730 		/* "GBGB B5B5\n", use space or tab as seperator, but change
4731 		 * tab to space */
4732 	    j=strlen((char *) p);
4733 	    if (j >= 10) {
4734 		while (*++p != '\0')
4735 			if (*p == ' ' || *p == '\t') {
4736 			    *p = ' ';
4737 			    if (strlen((char *) p) >= 6) wordmap=1;
4738 			    k2 = B5POS(p[1], p[2]);
4739 			    break;
4740 			}
4741 		p = &cst[0];
4742 	    }
4743 	    if (k1<0 || k2<0) continue;  /* mapping line not complete */
4744 
4745 /* word (phrase) mapping */
4746 	    if (wordmap) {
4747 		p[j-1] = ' '; p[j]='\0';
4748 		if (dirc==B5GB) k1=k2;
4749 	/* allow more than one pair  */
4750 		if (gbb5_ptstr[k1]!=NULL) j += strlen((char *)gbb5_ptstr[k1]);
4751 		t = (unsigned char *) calloc(j+1, sizeof(unsigned char));
4752 			/* if not enough space, ignore current pair */
4753 		if (t==NULL) continue;
4754 		t[0]='\0';
4755 		if (gbb5_ptstr[k1]!=NULL) {
4756 			strcpy((char *) t, (char *) gbb5_ptstr[k1]);
4757 			free(gbb5_ptstr[k1]);
4758 		}
4759 		gbb5_ptstr[k1] = t;
4760 		strcat((char *) gbb5_ptstr[k1], (char *) p);
4761 
4762 
4763 
4764 		continue;
4765 	    }
4766 /* else: char mapping, overwrite previous ones */
4767 	    if (dirc==GBB5) gbb5_fstr[k1]=k2;
4768 	    else {
4769 		gbb5_fstr[k2]=k1;
4770 		    /* multiple mapping possible */
4771 		p += 4;
4772 		while (strlen((char *) p) >=3) {
4773 				/* always terminated with EOL */
4774 			if ((k2=B5POS(p[0], p[1])) >= 0) gbb5_fstr[k2]=k1;
4775 			p += 2;
4776 		}
4777 	    }
4778 	}
4779 	fclose(in);
4780 }
4781 
gbb5conv(FILE * in,int dirc)4782 void gbb5conv(FILE *in, int dirc)
4783 {
4784 	int     c1, c2, idx, matched;
4785 	unsigned int ch;
4786 	unsigned char *m, *p, *t, s1[45], s2[45];
4787 
4788 	sbufp=0;
4789 	while ((c1=sgetc(in)) != EOF) {
4790 	    if (c1>=0xa1) {
4791 		if ((c2=sgetc(in))==EOF) break;
4792 		else if (c2>=0xa1 || (dirc==B5GB && c2>=0x40)) {
4793 		    idx = (dirc==B5GB)? B5POS(c1, c2) : GBPOS(c1, c2);
4794 /* consider word mapping first */
4795 		    if ((m=gbb5_ptstr[idx]) != NULL) {
4796 			matched=0;
4797 			while (strlen((char *)m) >= 9) {
4798 			    p=m;
4799 			/*  k=0; while ((s1[k] = *p++) != ' ') k++;
4800 			    sscanf((char *) p, "%s", (char *) s2);
4801 			    s1[k]=s2[strlen((char *) s2)+1]='\0';
4802 			*/
4803 			    sscanf((char *)p, "%s %s", (char *)s1, (char *)s2);
4804 			/* advance pointer to next word pair */
4805 			    m += strlen((char *) s1) + strlen((char *) s2) + 2;
4806 			/* compare with current word pair */
4807 			    p = (dirc==B5GB)? &s2[1] : &s1[1];
4808 			    t = p+1;
4809 			    while (*++p != '\0') {
4810 				if ((c1=sgetc(in)) != *p) {
4811 					sungetc(c1);
4812 					while (--p >= t) sungetc(*p);
4813 					break;
4814 				}
4815 			    }
4816 			    if (p>t) {  /* words match, map word */
4817 				p = (dirc==B5GB)? &s1[0] : &s2[0];
4818 				while (*p != '\0')
4819 				    fprintf(out, "%c", *p++);
4820 				matched++;
4821 				break;
4822 			    }
4823 			}
4824 			if (matched) continue; /* while sgetc(in) loop */
4825 			/* else words not match, map char */
4826 		    }
4827 /* one to one char mapping */
4828 		    if (dirc==B5GB) {
4829 			ch = (gbb5_fstr[idx]==30000)? GBbox : gbb5_fstr[idx];
4830 			fprintf(out, "%c%c", GBB1(ch), GBB2(ch));
4831 		    }
4832 		    else {
4833 			ch = (gbb5_fstr[idx]==30000)? B5box : gbb5_fstr[idx];
4834 			fprintf(out, "%c%c", B5B1(ch), B5B2(ch));
4835 		    }
4836 		}
4837 		else fprintf(errout, "Bad pair: %02X%02X\n", c1, c2);
4838 	    }
4839 	    else fprintf(out, "%c", c1);
4840 	}
4841 }
4842 
convertEOL(unsigned char * t,int * jmax)4843 void convertEOL(unsigned char *t, int *jmax)
4844  /* CR or CR-LF to LF, for a unified treatment */
4845 {
4846 	int	nc=0;	/* # of CR-LF converted to LF */
4847 	unsigned char *s;
4848 
4849 	if (lcode==UTF) return; /* don't do this for unicode */
4850 	s=t;
4851 	while (*t = *s) {
4852 		if (*s==CR) {
4853 			*t = LF;
4854 			if (*++s == LF) nc++;
4855 			else s--;
4856 		}
4857 		s++; t++;
4858 	}
4859 	*jmax -= nc;
4860 }
4861 
CodeConversion()4862 void CodeConversion()
4863 {
4864 	int	conv_code, n;
4865 	do {
4866 	    conv_code = convcode;	/* save original convcode */
4867 	    switch(convcode) {
4868 	    case HZGB:
4869 		if (nHzline==9999) nHzline = CheckLineLen();
4870 		break;
4871 	    case HZB5:
4872 		convcode=HZGB;
4873 		if (nHzline==9999) nHzline = CheckLineLen();
4874 		convers(0);
4875 		convcode=GBB5;
4876 		gbb5convinit(GBB5);
4877 		break;
4878 	    case GBB5: case B5GB:
4879 		gbb5convinit(convcode);
4880 		break;
4881 	    case B5HZ:
4882 		convcode=B5GB;
4883 		gbb5convinit(B5GB);
4884 		convers(0);
4885 		convcode=GBHZ;
4886 		break;
4887 	    case GBUNI:	case B5UNI: case KSCUNI: case JISUNI:
4888 		if (convcode==GBUNI) n = GB;
4889 		else if (convcode==B5UNI) n = B5;
4890 		else n = (convcode==KSCUNI)? KSC : JIS;
4891 		loadUNImappingtable(n, 1);
4892 		if (code==UTF8) convcode=CJKUTF8;
4893 		else if (code==UTF7) convcode=CJKUTF7;
4894 		else convcode = (code==UTF16)? CJKUTF16LE : CJKUTF16;
4895 		break;
4896 	    case UNIGB:	case UNIB5: case UNIKSC: case UNIJIS:
4897 			/* assume 16-bit, 8-bit or 7-bit utf */
4898 		if (convcode==UNIGB) n = GB;
4899 		else if (convcode==UNIB5) n = B5;
4900 		else n = (convcode==UNIKSC)? KSC : JIS;
4901 		loadUNImappingtable(n, 0);
4902 			/* first convert to UTF-16BE then to proper code */
4903 		if (code==UTF7) convcode = UTF7CJK;
4904 		else if (code==UTF8) convcode = UTF8CJK;
4905 		else convcode = (code==UTF16)? UTF16LECJK : UTF16CJK;
4906 		convers(0);
4907 	    	convcode = conv_code;	/* restore old original convcode */
4908 		break;
4909 	    case TOSHORTPS: case PAGEPRINT:  /* old PSPRINT function */
4910 		convers(10);
4911 		exit(0);
4912 		break;
4913 	    default: break;
4914 	    }
4915 	    convers(convt_and_print? 0:1); 	/* 1 = conversion only */
4916 	    convcode = conv_code;	/* restore old original convcode */
4917 	} while (OIOU(0) != NT);
4918 }
4919 
GetCharUsage()4920 void GetCharUsage()
4921 /* prepare char statistics for buliding dict */
4922 {
4923 	long	nchars_doc;	/* # of chars in document */
4924 	long	ndchar_font;	/* # of different char/font variations */
4925 	long	ndchar_font_1;  /* # of diff. char/font var. with 1 occur. */
4926 	long	m;
4927 	unsigned int i, j;
4928 	struct FontTag *F;
4929 
4930 	m=0;
4931 	nchars_doc = ndchar_font = ndchar_font_1 = 0;
4932 	for (j=0; j<MAXLINES; j++) linedif[j]=0;
4933 	for (F=Fonts; F!=NULL; F=F->p) {
4934 		/* white space does not count: not 0 addr for GBK/B5P */
4935 	    F->fstring[Addr(cspace/256, cspace%256)]=0;
4936 	    F->ndchar=0;	/* # of different chars used for this font */
4937 	    for (i=0; i < F->nchar; i++) {
4938 		if (F->fstring[i] == 0) continue;
4939 		F->ndchar++;
4940 		nchars_doc += F->fstring[i];
4941 		ndchar_font++; /*N++;*/
4942 		if (F->fstring[i]==1) ndchar_font_1++; /*n++;*/
4943 			/* usage histogram */
4944 		linedif[(F->fstring[i] > MAXLINES-2)?
4945 			MAXLINES-2 : F->fstring[i] ]++;
4946 	    }
4947 
4948 	    F->fdict = (unsigned int *) calloc(F->ndchar, sizeof(unsigned int));
4949 	    if (F->fdict==NULL) MemExit();
4950 	    F->k = F->nCN = F->ndchar;
4951 	}
4952 
4953 	if (nchars_doc > 0) fprintf(stderr,
4954 "There are %ld characters in the document (%ld %s)\n\n",
4955 nchars_doc, ndchar_font,
4956 (Fonts->p==NULL)? "unique characters" : "char/font combinations");
4957 
4958 	j = (int) (ndchar_font - ndchar_font_1);
4959 	if (nCN > j) nCN = j; /* # of chars in dict(s) cannot exceed nCN */
4960 	m = ndchar_font;
4961 	j=0;
4962 	if (ndchar_font > 0) {
4963 	    while (++j <= MAXLINES-2) {
4964 		if (m<=0) break;
4965 		if (linedif[j] == 0) continue;
4966 		else if (j==MAXLINES-2) j=65000;
4967 		for (F=Fonts; F!=NULL; F=F->p) {
4968 		    for (i=0; i < F->nchar; i++) {
4969 			if (F->fstring[i]>0 && F->fstring[i]<=j) {
4970 			    F->fdict[--(F->k)]=i; F->fstring[i] += 30000;
4971 			    if ((int) m > nCN) (F->nCN)--;
4972 			    if (--m==0) break;
4973 			}
4974 		    }
4975 		    if (m==0) break;
4976 		}
4977 	    }
4978 	    for (F=Fonts; F!=NULL; F=F->p) {
4979 
4980 		if (F->nCN > 0) for (j=0; j < F->nCN; j++)
4981 			F->fstring[F->fdict[j]] = j+60000;
4982 		if (F->nCN < F->ndchar) for (j = F->nCN; j < F->ndchar; j++)
4983 			F->fstring[F->fdict[j]] -= 29900;
4984 	    }
4985 	}
4986 }
4987 
print_range_check(int npg)4988 int print_range_check(int npg)
4989 {
4990 	return (npg>=bp && (!ep || npg<=ep) &&
4991 	  (!odd || (odd==1 && npg%2) || (odd>=2 && !(npg%2))))? 1:0;
4992 }
4993 
set_doc_defaults()4994 void set_doc_defaults()
4995 /*
4996  * restore to original settings after prescan mode
4997  */
4998 {
4999 	int	j;
5000 
5001 	PCN=SCN=1;
5002 	column = defcolumn;
5003 	Ca=defCa; Ci=defCi;
5004 	Cx=defCx; Cy=defCy;
5005 	if (nEF != defnEF) {
5006 		nEF=defnEF;
5007 		getEfontdata(1);
5008 	}
5009 	/*if (nEF%nEFfamily == 2) for (j=0; j<129; j++) Wasc[j] = 1.;*/
5010 
5011 	ptspc==defptsi;
5012 	pts=defpts;
5013 	charsize(defpts);
5014 	V=TM; H=LM;
5015 	cRM = RM; cBM = BM; cTM=cLM=0;
5016 	if (column>1) cRM = LM + columnWidth();
5017 	spaceH = -1; Ha = 0;
5018 	pgpd=0; pgcount=pgcount_bak;
5019 	Prntpage = print_range_check(pgcount);
5020 	inCH=100; newpos=1;
5021 	ascbuf.p=ascbuf.pp=0;
5022 	indentL=indentR=0;
5023 	color.gray = color.red = color.green = color.blue = 0.0;
5024 }
5025 
main(int argc,char ** argv)5026 main(int argc, char **argv)
5027 {
5028     int     j, jmax, c, endfile, buftoosmall;
5029     unsigned char *s, *p;
5030     unsigned char *mbuf;	/* main buffer */
5031     unsigned int mbufsz, bufused;
5032     float   Cis, Cas, Cascs, Cxs, Cys;
5033     int	    ptspcs;
5034     int     snEF, CSPs, CLPs, CIPs, scnsp, sfrl, inCHs, sctradj;
5035     int	    indentRs, indentLs;
5036     struct FontTag *sFontptr;
5037     struct ColorGrayStr colors;
5038     int	    linewidths;
5039     FILE    *in;
5040 
5041     mRinf=Rinf=NULL;
5042     mbuf=NULL;
5043     init(argc, argv);
5044 
5045     if (bmpshift) CharBMPshift(); /* exit */
5046 
5047     if (convcode!=FILT && breakfile>10) { /* multiple input, multiple output */
5048 	mRinf = Rinf->p;
5049 	Rinf->p = NULL;
5050     }
5051 
5052     if (convcode && convcode!=FILT) {
5053 	CodeConversion();
5054 	if (convt_and_print) convcode = NT;
5055 	else {
5056 		if (stdinput) remove(Rinf->t);
5057 		signature();
5058 		exit(0);
5059 	}
5060     }
5061 
5062     if (timestat>=3) {
5063 	statinit();
5064 	stat_scan_output(); /* exit  */
5065     }
5066 
5067     if (mbuf==NULL) {
5068 	mbufsz=BUFSIZE;
5069 	mbuf = (unsigned char *) calloc(mbufsz, sizeof(unsigned char));
5070 	if (mbuf==NULL) MemExit();
5071     }
5072 
5073     if (convcode==FILT) {
5074 	fprintf(errout, (fix)? "Repair ...\n" :
5075 		"Filter out functional sequences ...\n");
5076 	if (nHzline==9999) nHzline = CheckLineLen();
5077 	if (nHzline==9999 && fix!=2) nHzline=70;
5078 	if (nHzline > 160 && fix==2) copies=nHzline=80;
5079 	nchar=odd=0;
5080 	if (copies==1) copies=100;
5081     }
5082 
5083     style((convcode==FILT || mute)? 0:1);
5084 
5085 /* one-input, one-output loop */
5086     do {
5087 	if (convcode != FILT) {
5088 		if (DetectMIMEType() == 1) {
5089 			j = convcode;
5090 			convcode=MIMEQP; convers(0);
5091 			convcode = j;
5092 		}
5093 		if (addrlabel) {
5094 			j = convcode;
5095 			convcode=ADDLBAS; convers(0);
5096 			convcode = j;
5097 		}
5098 		if (lcode==JIS) jispreproc();
5099 		else if (lcode==KSC) kscpreproc();
5100 		else if (lcode==UTF) unicodepreproc();
5101 		else if (lcode==GBK || lcode==B5P) ;
5102 		else gbb5preproc();
5103 		if (!mute) fprintf(errout, "Scanning document(s) ...\n");
5104 	}
5105 
5106 /* Scan/Print mode loop */
5107 	for (PreScanMode=1; PreScanMode>=0; PreScanMode--) {
5108 	    set_doc_defaults();
5109 	    if (convcode!=FILT && !PreScanMode) {
5110 		GetCharUsage();
5111 		if (*PSfile==0) {
5112 			strcpy(PSfile, Rinf->s);
5113 			FName(PSfile, PSstr);
5114 		}
5115 		if (!mute) fprintf(errout, "%s --> PS ...\n", codename[lcode]);
5116 		header();
5117 	    }
5118 	    endfile=0;
5119 	    inf=Rinf; in=inf->fp;
5120 	    mbuf[0]=fgetc(in); mbuf[1]='\0'; p = mbuf;
5121 	    while (p[0]!='\0') {
5122 		/* reorganize buf */
5123 		if (!endfile && strlen((char *) p) < mbufsz-2048) {
5124 		    j=0;
5125 		    if (p != mbuf) while (mbuf[j++] = *p++) ;
5126 		    jmax=strlen((char *) mbuf); j=mbufsz-jmax-5;
5127 		    while (--j) {
5128 			if ((c=getc(in)) != EOF) {
5129 				if (c!='\0') mbuf[jmax++]=c;
5130 			}
5131 			else {
5132 			    if (PreScanMode) rewind(in);
5133 			    else {
5134 				fclose(in); inf->fp=NULL;
5135 				if (input_file_layer > 0) remove(inf->s);
5136 			    }
5137 			    if (inf->p == NULL) {
5138 				endfile=1; break;
5139 			    }
5140 			/* else */
5141 			    inf=inf->p;
5142 			    if ((in = inf->fp) == NULL) {
5143 				endfile=1; break;
5144 			    }
5145 			    else if (breakfile && convcode!=FILT) {
5146 			/* does not work with unicode */
5147 				mbuf[jmax++]='@'; mbuf[jmax++]='[';
5148 				mbuf[jmax++]='P';
5149 				mbuf[jmax++]= '0'+(breakfile-1);
5150 				mbuf[jmax++]=']';
5151 				j -= 5;
5152 			    }
5153 			    else {
5154 				mbuf[jmax++]=EOL; j--;
5155 			    }
5156 			}
5157 		    }
5158 		    mbuf[jmax]='\0';
5159 		    /*if (convcode!=FILT)*/ convertEOL(mbuf, &jmax);
5160 		    p = mbuf;
5161 		}
5162 		s=p; H = LM+indentL;
5163 /* save status variables that will be used and changed by search */
5164 		Cis=Ci; Cas=Ca; Cascs=Casc; Cxs=Cx; Cys=Cy; ptspcs=ptspc;
5165 		snEF=nEF;
5166 		CSPs = CSP; CLPs = CLP; CIPs = CIP;
5167 		scnsp=cnsp; sfrl=frl; inCHs=inCH;
5168 		sctradj=centraladj;
5169 		sline=fnewline=0;
5170 		/*lineclp[0]=*/ lineclp[1]=CLP;
5171 		/*linecip[0]=*/ linecip[1]=CIP;
5172 		frl=NT; cnsp=0; inCH=100; ascbuf.p=ascbuf.pp=0;
5173 		sFontptr=CurrentFont;
5174 		indentRs=indentR;
5175 		indentLs=indentL;
5176 		colors.gray = color.gray;
5177 		colors.red = color.red;
5178 		colors.green = color.green;
5179 		colors.blue = color.blue;
5180 		linewidths = linewidth;
5181 /* SEARCH */
5182 		bufused = (unsigned int) (p - mbuf);
5183 		buftoosmall = 0;
5184 		for (;;) {
5185 		    while (!fnewline && *s!='\0' && (s[1]!='\0' || endfile) )
5186 			s = (lcode==UTF)? doAC_unicode(s, 0) : doAC(s, 0);
5187 		    if (SCN==2 || convcode==FILT) break;
5188 		    else if ( span(0) || (endfile && s[0]=='\0') ) {
5189 			if (endfile && s[0]=='\0') {  /* see issfs  SCN=2 */
5190 				if (s[-1]!=EOL) newline(0, 1);
5191 				cBM=span(10);
5192 			}
5193 			else cBM = BM;
5194 			cLM = LM;  /* this may create problem */
5195 			pcolumn = 1;
5196 			break;
5197 		    }
5198 		    else if (!endfile &&
5199 				(s[0]=='\0' || (s[0]!='\0' && s[1]=='\0')) ) {
5200 /* needs to recover all status variables */
5201 			buftoosmall = 1;
5202 			break;
5203 		    }
5204 		    fnewline = 0;
5205 		}
5206 		if (convcode==FILT) { p=s; continue;}
5207 /* recover status variables */
5208 		Ci=Cis; Ca=Cas; Casc=Cascs; Cx=Cxs; Cy=Cys; ptspc=ptspcs;
5209 		CSP = CSPs; CLP = CLPs; CIP = CIPs;
5210 		cnsp=scnsp; frl=sfrl; inCH=inCHs;
5211 		centraladj=sctradj;
5212 		ascbuf.p=ascbuf.pp=0;
5213 		indentR=indentRs;
5214 		indentL=indentLs;
5215 		color.gray = colors.gray;
5216 		color.red = colors.red;
5217 		color.green = colors.green;
5218 		color.blue = colors.blue;
5219 		linewidth = linewidths;
5220 		if (nEF != snEF) {
5221 			nEF=snEF;
5222 			getEfontdata(0);
5223 		}
5224 		if (CurrentFont != sFontptr) {
5225 			strcpy(HBFname, sFontptr->FontName);
5226 			HBFopen();
5227 		}
5228 		if (buftoosmall) {
5229 			if (mbufsz>MAXBUFSZ) MemExit();
5230 			mbufsz += 3072;
5231 			mbuf = (unsigned char *) realloc(mbuf, mbufsz);
5232 			if (mbuf==NULL) MemExit();
5233 			p = mbuf; p += bufused;
5234 			continue;
5235 		}
5236 /* PRINT */
5237 		pline=1; H=cLM+indentL;
5238 		/*if (V==cTM)*/ V += linecip[1];
5239 
5240 		if (cTM+linecip[0]*0.75 > BM && cTM+linecip[1] > BM+BMover) {
5241 			endpage(0);
5242 			V=cTM=TM; H=cLM=LM;
5243 			PCN=SCN=1; pcolumn=1;
5244 			continue;
5245 		}
5246 		do {
5247 		    fnewline=0;
5248 		    while (!fnewline && *p!='\0' && (p[1]!='\0' || endfile) )
5249 			p = (lcode==UTF)? doAC_unicode(p, 1) : doAC(p, 1);
5250 		} while (pline<=sline && *p!='\0');
5251 	    }
5252 	    if (convcode==FILT) {
5253 		if (sbufp) sbufprint(EOL);
5254 		convers(1);
5255 		PreScanMode--;	/* bypass */
5256 	    }
5257 	    else { 	/* last EOL is ignored, explicit action needed */
5258 		if (ascbuf.p) {
5259 		    clearascbuf(1, 1); endAC(1);
5260 		}
5261 		endpage(1);
5262 	    }
5263 	} /* end of PreScanMode loop */
5264 	if (booklet) tobooklet();
5265     } while (OIOU(1) != NT); /* one-input, one-output loop */
5266 
5267     free(mbuf);
5268     cleanup(0);
5269     if (stdinput) remove(Rinf->t);
5270     signature();
5271     exit(0);
5272 }
5273 
OIOU(int fstr_used)5274 int OIOU(int fstr_used)
5275 /* one input one output: multiple input, seperate output
5276       Does not work for convcode=FILT because of "breakfile" */
5277 {
5278 	int	j;
5279 	struct FontTag *F;
5280 
5281 	if (fstr_used) {	/* re-initialize fstring and ptstring */
5282 	    for (F=Fonts; F!=NULL; F=F->p) {
5283 		for (j=0; j < F->nchar; j++) {
5284 		    if (F->fstring[j]>0 && F->fstring[j]<60000) {
5285 			if (F->ptstring[j] != NULL && F->ptstring[j] != dummy)
5286 				free(F->ptstring[j]);
5287 			F->ptstring[j]=NULL;
5288 		    }
5289 		    F->fstring[j]=0;
5290 		}
5291 	    }
5292 	}
5293 	if (convcode!=FILT && breakfile>10 && mRinf!=NULL) {
5294 		inf = Rinf = mRinf;
5295 		mRinf = Rinf->p;
5296 		Rinf->p = NULL;
5297 	/* set to default values: there are others affected, not clean */
5298 		init(RINIT, NULL);
5299 		opnfile(OUT);
5300 		PSfile[0]='\0';
5301 		code=codecmd;
5302 		pgpd=0; pgcount=1;
5303 		nCN=2048;
5304 		return 1;
5305 	}
5306 	else return NT;
5307 }
5308 
doAC(unsigned char * q,int pr)5309 unsigned char *doAC(unsigned char *q, int pr)
5310 {
5311 	int     k, j=1;
5312 	unsigned char c1, c2;
5313 
5314 	c2=0; c1 = *q++;
5315 	if (c1>=b1l) {  /* b1l=0xa1, or 0x30 if utf */
5316 	    if (q[0]=='\0') ;
5317 	    else {
5318 		c2 = *q++;
5319 		if (c2 >= b2l) {
5320 		    if (lcode==GB && alnumadjust) { /* also for JIS ? */
5321 			if (c1==0xa3 && isalnum(c2-128)) c1=c2-128;
5322 			else if (c1==0xa1 && c1==c2 && !inCH && *q>=c1)
5323 				c1=0x20; /* ascii non-ascii_space ascii */
5324 			else j = 2;
5325 		    }
5326 		    else j = 2;
5327 		}
5328 		/*else if (lcode==B5 && c2 >= 0x40) j = 2; */
5329 		else {q--; c2=0;}
5330 	    }
5331 	}
5332 	else if (c1=='@' && q[0]=='[') {
5333 		if (k=isfs(q, pr)) {
5334 			q += k; j=0;
5335 		}
5336 	}
5337 
5338 	if (j==2) k = putCH(c1, c2, pr);
5339 	else if (j==1) {
5340 	    if (c1==EOL && *q=='\0' && pr) k=0; /* Don't print the last EOL */
5341 	    else if (!vgb || !isvgb(c1)) {
5342 		k = putASC(c1, q[0], pr);
5343 	    }
5344 	    else k = putCH(0xa3, c1+128, pr);
5345 	}
5346 	else k=0;
5347 	if (k==1 && c2!=0) k++;         /* (c1, c2) --> c1-128 */
5348 	if (convcode==FILT && !k) k = filter(c1, (j==1)? q[0]:c2, q, j);
5349 	return (q-k);
5350 }
5351 
MemExit()5352 void MemExit()
5353 {
5354 	fprintf(stderr, "CNPRINT: not enough memory\n");
5355 	exit(2);
5356 }
5357 
Rfopen(char * fn,char * mod)5358 FILE *Rfopen(char *fn, char *mod)
5359 {
5360 	char cst[100];
5361 	struct Roots *rt;
5362 	FILE *fp;
5363 
5364 	rt=root;
5365 	do {
5366 		cst[0]='\0';
5367 		if (rt!=NULL) strcpy(cst, rt->s);
5368 		strcat(cst, fn);
5369 /* fprintf(errout, "open: @%s@\n", cst);
5370 */
5371 		if ((fp=fopen(cst, mod))!=NULL) return fp;
5372 		if (rt!=NULL) rt = rt->p;
5373 	} while (rt!=NULL);
5374 	return NULL;
5375 }
5376 
filter(unsigned char c1,unsigned char c2,unsigned char * q,int j)5377 int filter(unsigned char c1, unsigned char c2, unsigned char *q, int j)
5378 
5379 /*
5380  * now assumes CR or CR/LF has been converted to LF
5381  * does not handle unicode
5382  */
5383 {
5384     int n=0, k;
5385     if (c1==LF && breakfile) {
5386 	    if (fnchar >= (breakfile-2)*1024L) {
5387 		convers(100);   /* save into small files */
5388 		fnchar = 0;
5389 	    }
5390     }
5391     switch(fix) {
5392 	case 0:
5393 		if (j==1) sbufprint(c1);
5394 		else if (j==2) {
5395 			sbufprint(c1); sbufprint(c2);
5396 		}
5397 		break;
5398 	case 3: case 4:
5399 	    if ((j==1 && (c1==' ' || c1=='\t')) || ((c1*256)+c2)==cspace) {
5400 		for (k=0; k<j; k++) {
5401 		    if (ignorespace!=nchar || (ignorespace==nchar && nchar<4))
5402 			sbufprint(' ');
5403 		    nchar++; ignorespace++;
5404 		}
5405 	    }
5406 	    else {
5407 		if (ignorespace==nchar && nchar<4 && (nchar>0 || fix==4) ) {
5408 		    if (c1!=EOL)
5409 			for (k=nchar; k<4; k++) sbufprint(' ');
5410 		    nchar=4;
5411 		}
5412 		nchar++; ignorespace=0;
5413 		sbufprint(c1);
5414 		if (c1==LF) nchar=0;
5415 		if (j==2) {
5416 		    sbufprint(c2); nchar++;
5417 		}
5418 	    }
5419 	    break;
5420 	case 7: /* for CStar: in V1.3a, if HZ and non-punctuation, add
5421 			space before CH char, should be more intelligent */
5422 		if (j==1) sbufprint(c1);
5423 		else if (j==2) {
5424 if ( (c1==0xA1 && c2<=0xC3) || (c1==0xA3 && !isalnum(c2-0x80)) ) ;
5425 		    /* else if (sbufp==0) ;
5426 		    else if (sbuf[sbufp-1]==' ' || sbuf[sbufp-1]=='\t'); */
5427 		    else sbufprint(' ');
5428 		    sbufprint(c1); sbufprint(c2);
5429 		}
5430 	    break;
5431 	case 8: /* for CStar: if ...HZ HZ..., delete space --> ...HZHZ... */
5432 		if (j==1) {
5433 		    if (c1==' ' && c2>=0xA1) {
5434 			; /* if (sbufp==0) ;
5435 			else if (sbuf[sbufp-1]==' ' || sbuf[sbufp-1]=='\t')
5436 				sbufprint(c1); */
5437 		    }
5438 		    else sbufprint(c1);
5439 		}
5440 		else if (j==2) {
5441 		    sbufprint(c1); sbufprint(c2);
5442 		}
5443 	    break;
5444 	default:        /* 1 2 6 */
5445 	if (j==1) {
5446 	    if (nchar>=nHzline-2 && fix!=2) ignorespace=suppress; /* space */
5447 	    switch(c1) {
5448 		case LF:
5449 		/*case CR:               / * CR, LF, or CR+LF * /
5450 		    if (c1==CR && c2==LF) n--;  / * advance buf pointer by 1 */
5451 		    if (nchar<nHzline-2) {
5452 			ignorespace = ( (fix==2 && nchar>0) ||
5453 				(ignoreEOL && nchar==0) )? 1:0;
5454 			if (ignoreEOL) ignoreEOL=0;  /* fix=6, ignore 2nd */
5455 			else if (fix!=2 || (fix==2 && nchar==0) || EPS)
5456 				sbufprint(EOL);         /* EPS: keep EOL */
5457 		    }
5458 		    else {
5459 			if (fix==2 || EPS || nchar>copies) sbufprint(EOL);
5460 			if (EPS || fix==2) ignorespace=0;  /* copies: nmax */
5461 			if (fix==6) ignoreEOL=1;
5462 		    }
5463 		    nchar=0;
5464 		    break;
5465 		case ' ': case '\t':
5466 		    if (c2==LF) break;
5467 		    if (c1=='\t') nchar = (nchar/8 + 1) * 8;
5468 		    else nchar++;
5469 		    if (!ignorespace) sbufprint(c1);
5470 		    break;
5471 		case ',': case '.': case ':': case ';':
5472 		case '(': case ')': case '!': case '?':
5473 		case '"':
5474 		    if (!mute) { /* mute = map to CH */
5475 			nchar++; sbufprint(c1);
5476 			break;
5477 		    }
5478 		    else if (c1=='.' && c2=='.') {  /* .... do not convert */
5479 			do {
5480 			    nchar++; sbufprint(c1); n--;
5481 			} while (*q++ == c1);
5482 			n++;
5483 			break;
5484 		    }
5485 		    if (c2==' ') n--;  /* advance buffer pointer by 1 */
5486 		    if (lcode==GB) {
5487 			if (c1=='.') {
5488 				c1=0xA1; c2=0xA3;
5489 			}
5490 			else if (pausqm && c1=='"') {/* quot. mark pair? */
5491 				c2=0xB0+odd; c1=0xA1;
5492 				odd=(odd)? 0:1;
5493 			}
5494 			else {
5495 				c2=c1+0x80; c1=0xA3;
5496 			}
5497 		    }
5498 		    else if (lcode==B5) {
5499 			switch (c1) {
5500 			    case '"':
5501 				if (pausqm && c1=='"') {
5502 					c2=0xA7+odd;
5503 					odd=(odd)? 0:1;
5504 				}
5505 				else c2 = 0xB2;
5506 				break;
5507 			    case ',': c2=0x41; break;
5508 			    case '.': c2=0x43; break;
5509 			    case ':': c2=0x52; break;
5510 			    case ';': c2=0x51; break;
5511 			    case '(': c2=0x5D; break;
5512 			    case ')': c2=0x5E; break;
5513 			    case '?': c2=0x48; break;
5514 			    case '!': c2=0x54; break;
5515 			    default: break;
5516 			}
5517 			c1=0xA1;
5518 		    }
5519 		    else if (lcode==JIS) {
5520 			switch (c1) {
5521 			    case '"':
5522 				if (pausqm && c1=='"') {
5523 					c2=0xC8+odd;
5524 					odd=(odd)? 0:1;
5525 				}
5526 				else c2 = 0xED;
5527 				break;
5528 			    case ',': c2=0xA4; break;
5529 			    case '.': c2=0xA3; break;
5530 			    case ':': c2=0xA7; break;
5531 			    case ';': c2=0xA8; break;
5532 			    case '(': c2=0xCA; break;
5533 			    case ')': c2=0xCB; break;
5534 			    case '?': c2=0xA9; break;
5535 			    case '!': c2=0xAA; break;
5536 			    default: break;
5537 			}
5538 			c1=0xA1;
5539 		    }
5540 		    nchar += (1-n);
5541 		    sbufprint(c1); sbufprint(c2);
5542 		    break;
5543 		default:
5544 		    nchar++;            /* ignore news head char '>' */
5545 		    if (nchar==1 && c1==newshd && timestat) break;
5546 		    if (isprint(c1)) sbufprint(c1);
5547 		    break;
5548 	    }
5549 	}
5550 	if (j==2) {
5551 	    if (pausqm) switch((c1*256)+c2) {
5552 		case 0xA1B0: case 0xA1B1: case 0xA1E5: case 0xA3B2:
5553 		    c1=0xA1; c2=0xB0+odd;
5554 		    odd=(odd)? 0:1;
5555 		    break;
5556 		case 0xA3AE:
5557 		    c1=0xA1; c2=0xA3;
5558 		    break;
5559 		default:
5560 		    break;
5561 	    }
5562 	    if (!ignorespace || ((c1*256)+c2)!=cspace) {
5563 		sbufprint(c1); sbufprint(c2);
5564 	    }
5565 	    nchar+=2;
5566 	}
5567 /* j=0, ignore */
5568 	break;
5569     }
5570     fnchar += (j-n);
5571     return n;
5572 }
5573 
sbufprint(int c)5574 void sbufprint(int c)
5575 {
5576 	int j = -1;
5577 	ignoreEOL=0;
5578 	sbuf[sbufp++]=c;
5579 	if (c==EOL) {
5580 		j=sbufp;
5581 		while(--j) if (sbuf[j-1] != ' ' && sbuf[j-1] != '\t') break;
5582 		if (j != sbufp-1) {
5583 			sbuf[j]=EOL; sbufp=j+1;
5584 		}
5585 	}
5586 	if (sbufp>SBUFSIZE-1 || c==EOL) {
5587 		for (j=0; j<sbufp; j++) fputc(sbuf[j], out);
5588 		sbufp=0;
5589 	}
5590 }
5591 
sgetc(FILE * in)5592 int sgetc(FILE *in)
5593 {
5594 	return (sbufp>0)? sbuf[--sbufp] : getc(in);
5595 }
5596 
sungetc(int c)5597 int sungetc(int c)
5598 {
5599 	if (sbufp>=SBUFSIZE) {
5600 		fprintf(stderr, "sungetc: too many chars\n");
5601 		return -1;
5602 	}
5603 	else sbuf[sbufp++]=c;
5604 	return c;
5605 }
5606 
bell()5607 void bell()
5608 {
5609 	fprintf(stderr, "%c", 7);
5610 }
5611 
5612 
SkipESCSeq(FILE * in,int c,int * state)5613 int SkipESCSeq(FILE *in, int c, int *state)
5614 {
5615 	int temp = *state;
5616 	if (c == '$' || c == '(') sgetc(in);
5617 	*state = (c == 'K' || c == '$')? 1 : 0;
5618 	return (temp == *state)? 0 : 1;
5619 }
5620 
5621 
DetectJPCodeType()5622 int DetectJPCodeType()
5623 {
5624 	int c = 0, dct = ASCII;  /* detected code type */
5625 	FILE *in;
5626 
5627 	inf=Rinf;
5628 	sbufp=0;
5629 	while ((in = inf->fp) != NULL) {
5630 	    while (dct==EUCORSJIS || dct==ASCII) {
5631 		if ((c=sgetc(in)) == EOF) break;
5632 		if (c==ESC) {
5633 		    if ((c=sgetc(in)) == '$') {
5634 			c=sgetc(in);
5635 			if (c=='B' || c=='@') dct=JIS;  /* B: NEW, @: OLD */
5636 		    }
5637 		    else if (c=='K') dct=JIS;       /* NEC */
5638 		}
5639 		else if ((c>=129 && c<=141) || (c>=143 && c<=159))
5640 		    dct=SJIS;
5641 		else if (c==SS2) {
5642 		    c=sgetc(in);
5643 		    if ((c>=64 && c<=126) || (c>=128 && c<=160) ||
5644 			(c>=224 && c<=252)) dct=SJIS;
5645 		    else if (c>=161 && c<=223) dct=EUCORSJIS;
5646 		}
5647 		else if (c>=161 && c<=223) {
5648 		    c=sgetc(in);
5649 		    if (c>=240 && c<=254) dct=EUC;
5650 		    else if (c >= 161 && c <= 223) dct = EUCORSJIS;
5651 		    else if (c >= 224 && c <= 239) {
5652 			dct = EUCORSJIS;
5653 			while (c >= 64 && c != EOF && dct == EUCORSJIS) {
5654 			    if (c >= 129) {
5655 				if (c <= 141 || (c >= 143 && c <= 159))
5656 				    dct = SJIS;
5657 				else if (c >= 253 && c <= 254)
5658 				    dct = EUC;
5659 			    }
5660 			    c = sgetc(in);
5661 			}
5662 		    }
5663 		    else if (c <= 159) dct = SJIS;
5664 		}
5665 		else if (c >= 240 && c <= 254) dct = EUC;
5666 		else if (c >= 224 && c <= 239) {
5667 		    c = sgetc(in);
5668 		    if ((c >= 64 && c <= 126) || (c >= 128 && c <= 160))
5669 			dct = SJIS;
5670 		    else if (c >= 253 && c <= 254) dct = EUC;
5671 		    else if (c >= 161 && c <= 252) dct = EUCORSJIS;
5672 		}
5673 	    }
5674 	    rewind(in);
5675 	    if ((inf=inf->p) == NULL) break;
5676 	}
5677 	inf=Rinf;
5678 	return dct;
5679 }
5680 
han2zen(FILE * in,int * p1,int * p2,int codein)5681 void han2zen(FILE *in, int *p1, int *p2, int codein)
5682 {
5683 	int tmp = *p1, junk, maru = 0, nigori = 0;
5684 	static int mtable[][2] = {
5685     {129,66},{129,117},{129,118},{129,65},{129,69},{131,146},{131,64},
5686     {131,66},{131,68},{131,70},{131,72},{131,131},{131,133},{131,135},
5687     {131,98},{129,91},{131,65},{131,67},{131,69},{131,71},{131,73},
5688     {131,74},{131,76},{131,78},{131,80},{131,82},{131,84},{131,86},
5689     {131,88},{131,90},{131,92},{131,94},{131,96},{131,99},{131,101},
5690     {131,103},{131,105},{131,106},{131,107},{131,108},{131,109},
5691     {131,110},{131,113},{131,116},{131,119},{131,122},{131,125},
5692     {131,126},{131,128},{131,129},{131,130},{131,132},{131,134},
5693     {131,136},{131,137},{131,138},{131,139},{131,140},{131,141},
5694     {131,143},{131,147},{129,74},{129,75} };
5695 
5696 	if (codein == SJIS) {
5697 		*p2 = sgetc(in);
5698 		if (*p2 == 222) {
5699 			if (ISNIGORI(*p1)) nigori = 1;
5700 			else sungetc(*p2);
5701 		}
5702 		else if (*p2 == 223) {
5703 			if (ISMARU(*p1)) maru = 1;
5704 			else sungetc(*p2);
5705 		}
5706 		else sungetc(*p2);
5707 	}
5708 	else if (codein == EUC) {
5709 		junk = sgetc(in);
5710 		if (junk == SS2) {
5711 			*p2 = sgetc(in);
5712 			if (*p2 == 222) {
5713 			    if (ISNIGORI(*p1)) nigori = 1;
5714 			    else {
5715 				sungetc(*p2);
5716 				sungetc(junk);
5717 			    }
5718 			}
5719 			else if (*p2 == 223) {
5720 			    if (ISMARU(*p1)) maru = 1;
5721 			    else {
5722 				sungetc(*p2);
5723 				sungetc(junk);
5724 			    }
5725 			}
5726 			else {
5727 				sungetc(*p2);
5728 				sungetc(junk);
5729 			}
5730 		}
5731 		else sungetc(junk);
5732 	}
5733 	if (*p1 >= 161 && *p1 <= 223) {
5734 		*p1 = mtable[tmp - 161][0];
5735 		*p2 = mtable[tmp - 161][1];
5736 	}
5737 	if (nigori) {
5738 		if ((*p2>=74 && *p2<=103) || (*p2>=110 && *p2<=122)) (*p2)++;
5739 		else if (*p1 == 131 && *p2 == 69) *p2 = 148;
5740 	}
5741 	else if (maru && *p2 >= 110 && *p2 <= 122) *p2 += 2;
5742 }
5743 
sjis2jis(int * p1,int * p2)5744 void sjis2jis(int *p1, int *p2)
5745 {
5746 	unsigned char c1, c2;
5747 	int adjust, rowOffset, cellOffset;
5748 
5749 	c1 = *p1; c2 = *p2;
5750 	adjust = c2 < 159;
5751 	rowOffset = c1 < 160 ? 112 : 176;
5752 	cellOffset = adjust ? (c2 > 127 ? 32 : 31) : 126;
5753 	*p1 = ((c1 - rowOffset) << 1) - adjust;
5754 	*p2 -= cellOffset;
5755 }
5756 
shift2seven(FILE * in,char * ki,char * ko)5757 void shift2seven(FILE *in, char *ki, char *ko)
5758 {
5759 	int p1, p2, state = OUT;
5760 
5761 	while ((p1 = sgetc(in)) != EOF) {
5762 	    if (p1 == EOL || p1 == CR) {
5763 		if (state==IN) {
5764 			state = OUT;
5765 			fprintf(out, "%c%s", ESC, ko);
5766 		}
5767 		fprintf(out, "%c", p1);
5768 	    }
5769 	    else if (SJIS1(p1)) {
5770 		p2 = sgetc(in);
5771 		if (SJIS2(p2)) {
5772 			sjis2jis(&p1, &p2);
5773 			if (state==OUT) {
5774 				state=IN;
5775 				fprintf(out, "%c%s", ESC, ki);
5776 			}
5777 		}
5778 		fprintf(out, "%c%c", p1, p2);
5779 	    }
5780 	    else if (HANKATA(p1)) {
5781 		han2zen(in, &p1, &p2, SJIS);
5782 		sjis2jis(&p1, &p2);
5783 		if (state==OUT) {
5784 			state=IN;
5785 			fprintf(out, "%c%s", ESC, ki);
5786 		}
5787 		fprintf(out, "%c%c", p1, p2);
5788 	    }
5789 	    else {
5790 		if (state==IN) {
5791 			state = OUT;
5792 			fprintf(out, "%c%s", ESC, ko);
5793 		}
5794 		fprintf(out, "%c", p1);
5795 	    }
5796 	}
5797 	if (state==IN) fprintf(out, "%c%s", ESC, ko);
5798 }
5799 
euc2seven(FILE * in,char * ki,char * ko)5800 void euc2seven(FILE *in, char *ki, char *ko)
5801 {
5802 	int p1, p2, state = OUT;
5803 
5804 	while ((p1 = sgetc(in)) != EOF) {
5805 	    if (p1 == EOL || p1 == CR) {
5806 		if (state==IN) {
5807 			state = OUT;
5808 			fprintf(out, "%c%s", ESC, ko);
5809 		}
5810 		fprintf(out,"%c",p1);
5811 	    }
5812 	    else {
5813 		if (ISEUC(p1)) {
5814 			p2 = sgetc(in);
5815 			if (ISEUC(p2)) {
5816 				p1 -= 128; p2 -= 128;
5817 				if (state==OUT) {
5818 					state=IN;
5819 					fprintf(out, "%c%s", ESC, ki);
5820 				}
5821 			}
5822 			fprintf(out, "%c%c", p1, p2);
5823 		}
5824 		else if (p1 == SS2) {
5825 			p2 = sgetc(in);
5826 			if (HANKATA(p2)) {
5827 				p1 = p2;
5828 				han2zen(in, &p1, &p2, EUC);
5829 				sjis2jis(&p1, &p2);
5830 				if (state==OUT) {
5831 					state=IN;
5832 					fprintf(out, "%c%s", ESC, ki);
5833 				}
5834 			}
5835 			fprintf(out, "%c%c", p1, p2);
5836 		}
5837 		else {
5838 			if (state==IN) {
5839 				state = OUT;
5840 				fprintf(out, "%c%s", ESC, ko);
5841 			}
5842 			fprintf(out, "%c", p1);
5843 		}
5844 	    }
5845 	}
5846 	if (state==IN) fprintf(out, "%c%s", ESC, ko);
5847 }
5848 
seven2seven(FILE * in,char * ki,char * ko)5849 void seven2seven(FILE *in, char *ki, char *ko)
5850 {
5851 	int temp, p1, p2, change, state = OUT;
5852 
5853 	while ((p1 = sgetc(in)) != EOF) {
5854 	    if (p1 == ESC) {
5855 		temp = sgetc(in);
5856 		change = SkipESCSeq(in, temp, &state);
5857 		if (change) fprintf(out, "%c%s", ESC, (state==IN)? ki : ko);
5858 	    }
5859 	    else if (p1 == EOL || p1 == CR) {
5860 		if (state==IN) {
5861 			state = OUT;
5862 			fprintf(out, "%c%s", ESC, ko);
5863 		}
5864 		fprintf(out, "%c", p1);
5865 	    }
5866 	    else {
5867 		if (state==IN) {
5868 			p2 = sgetc(in);
5869 			fprintf(out, "%c%c", p1, p2);
5870 		}
5871 		else fprintf(out, "%c", p1);
5872 	    }
5873 	}
5874 	if (state==IN) fprintf(out, "%c%s", ESC, ko);
5875 }
5876 
jispreproc()5877 void jispreproc()    /* convert to 7-bit, then to 8-bit */
5878 {
5879 	if (code==UNKNOWN || (code==JIS && defcode!=JIS)) {
5880 		code = DetectJPCodeType();
5881 		if (!mute) fprintf(errout,
5882 			"Detected input code: %s\n", codename[code]);
5883 	}
5884 	switch (code) {
5885 	    case EUCORSJIS :
5886 		if (!mute) {
5887 			fprintf(stderr, "Treat as Shift-JIS, OK ? (Y/N)\n");
5888 			bell();
5889 			if (yes(0)) code=SJIS;
5890 			else exit(0);
5891 		}
5892 		else code=SJIS;
5893 		break;
5894 	    case ASCII :
5895 		if (mute) {
5896 			break;
5897 		}
5898 		fprintf(errout,
5899 "Might be damaged New- or Old-JIS, repair? (Y/N)\n");
5900 		bell();
5901 		if (yes(1)) {
5902 			convcode=JISRP; convers(0);
5903 			fprintf(errout,
5904 "Repaired version saved: %s\n", Rinf->s);
5905 		}
5906 		else return;
5907 		break;
5908 	    default: break;
5909 	}
5910 /* convert to 7-bit JIS according to input code type */
5911 	convcode=JISCVT;
5912 	convers(0);
5913 /* convert to 8-bit for unified GB/B5/JIS/KSC processing */
5914 	nHzline = CheckLineLen();
5915 	convcode=JIS8;
5916 	convers(0);
5917 }
5918 
kscpreproc()5919 void kscpreproc()
5920 {
5921       ;
5922 }
5923 
gbb5preproc()5924 void gbb5preproc()
5925 {
5926 	int dct=UNKNOWN;
5927 	if (code==UNKNOWN || (code==GB && defcode!=GB)) {
5928 		dct = DetectCNCodeType();
5929 		if (!mute) fprintf(errout,
5930 			"Detected input code: %s\n", codename[dct]);
5931 	}
5932 	else dct=code;
5933 	switch (dct) {
5934 	    case UNKNOWN: break;
5935 	    case GB: break;
5936 	    case GBORB5:
5937 		if (dct==code) break;
5938 		else if (mute) code=defcode;
5939 		else if (code==GB || defcode==GB) {
5940 			fprintf(errout, "Treat as GB\n");
5941 			code=GB;
5942 		}
5943 		else {
5944 			fprintf(stderr,
5945 "Please supply code type at command-line.\n");
5946 			cleanup(1); exit(0);
5947 		}
5948 		break;
5949 	    case B5:
5950 		if (defcode!=B5 && code!=B5 && !mute) {
5951 			fprintf(stderr, "Is that right (Y/N)?\n");
5952 			bell();
5953 			if (yes(1)) code=dct;
5954 			else if (code==UNKNOWN) {
5955 				fprintf(stderr,
5956 "Please supply code type at command-line.\n");
5957 				cleanup(1); exit(0);
5958 			}
5959 		}
5960 		else if (code==UNKNOWN) code=dct;
5961 		break;
5962 	    case ZW: case HZ: case CNS:
5963 		if (mute) code=dct;
5964 		else if (dct != code) {
5965 			fprintf(stderr, "Is that right (Y/N)?\n");
5966 			bell();
5967 			if (yes(1)) code=dct;
5968 			else fprintf(errout,
5969 "Treat as %s\n", codename[(code==UNKNOWN)? (code=defcode) : code]);
5970 		}
5971 		else if (code==UNKNOWN) code=dct;
5972 		if (code==CNS) convcode=CNSB5;
5973 		else convcode=(code==ZW)? ZWGB : HZGB;
5974 		break;
5975 	    case ASCII:
5976 		code = defcode; break;
5977 	    default:
5978 		exit(0); break;
5979 	}
5980 	switch(code) {
5981 	    case GB: case HZ: case ZW:
5982 		if (lcode!=GB) init(RINIT, NULL);
5983 		break;
5984 	    case B5: case CNS:
5985 		if (lcode!=B5) init(RINIT, NULL);
5986 		break;
5987 	    default:
5988 		break;
5989 	}
5990 	if (convcode) {
5991 		nHzline = CheckLineLen();
5992 		convers(0);
5993 	}
5994 }
5995 
DetectCNCodeType()5996 int DetectCNCodeType()
5997 {
5998 	int c = 0, n=0, dct = ASCII;  /* detected code type */
5999 	FILE *in;
6000 
6001 	inf=Rinf;
6002 	sbufp=0;
6003 	while ((in = inf->fp) != NULL) {
6004 	    while (dct==ASCII || dct==GBORB5) {
6005 		if ((c=sgetc(in)) == EOF) break;
6006 		else if (c==ESC) {
6007 		    n++;
6008 		    if ((c=sgetc(in)) == '$') {
6009 			n++;
6010 			if ((c=sgetc(in)) == 'C') {
6011 			    c=sgetc(in);
6012 			    if (c=='G' || c=='H') dct=CNS;
6013 			}
6014 		    }
6015 		}
6016 		else if (c>=0xA1) {
6017 		    c = sgetc(in);
6018 		    if (c>=0x40 && c<=0x7E) dct=B5;
6019 		    else if (c>=0xA1) dct=GBORB5;
6020 		    else sungetc(c); /* bad codes */
6021 		    n+=2;
6022 		}
6023 		else if (c == '~') {
6024 		    c = sgetc(in);
6025 		    if (c=='{' || c=='}') dct=HZ;
6026 		    n+=2;
6027 		}
6028 		else if (c=='z' && n==0) {
6029 		    c = sgetc(in);
6030 		    if (c=='W') dct=ZW;
6031 		    n+=2;
6032 		}
6033 		else if (c==EOL) n=0;
6034 	    }
6035 	    rewind(in);
6036 	    if ((inf=inf->p) == NULL) break;
6037 	}
6038 	inf=Rinf;
6039 	return dct;
6040 }
6041 
DetectMIMEType()6042 int DetectMIMEType()
6043 /*
6044  * this is independent of language/encoding type. It is another layer.
6045  * It can be either quoted printable (QP) or base64. In either case,
6046  * we need to get back the original.
6047  * 	Right now we only care about QP. We look for "=B7 =C3", "=B7=C3"
6048  * or "=\n" pattern ("=B7s3" will not count)
6049  */
6050 {
6051 	int c=0, n=0;		/* code type */
6052 	FILE *in;
6053 
6054 	inf=Rinf;
6055 	sbufp=0;
6056 	while ((in = inf->fp) != NULL) {
6057 	    while (n < 5) {
6058 		if ((c=sgetc(in)) == EOF) break;
6059 		else if (c == '=') {
6060 		    if ((c=sgetc(in)) == EOL) n++;	/* =\n */
6061 		    else if (c == '=') sungetc(c);
6062 		    else if (isxdigit(c)) {
6063 			c = sgetc(in);
6064 			if (c == '=') sungetc(c);
6065 			else if (isxdigit(c)) {		/* OK =B4 */
6066 			    c=sgetc(in);
6067 			    if (c == ' ' || c == '=') n++;
6068 			    sungetc(c);
6069 			}
6070 		    }
6071 		}
6072 	    }
6073 	    rewind(in);
6074 	    if ((inf=inf->p) == NULL) break;
6075 	}
6076 	inf=Rinf;
6077 	return (n<5)? 0:1;
6078 }
6079 
unicodepreproc()6080 void unicodepreproc()
6081 
6082 {
6083 	if (code==UNKNOWN || code==UTF) code=DetectUnicodeType();
6084 	switch(code) {
6085 	    case UTF7: case UTF8:
6086 		convcode = (code==UTF7)? UTF7TOUNI : UTF8TOUNI;
6087 		break;
6088 	    case UTF16:
6089 		convcode = UTF16LETOUNI;
6090 		break;
6091 	    default:
6092 		code = UTF;
6093 		convcode = UTF16BETOUNI;
6094 		break;
6095 	}
6096 	if (!mute) fprintf(errout, "Code type is %s\n", codename[code]);
6097 	convers(0);
6098 }
6099 
DetectUnicodeType()6100 int DetectUnicodeType()
6101 
6102 {
6103 	int	c1, c2, dct=UNKNOWN;
6104 	FILE	*in;
6105 
6106 	in = Rinf->fp;
6107 	c1 = fgetc(in);
6108 	c2 = fgetc(in);
6109 	switch(c1) {
6110 	case 0xFE:
6111 		if (c2==0xFF) dct=UTF;
6112 		break;
6113 	case 0xFF:
6114 		if (c2==0xFE) dct=UTF16;
6115 		break;
6116 	case 0xEF:
6117 		if (c2==0xBB && 0xBF==fgetc(in)) dct=UTF8;
6118 		break;
6119 	default:
6120 		break;
6121 	}
6122 	rewind(in);
6123 	return dct;
6124 }
6125 
utf8_getc(FILE * fp)6126 long utf8_getc(FILE *fp)       /* utf8 to 2-byte unicode */
6127 {
6128 	int     c, extras;
6129 	long    wc;
6130 	unsigned bit;
6131 
6132 	if ((c = getc(fp)) == EOF) return EOF;
6133 	if ((c & 0x80) == 0)            /* ASCII character */
6134 		return c;
6135 	if ((c & 0xc0) == 0x80)         /* unexpected tail character */
6136 		return CODE_ERROR;
6137 	/* how many extra bytes? */
6138 	extras = 1;
6139 	for (bit = 0x20; (c & bit) != 0; bit >>= 1) extras++;
6140 	if (extras > 5) return CODE_ERROR;
6141 	/* put all the bits together */
6142 	wc = c & (bit-1);
6143 	while (extras-- > 0) {
6144 		if ((c = getc(fp)) == EOF) return EOF;
6145 		if ((c & 0xc0) != 0x80) { /* unexpected head character */
6146 			ungetc(c, fp);
6147 			return CODE_ERROR;
6148 		}
6149 		wc = (wc<<6) | (c&0x3f);
6150 	}
6151 	return wc;
6152 }
6153 
invert()6154 static void invert()
6155 {
6156 	int     i;
6157 	unsigned char   *s;
6158 
6159 	utf_initzd = IN;
6160 	for (i = 0; i < NUMBYTES; i++) char_type[i] = 0;
6161 	for (s = base64; *s != '\0'; s++) {
6162 		char_type[*s] |= BASE64;
6163 		inv_base64[*s] = s - base64;
6164 	}
6165 	for (s = safe; *s != '\0'; s++) char_type[*s] |= SAFE;
6166 	for (s = optional; *s != '\0'; s++) char_type[*s] |= OPTIONAL;
6167 	for (s = space; *s != '\0'; s++) char_type[*s] |= SPACE;
6168 }
6169 
6170 
utf7_getc(FILE * fp)6171 long utf7_getc(FILE *fp)    /* utf7 to 2-byte unicode */
6172 {
6173 	int     c;
6174 
6175 	if (! utf_initzd) invert();
6176 	for (;;) {
6177 		if ((c = getc(fp)) == EOF) return EOF;
6178 		if (! in_base64) {
6179 			if (c != '+') return c;
6180 			if ((c = getc(fp)) == EOF) return EOF;
6181 			if (c == '-') return '+';
6182 			in_base64 = IN;
6183 			nbits = 0;
6184 		}
6185 	/* now we're in Base64 mode */
6186 		while (char_type[c]&BASE64) {
6187 			bit_buffer <<= 6;
6188 			bit_buffer |= inv_base64[c];
6189 			nbits += 6;
6190 			if (nbits >= 16) {
6191 				nbits -= 16;
6192 				return ((bit_buffer >> nbits)&0xffffL);
6193 			}
6194 			if ((c = getc(fp)) == EOF) return EOF;
6195 		}
6196 		in_base64 = OUT;
6197 		if (c != '-') return c;
6198 	}
6199 }
6200 
getroot()6201 void getroot()
6202 {
6203 	char *s, *t;
6204 	int n, c = ':'; /* unix */
6205 	struct Roots *rt;
6206 	char defpath[50];
6207 
6208 #ifdef VMS
6209 	c = ',';
6210 #endif
6211 	root = (struct Roots *) calloc(1, sizeof(struct Roots));
6212 	if (root == NULL) MemExit();
6213 	rt = root; root->p = NULL; root->s=NULL;
6214 	s=getenv("HBFPATH");
6215 
6216 	if (s==NULL) {
6217 		defpath[0]='\0';
6218 #ifdef unix
6219 		strcpy(defpath, "/usr/local/share/cnprint");
6220 #endif
6221 		s=defpath;
6222 	}
6223 	do {
6224 		if (root->s!=NULL && rt->p==NULL) {
6225 		    rt->p = (struct Roots *)
6226 			calloc(1, sizeof(struct Roots));
6227 		    if (rt->p==NULL) MemExit();
6228 		    rt = rt->p; rt->p = NULL;
6229 		}
6230 		if (s!=NULL) t = strchr(s, c);
6231 		else t = NULL;
6232 		if (t!=NULL) n = (int) (t-s);
6233 		else n = (s==NULL)? 0 : strlen(s);
6234 		if ( (rt->s = (char *) calloc(n+2, sizeof(char))) == NULL)
6235 			MemExit();
6236 		if (n) {
6237 			strncpy (rt->s, s, n);
6238 			s += n;
6239 			if (t!=NULL) s++;
6240 #ifdef unix
6241 			if (rt->s[n-1] != '/') strcat(rt->s, "/");
6242 #endif
6243 		}
6244 		else {
6245 			(rt->s)[0] = '\0';
6246 			s=NULL;
6247 		}
6248 
6249 	} while (s!=NULL);
6250 
6251 /*	rt=root;
6252 	do {
6253 		fprintf(errout, "rt->s: .%s.\n", rt->s);
6254 		if (rt!=NULL) rt = rt->p;
6255 	} while (rt!=NULL);
6256 */
6257 }
6258 
FName(char * s,char * t)6259 void FName(char *s, char *t)
6260 
6261 {
6262 	int j, k;
6263 #ifdef VMS
6264 	j=strlen(s);
6265 	while (s[j]!=';' && j) j--;
6266 	if (j>1) s[j]='\0';
6267 #endif
6268 	strcat(s, t);
6269 }
6270 
RE_name(char * fn_old,char * fn_new)6271 void RE_name(char *fn_old, char *fn_new)
6272 {
6273 	char p[100];
6274 #ifdef unix
6275 # ifdef MUSER
6276 	sprintf(p, "cp %s %s", fn_old, fn_new);
6277 	system(p);
6278 	remove(fn_old);
6279 # else
6280 	sprintf(p, "mv %s %s", fn_old, fn_new);
6281 	system(p);
6282 # endif
6283 #else
6284 	if (rename(fn_old, fn_new)!=0) {
6285 		sprintf(p, "copy %s %s", fn_old, fn_new);
6286 		system(p);
6287 		remove(fn_old);
6288 	}
6289 #endif
6290 }
6291 
tobooklet()6292 void tobooklet()
6293 {
6294 	int     j, k, xpos[17];
6295 	int     Nppg;           /* physical pages */
6296 	int     npg;            /* nominal page number */
6297 	long    filepos;
6298 	FILE    *in;
6299 
6300 	if (!mute) fprintf(errout, "Convert PS file to booklet format...\n");
6301 	Nppg = (pgpd+2*booklet-1)/(booklet*2);
6302 	Nppg *= 2;
6303 /* positions of each page on a physical page (sheet of paper) */
6304 	for (j=1; j<=booklet/2; j++) {  /* booklet must be even number */
6305 		xpos[j] = xpos[j+3*booklet/2] = Xa*j + RM*(j-1);
6306 		xpos[j+booklet/2] = xpos[j+booklet] =
6307 			Xa*(j+1+booklet/2) + RM*(j+booklet/2-1);
6308 	}
6309 
6310 	FName(Rinf->s, "bk");
6311 	RE_name(tempfile, Rinf->s);
6312 	opnfile(IN); opnfile(OUT);
6313 	in=Rinf->fp;
6314 
6315 	copypage(0, 0, 1, in, &filepos); /* copy header */
6316 	for (j=1; j<=Nppg; j++) {
6317 	    for (k=booklet; k>=1; k--) {
6318 		if (k <= booklet/2)
6319 		    npg = (Nppg*booklet - (j-1)*booklet/2) - (booklet/2-k);
6320 		else npg = (j-1)*booklet/2 + (k-booklet/2);
6321 		if (k==booklet) fprintf(out,
6322 "\n%%%%Page: %d %d\nCN31Dict begin\n", j, npg);
6323 		if (npg<=pgpd) copypage(npg,
6324 			xpos[k + booklet*((j+1)%2)], 0, in, &filepos);
6325 		if (k==1) fprintf(out, "SP end %% CN31Dict\n");
6326 	    }
6327 	    fprintf(errout, (j%5 == 0 || j==Nppg)? "%5d\n" : "%5d", j);
6328 	}
6329 	trailer(Nppg);
6330 	remove(Rinf->s);
6331 	if (ferror(out)) {
6332 		fprintf(stderr,
6333 "WARNING: PS file %s write error, possibly out of memory.\n", tempfile);
6334 		bell(); exit(-5);
6335 	}
6336 	fclose(out);
6337 	outputToDev();
6338 }
6339 
copypage(int npg,int xp,int ht,FILE * in,long * pfilepos)6340 int copypage(int npg, int xp, int ht, FILE *in, long *pfilepos)
6341 /*
6342  * pfilepos: copy selected page to output, for booklet
6343  * xp: x-position; ht: -1 trailer; 1, header
6344  */
6345 {
6346 	int     j, k, Prntpage=0;
6347 	char    cst[256];
6348 
6349 	if (npg > 0) fseek(in, *pfilepos, 0);
6350 	if (ht==1) Prntpage=2;   /* ht==1, copy header */
6351 	while (fgets(cst, 255, in)!=NULL) {
6352 	    if (Prntpage>=2) {
6353 		if (strncmp(cst, "EP", 2)==0) {
6354 		    fprintf(out, "EP\n"); break;
6355 		}
6356 		else fprintf(out, "%s", cst);
6357 		if (npg<=0) {
6358 		    if (strncmp(cst, "%%EndSetup", 10)==0) {
6359 			*pfilepos = ftell(in);
6360 			break;
6361 		    }
6362 		}
6363 	    }
6364 	    else if (Prntpage) {
6365 		if (strncmp(cst, "BP", 2)==0) {
6366 			/* BP -2550 LRT 180 186 translate */
6367 		    sscanf(cst, "%*s%d%*s%*d%d", &j, &k);
6368 		    fprintf(out, "BP %d LRT %d %d translate\n", j, xp, k);
6369 		    Prntpage++;
6370 		}
6371 	    }
6372 	    else if (strncmp(cst, "%%Page:", 7)==0) {
6373 		/* Prntpage=0; */
6374 		sscanf(cst, "%*s%d%d", &k, &j);
6375 		if (j==npg) {
6376 			Prntpage=1;
6377 			fprintf(out, "%%face page: %d %d\n", k, npg);
6378 			continue;
6379 		}
6380 	    }
6381 	}
6382 	return 1;
6383 }
6384 
6385 
6386 #ifdef PSPRINT
toshortline(FILE * in)6387 void toshortline(FILE *in)
6388 /* break long lines to short ones: some printer has problem with long lines */
6389 {
6390 	int	c;
6391 	int	hexd=0;		/* # of continuous Hexidecimal digits */
6392 	int	comment=0;	/* PS comment lines */
6393 	int	bop=0;		/* 1: (; 0: ) */
6394 	int	charcount=0;
6395 
6396 	while ( (c=fgetc(in)) != EOF) {
6397 		if (c=='(') bop=1;
6398 		else if (c==')') bop=0;
6399 		if (c==LF || c==CR) {
6400 			c=getc(in);
6401 			if (c!=LF && c!=EOF) ungetc(c, in);
6402 			charcount=0; comment=hexd=0;
6403 			fputc(EOL, out);
6404 		}
6405 		else if (c=='\\') {
6406 			c=getc(in);
6407 			if (charcount > MAXLENGTH-6 && c!=EOL) {
6408 				if (bop) fputc('\\', out);
6409 				fputc(EOL, out);
6410 				if (comment) fputc('%', out);
6411 				charcount=0; hexd=0;
6412 			}
6413 			fputc('\\', out);
6414 			fputc(c, out);
6415 			if (c==EOL) {
6416 				charcount=comment=0;
6417 				c=getc(in);
6418 				if (c==EOL) ;
6419 				else ungetc(c, in);
6420 			}
6421 		}
6422 		else if (charcount>MAXLENGTH && (isbreaka(c) || isbreakb(c))) {
6423 			if (isbreakb(c)) fputc(c, out);
6424 	/* if inside a char string, add line-continuation mark */
6425 			if (bop) fputc('\\', out);
6426 			fputc(EOL, out);
6427 			if (comment) fputc('%', out);
6428 			if (isbreaka(c)) fputc(c, out);
6429 			charcount=1; hexd=0;
6430 		}
6431 		else if (charcount>MAXLENGTHA && c=='/' && !bop) {
6432 					/* not inside () */
6433 			fputc(EOL, out);
6434 			if (comment) fputc('%', out);
6435 			fputc(c, out);
6436 			charcount=1; hexd=0;
6437 		}
6438 		else if (charcount>MAXLENGTHB) {
6439 			if (hexd==0 || hexd==10) {
6440 						/* line-continuation */
6441 				if(hexd==0) fputc('\\', out);
6442 				fputc(EOL, out);
6443 				if (comment) fputc('%', out);
6444 				charcount=0; hexd=0;
6445 			}
6446 			if (isxdigit(c)) hexd++;
6447 			else hexd=0;
6448 			charcount++;
6449 			fputc(c, out);
6450 		}
6451 		else {
6452 			if (c=='%' && !bop) comment++;
6453 			fputc(c, out);
6454 			charcount++;
6455 			if (isxdigit(c)) hexd++;
6456 			else hexd=0;
6457 			if (hexd==78) {
6458 				fputc(EOL, out);
6459 				if (comment) fputc('%', out);
6460 				charcount=hexd=0;
6461 			}
6462 		}
6463 	}
6464 }
6465 #endif  /* PSPRINT */
6466 
6467 #ifdef PSPRINT
pageprint(FILE * in)6468 void pageprint(FILE *in)
6469 /* print selected pages, must be DSC conforming, no error checking.
6470  * by standard, EPS file must be bracketed with
6471 	%%BeginDocument
6472 	%%EndDocument
6473  * pair.  Ignore the "##Page: " comments in EPS file.
6474  * Note: it does not adjust the page numbers and # of pages.
6475  */
6476 {
6477 	int	j, npg=0, EPSlevel=0;
6478 	char	cst[256];
6479 	int	Prntpage=1;
6480 
6481 	while (fgets(cst, 255, in)!=NULL) {
6482 	    if (EPSlevel) {
6483 		if (strncmp(cst, "%%EndDocument", 13)==0) EPSlevel--;
6484 	    }
6485 	    else if (strncmp(cst, "%%BeginDocument", 15)==0) {
6486 		EPSlevel++;
6487 	    }
6488 	    else if (strncmp(cst, "%%Page:", 7)==0) {
6489 		sscanf(cst, "%*s%*s%d", &j);
6490 		if (j>npg) npg=j;
6491 		if (npg>0) {
6492 		    if (npg>=bp && (ep==0 || npg<=ep)) {
6493 			if (odd==0 || ((odd%2)==(npg%2))) Prntpage=1;
6494 			else Prntpage=0;
6495 		    }
6496 		    else Prntpage=0;
6497 		}
6498 		if (Prntpage) fprintf(stderr, "%s\tYES\n", cst);
6499 	    }
6500 	    else if (strncmp(cst, "%%Trailer", 9)==0) {
6501 		Prntpage=1;
6502 	    }
6503 	    if (Prntpage) fprintf(out, "%s", cst);
6504 	}
6505 }
6506 #endif  /* PSPRINT */
6507 
6508 
6509 /* for decoding of mime quoted printable */
6510 
mimeqp_hex(int x)6511 int mimeqp_hex(int x)
6512 {
6513 	return (isdigit(x)? (x-'0') : (islower(x) ? (x-'a'+10):(x-'A'+10)) );
6514 }
6515 
mimeqpdecode(FILE * in)6516 void mimeqpdecode(FILE *in)
6517 {
6518 	int	c1, c2;
6519 
6520 	sbufp=0;
6521 	while ((c1=sgetc(in)) != EOF) {
6522 	    if (c1 != '=')
6523 		fputc(c1, out);
6524 	    else {
6525 		c1 = sgetc(in);
6526 		c2 = sgetc(in);
6527 		if (c1==CR || c1==LF) {
6528 			if (c1==LF || (c1==CR && c2 != LF)) sungetc(c2);
6529 			continue;
6530 		}
6531 		else if (!isxdigit(c1) || !isxdigit(c2)) {
6532 			sungetc(c2);
6533 			sungetc(c1);
6534 			fputc('=', out);
6535 			continue;
6536 		}
6537 		fputc(mimeqp_hex(c1)*16 + mimeqp_hex(c2), out);
6538 	    }
6539 	}
6540 }
6541 
6542 /* end of MIME handling */
6543 
strfilecmp(char * s,FILE * fp)6544 int strfilecmp(char *s, FILE *fp)
6545 /* if EQ, eat the str, otherwise, use sungetc() */
6546 {
6547 	int	c, j, len;
6548 
6549 	len  = strlen(s);
6550 	j = 0;
6551 	while (j < len && (c=sgetc(fp)) != EOF) {
6552 	    if (c == s[j]) j++;
6553 	    else {
6554 		sungetc(c);
6555 		while (--j >= 0) sungetc(s[j]);
6556 		break;
6557 	    }
6558 	}
6559 	return (j==len)? 0:1; /* like strcmp(), EQ=0 */
6560 }
6561 
addLBAS(FILE * in)6562 void addLBAS(FILE *in)
6563 /*
6564  * add sender information to every label, forming sender-receiver pair
6565  * if addrlabel>1, fill the whole page with everything before the first
6566  * @[LB as receiver address
6567  */
6568 {
6569 	int	nlbas=0, nlbar=0, nlabel=0;
6570 	int	j, c1, c2;
6571 	unsigned char *lbas, *lbar;
6572 
6573 	lbas = (unsigned char *) calloc(LBASMAX, sizeof(char));
6574 	lbar = (unsigned char *) calloc(LBASMAX, sizeof(char));
6575 	if (lbas==NULL || lbar==NULL) MemExit();
6576 
6577 	sbufp=0;
6578 
6579 
6580 	if (addrlabel > 1) {
6581 	    while ((c1=sgetc(in)) != EOF) {
6582 		if (c1=='@' && strfilecmp("[LB", in)==EQ) {
6583 			sungetc('B'); sungetc('L');
6584 			sungetc('['); sungetc(c1);
6585 			break;
6586 		}
6587 		else lbar[nlbar++] = c1;
6588 		if (nlbar >= LBASMAX-1) break;
6589 	    }
6590 	    lbar[nlbar]='\0';
6591 	}
6592 
6593 
6594 	while ((c1=sgetc(in)) != EOF) {
6595 		if (c1=='@' && strfilecmp("[LBAS]", in)==EQ) {
6596 			if (lb_eat_EOL && (c1=sgetc(in)) != LF) sungetc(c1);
6597 			break;
6598 		}
6599 
6600 		else if (c1=='@' && strfilecmp("[LB", in)==EQ) {
6601 			nlabel++;
6602 			fprintf(out, "%s", "@[LB");
6603 		}
6604 		else fputc(c1, out);
6605 	}
6606 	while ((c1=sgetc(in)) != EOF) {
6607 		if (c1=='@' && strfilecmp("[LB", in)==EQ) {
6608 			sungetc('B'); sungetc('L');
6609 			sungetc('['); sungetc(c1);
6610 			break;
6611 		}
6612 		else lbas[nlbas++] = c1;
6613 		if (nlbas >= LBASMAX-1) break;
6614 	}
6615 	lbas[nlbas]='\0';
6616 
6617 
6618 	while ((c1=sgetc(in)) != EOF) {
6619 	    fputc(c1, out);
6620 	    if (c1 == '@' && strfilecmp("[LB", in)==EQ) {
6621 		nlabel++;
6622 		fprintf(out, "%s", "[LB");
6623 		fputc(c1=sgetc(in), out);
6624 		j=0;
6625 		if (c1==']') j=nlbas;
6626 		else if (isdigit(c1)) {
6627 			fputc(c2=sgetc(in), out);
6628 			if (isdigit(c2)) {
6629 				fputc(c1=sgetc(in), out);
6630 				if (c1==']') j=nlbas;
6631 			}
6632 		}
6633 		if (nlbas>0 && j==nlbas) {
6634 			for (j=0; j<nlbas; j++) fputc(lbas[j], out);
6635 			if (lb_eat_EOL && (c1=sgetc(in)) != LF) sungetc(c1);
6636 		}
6637 	    }
6638 	}
6639 
6640 
6641 	while (nlabel++ < addrlabel && nlbar > 0) {
6642 		fprintf(out, "%s", "@[LB]");
6643 		for (j=0; j<nlbar; j++) fputc(lbar[j], out);
6644 	}
6645 
6646 	free(lbas);
6647 	free(lbar);
6648 }
6649 
loadUNImappingtable(int chcode,int dire)6650 void loadUNImappingtable(int chcode, int dire)
6651 {
6652 	char	tablefile[100], *p;
6653 	int	b1low, b2low;
6654 	short	spacechar;
6655 	int	j, k;
6656 	FILE	*fp;
6657 
6658 	switch(chcode) {
6659 	    case GB:
6660 		strcpy(tablefile, "gb2312.uni");
6661 		break;
6662 	    case B5:
6663 		strcpy(tablefile, "big5.uni");
6664 		break;
6665 	    case JIS:
6666 		strcpy(tablefile, "jis0208.uni");
6667 		break;
6668 	    case KSC:
6669 		strcpy(tablefile, "ksc5601n.uni");
6670 		break;
6671 	    default:
6672 		strcpy(tablefile, "notable.uni");
6673 		break;
6674 	}
6675 
6676 	if (dire == 1) { /* CJK uses unicode font or CJK --> UNI */
6677 		if (b1l == 0x00) {
6678 			b1l = 0xA1;
6679 			b2l = (chcode==B5)? 0x40 : 0xA1;
6680 		}
6681 		b1low = b1l;
6682 		b2low = b2l;
6683 		spacechar = 0x3000;
6684 	}
6685 	else { 	/* convert UNI to CJK */
6686 		b1low=b2low=0;
6687 		spacechar = (chcode==B5)? 0xA140 : 0xA1A1;
6688 	}
6689 
6690 	UNItablemap = (unsigned short **)
6691 		calloc((0xFF-b1low+1), sizeof(unsigned short *));
6692 	if (UNItablemap==NULL) MemExit();
6693 	for (j=0; j<=0xFF-b1low; j++) {
6694 	    UNItablemap[j] = (unsigned short *)
6695 		calloc((0xFF-b2low+1), sizeof(unsigned short));
6696 	    if (UNItablemap[j]==NULL) MemExit();
6697 	    for (k=0; k<=0xFF-b2low; k++)
6698 		UNItablemap[j][k] = spacechar;
6699 	}
6700 	if ((fp=Rfopen(tablefile, "r"))==NULL) {
6701 		fprintf(stderr, "Can't open unicode mapping file --- %s\n",
6702 			tablefile);
6703 		exit(0);
6704 	}
6705 
6706 
6707 	p = tablefile;
6708 	while (fgets(p, 99, fp) != NULL) {
6709 	    if (p[0]=='0' && p[1]=='X') {
6710 		sscanf(p, "%i%i", &j, &k);
6711 		if (dire == 1) UNItablemap[j/256-b1low][j%256-b2low]
6712 			= (unsigned short) k;
6713 		else UNItablemap[k/256][k%256] = (unsigned short) j;
6714 	    }
6715 	}
6716 	fclose(fp);
6717 }
6718 
mapToUnicode(unsigned char * c1,unsigned char * c2)6719 void mapToUnicode(unsigned char *c1, unsigned char *c2)
6720 /*if (UnicodeTTF && lcode != UTF) mapToUnicode(&c1, &c2);*/
6721 {
6722 	unsigned short k = UNItablemap[*c1-b1l][*c2-b2l];
6723 	*c1 = (unsigned char) (k/256);
6724 	*c2 = (unsigned char) (k%256);
6725 }
6726 
getcode_unicode(unsigned char * p,int * c1,int * c2)6727 int getcode_unicode(unsigned char *p, int *c1, int *c2)
6728 /*
6729  * get a 16-bit code of unicode, return # of bytes used:
6730    	a positive value for success.
6731 	zero or a negative value for end of line in char string *p,
6732  * The code value is returned via pointers
6733  */
6734 {
6735 	int	c3, n=2;
6736 
6737 	if ((*c1 = *p++) == '\0') return 0;
6738 	if ((*c2 = *p++) == '\0') return -1;
6739 	if (*c1 == U2ESC) {
6740 		/* we trust the escaped 2-byte file: no error handling */
6741 	    if (*c2 == U2ESC2) *c1 = 0x00;
6742 		/* now we need to get a new *c2 */
6743 	    if ((*c2 = *p++) == '\0') return -2;
6744 	    n++;
6745 	}
6746 	if (*c2 == U2ESC) {
6747 	    if ((c3 = *p++) == '\0') return -n;
6748 	    n++;
6749 	    if (c3 == U2ESC2) *c2 = 0x00;
6750 	}
6751 	return n;
6752 }
6753 
unicode_isfs(unsigned char * q,int pr)6754 int unicode_isfs(unsigned char *q, int pr)
6755 /*
6756  * convert unicode seq to ASCII seq, and call isfs()
6757    return # of bytes used
6758  * limitation: @[xxx], use of codes > 0x00FF is limited
6759  */
6760 {
6761 	int	c1, c2, m, j;
6762 	unsigned char fsq[50], *ps1;
6763 
6764 	ps1 = q;
6765 	for (j=0; j<49; j++) {
6766 		m = getcode_unicode(q, &c1, &c2);
6767 
6768 		if (m < 0) return 0; /* EOF */
6769 		q += m;
6770 		/*else if (c1 != 0x00) return 0;  / * only allow ASCII */
6771 		if (j==0 && c1!=0x00 && c2!='[')
6772 			return 0;
6773 		else if (isUnicodeASCII(c1, c2)) {
6774 		    fsq[j] = c2;
6775 	 	    if (c2==']') {	/* end of @[...], stop */
6776 			fsq[++j]='\0';
6777 			m = isfs(fsq, pr);
6778 
6779 /* m<0: push back chars (e.g. '@'), assume each ASCII is 2 bytes in unicode */
6780 			return (m > 0)? (int)(q-ps1) : m*2;
6781 		    }
6782 		}
6783 		else { /* allow some Unicode chars */
6784 		    fsq[j++] = c1;
6785 		    fsq[j] = c2;
6786 		}
6787 	}
6788 	return 0;	/* pattern @[...] not found */
6789 }
6790 
doAC_unicode(unsigned char * q,int pr)6791 unsigned char *doAC_unicode(unsigned char *q, int pr)
6792 /*
6793  * for unicode only
6794  * since everything is two-byte with unicode, functional sequence
6795    like @[C2] would not work. This implementation tries to build
6796    an ASCII version of the sequence so that it will work with isfs.
6797  * filter() will not work for unicode too
6798  */
6799 {
6800 	unsigned char *ps1, *ps2;
6801 	int     k, j, m;
6802 	int	c1, c2, c3, c4;
6803 
6804 /* we work with unicode, there is no ASCII code here. However, we still
6805  * need to convert "ASCII" chars to ASCII and use putASC() to process.
6806  */
6807 	ps1 = q;
6808 	m = getcode_unicode(q, &c1, &c2);
6809 	if (m < 0) return (q-m);
6810 	ps2 = q = q + m;
6811 	if (c1==0x00 && c2=='@') {
6812 		k = unicode_isfs(q, pr);
6813 		if (k > 0) return (q+k); /* used */
6814 	}
6815 	if (isUnicodeASCII(c1, c2)) {
6816 		getcode_unicode(q, &c3, &c4);
6817 		if (c3 >= 0x01) c4 = 0xB4;
6818 		k = putASC(c2, c4, pr);
6819 		if (k > 0) {
6820 		    if (k==1) return ps1;
6821 		    else { /* push back those in ascbuf: ps1 - 3*(k-1) */
6822 			k--; m = 3*k;
6823 			for (; k>0; k--) if (ascbuf.s[k] == U2ESC) m++;
6824 			return (ps1-m);
6825 		    }
6826 		}
6827 	}
6828 	else {
6829 		k = putCH(c1, c2, pr);
6830 		return (k==0)? ps2 : ps1; /* k: 0 (used) or 2 */
6831 	}
6832 	return q;
6833 }
6834 
isASCfont(char * fn)6835 int isASCfont(char *fn)
6836 /*
6837  * find the font number for an ASC font
6838  */
6839 {
6840 	int	j;
6841 
6842 	for (j=0; j<nEFmax; j++) {
6843 		if (strlen(EFontnames[j]) < 3) continue;
6844 
6845 		if (strcmp(fn, EFontnames[j]) == EQ) return j;
6846 	}
6847 	return -1; /* no match */
6848 }
6849 
hex2float1(char c1,char c2)6850 float hex2float1(char c1, char c2)
6851 {
6852 	int	k;
6853 	float	x;
6854 
6855 	if (isdigit(c1)) k = c1 - '0';
6856 	else k = c1 - (isupper(c1)? 'A' : 'a') + 10;
6857 	k *= 16;
6858 	if (isdigit(c2)) k += c2 - '0';
6859 	else k += c2 - (isupper(c2)? 'A' : 'a') + 10;
6860 
6861 	x = (k/255.0)*1000;
6862 	x = ((int) x) / 1000.;
6863 	return x;
6864 }
6865 
int3pts2dot(unsigned char * t)6866 int int3pts2dot(unsigned char *t)
6867 {
6868 	char	*s;
6869 	int	k;
6870 	s = (char *) t;
6871 	k = (s[0]-'0')*100 + (s[1]-'0')*10 + (s[2]-'0');
6872 	return (int) (k/ppd);
6873 }
6874 
6875 
getEfontlist()6876 int getEfontlist()
6877 {
6878 	int	j, k;
6879 	char	cst[150], s1[120], s2[120];
6880 	FILE	*fp;
6881 
6882 	if ((fp=Rfopen("cnprint.afl", "r"))==NULL) {
6883 		fprintf(stderr,
6884 "Can't open ASCII font list file: cnprint.afl\n");
6885 		return 0;
6886 	}
6887 	while (fgets(cst, 149, fp) != NULL) {
6888 	    if (cst[0]=='#') continue;
6889 	    if (strncmp(cst, "TotalFonts_Families", 19) == EQ) {
6890 		if (sscanf(cst, "%*s%d%d", &j, &k)==2
6891 				&& j>0 && k>0 && j >= k*4) {
6892 			nEFmax = j;
6893 			nEFfamily = k;
6894 			break;
6895 		}
6896 		else {
6897 			fclose(fp);
6898 			return 0;
6899 		}
6900 	    }
6901 	}
6902 	EFontnames = (char **) calloc(nEFmax, sizeof(char *));
6903 	if (EFontnames==NULL) MemExit();
6904 	EFmetricfiles = (char **) calloc(nEFmax, sizeof(char *));
6905 	if (EFmetricfiles==NULL) MemExit();
6906 	for (j=0; j<nEFmax; j++) EFontnames[j]=zerolenstr;
6907 
6908 	k=0;
6909 	while (fgets(cst, 149, fp) != NULL) {
6910 	    if (cst[0]=='#') continue;
6911 	    if (sscanf(cst, "%d%s%s", &j, s1, s2 )==3 && j>=0) {
6912 		EFontnames[j] = (char *) calloc(strlen(s1)+1, sizeof(char));
6913 		if (EFontnames[j]==NULL) MemExit();
6914 		EFmetricfiles[j] = (char *) calloc(strlen(s2)+1, sizeof(char));
6915 		if (EFmetricfiles[j]==NULL) MemExit();
6916 		strcpy(EFontnames[j], s1);
6917 		strcpy(EFmetricfiles[j], s2);
6918 		k++;
6919 	    }
6920 	}
6921 
6922 	fclose(fp);
6923 	return k;
6924 }
6925 
6926