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