/* ************************************************** * CNPRINT.C For CNPRINT Version 3.10 (VMS & UNIX) * * ************************************************** Copyright YIDAO CAI (~{2LR@5@~}), 1992-1999 All Rights Reserved. Free for non-commercial and personal use only. The source code, or part of it, original or modified, may not be included in any other software, without permission from the author. See "Author" section of the help file for details. Disclaimer: Posting CNPRINT on any FTP site does not imply the author's endorsement of the beliefs of the organization who owns the FTP site. CNPRINT, a utility to print Chinese/Japanese/Korean text (or convert to PostScript) under DOS, VMS and UNIX systems. It works just as a print command on your system. Currently GB, Hz, zW, BIG-5, JIS (new-, old-, NEC-), EUC, shifted-JIS, KSC, UTF8 and UTF7 are supported. *** PLEASE read CNPRINT.HELP first EVEN if you have used CNPRINT before *** YIDAO CAI cai@neurophys.wisc.edu MAR-20-1999 **************************************************** */ /*#define STAT #define CNS_SUPPORT */ #define PSPRINT #ifdef VMS /** avoid using #ifndef **/ #else # ifdef unix /* */ # else # define unix # endif /* for multi-users on unix */ # define MUSER #endif #include #include #include #include #include #define TIME 1 #define GBstr "_gb" #define B5str "_b5" #define PSstr "_ps" #define HZstr "_hz" #define JISstr "_jis" #define Version "CNPRINT V3.10 (VMS & UNIX) MAR-20-1999" #define EOL '\n' #define CR 13 #define FF 12 #define LF 10 #define ESC 0x1B #define CTRLD 4 #define IN 1 #define OUT 0 #define R 1 #define L 2 #define RMXY 11 /* rotate and move */ #define RMX 12 #define RMY 13 #define NT 0 #define EQ 0 #define T 3 #define B 4 #define RMIRROR 5 /* code types */ #define UNKNOWN 0 #define ASCII 1 #define ZW 2 #define HZ 3 #define GB 4 #define GBORB5 5 #define B5 6 #define CNS 7 #define GBK 8 /* extended (kuozhan) GB */ #define B5P 9 /* Big5 plus */ #define JIS 11 /* JIS-0208, Japanese */ #define SJIS 12 #define EUC 13 #define EUCORSJIS 14 #define KSC 16 /* KSC-5601-1987, Korean */ #define UTF 17 /* double unicode */ #define UTF7 18 /* 7-bit unicode */ #define UTF8 19 /* 8-bit unicode */ static char *codename[]={"Unknown", "ASCII", "zW", "Hz", "GB", "GB or BIG5", "BIG5", "CNS", "GBK", "Big5+", "", "JIS", "Shift-JIS", "EUC", "EUC or Shift-JIS", "", "KSC", "UTF", "UTF7", "UTF8", "", ""}; /* conversion codes */ #define HZGB 1 #define GBHZ 2 #define FIL 3 #define ZWGB 4 #define JIS8 5 /* 7-bit JIS to 8-bit JIS */ #define JISRP 6 /* repair damaged JIS file */ #define JISCVT 7 /* convert EUC etc to 7-bit JIS */ #define HZPGB 8 #define HZPB5 9 #define KSC8 10 /* 7-bit KSC to 8-bit KSC */ #define UTF7TOUNI 11 /* 7-bit unicode to double-byte */ #define UTF8TOUNI 12 /* 8-bit unicode to double-byte */ #define CNSB5 13 /* CNS planes 1/2 to Big5 */ #define GBB5 14 /* GB to B5 */ #define HZB5 15 #define B5GB 16 #define B5HZ 17 #define TOSHORTPS 18 #define PAGEPRINT 19 #define MIMEQP 20 /* decoding mime quoted printable */ #define MIME64 21 /* decoding mime base64 */ #define ADDLBAS 22 /* filter input file, add sender's address */ #ifdef PSPRINT #define isbreaka(c) (c==' ' || c=='(' || c=='{') #define isbreakb(c) (c=='}' || c==')') #define MAXLENGTHA 20 #define MAXLENGTH 72 #define MAXLENGTHB 99 #endif /* paper sizes */ #define LETTER 1 #define LEGAL 2 #define A3 3 #define A4 4 #define BUFSIZE 8192 #define MAXBUFSZ 60000 #define SBUFSIZE 256 #define ASCBUFSIZE 300 #define MAXLINES 350 /* max # of lines, affect multiple column options */ #define LBASMAX 500 /* max # of chars for sender's address */ #define isvgb(c) (c==0x21 || c==0x2c || c==0x3A || c==0x3B || c==0x3F) #define MSBoff(c) (c & 0x7f) #define MSBon(c) (c | 0x80) #define GBPOS(a, b) (((a)-0xa1)*94 + ((b)-0xa1)) #define GBB1(n) ((n)/94 + 0xa1) #define GBB2(n) ((n)%94 + 0xa1) #define B5POS(a, b) (((a)-0xa1)*157 + (b) - ((b)>=0xa1 ?(0xa1-63):0x40)) #define B5B1(n) (((n)/157) + 0xa1) #define B5B2(n) ((n)%157 + (((n)%157)<63 ? 0x40 : (0xa1-63))) #define GBbox 85 /* index postion of 0xA1F5 */ #define B5box 27 /* 0xA1BC */ /* jis */ #define SS2 142 #define SJIS1(A) ((A >= 129 && A <= 159) || (A >= 224 && A <= 239)) #define SJIS2(A) (A >= 64 && A <= 252) #define HANKATA(A) (A >= 161 && A <= 223) #define ISEUC(A) (A >= 161 && A <= 254) #define ISMARU(A) (A >= 202 && A <= 206) #define ISNIGORI(A) \ ((A >= 182 && A <= 196) || (A >= 202 && A <= 206) || (A == 179)) /** margins, line space (CLP) and char spaces **/ int LM, RM, TM, BM, CSP, CLP, CIP, H, V; int BMover=8; /* allow to exceed BM by this amount in dots */ float XX=0.0, YY; /* actual paper size in inch, e.g. 8.5x11 */ int Xw, Yh, Xa, Ya; /* "" in dots, Xa (lm), Ya (tm) */ float pts, defpts; /* 1 pts = 1/72 inch */ float ppd = -1; /* pts per dot, default .24, assume device res 300dpi */ static float Cw=0.72; /* char width/line space */ float Ci, Ca, defCi, defCa; /* space between lines, characters */ /* Additional char spacing for font, FontCa >= -5 must be set in HBF/HTF */ float FontCa; float FontptsScale ; /* scale a char in both x and y */ float Casc=0.5; /* ASC_width / CH_width */ int nCN=2048, copies=1; /* # of entries in CNdict */ int nHzline=9999; /* # of chars per Hz/JIS line, default 70 */ char prntcmd[80]; char PSfile[100], EPSfile[80], KWfile[80], tempfile[80]; char DictExt[2]; /* CNdict extension for EPS */ int ptspc, defptsi; /* currently used pts, defpsti=INT(defpts+.5) */ int mx, my, CHsize; /* bitmap mx by my, string length CHsize */ int inCH=100, newpos=1; int filecount=1, fprntfile=1; int fputnpage=6; /* page number position 1-6 */ int pgpd=0; /* physical pages actually printed */ int pgcount=1, pgcount_bak; int bp=0, ep=0; /* page numbers to begin/end printing */ int Prntpage, odd=0; /* page-print: 0/1/2, print all/odd/even pages */ int twoside=0; /* two-sided format */ int booklet=0; /* output booklet format */ int frl=NT; /* right-left */ int fnewline=1; int cnsp=0; /* special CH char */ unsigned int *fstring, *fdict, nchar; unsigned int cspace, b1l, b2l; /* space char, lowerest byte-1(2) */ unsigned int b2h_range1, b2gap, b2span; /** Big5: b2span = 63+94=157; b1l=0xA1; b2l=0x40; b2h_range1=0x7E; b2gap=34; **/ unsigned char **ptstring, *array; float gray=.0; /* 0 black, .9 white */ float Cx=1., Cy=1., defCx, defCy; int stdinput=0, stdoutput=0; /* use stdin/stdout */ int code=UNKNOWN, defcode=UNKNOWN, convcode=NT; int codecmd, convcodecmd; int big5=0, lcode; /* language code (GB, B5, JIS, KSC) */ int pausqm=0; /* pause at every (pause) pages */ int landscape=0, EPS=0, IncEPS=0; /* generate EPS, EPS file included */ int vertical=0, Rotate=0, vgb=0; int suppress=0, mute=0, keepPS=0; /* mute menu or map .,:; to CH */ int manualfeed=0, envelope=0; int adjust=1; /* adjust spaces between punctuation marks */ int alnumadjust=0; /* adjust alnum from CH to English */ int timestat=0; /* suppress time / statistics about document */ int charstat=1; /* char/word statistics */ int AdjAtEndDoc=1; /* BM adjust at end of document if multicolumn */ int cmdlinehbf=0; /* hbf filename supplied in command-line */ int cgap=0; /* gap between columns in pts, use default if zero */ int vgap=0; /* vertical gap when column # changes (def. 1.5 line spacing) */ int euro=0; /* European chars, def: auto-detect; -1, disable */ int tabascii=0; /* set tab width according to CH (0) or ASCII(1) default 0 (1 if ASCII file selected) */ int addrlabel=0; /* mode for printing address labels */ int lbn=0, lbnx=2, lbny=5; float lbxp=.5, lbyp=1.0, lbxinc=4.25, lbyinc=2.0; void addLBAS(FILE *); unsigned char *buf; /* main buffer */ /* special effect */ int fshade=0; struct {int x; int f;} UDline; /* underline */ /* for central adjust; */ int centraladj=0, spaceH; /* spaceH: H value of 1st non-space char */ int startline=1; /* previous line ended with EOL */ /* ASC font */ int nEF = -1, defnEF, nEFs[40]; float Wasc[129]; /* width of ASC char re Courier */ static char *EFname[]={"AvantGarde-Book", "", "Courier", "Helvetica", "", "", "Palatino-Roman", "Times-Roman", "ZapfChancery-MediumItalic", "ZapfDingbats", "AvantGarde-BookOblique", "", "Courier-Oblique", "Helvetica-Oblique", "", "", "Palatino-Italic", "Times-Italic", "", "", "AvantGarde-Demi", "", "Courier-Bold", "Helvetica-Bold", "", "", "Palatino-Bold", "Times-Bold", "", "", "AvantGarde-DemiOblique", "", "Courier-BoldOblique", "Helvetica-BoldOblique", "", "", "Palatino-BoldItalic", "Times-BoldItalic", "", "Symbol"}; /* for search */ int PCN, SCN; int cTM, cBM, cLM, cRM, Ha; int pline=0, pcolumn=1; int sline=0, column=1, defcolumn; /* defcolumn is the one set for doc */ int lineclp[MAXLINES], linedif[MAXLINES], linecip[MAXLINES]; /** output ascii buffer: p is the total # of char, pp and Hp are the # of chars and H position after the last white space **/ struct {unsigned char s[ASCBUFSIZE]; int p, pp, Hp;} ascbuf; /* for efficient multiple font/language handling */ int PreScanMode=1; struct FontTag { char FontName[80]; /* HBF/TTF/HTF */ int FontID; /* numerical */ int ttf_font; int lcode; /* needed only for multiple language */ int mx, my; unsigned int *fstring, *fdict, nchar, cspace, b1l, b2l; unsigned int b2h_range1, b2gap, b2span; unsigned int ndchar, nCN, k; unsigned char **ptstring; struct FontTag *p; } *Fonts=NULL, *CurrentFont; /* for HBF */ char HBFname[80], defHBFname[80]; struct Roots {char *s; struct Roots *p;} *root; struct Bytes {int l; int h; int a;} *b2; struct HBFrange {unsigned int l; unsigned int h; long offset; char bmfname[50]; FILE *fp;} *seg; int nb2, nseg, GR=0; /* GL(GR=0): 7-bit form */ void construct_fontname(char *); /* for TTF font support */ int ttf_font=0; /* will auto detect */ char TTFfile[120]; int PSLlevel=1; /* language level, if 2, use Base85 compression */ unsigned char dummy[2]; FILE *fpTTF; /* repairs */ int ignorespace=0, fix=0, ignoreEOL=0; /* fix/repair */ int breakfile=0; /* break big file into small (>12k, def: 64k) ones; or (when multi-input), in -fpg# start a new page for each input (optional) if within # (<=9) lines to bottom, or (when multi-input) multiple output (>10) */ long fnchar=0; /* char count in small file */ char newshd='>'; /* initial char for news replys */ unsigned char sbuf[SBUFSIZE]; int sbufp=0; /* pointer to sbuf */ int bmpshift=0, bmpshift_dir=NT; /* shift bitmap of a char */ unsigned int bmpshift_ch, bmpshift_ch2; /* for utf & utf7: convert to two-byte unicode */ long utf7_getc(), utf_getc(); static unsigned char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; static unsigned char safe[] = "'(),-.:?"; static unsigned char optional[] = "!\"#$%&*;<=>@[]^_`{|}"; static unsigned char space[] = " \t\n\r"; #define NUMBYTES 256 #define BASE64 0x01 #define SAFE 0x02 #define OPTIONAL 0x04 #define SPACE 0x08 #define CODE_ERROR 0x80 static char inv_base64[128]; static char char_type[NUMBYTES]; static int utf_initzd; static int in_base64; static unsigned long bit_buffer; static int nbits; #define U2ESC 0x4D /* ESCs for 2-byte unicode */ #define U2ESC2 0x21 /* 0x4D4D = 0x4D, 0x4D21(M!) = 0x00 */ /* functions */ void newline(int, int), endAC(), usage(int), opnfile(int); void HBFclose(), convers(int), MemExit(), cleanup(int); void header(), PSctrl(), FName(char *, char *); FILE *Rfopen(char *, char *); void shift2seven(), euc2seven(), seven2seven(); void han2zen(), sjis2jis(), jisrepair(); void charsize(float); float getnew(float, int); void endpage(int); void putBitmap(unsigned char *); int RE_name(char *, char *); void mimeqpdecode(FILE *in); struct INfiles {char *s; char *t; FILE *fp; struct INfiles *p;} *Rinf, *inf, *mRinf; struct WordFreqstr {unsigned char *s; int *addrs; int j; int freq; struct WordFreqstr *p;} *WordFreq; int extraEOL = 0; /* before error message */ FILE *out, *HBF, *errout, *msgout; #ifdef CNS_SUPPORT /* begin CNS support */ /* #include "cnsb5.h" */ #else /* no CNS support */ cns2b5(FILE *in) /* CNS to Big5 convertion */ { fprintf(stderr, "No CNS subroutines, please follow instructions in file cns2b5.c\n\ (available by ftp at ftp.neurophys.wisc.edu:/pub/cn,\n\ use \"anonymous\" as user name)\n"); return 1; } #endif /* CNS support */ insertEOL() /* print an EOL, to put message between page numbers */ { if (extraEOL) fputc('\n', errout); extraEOL = 0; return 1; } int IncludeEPS(s) char *s; { char feps[80], cst[256]; int llx, lly, urx, ury; FILE *fp; if (!inCH) endAC(1); if (s[0]!='\0') strcpy (feps, s); else if (!stdinput) { insertEOL(); fprintf(stderr, "Please enter full name of EPS file to be included:\n"); gets(feps); } if ((fp=fopen(feps, "r"))==NULL) { insertEOL(); fprintf(stderr, "Can't open EPS file -> %s\n", feps); bell(); return 0; } while (fgets(cst, 255, fp)!=NULL) if (strncmp(cst, "%%BoundingBox", 13)==0) break; sscanf(cst, "%*s%d%d%d%d", &llx, &lly, &urx, &ury); fprintf(out, "\nBeginEPSF\ncpx cpy translate dpi 72 div dup scale %d %d translate\n\ %%%%BeginDocument: %s\n", 0-llx, 0-lly, feps); rewind(fp); while(fgets(cst, 255, fp)!=NULL) fprintf(out, "%s", cst); fprintf(out, "\n%%%%EndDocument\nEndEPSF\n"); fclose(fp); IncEPS++; return 1; } int HBFopen() { /* open HBF file, set segment and byte-2-ranges, open bitmap files */ int j, m; char cst[120]; extern FILE *TTFopen_init(char *); if ((HBF=Rfopen(HBFname, "r"))==NULL) { insertEOL(); fprintf(stderr, "Can't open HBF or TTF header file -> %s\n\ Please check if the path/directory/filename is correct\n\ and see Part VI of the help file\n\ about the name convention for HBF files: cn*##.hbf\n", HBFname); bell(); if (*defHBFname==0) exit(-1); else return 0; } /* check if it is HBF, HTF (header file for TTF), or TTF font itself * the default is TTF font itself * HTF contains the first line as "TTF_FILE: name_of_ttf_file" * and possibly some comment lines **** optionally, it can have a line to specify additional char spacing, e.g. **** "_AddCharSpacing: .5 " sets FontCa=0.5 (1=standard, 8% char **** width, def=0, range < 20, > -5) **** "_CharSizeScaling: 1.02" scales the whole char (note: very sensitive). **** These lines can also be put in the HBF file after all regular **** HBF property lines but before the line "HBF_END_FONT" **** * * problem here: bitmap files might be recognized as TTF font file */ FontCa=0.; /* reset font-specific parameters */ FontptsScale=1.; if (fgets(cst, 119, HBF) != NULL) { if (strncmp(cst, "HBF_START", 9) != EQ) { if (strncmp(cst, "TTF_FILE", 8)==EQ) { sscanf(cst, "%*s%s", &TTFfile); while (fgets(cst, 119, HBF) != NULL) { if (strncmp(cst, "_AddCharSpacing", 15) == EQ) sscanf(cst, "%*s%f", &FontCa); else if (strncmp(cst, "_CharSizeScaling", 16) == EQ) sscanf(cst, "%*s%f", &FontptsScale); } } else strcpy(TTFfile, HBFname); fclose(HBF); ttf_font = 1; fpTTF = TTFopen_init(TTFfile); /* mx, my: use those of load_cmap (ymax or EM) */ if (mx < my) mx=my; my=mx; if (PSLlevel != 2) { PSLlevel=2; fprintf(stderr, "TTF font needs level 2 PS language level, this PS file may not work.\n\ Please use -level option on command line\n"); } RegisterFont(); return 1; } } /* HBF file */ GR=0; while (fgets(cst, 119, HBF)!=NULL) if (strncmp(cst, "HBF_BITMAP_BOUNDING_BOX", 23)==0) break; sscanf(cst, "%*s%d%d", &mx, &my); CHsize=my*((mx+7)/8); if (array!=NULL) free(array); array = (unsigned char *) calloc(CHsize+1, sizeof(unsigned char)); if (array==NULL) MemExit(); while (fgets(cst, 119, HBF)!=NULL) if (strncmp(cst, "HBF_START_BYTE_2_RANGES", 23)==0) break; sscanf(cst, "%*s%d", &nb2); b2 = (struct Bytes *) calloc(nb2, sizeof(struct Bytes)); if (b2==NULL) MemExit(); for (j=0; j= 0xa1) GR=1; /* GL: 7-bit form */ if (b2[j].a==1) { fprintf(stderr, "Your system is special, please run hbfhx2d.c on all your HBF files\n\ (ftp: ftp.neurophys.wisc.edu:/pub/cn)\n"); exit(0); } } while (fgets(cst, 119, HBF)!=NULL) if (strncmp(cst, "HBF_START_CODE_RANGES", 21)==0) break; sscanf(cst, "%*s%d", &nseg); seg = (struct HBFrange *) calloc(nseg, sizeof(struct HBFrange)); if (seg==NULL) MemExit(); for (j=0; j0) { for (m=0; m %s\n\ Please make sure the path/directory/filename is correct\n\ and the HBF file is properly written\n", seg[j].bmfname); bell(); if (*defHBFname==0) exit(-2); else return 0; } } } /* this is an extended HBF property only for cnprint, put it at the * after all regular HBF property lines, but before the HBF_END_FONT line * this line sets additional char spacing FontCa */ while (fgets(cst, 119, HBF) != NULL) { if (strncmp(cst, "_AddCharSpacing", 15) == EQ) sscanf(cst, "%*s%f", &FontCa); else if (strncmp(cst, "_CharSizeScaling", 16) == EQ) sscanf(cst, "%*s%f", &FontptsScale); } RegisterFont(); return 1; } void HBFclose() { /* Reset segment and byte-2-ranges, close bitmap files and HBF file */ int j; if (ttf_font) { TTFclose(fpTTF); ttf_font=0; return; } for (j=0; j= seg[i].l && ch <= seg[i].h) { /* treat as if segment starts at lowest byte 2, then compensate */ off = seg[i].l%256 - b2[0].l; k = ch - seg[i].l + off; j = k%256; k /= 256; if (nb2==1) addr = k*b2[0].a + j - off; else if (nb2==2) { addr = k*(b2[0].a + b2[1].a) + j - off; if (j > b2[0].a) addr -= (b2[1].l-b2[0].h-1); if (off > b2[0].a) addr += (b2[1].l-b2[0].h-1); } else /* can't handle yet, but it seems enough for now */ return -5; addr = addr*CHsize + seg[i].offset; fseek(seg[i].fp, addr, 0); k = (int) fread(array, CHsize, 1, seg[i].fp); if (bmpshift_dir) { if (bmpshift_dir != RMIRROR) fprintf(errout, "R%d ", k); CharBitmapShift(seg[i].fp, addr, array); } return k; } insertEOL(); if (!mute) fprintf(errout, "Out of Range Char: %04X\n", ch); for (j=0; j strlen(v[0])) return 0; if (strncmp(s, v[0], j)==0) { v[0] += j-1; return 1; } else if (s[j-1]=='=' && v[0][j-1]=='/') { if (strncmp(s, v[0], j-1)==0) { v[0] += j-1; return 1; } else return 0; } return 0; } char *readstr(v, s) char *v[], *s; { v[0]++; sscanf(*v, "%s", s); v[0] += (strlen(s)-1); return s; } float readfv(v, s) char *v[], *s; { float x; char *readstr(); sscanf(readstr(v, s), "%f", &x); return x; } initinputfile(cst) char *cst; { char *s; #ifdef VMS char s2[80], sd[70], s3[40]; int n, wc=0; FILE *tmp; s = cst; while (*s!='\0') { if (*s=='*' || *s=='?') wc++; s++; } if (wc) { n = strlen(cst); while(n--) if (cst[n]==']') break; sd[0]='\0'; if (n>0) { strcpy(sd, cst); sd[n+1]='\0'; } strcpy(s2, "dir/output=dir.tmp "); strcat(s2, cst); system (s2); tmp=fopen("dir.tmp", "r"); fgets(s2, 79, tmp); while (fgets(s2, 79, tmp)!=NULL) { if (strncmp(s2, "Directory", 9)==0 || strlen(s2)<=2) continue; if (strncmp(s2, "Total of", 8)==0) break; s2[strlen(s2)-1]='\0'; if (!mute) fprintf(errout, "%s (Y/N)?", s2); if (mute || yes(1)) { sscanf(s2, "%s", s3); strcpy(s2, sd); strcat(s2, s3); initinputfile(s2); } } system("del dir.tmp;"); return 1; } #endif if (inf->fp == stdin) { inf->t = (char *) calloc(strlen(cst) + 2, sizeof(char)); if (inf->t == NULL) MemExit(); strcpy(inf->t, cst); } if (inf->s != NULL) { inf->p = (struct INfiles *) calloc(1, sizeof(struct INfiles)); if (inf->p == NULL) MemExit(); inf = inf->p; } inf->s = (char *) calloc (strlen(cst) + 5, sizeof(char)); if (inf->s == NULL) MemExit(); strcpy(inf->s, cst); opnfile(IN); return 1; } void init(int argc, char **v) { char c, cst[100], *readstr(); int m, j=0, ASCfile=0, HBFopen(); float ptscmd, Cxcmd, Cycmd, Cicmd, Cacmd, Casccmd; float rmcmd, lmcmd, tmcmd, bmcmd, readfv(); int columncmd=0, eurocmd=0, fputnpagecmd = -2; int papersize=UNKNOWN; if (argc==999) goto B5INIT; prntcmd[0]='\0'; EPSfile[0]='\0'; KWfile[0]='\0'; tempfile[0]='\0'; *HBFname=0; *defHBFname=0; *PSfile=0; errout = stderr; ptscmd=Cxcmd=Cycmd=0.; Cicmd=Cacmd=Casccmd=0.; rmcmd=lmcmd=tmcmd=bmcmd=0.; Rinf = (struct INfiles *) calloc(1, sizeof(struct INfiles)); if (Rinf == NULL) MemExit(); inf = Rinf; inf->fp = stdin; /* for unix pipeline */ while (--argc>0) if (*(++v)[0] == '-') { if (*(v[0]+1)=='\0') stdinput=mute=1; while (c = *++v[0]) { switch (c) { case '5': code=B5; big5++; break; case 'a': if (isstr("aa", v)) ASCfile++; else if (isstr("a3", v)) papersize=A3; else if (isstr("a4", v)) papersize=A4; else alnumadjust++; break; case 'b': if (isstr("b52gb", v)) convcode=B5GB; else if (isstr("b52hz", v)) convcode=B5HZ; else if (isstr("big5p", v)) code=B5P; else if (isstr("big5", v)) { code=B5; big5++; } else if (isstr("bmps", v)) { if ((bmpshift=num(v, 2)) > 0) { argc--; v++; v[0]--; sscanf(readstr(v, cst), "%x", &bmpshift_ch); v++; if (**v == '0') { argc--; v[0]--; sscanf(readstr(v, cst), "%x", &bmpshift_ch2); } else { v--; bmpshift_ch2 = bmpshift_ch; } } } else if (isstr("bm=", v)) bmcmd = readfv(v, cst); else if (isstr("bk", v)) { booklet = num(v, 1); if (booklet==0) booklet=2; } else if (bmpshift) bmpshift_dir=B; else { m=num(v, 3); if (*++v[0]=='e') { bp=m; ep=num(v, 3); } else { v[0]--; pgcount=m; } } break; case 'c': if (isstr("cns", v)) { code=CNS; break; } else if (isstr("cgap=", v)) cgap = readfv(v, cst); else if ((m=num(v, 1)) < 1) break; else columncmd=m; if ((m=num(v, 2)) >= 10) cgap=m; else if (m && m<10) v[0]--; break; case 'd': adjust=0; Casc=0.5; break; case 'e': if (isstr("euc", v)) code=EUC; else if (isstr("even", v)) odd += 2; else if (isstr("extr", v)) convcode=PAGEPRINT; else if (isstr("euro", v)) eurocmd++; else if (isstr("env", v)) { envelope = 1; Casccmd = 0.6; if (*++v[0]=='s') envelope++; /* small size */ else v[0]--; m = num(v, 1) + 20; /* Is -env1? */ if (m!=21) break; /* the CNLIST option is -r21 */ sprintf(cst, "cnlist %s -o/name.tmp -r%d ", (strlen(KWfile)>0)? KWfile : "revlis.4", m); argc--; v++; v[0]--; strcat(cst, readstr(v, KWfile)); argc--; v++; v[0]--; strcat(cst, " "); strcat(cst, readstr(v, KWfile)); fprintf(errout, "%s\n", cst); system(cst); initinputfile("name.tmp"); } else if (m=num(v, 3)) { Casccmd = m/10.; if (m>=10) Casccmd /= 10.; } else { isstr("eps", v); /* def: eps */ EPS=1; fputnpage=0; keepPS=1; if (isstr("ms", v)) EPS++; } break; case 'f': if (isstr("fpg", v)) breakfile = 1 + num(v, 1); else if (isstr("f=", v)) { strcpy(HBFname, readstr(v, cst)); cmdlinehbf=1; } else twoside=1; break; case 'g': if (isstr("gb2hz", v)) convcode=GBHZ; else if (isstr("gb2b5", v)) convcode=GBB5; else if (isstr("gbk", v)) code=GBK; else if (isstr("gb", v)) code=GB; break; case 'h': if (isstr("hz2gb", v)) convcode=HZGB; else if (isstr("hz2b5", v)) convcode=HZB5; else if (isstr("hz", v)) code=HZ; else if ((m=num(v, 2)) > 0) nEF=m; else { usage(2); exit(0); } break; case 'i': stdinput=mute=1; if (isstr("io", v)) stdoutput=1; break; case 'j': if (isstr("jis8", v)) code=SJIS; else if (isstr("jis", v)) code=JIS; else AdjAtEndDoc=0; break; case 'k': if (isstr("ksc", v)) code=KSC; else if ((m=num(v, 3)) > 0) breakfile=m; else if (isstr("k=", v)) strcpy(KWfile, readstr(v, cst)); else breakfile = 64; break; case 'l': if (isstr("lm=", v)) lmcmd = readfv(v, cst); else if (isstr("letter", v)) papersize=LETTER; else if (isstr("legal", v)) papersize=LEGAL; else if (isstr("label", v)) addrlabel=1; else if (isstr("level", v)) PSLlevel = num(v, 2); else if (bmpshift) bmpshift_dir=L; else { landscape = 1+num(v,1); column = 2; } break; case 'm': if (isstr("mfeed", v)) manualfeed = (manualfeed)? 0:1; else if (isstr("mimeqp", v)) convcode=MIMEQP; else { m=num(v,3); if (!m) mute = (mute)? 0:1; else copies=m; } break; case 'n': m=num(v, 4); if (m) nHzline=m; else if (isstr("nopage", v)) fputnpagecmd=0; else if (isstr("n=", v)) { m=num(v, 4); if ( m>=0 && m<=4000) nCN=m; } break; case 'o': if (isstr("o=", v)) { strcpy(PSfile, readstr(v, cst)); keepPS++; } else if (isstr("out", v)) stdoutput++; else if (isstr("odd", v)) odd++; else odd++; break; case 'p': pausqm=4; if (m=num(v,1)) pausqm=m; break; case 'q': if (isstr("q=", v)) strcpy(prntcmd, readstr(v, cst)); break; case 'r': if (isstr("rm=", v)) rmcmd = readfv(v, cst); else if ( (m=num(v, 1)) == 5) { bmpshift_dir = RMIRROR; v[0]--; } else if (m) { convcode=FIL; fix=m;} else if (!isstr("r=", v)) bmpshift_dir = (bmpshift)? R : RMIRROR; else if ( (m=num(v, 4)) > 30) ppd=72./m; break; case 's': if (isstr("size=", v)) ptscmd = readfv(v, cst); else if (isstr("short", v)) convcode=TOSHORTPS; else suppress = (num(v, 1) > 1)? 2:1; break; case 't': if (isstr("tab", v)) tabascii++; else if (isstr("tm=", v)) tmcmd = readfv(v, cst); else if (bmpshift) bmpshift_dir=T; else { timestat++; if (fix && isalnum(*(v[0]+1))) newshd = *++v[0]; } break; case 'v': if (isstr("vgap=", v)) vgap = readfv(v, cst); else { vertical++; Rotate=1; /*adjust=0;*/ fputnpage=4; } break; case 'w': fprntfile=0; break; case 'x': case 'y': if (m=num(v, 1)) { if (c=='x') Cxcmd += (m/10.); else Cycmd += (m/10.); } break; case 'z': if (isstr("zw", v)) code=ZW; else convcode++; break; case 'u': if (isstr("utf8", v)) code=UTF8; else if (isstr("utf7", v)) code=UTF7; else if (isstr("utf", v)) code=UTF; else { mute=1; errout=fopen("log.1", "w"); } break; default: fprintf(stderr, "Problem option: -%c\n", c); usage(11); exit(0); break; } } } else if (argc!=999) initinputfile(*v); /* end while-if */ getroot(); /* get default code type, ppd, tempfile */ if (getdata(4)==0) defcode=GB; if (ppd<0.) ppd=.24; if (strlen(tempfile)<2) strcpy(tempfile, "CNPRINT.TMP"); #ifdef MUSER /* use pid instead of time */ sprintf(cst, "%d", (int) getpid()); strcat(tempfile, cst); #endif if (Rinf->fp == stdin && !bmpshift) { #ifdef VMS usage(0); exit(1); #else if (stdinput) { /*fprintf(errout, "CNPRINT: use standard input\n");*/ # ifdef MUSER sprintf(cst, "/tmp/cnpstdin%d", (int) getpid()); # else strcpy(cst, "cnpstdin.tmp"); # endif opnfile(OUT); while ( (c=fgetc(stdin)) != EOF) fputc(c, out); fclose(out); out=NULL; RE_name(tempfile, cst); initinputfile(cst); } else { usage(0); exit(1); } #endif } opnfile(OUT); if (!mute) fprintf(errout, "%s\n\n", Version); /* prepare for multiple output */ codecmd=code; convcodecmd=convcode; B5INIT: if (argc==999) { lcode=UNKNOWN; HBFclose(); if (fstring!=NULL) free(fstring); if (ptstring!=NULL) free(ptstring); fstring=NULL; ptstring=NULL; if (!cmdlinehbf) *HBFname=0; } if (code>=ZW && code<=GB) lcode=GB; else if (code==B5 || code==CNS) lcode=B5; else if (code>=JIS && code<=EUC) lcode=JIS; else if (code>=UTF && code<=UTF8) lcode=UTF; else if (code==KSC || code==GBK || code==B5P) lcode=code; else lcode=defcode; /* else use default */ if (vertical>1 && lcode==GB) vertical=vgb=1; if (*HBFname==0) getdata(2); if (*HBFname==0) { if (lcode!=GB) { fprintf(stderr, "No HBF file specified for %s in either cnprint.cmd or command line\n\ Please read Part IV of the help file\n\ on how to specify font file for %s documents.\n", codename[lcode], codename[lcode]); bell(); exit(7); } else strcpy(HBFname, "cnj24.hbf"); } j=strlen(HBFname); if ((j==3 || j==4) && isdigit(HBFname[1]) && isdigit(HBFname[2])) { /* if j24, k256 or alike, construct HBFname */ strcpy(cst, HBFname); strcat(cst, ".hbf"); construct_fontname(cst); } strcpy(defHBFname, HBFname); if (convcode==GBHZ || convcode==GBB5 || convcode==B5GB || convcode==B5HZ) return; if (!HBFopen()) exit(0); /* if (lcode==KSC) adjust=0; */ if (argc==999 || bmpshift) return; if (papersize != UNKNOWN) switch (papersize) { case LETTER: XX=8.5; YY=11.; break; case LEGAL: XX=8.5; YY=13.5; break; case A3: XX=11.69; YY=16.54; break; case A4: XX=8.27; YY=11.69; break; default: break; } if (!getdata(3)) { XX=8.5; YY=11.; pts = ((landscape)? 11.6 : 13.6)/(Cx+Cy-1); Ca=1.; Ci=Cy+(Cx-1.)/2.; LM=261; RM=219; TM=252; BM=275; /* mm*10 */ if (landscape) { LM=153; RM=152; TM=200; BM=220; } } if (prntcmd[0]=='\0') fprntfile=0; if (booklet) { column = booklet; LM=RM=100; landscape = 1; } if (landscape>1) { LM=153; RM=152; TM=200; BM=220; switch (landscape) { case 2: Cy=1.2; Ci=1.1; pts=11.6; break; case 3: pts=11.6; break; case 4: Cy=1.2; Ci=1.1; pts=11.3; break; case 5: pts=11.3; break; default: break; } } if (ASCfile) { Ci=0.5; Casc=0.6; TM=180; BM=180; /* mm*10 */ tabascii = (tabascii)? 0:1; } ascbuf.p=ascbuf.pp=0; /* command line values have top priority */ if (envelope) { landscape=1; TM=(XX>8.4)? 700 : 640; BM = TM - 40; RM=120; LM=(YY>11.2)? 823 : 648; if (envelope==2) LM += 750; fputnpage=0; manualfeed++; Ci=.5; Casc=.6; if (nEF<0) nEF=3; } if (addrlabel) { LM=RM=TM=BM=25.4; /* 2.54 mm, 0.1 inch */ fputnpage=0; manualfeed++; Ci=.5; Casc=.6; if (nEF<0) nEF=3; } if (columncmd>0) column=columncmd; if (Cxcmd>0.01) Cx=Cxcmd; if (Cycmd>0.01) Cy=Cycmd; if (Cicmd>0.01) Ci=Cicmd; if (Cacmd>0.001) Ca=Cacmd; if (rmcmd>0.01) RM=rmcmd*10; if (lmcmd>0.01) LM=lmcmd*10; if (tmcmd>0.01) TM=tmcmd*10; if (bmcmd>0.01) BM=bmcmd*10; if (Casccmd>0.01) Casc=Casccmd; if (ptscmd>1.) pts=ptscmd; if (eurocmd) euro = (euro>=0)? -1 : 1; if (fputnpagecmd >= 0) fputnpage=fputnpagecmd; if (nEF<0) nEF=2; /* def: Courier */ getEfontdata(); /* make it the last one */ } void construct_fontname(char *str) { if (lcode==UTF) sprintf(HBFname, "cnu%s", str); else if (lcode==GBK) sprintf(HBFname, "cng%s", str); else if (lcode==B5P) sprintf(HBFname, "cnp%s", str); else sprintf(HBFname, "cn%s%s", ((lcode==B5)? "5" : ((lcode==JIS) ? "j" : ( (lcode==KSC)? "k" : ""))), str); } RegisterFont() { struct FontTag *F; int j, k; CurrentFont = NULL; if (Fonts!=NULL) { for (F = Fonts; F != NULL; F = F->p) { if (strcmp(HBFname, F->FontName) == EQ) { CurrentFont = F; break; } else if (F->p==NULL) break; } } if (CurrentFont != NULL) { /* not a new font */ if (PreScanMode) { /* copy lcode related properties, but not needed for now */ ; } fstring = CurrentFont->fstring; ptstring = CurrentFont->ptstring; mx = CurrentFont->mx; my = CurrentFont->my; ttf_font = CurrentFont->ttf_font; return; } /* new font */ CurrentFont = (struct FontTag *) calloc(sizeof(struct FontTag), 1); if (CurrentFont == NULL) MemExit(); CurrentFont->p = NULL; if (Fonts==NULL) { Fonts = CurrentFont; CurrentFont->FontID = 1; } else { /* add to the chain: F is the last one on the chain */ F->p = CurrentFont; CurrentFont->FontID = F->FontID + 1; } F = CurrentFont; strcpy(F->FontName, HBFname); F->mx = mx; F->my = my; F->ttf_font = ttf_font; switch (lcode) { case UTF: cspace = 0x3000; b2span = 256; b2gap = 0; b1l=0x30; b2l=0x00; b2h_range1=0xFE; nchar = (unsigned int) 53248; break; case B5: cspace = 0xA140; b2span = 157; b2gap = 34; b1l=0xA1; b2l=0x40; b2h_range1=0x7E; nchar = 13973; /* (63+94)*89 */ break; case GBK: case B5P: cspace = (lcode==GBK)? 0xA1A1 : 0xA140; b2span = 190; b2gap = 1; b1l=0x81; b2l=0x40; b2h_range1=0x7E; nchar = 23940; break; default: /* GB, KSC, JIS */ cspace = 0xA1A1; b2span = 94; b2gap = 0; b1l=0xA1; b2l=0xA1; b2h_range1=0xFE; nchar = (lcode==GB)? 8178 : 7876; /* 94*87 or 94*84 */ break; } k=0; if (!ttf_font) { for (j=0; jnchar = nchar; F->lcode = lcode; F->cspace = cspace; F->b1l = b1l; F->b2l = b2l; F->b2h_range1 = b2h_range1; F->b2gap = b2gap; F->b2span = b2span; F->fstring = fstring; F->ptstring = ptstring; } int getdata(n) int n; { char t[100], str[20], *s; int j, k, m[10]; float x1, x2, x3, x4; FILE *cmd; if ((cmd=Rfopen("cnprint.cmd", "r"))==NULL) { if (n>0) fprintf(errout, "Can't open file cnprint.cmd\n\ Please check if it exists or if the path is correct\n\ and/or read the help file for information on cnprint.cmd\n"); return 0; } switch(n) { case 1: /* get metric data for ASCII fonts */ if (strlen(EFname[nEF])<=1) return 0; while (fgets(t, 98, cmd)!=NULL) { if (strncmp(EFname[nEF], t, strlen(EFname[nEF]))==0) break; } k=0; while (fgets(t, 98, cmd)!=NULL) { if (!strncmp(t, "DATA", 4)) { sscanf(t, "%*s%d%d%d%d%d%d%d%d%d%d", &m[0], &m[1], &m[2], &m[3], &m[4], &m[5], &m[6], &m[7], &m[8], &m[9]); j=0; while(k<129) { Wasc[k++]=m[j++]/10000.; if (j==10) break; } } if (k>=129) break; } if (k<129) { fclose(cmd); return 0; } break; case 2: /* Default BIG5/JIS/KSC fonts */ if (lcode==B5P) strcpy(str, "BIG5PLUS_FONT"); else if (lcode==GBK) strcpy(str, "GBK_FONT"); else strcpy(str, (lcode==B5)? "BIG5FONT" : ((lcode==JIS)? "JIS_FONT" : ((lcode==KSC)? "KSC_FONT" : ((lcode==UTF)? "UTF_FONT" : "GB_FONT")))); while(fgets(t, 98, cmd)!=NULL) { if (strncmp(t, "DEFAULT_", 8)) continue; if (strncmp((t+8), str, strlen(str)) != EQ) continue; sscanf(t, "%*s%s", HBFname); break; } break; case 3: /* PS print command, paper size, margins, etc */ x1=x2=0.; if (XX < 1.0) { while(fgets(t, 98, cmd)!=NULL) { if (strncmp(t, "DEFAULT_PAPERSIZE", 17)) continue; sscanf(t, "%*s%f%f", &x1, &x2); break; } if (x1<1. || x2<1.) {XX=8.5; YY=11.;} else {XX=x1; YY=x2;} rewind(cmd); } if (fprntfile) while(fgets(t, 98, cmd)!=NULL) { if (strncmp(t, "PS_PRINT_COMMAND", 16)) continue; s = &t[j=17]; while(s[0]==' ') s = &t[++j]; j=0; while(s[j]) if (s[j++]==EOL) s[j-1] = '\0'; if (!strlen(prntcmd)) strcpy(prntcmd, s); break; } rewind(cmd); while(fgets(t, 98, cmd)!=NULL) { if (strncmp(t, "POSTSCRIPT_LANGUAGE_LEVEL", 25)) continue; if (sscanf(t, "%*s%%d", &k) == 1) { if (k==1 || k==2) PSLlevel=k; } break; } rewind(cmd); x1=x2=x3=x4=0.; while(fgets(t, 98, cmd)!=NULL) { if (strncmp(t, "PAPER_MARGINS", 13)) continue; /* margin: R L T B */ if (!landscape) sscanf(t, "%*s%f%f%f%f", &x1, &x2, &x3, &x4); else sscanf(t, "%*s%*f%*f%*f%*f%f%f%f%f", &x1, &x2, &x3, &x4); break; } if (x1<2.9 || x2<2.9 || x3<2.9 || x4<2.9) { LM=261; RM=219; TM=252; BM=275; /* mm*10 */ if (landscape) { LM=153; RM=152; TM=200; BM=220; } } else { LM = x1*10; RM = x2*10; TM = x3*10; BM = x4*10;} rewind(cmd); x1=x2=x3=x4=0.; while(fgets(t, 98, cmd)!=NULL) { if (strncmp(t, "SIZE_SPACE", 10)) continue; /* Ppts, Lpts, char & line space */ sscanf(t, "%*s%f%f%f%f", &x1, &x2, &x3, &x4); break; } if (x1<2. || x2<2. || x3<.01 || x4<.01) { pts = ((landscape)? 11.6 : 13.6)/(Cx+Cy-1); Ca=1.; Ci=Cy+(Cx-1.)/2.; } else { pts = (landscape)? x2 : x1; Ca=x3; Ci = (x4>.99 && x4<1.01)? (Cy+(Cx-1.)/2.) : x4; } rewind(cmd); x1=x2=0.; while(fgets(t, 98, cmd)!=NULL) { if (strncmp(t, "WIDTH-HEIGHT", 12)) continue; /* Cx, Cy */ sscanf(t, "%*s%f%f", &x1, &x2); break; } if (x1>=1.0) Cx=x1; if (x2>=1.0) Cy=x2; if (Cx>1.01 && Cy>1.01) Cy=1.; rewind(cmd); x1 = .5; /* default: euro = 0 (auto detect) */ while(fgets(t, 98, cmd)!=NULL) { if (strncmp(t, "EUROPEAN-LANGUAGE", 17)) continue; sscanf(t, "%*s%f", &x1); break; } if (x1 < -.2) euro = -1; /* disable auto detect */ else if (x1 > .8) euro = 1; rewind(cmd); k = -1; /* default page number position: H, V */ while(fgets(t, 98, cmd)!=NULL) { if (strncmp(t, "PAGE_NUMBER_POSITION", 20)) continue; sscanf(t, (vertical)? "%*s%*s%d":"%*s%d", &k); if (k>=0 && k<=6) fputnpage=k; break; } rewind(cmd); /* address label data */ while(fgets(t, 98, cmd)!=NULL) { if (strncmp(t, "ADDRESS_LABEL", 13) != EQ) continue; sscanf(t, "%*s%d%d%f%f%f%f", &j, &k, &x1, &x2, &x3, &x4); lbnx=j; lbny=k; lbxp=x1; lbyp=x2; lbxinc=x3; lbyinc=x4; break; } break; case 4: /* default encoding, tempfile & device res */ while(fgets(t, 98, cmd)!=NULL) { if (strncmp(t, "DEFAULT_ENCODING", 16)) continue; sscanf(t, "%*s%s", tempfile); break; } if (strncmp(tempfile, "JIS", 3)==0) defcode=JIS; else if (strncmp(tempfile, "KSC", 3)==0) defcode=KSC; else if (strncmp(tempfile, "BIG5P", 5)==0) defcode=B5P; else if (strncmp(tempfile, "BIG5", 4)==0) defcode=B5; else if (strncmp(tempfile, "GBK", 3)==0) defcode=GBK; else if (strncmp(tempfile, "UNICODE", 7)==0) { defcode=UTF8; lcode=UTF; } else defcode=GB; if (code==UNKNOWN) lcode=defcode; tempfile[0]='\0'; rewind(cmd); while(fgets(t, 98, cmd)!=NULL) { if (strncmp(t, "TEMPFILE", 8)) continue; sscanf(t, "%*s%s", tempfile); break; } rewind(cmd); x1=0.; while(fgets(t, 98, cmd)!=NULL) { if (strncmp(t, "DEVICERES", 9)) continue; sscanf(t, "%*s%f", &x1); if (x1>30. && ppd<0.) ppd=72./x1; break; } break; case 5: /* default GB<->B5 table file */ while(fgets(t, 98, cmd)!=NULL) { if (strncmp(t, "DEFAULT_GBB5_TABLEFILE", 22)) continue; sscanf(t, "%*s%s%s", KWfile, EPSfile); break; } break; default: break; } fclose(cmd); return 1; } void opnfile(int n) { if (n==IN) { if ((inf->fp = fopen(inf->s, "r")) == NULL) { insertEOL(); fprintf(errout, "Can't open input file -> %s\n", inf->s); bell(); exit (-3); } } else if ((out=fopen(tempfile, "w"))==NULL) { insertEOL(); fprintf(errout, "Can't open output file\n"); bell(); exit (-4); } } void style(int menu) { int a, b, j; float lm, rm, tm, bm, x, pr, pb, os=0., gap; float Ck; /* ~~~ mm/dot ~~~ */ char s[100], cst[100]; static char *npagepos[]={"No Page Number", "Upper Left", "Upper Middle", "Upper Right", "Lower Left", "Lower Middle", "Lower Right"}; Ck=ppd*25.4/72; /* mm/dot */ Xw=XX*72/ppd; Yh=YY*72/ppd; pr=Xw*Ck; pb=Yh*Ck; if (landscape) { x=pr; pr=pb; pb=x; } lm = LM/10.; rm = RM/10.; /* mm*10 --> mm */ tm = TM/10.; bm = BM/10.; gap = (cgap)? cgap : 2.5*Cw*pts; gap *= 25.4/72; /* pts --> mm */ if (menu) do { charsize(pts); if (booklet) rm=lm=(rm+lm)/2.; if (fputnpage) fprintf(errout, " N: Page Numbering. %s. Starting page number: %d\n", npagepos[fputnpage], pgcount); else fprintf(errout, " N: Page Numbering. No.\n"); x = (Cx>Cy)? Cx : 1./Cy; fprintf(errout, " X: Character Width/Height. %5.2f (Y: H/W. %5.2f)\n", x, 1./x); fprintf(errout, " L: Left Margin. %6.1f mm S: Character Size. %6.2f mm (%4.1f pts)\n\ R: Right Margin. %6.1f mm A: Character Space.%6.2f (1=standard)\n\ T: Top Margin. %6.1f mm I: Line Space. %6.2f (1=standard)\n\ B: Bottom Margin. %6.1f mm H: English Font. %s.\n", lm, CSP*Ck, pts, rm, Ca, tm, Ci, bm, EFname[nEF]); fprintf(errout, " F: Two-Sided. %s.\t U: Envelope. %s.\n", ((twoside)? "Yes" : "No"), (envelope ? "Yes" : "No")); fprintf(errout, " V: Vertical Mode. %s.\t E: EPS Output. %s.\n", (vertical ? "Yes" : "No"), (EPS ? "Yes" : "No")); fprintf(errout, " C: Page Column(s). %d \t D: EPS Page Header. %s.\n", column, strlen(EPSfile)? EPSfile : "None"); fprintf(errout, " M: Manual Feed. %s.\t O: Orientation. %s.\n", (manualfeed ? "Yes":"No"), (landscape ? "Landscape":"Portrait")); fprintf(errout, " P: Print PS file. %s.\t Q: Quit.\n\n", (fprntfile ? "Yes":"No")); /*a = 10.*(pb-bm-tm + (1-Cw)*CLP*Ck)/(CLP*Ck);*/ a = 10.*(pb-bm-tm + (CLP-CIP)*Ck)/(CLP*Ck); if (booklet) b = 10.*(pr-rm*(column+2))/(CSP*Ck)/column; else { b = 10.*(pr-rm-lm-gap*(column-1)) / (CSP*Ck)/column; } fprintf(errout, " There are about %g lines in a page and %g words in a line\n\n\ \tN, P, S, A, I, L, R, T, B, H, E, F, ..., Q\n\n\ Type one of the above to change, or press RETURN key to continue\n", a/10.0, b/10.0); gets(cst); if (cst[0] != '\0') switch (toupper(cst[0])) { case 'X': x = (Cx>Cy)? Cx : 1./Cy; fprintf(errout, "\tX: Character Width/Height. Current: %5.2f\n", x); Cx=getnew(Cx, 5); Cy=1.; break; case 'Y': x = (Cx>Cy)? Cx : 1./Cy; fprintf(errout, "\tY: Character Height/Width. Current: %5.2f\n", 1./x); Cy=getnew(Cy, 5); Cx=1.; break; case 'V': vertical = (vertical)? 0 : 1; if (fputnpage) fputnpage = (vertical)? 4:6; break; case 'C': fprintf(errout, "\tC: Page Column(s). Current: %d\n", column); column=getnew(column+0.1, 4); break; case 'E': EPS = (EPS)? 0 : 1; break; case 'M': manualfeed = (manualfeed)? 0 : 1; break; case 'O': landscape=(landscape)? 0:1; x=pr; pr=pb; pb=x; break; case 'U': envelope=1; if (!landscape) { landscape=1; x=pr; pr=pb; pb=x; } fputnpage=0; bm=tm=(XX>8.4)? 70. : 64.; rm=25.4; lm=(YY>11.2)? 82.3 : 64.8; break; case 'F': twoside=(twoside)? 0:1; break; case 'D': fprintf(errout, "Please enter full name of the EPS file to be used as page header:\n"); gets(EPSfile); fprintf(errout, "Page header on the first page (Y/N)?\n"); gets(s); if (toupper(s[0]) != 'N') IncEPS=1; break; case 'N': if (fputnpage) fprintf(errout, "\tN: Page Numbering. Current: %s. Starting page number: %d\n", npagepos[fputnpage], pgcount); else fprintf(errout, "\tN: Page Numbering. Current: No.\n"); fprintf(errout, "\nEnter any number to change/select starting page number,\n\ \tN: no page numbering\n\tP: change page number position\n\ or press RETURN to continue\n"); gets(s); switch (toupper(s[0])) { case 'N': fputnpage=0; break; case 'P': for (j=0; j<7; j++) fprintf(errout, "\t%d: %s\n", j, npagepos[j]); fprintf(errout, "Please select one, or press RETURN to continue\n"); gets(s); if (isdigit(s[0]) && s[0] <= '6') fputnpage = s[0]-'0'; break; case '\0': break; default: if (toupper(s[0])!='Y') sscanf(s,"%d", &a); else a=pgcount; if (bp && a>bp) { fprintf(errout, "Input greater than %d, the page to begin printing, OK?!\n", bp); bell(); gets(s); } else { pgcount=a; if (!fputnpage) fputnpage = (vertical)? 4:6; } break; } break; case 'P': fprntfile=(fprntfile)? 0:1; if (fprntfile && strlen(prntcmd)<=2) { fprintf(errout, "Print command invalid/not found, please enter new one:\n"); bell(); gets(s); sscanf(s, "%s", prntcmd); if (strlen(prntcmd)<=2) fprntfile=0; } break; case 'S': fprintf(errout, "\tCharacter Size. Current: %7.2f mm (%4.1f pts)\n\ \t\t****** 1 pts = 3.556 mm ******\n", CSP*Ck, pts); pts=getnew(pts,0); break; case 'A': fprintf(errout, "Standard is 8%% of the size of a Chinese character\n\ \tA: Character Space. Current: %7.3f (1=standard)\n", Ca); Ca=getnew(Ca,2); break; case 'I': fprintf(errout, "Standard is 50%% of the size of a Chinese character\n\ \tI: Line Space. Current: %7.3f (1=standard)\n", Ci); Ci=getnew(Ci,2); break; case 'L': fprintf(errout, "\tLeft Margin. Current: %6.1f mm\n\n", lm); lm=getnew(lm,1); if (booklet) rm=lm; break; case 'R': fprintf(errout, "\tRight Margin. Current: %6.1f mm\n\n", rm); rm=getnew (rm,1); if (booklet) lm=rm; break; case 'T': fprintf(errout, "\tTop Margin. Current: %6.1f mm\n\n", tm); tm=getnew (tm,1); break; case 'B': fprintf(errout, "\tBottom Margin. Current: %6.1f mm\n\n", bm); bm=getnew (bm,1); break; case 'H': fprintf(errout, "\tH: English Font. Current: %s\n\n", EFname[nEF]); for (j=0; j<10; j++) if (strlen(EFname[j]) > 1) fprintf(errout, "%4d: %s\n", j, EFname[j]); fprintf(errout, "0-9: Normal 10-19: Oblique/Italic 20-29: Bold 30-39: Bold & Oblique\n"); nEF=getnew(nEF+0.1, 3); getEfontdata(); break; case 'Q': cleanup(1); exit(0); default: break; } } while (cst[0] != '\0'); if ( (lm+rm) > XX*25. || (tm+bm) > YY*25.) { fprintf(stderr, "Supplied paper margins out of range.\n"); exit(0); } charsize(pts); defpts=pts; defptsi = ptspc = (defpts+0.5); defCa=Ca; defCi=Ci; defcolumn=column; defCx=Cx; defCy=Cy; defnEF=nEF; cgap = gap/Ck; if (vgap==0) vgap = 1.5*(CLP-CIP); else vgap = vgap/ppd; if (booklet) { j = (pr - rm*(column+2))/Ck/CSP/column + 0.5; RM = j*CSP; /* width of each "column" */ /* margins applies to all, except central one for staping, twice as wide */ LM = (pr/Ck-column*RM)/(column+2); RM += LM; booklet = column; /* in case it is changed */ column = 1; } else { LM = lm/Ck; RM = (pr - rm)/Ck; /** RM = ((RM-LM-cgap*(column-1)+CSP/2)/CSP)*CSP+LM; **/ } TM = (tm + os)/Ck; BM = (pb - bm - os)/Ck; BM = (BM - TM + (CLP-CIP) + CLP/2) / CLP * CLP + TM; j = x = (RM - LM - cgap*(column-1)) / (float) CSP / column; if (column>1) { /* & not booklet */ if (x-j > 0.65) { x = (1 - x + j++) * CSP*column; RM += x*0.45; LM -= x*0.15; } else if ((x=(x-j)*CSP*column) > 0.3*cgap*(column-1)) { RM -= x*0.45; LM += x*0.15; } cgap = (RM - LM - j*CSP*column)/(column-1); } else if (!booklet) { /* & column = 1 */ if (x-j > 0.50) { x = (1 - x + j++) * CSP; RM += x*0.651; LM -= x*0.35; } else { x = (x - j) * CSP; RM -= x*0.65; LM += x*0.35; } } /** fprintf(stderr, "cgap = %d j = %d, CSP = %d\n", cgap, j, CSP); **/ if (menu) fprintf(errout, " There are %d lines in a page and %d words in a line\n\n", (BM-TM)/CLP, j); RM -= LM; BM -= TM; Xa = LM; Ya = TM; LM=TM=0; nEFs[nEF]++; pgcount_bak = pgcount; if (bp < pgcount) bp=pgcount; if (ep && ep=1.) return x; else if (n==1 && x<=200. && x>=5.) return x; else if (n==2 && x<=20. && x>=0.01) return x; else if (n==3 && x<40. && x>= -0.1) return x+0.1; else if (n==4 && x<20. && x>= 0.9) return x+0.11; else if (n==5 && x<11. && x>= .1) return x; else { fprintf(errout, "WARNING: input value out of range, ignored !\n\n"); bell(); return y; } } void cleanup(int deltempfile) { inf=Rinf; while (inf != NULL) { if (inf->fp != NULL) fclose(inf->fp); inf = inf->p; } HBFclose(); if (deltempfile) { fclose(out); remove(tempfile); } } void newline(int pr, int ret) { void shade(); int x; /* search */ if (!pr) { fnewline=1; Ha=0; endAC(0); inCH=100; if (++sline > MAXLINES) { bell(); fprintf(stderr, "MAXLINES (%d) exceeded, abort\n", MAXLINES); exit(0); } lineclp[1+sline]=CLP; linecip[1+sline]=CIP; linedif[sline] = (H=0)? (cRM-H):0; if (ret && centraladj /*&& startline*/) { linedif[sline] = (cRM - LM - (H-spaceH))/(-2); } H=LM; cnsp=0; spaceH = -1; return; } /* print */ /*ascbuf.p=0;*/ if (fshade) shade(); else endAC(pr); spaceH = -1; V += lineclp[++pline]; H = cLM; /**fprintf(stderr, "newline: pline points to %d, V=%d cTM=%d cBM=%d, BM=%d H=%d cLM=%d\n", pline, V, cTM, cBM, BM, H, cLM); **/ if (V > cBM+BMover || pline > sline) { /*pline--;*/ x = columnWidth(); if (++pcolumn <= column) { V = cTM + linecip[pline]; H=cLM=LM+(x+(RM-LM-x*column)/(column-1))*(pcolumn-1); } else if (V > BM+BMover) { endpage(0); V=cTM=TM; H=cLM=LM; PCN=SCN=1; /* see isfs, PCN=2 */ pline=1; sline=0; /* force to search */ pcolumn=1; } cRM = cLM + x; } fnewline=1; Ha=0; if (fshade) ; if (UDline.f) UDline.x = H; cnsp=0; } void endpage(int endDoc) { char s[80]; void putnpagetime(), trailer(), pagesetup(); int pp, j, k; if (Prntpage && !PreScanMode) { if (pgpd++==0) bell(); if (!mute) fprintf(errout, (pgpd%5 == 0 || endDoc)? "%5d\n" : "%5d", pgcount); extraEOL = 1; putnpagetime(); fprintf(out, "EP SP\n"); fprintf(out, "end %% CN31%sDict\n", DictExt); } pgcount++; pp = (pausqm)? pausqm:1; Prntpage = print_range_check(pgcount); if (twoside) { j = (landscape)? Yh:Xw; k = Xa; Xa = j-RM-Xa; RM = j-Xa-k; } if (PreScanMode) return; if (endDoc || (pausqm && !(pgpd%pp)) ) { insertEOL(); trailer(0); if (ferror(out)) { fprintf(stderr, "WARNING: PS file %s write error, possibly out of memory/disk space.\n\ Suggestion: delete PS file and run CNPRINT again, use the -b#e# option\n\ to print fewer pages at a time\n", tempfile); bell(); exit(-5); } fclose(out); if (!booklet) outputToDev(); if (pausqm && !fprntfile) { fprintf(errout,"Please press RETURN to continue"); bell(); gets(s); } filecount++; if (!endDoc) { opnfile(OUT); header(); pgpd=0; } } else if (Prntpage) pagesetup(); } outputToStdout(char *fn) { char s[100]; FILE *in; if ((in=fopen(fn, "r"))==NULL) fprintf(stderr, "CNPRINT File open error: %s", fn); else { while(fgets(s, 99, in)!=NULL) printf("%s", s); fclose(in); } return 1; } outputToDev() { char s[100], fn[100]; if (stdoutput) outputToStdout(tempfile); else if (fprntfile) { sprintf(s, "%s %s", prntcmd, tempfile); #ifdef VMS if (!keepPS) sprintf(s, "%s/delete %s", prntcmd, tempfile); #endif system(s); bell(); #ifdef VMS ; #else if (!mute) { fprintf(errout, "Job has been sent to the printer\n\ Please press RETURN after the print job is finished"); gets(s); } if (!keepPS) remove(tempfile); #endif } if (keepPS || (!fprntfile && !stdoutput)) { strcpy(fn, PSfile); if (pausqm) { sprintf(s, "%d", filecount); FName(fn, s); } RE_name(tempfile, fn); fprintf(errout, "PS File: %s\n", fn); } return 1; } void trailer(int Nppg) /* # of pages (booklet), use pgpd if 0 (regular) */ { int j=0; struct FontTag *F; fprintf(out, "%%%%Trailer\n"); if (!EPS) fprintf(out, "%%%%Pages: %d\n", (Nppg==0)? pgpd : Nppg); while (j<40) if (nEFs[j++]>0) { fprintf(out, "%%%%DocumentNeededResources: font %s\n", EFname[j-1]); break; } while (j<40) if (nEFs[j++]>0) fprintf(out, "%%%%+: font %s\n", EFname[j-1]); fprintf(out, "%%%%DocumentSuppliedResources: procset CN31%sDict\n", DictExt); for (F=Fonts; F!=NULL; F=F->p) { if (F->nCN>0) for (j=1; j<=(1+(F->nCN-1)/256); j++) fprintf(out, "%%%%+: font CN%df%d%d%s\n", F->FontID, F->mx, j, DictExt); } fprintf(out, "%%%%EOF\n"); if (Nppg) return; if (EPS) { fprintf(errout, "Be sure to adjust the BoundingBox in the EPS file,\n\ otherwise the EPS file may be placed outside the display/print area\n"); if (pgpd>1) { bell(); fprintf(errout, "WARNING: PS file does NOT comform to EPSF format: more than 1 page\n"); } } if (IncEPS) fprintf(errout, "If the included EPS image is not printed/displayed,\n\ most likely you forgot to adjust the BoundingBox in the EPS file\n"); } void pagesetup() { if (!EPS) fprintf(out, "\n%%%%Page: %d %d\n", pgcount, pgpd+1); if (!EPS && !booklet) fprintf(out, "%%%%BeginPageSetup\n"); fprintf(out, "CN31%sDict begin\n", DictExt); if (landscape) fprintf(out, "BP -%d LRT %d %d translate\n", Xw, Xa, Xw-BM-Ya); else fprintf(out, "BP %d %d translate\n", Xa, Yh-BM-Ya); PSctrl(); if (!EPS && !booklet) fprintf(out, "%%%%EndPageSetup\n"); if (strlen(EPSfile)) { if (pgcount==1 && !IncEPS) return; fprintf(out, "%d 0 Q\n", BM); IncludeEPS(EPSfile); } } void putnpagetime() { /** need change: use edge of paper as reference instead of BM, RM * No, it would not work for booklet mode! **/ struct tm *time_str; int i=0, pnp, px, py, tx, ty; time_t time_val; char s[80], fmt[60]; float BSO = 7.2/ppd; /* 0.1 inch */ endAC(1); if (!fputnpage) return; pnp=fputnpage; if ((twoside || booklet==2) && !(pgcount%2)) { if (pnp==1 || pnp==4) pnp += 2; else if (pnp==3 || pnp==6) pnp -= 2; } if (vertical) { px = tx = (pnp>3)? (RM+4.5*BSO) : (LM-4*BSO); if (pnp==1 || pnp==4) { /* left */ py = BM-4*BSO; ty = TM + 4*BSO; } else if (pnp==2 || pnp==5) { /*middle */ ty = py = (BM-TM+3*BSO)/2; tx = (pnp<3)? (RM+4.5*BSO) : (LM-4*BSO); } else { /*right */ py = TM + 4*BSO; ty = BM - 4*BSO; } } else { py = ty = (pnp>3)? (BM+4.5*BSO) : (TM-4*BSO); if (pnp==1 || pnp==4) { /* left */ px = LM; tx = RM; } else if (pnp==2 || pnp==5) { /*middle */ tx = px = (RM-LM-3*BSO)/2; ty = (pnp<3)? (BM+4.5*BSO) : (TM-4*BSO); } else { /*right */ px = RM - 6*BSO; tx = LM; } } /* use document default font/size for page number: previously whatever left */ i = 0.8338*(defpts*Cw*defCx/ppd)*20.*Casc; fprintf(out, "/%s [%g 0 0 %d 0 0] SF\n", EFname[defnEF], i/10.0, (int) (defpts*0.75*defCy/ppd) ); fprintf(out, (vertical)? "%d %d p add Qa gctr (%5d.) S grestore\n" : "%d %d Qa (%5d.) S\n", BM-py, px, pgcount); if (!TIME || timestat==1) return; time(&time_val); time_str = localtime(&time_val); if (timestat==2) strcpy(fmt, ((inf==Rinf)? inf->t : inf->s)); else strcpy(fmt, "CNPRINT"); i=strlen(fmt); strcat(fmt, " %a %d-%b-%y %H:%M:%S %Z"); strftime(s, 79, fmt, time_str); while ( (s[i]=toupper(s[i])) != '\0') ++i; i = (int) strlen(s)*3.6/ppd; if (pnp==2 || pnp==5) i /= 2; else if (pnp==3 || pnp==6) i=0; if (vertical) ty += i; else tx -= i; fprintf(out, (vertical)? "/Courier %d SF %d %d p add Qa gctr (%s) S grestore\n" : "/Courier %d SF %d %d Qa (%s) S\n", (int) (6./ppd), BM-ty, tx, s); } void header() { int j, n, urx, ury; time_t time_val; void CNdict(), pagesetup(); struct FontTag *F; if (EPS > 1) fprintf(out, "%c", CTRLD); /* ctrl-D: MS EPS */ fprintf(out, "%%!PS-Adobe-3.0 %s\n\ %%%%Creator: %s CYD UW-Madison WI USA\n\ %%%%Title: IN %s PS %s\n", (EPS)? "EPSF-3.0": "", Version, Rinf->t, PSfile); time(&time_val); DictExt[1]=DictExt[0]='\0'; if (EPS) { n = (int) time_val%62; if (n<10) DictExt[0] = n + '0'; else if (n<36) DictExt[0] = n - 10 + 'A'; else DictExt[0] = n - 36 + 'a'; } fprintf(out, "%%%%CreationDate: %s", ctime(&time_val)); j=(Yh-(Ya+BM+2*CLP))*ppd; if (j<=0) j=0; urx = Xw-RM-Xa; n=Xa; if (twoside) { n=(urx1 && !EPS) fprintf(out, "/#copies %d def\n", copies); for (F=Fonts; F!=NULL; F=F->p) { if (strcmp(HBFname, F->FontName) != EQ) { HBFclose(); strcpy(HBFname, F->FontName); HBFopen(); } fdict = F->fdict; j = nCN; nCN = F->nCN; /* if (nCN) fprintf(out, "/a{%d %d true [1 0 0 -1 0 %d]}B\n", mx, my, my);*/ n=0; while (nCN > 256*n) CNdict(++n, F->FontID); if (nCN>0 && !pausqm) { free(fdict); F->fdict=NULL; } nCN = j; } fprintf(out, "end %% CN31%sDict\n", DictExt); fprintf(out, "%%%%EndSetup\n"); if (strcmp(HBFname, defHBFname) != EQ) { HBFclose(); strcpy(HBFname, defHBFname); HBFopen(); } if (Prntpage) pagesetup(); } void CNdict(int n, int FontID) /* Fonts for frequently used characters with nCN entries */ { unsigned int i, m, c1, c2; int nch; long jn; float x; int HBFgetBitmap(); jn = /*(mx/24.)*/ (my/24.)*1.4 * ((nCN>=n*256)? 256:(nCN%256)); if (ttf_font) jn /= 6; /* j = (mx*my/24./24.)*(358./256.)*k; k = j*(344./358.);*/ x = mx*25./24.; fprintf(out, "%%%%BeginResource: font /CN%df%d%d%s %ld00 %ld00\n", FontID, mx, n, DictExt, jn+1, (long) (jn*0.961+1)); fprintf(out, "8 dict begin\n\ /FontType 3 def\n\ /FontMatrix [%7.5f 0 0 %7.5f 0 0] def\n\ /FontBBox [0 0 %6.3f %6.3f] def\n", 1./x, 1./x, x, x); fprintf(out, "/BuildGlyph{0 0 0 0 %d %d setcachedevice\n\ exch /CharProcs%d get exch 2 copy known not {pop /.notdef} if get exec}B\n\ /BuildChar{1 index /Encoding get exch get 1 index /BuildGlyph get exec}B\n", mx, my, n); fprintf(out, "/Encoding 256 array def\n\ Encoding 0 code putinterval\n"); if (nCN < n*256) fprintf(out, "%d 1 255 {Encoding exch /.notdef put} for\n", nCN%256); fprintf(out, "/CharProcs%d %d dict def\n\ CharProcs%d begin\n/.notdef {} def\n", n, (nCN>=n*256)? 257:(nCN%256+1), n); nch = (nCN < n*256)? nCN : n*256; for (i=(n-1)*256; i b2h_range1) c2 += b2gap; if (ttf_font) { fprintf(out, "/%02X{", i%256); TTFgen_PSproc(fpTTF, c1, c2); fprintf(out, "U}B\n"); ptstring[m] = dummy; /* provide a dummy address */ } else { fprintf(out, "/%02X {a{<", i%256); HBFgetBitmap(c1*256+c2); putBitmap(array); fprintf(out, ">}m}B\n"); ptstring[m] = array; } } fprintf(out, "end currentdict end\n/CN%df%d%d%s exch definefont pop\n\ %%%%EndResource\n", FontID, mx, n, DictExt); } void putBitmap(unsigned char *a) { void putBitmap85(); int j; if (PSLlevel==2) { putBitmap85(a, CHsize); return; } for (j=0; j 4) mlen = 4; base256 = 0; /*for (kb=0; kb<4; kb++) {*/ for (kb=0; kb= 0; kb--) {*/ else for (kb = 4; kb >= 4-mlen; kb--) { putc((base256 / divarray[kb] + '!'), out); base256 = base256 % divarray[kb]; char_on_line++; } if (char_on_line >= 75) { fprintf(out, "\n"); char_on_line=0; } /*}*/ } fprintf(out, "~"); } void PSctrl() /* should not be called when in SEARCH mode */ { float z, ns; int j, nsx, nsy, nx, ny; /* now allow @[xx] or @[xxx] for font size: 999 max */ if (ptspc <= 0 || ptspc >= 1000) ptspc=defptsi; z = (ptspc==defptsi)? defpts : ptspc; charsize(z); ns = FontptsScale * z * Cw/ppd; nsy = ns*Cy +.1; nsx = ns*Cx +.1; nx = (0.8338*CSP)*2.*Casc*10; ny = z*0.75*Cy/ppd; clearascbuf(1, 1); endAC(1); inCH=100; if (!Prntpage || PreScanMode) return; fprintf(out, "/p %d def /mx %d def /my %d def\n\ /scl{%d %d scale}B\n", CSP, mx, my, nsx, nsy); /* fprintf(out, "/p %d def\n/LL {%d %d %d %d scale true [%d 0 0 -%d 0 %d]} B\n", CSP, mx, my, nsx, nsy, mx, my, mx);*/ fprintf(out, "/tLL{%g %g scale}B\n", ns*Cx/mx, ns*Cy/my); if (CurrentFont->nCN>0) for (j=1; j<=(CurrentFont->nCN+255)/256; j++) { if (nsx!=nsy) fprintf(out, "/z%d{/CN%df%d%d%s [%d 0 0 %d 0 0] SF}B\n", j, CurrentFont->FontID, mx, j, DictExt, nsx, nsy); else fprintf(out, "/z%d{/CN%df%d%d%s %d SF}B\n", j, CurrentFont->FontID, mx, j, DictExt, nsx); } fprintf(out, "/fa{/%s%s [%d.%d 0 0 %d 0 0] SF}B\n", EFname[nEF], (euro>=1)? " ILE":"", nx/10, nx%10, ny); if (gray>0.01) fprintf(out, "%3.1f setgray\n", gray); } int isrlasc(c) int c; { /* L=left; R=right; NT=none */ if (!adjust) return NT; switch (c) { case 40 : case 60 : case 91 : case 123 : return L; case 33 : case 41 : case 44 : case 46 : case 58 : case 59 : case 62 : case 63 : case 93 : case 125 : case '-': return R; default: return NT; } } int isrlch(c1, c2) unsigned char c1, c2; { /* L=left; R=right; NT=none */ switch(lcode) { case B5: case B5P: if (c1!=0xA1) return NT;/* A145-A149, A150-A154, a1a9-a1ac */ if ((c2>=0x41 && c2<=0x44)||(c2>=0x4D && c2<=0x4F)) return R; else if (c2>=0x5D && c2<=0xA8) return (c2%2)? R : L; else return NT; case JIS: if (c1 > 0xA1) return NT; if (c2>=0xC6 && c2<=0xDB) return (c2%2)? R : L; else if (vertical) { if (c2>=0xA2 && c2<=0xA4) return R; else return NT; } else { /* A1A9, A1AA ? */ if ((c2>=0xA2 && c2<=0xA8) || (c2>=0xEB && c2<=0xED)) return R; else return NT; } case KSC: if (c1==0xA3) { switch (c2) { case 0xA8 : case 0xDB : case 0xFB : return L; /*case 0xA1 : case 0xA7 : case 0xBF : */ case 0xAE : case 0xBA : case 0xBB : case 0xDF : return (vertical)? NT:R; case 0xA9 : case 0xAC : case 0xDD : case 0xFD : return R; default: return NT; } } else if (c1!=0xA1) return NT; /*if (c2>=0xA2 && c2<=0xA3) return R; else */ if (c2>=0xAE && c2>=0xBD) return (c2%2)? R : L; else return NT; case GB: case GBK: switch (c1) { case 0xA1: if (c2>=0xAE && c2<=0xBF) c2%=2; switch (c2) { case 0: return L; case 1: case 0xA2 : case 0xA3 : /*case 0xC3 :*/ return R; case 0xE3 : case 0xE4 : case 0xE5 : return (vertical)? NT:R; default: return NT; } case 0xA3: switch (c2) { case 0xA8 : case 0xDB : case 0xFB : return L; case 0xE0 : return (vertical)? NT:L; case 0xA1 : case 0xA7 : case 0xAE : case 0xBA : case 0xBB : case 0xBF : case 0xDF : return (vertical)? NT:R; case 0xA9 : case 0xAC : case 0xDD : case 0xFD : return R; default: return NT; } default: return NT; } case UTF: /* unicode */ if (c1!=0x00) return NT; if (c2==0x01 || c2==0x02) return R; else if (c2>=0x08 && c2<=0x17) return (c2%2)? R : L; else return NT; break; default: break; } return NT; } unsigned char tovhb5(c) unsigned char c; { /* convert vertical big5 punctuations to horizontal ones or vice versa */ int j; if (c<0x5D || c>0x7D) return c; j = (c-0x5D)%4; if (j<2 && vertical) return (c+2); if (j>=2 && !vertical) return (c-2); return c; } int vchange(c1, c2) /* substitutions under vertical mode */ unsigned char *c1, *c2; { switch(lcode) { case JIS: if (*c1==0xA1) switch (*c2) { case 0xC6: case 0xC7: case 0xC8: case 0xC9: *c2 += 0x10; break; default: break; } break; case B5: case B5P: if (*c1==0xA1) switch (*c2) { /*case 0x43: *c1 = 0xA2; *c2 = 0x58; break; case 0x4D: *c2 = 0xA6; break; case 0x4E: *c2 = 0xAB; break;*/ case 0xA5: *c2 = 0x77; break; case 0xA6: *c2 = 0x78; break; case 0xA7: *c2 = 0x7B; break; case 0xA8: *c2 = 0x7C; break; default: break; } break; case GB: case GBK: if (*c1==0xA1) switch (*c2) { /* GB: default c1=0xA1 */ /*case 0xA2: *c2 = 0xE4; break; case 0xA3: *c2 = 0xE3; break;*/ case 0xAE: case 0xAF: case 0xB0: case 0xB1: *c2 += 0x0A; break; default: break; } /* problem: A1A3 is a comma, */ break; case KSC: if (*c1==0xA1) switch (*c2) { case 0xAE: case 0xAF: case 0xB0: case 0xB1: *c2 += 0x0A; break; default: break; } break; case UTF: /* unicode */ break; default: break; } return 1; } int rtch(c1, c2) unsigned char c1, c2; { /* R=rotate */ switch(lcode) { case JIS: switch (c1) { case 0xA1: if (c2>=0xA2 && c2<=0xA4) return RMXY; else return (c2>=0xC2)? NT : R; case 0xA2: return (c2<=0xEF)? NT : R; case 0xA3: return (c2<=0xD4)? NT : R; case 0xA6: return NT; case 0xA7: return (c2<=0xCF)? NT : R; default: return R; } case B5: case B5P: /* B5P should be compatible with B5 */ switch (c1) { case 0xA1: if (c2>=0x41 && c2<=0x43) return RMXY; else if (c2>=0x4D && c2<=0x4F) return RMXY; else if (c2>=0x5D && c2<=0x7C) return ((c2-0x5D)%4 <= 1)? R:NT; else return (c2>=0x7D && c2<=0xFE && c2!=0xC0)? NT : R; case 0xA2: if (c2>=0x40 && c2<=0x58) return NT; else if (c2>=0x62 && c2<=0xC2) return NT; else if (c2>=0xCF && c2<=0xFE) return NT; else return R; case 0xA3: return (c2>=0x40 && c2<=0x73)? NT : R; case 0xC8: return (c2>=0x41 && c2<=0x78)? NT : R; default: return R; } case GB: case GBK: /* hopefully GBK is compatible with GB */ switch (c1) { case 0xA1: switch (c2) { case 0xA2: case 0xA3: return RMXY; case 0xA9: return R; default: return NT; } case 0xA3: switch (c2) { case 0xA1: case 0xBF: case 0xBA: case 0xBB: return RMX; /* ! ? : ; */ case 0xAC: return RMXY; /* , */ default: return NT; } case 0xA6: case 0xA7: case 0xA9: return NT; case 0xA8: if (c2==0xE7) return NT; else return (c2 <= 0xC4)? NT : R; default: return R; } case KSC: /* needs work */ switch (c1) { case 0xA1: switch (c2) { default: return NT; } case 0xA3: switch (c2) { case 0xA1: case 0xBA: case 0xBF: return R; case 0xAC: return RMXY; default: return NT; } default: return R; } case UTF: if (c1>=0x01) return R; else if (c2==0x02 || (c2>=0x08 && c2<=0x17) ) return NT; else return R; break; default: break; } return NT; } int putASC(c, c2, pr) int c, c2, pr; { int p, k, ASP, isrlasc(), rl, rr=0; float x; static int map[] = { /* map some European chars, 128-160 */ 0xC7, 0xFC, 0xE9, 0xE2, 0xE4, 0xE0, 0xE5, 0xE7, 0xEA, 0xEB, 0xE8, 0xEF, 0xEE, 0xEC, 0xC4, 0xC5, 0xC9, 0xE6, 0xC6, 0xF4, 0xF6, 0xF2, 0xFB, 0xF9, 0xFF, 0xD6, 0xDC, 0xA2, 0xA3, 0xA5, 0xDF, 0x83, 0xE1}; cnsp=0; frl=NT; if (c==LF || c==FF) { clearascbuf(pr, 1); if (c==FF) { V = BM; pcolumn = column; } newline(pr, 1); return 0; } if (c=='\t') { clearascbuf(pr, 1); endAC(pr); x = (H-cLM)/(CSP*((tabascii)? Casc: 0.5)); k = x + 8.5; k = (k/8)*8; H += ((k-x)*CSP*((tabascii)? Casc: 0.5)); return 0; } k = (c>=' ' && c<=160)? (c-' ') : 0; /* change 126 to 160 */ ASP = CSP*Casc*Wasc[k]*10.; Ha += (ASP%10); ASP /= 10; if (c>=128 && c<=160) { c=map[c-128]; if (euro==0 && pr) { /* auto detect feature: end previous line with clearascbuf(1, 1) and endAC(1) in PSctrl() */ euro=1; PSctrl(); } } if (c!=' ') { rl=isrlasc(c); /* left-end char */ if (H > cRM-ASP*3/2 && rl==L && adjust) { clearascbuf(pr, 1); newline(pr, 0); return 1; } else if (H > cRM-ASP/2) { if (!adjust || H > cRM+2*CSP*Casc) { clearascbuf(pr, 1); newline(pr, 0); return 1; } else if (c2==LF /*|| c2==CR*/) /* no need for a new line */ rr=4; /* "abc ": include space in the current line, rr=3, treat as if H<0) { if (ascbuf.s[ascbuf.p-1]==' ') { clearascbuf(pr, 1); newline(pr, 0); return 1; } } } /* do not break digits like 108.9, does not work if 108.92 */ else if (rl==R && (c!='.' || !isdigit(c2))) rr=2; /* c2 is ascii and not left-end, here b1l=0xa1 or 0x30(utf), but ascbuf.p > 40% line, or last word > 15 chars */ else if (c215 || H-ascbuf.Hp >(cRM-cLM)*.3)) { clearascbuf(pr, 1); newline(pr, 0); return 1; } else if (ascbuf.p) { p = ascbuf.p-ascbuf.pp; clearascbuf(pr, 0); newline(pr, 0); /* push un-used chars back to major buffer, safe in most of cases */ return 1+p; } else newline(pr, 0); if (rr<2) return 1; /* rr<2: do not use char c; rr=2: use c & add newline; rr>2: use char c only */ } if (pr) { if (centraladj && spaceH == -1) { H -= linedif[pline]; spaceH = 1; } if (inCH && Prntpage && !PreScanMode) fprintf(out, "%d %d Qa fa\n(", BM-V, H); } else if (centraladj && spaceH == -1) spaceH = H; ascbuf.s[(ascbuf.p)++]=c; if (ascbuf.p==1) { ascbuf.Hp=H; ascbuf.pp=0; } inCH=OUT; if (rr==2) { clearascbuf(pr, 1); newline(pr, 0); return 0; } } else { if (inCH) newpos = 1; if (ascbuf.p) ascbuf.s[(ascbuf.p)++]=c; ascbuf.pp=ascbuf.p; ascbuf.Hp=H+ASP; /* introduces error (~Ha) */ if (centraladj) { if (centraladj==2 && spaceH == -1) { if (pr) { H -= linedif[pline]; spaceH=1; } else spaceH = H; } else if (pr && spaceH != 1) H -= ASP; } } H += ASP; if (Ha>=10) { H++; Ha -= 10; } return 0; } unsigned int Addr(int c1, int c2) { unsigned int a; a = (c1-b1l)*b2span + c2-b2l; if (c2 > b2h_range1) a -= b2gap; /*if (lcode==UTF) a = (c1-b1l)*256 + c2; else a = (lcode!=B5)? ((c1-0xA1)*94+c2-0xA1) : ( (c1-0xA1)*157 + ( (c2>=0xA1)? (63+c2-0xA1):(c2-0x40) ) ); */ return (a>nchar)? nchar : a; } int putCH(c1, c2, pr) unsigned char c1, c2; int pr; { int j, rl, rt, newl=0; void putBitmap(); unsigned int ch, addr; unsigned char tovhb5(); rl=rt=NT; if (lcode==B5) if ((big5>1 || vertical) && c1==0xA1) c2=tovhb5(c2); if (vertical) { vchange(&c1, &c2); rt = rtch(c1, c2); if (rt != NT) Rotate=1; } /*else rt=NT;*/ if (c1>=0xA4) cnsp=0; else if (adjust) { /* such adjustment should also be allowed for vertical printing, except * for some like : ; */ /* if (lcode==B5 || lcode==JIS) { cnsp=0; rl=isrlch(c1, c2); if (rl==L && H > cRM-CSP*3/2) newl=1; } else if (lcode==GB) { */ cnsp++; if ( (rl=isrlch(c1, c2))==NT ) cnsp=0; else if (rl==L) { if (H > cRM-2*CSP) { cnsp=1; newpos=1; if (H < cRM-CSP*5/4) { H -= ((frl==R)? CSP: CSP/2); if (frl==R) frl=NT; if (H < cRM-2*CSP) H=cRM-2*CSP; } else if (H < cRM-CSP*3/4 && frl==R) { H -= CSP; if (H < cRM-2*CSP) H=cRM-2*CSP; } else newl=1; } } else if (rl==R && frl==L) cnsp=1; /* } */ } if (!inCH) { if (ascbuf.p) clearascbuf(pr, 1); endAC(pr); /* also set newpos=1, inCH=100, ascbuf.p=0 */ } ch = (c1*256) + c2; if (ch != cspace) { if (adjust) { if (frl==R && H > cRM-CSP && H <=cRM-CSP/4 && !cnsp) { newpos=1; H = (H > cRM-CSP/2)? (H-CSP/2):(cRM-CSP); } else if (newl || (H>cRM-CSP*2/3 && rl!=R) || H>cRM+1.5*CSP) { newline(pr, 0); return 2; } if (cnsp >= 2) { if (!pr) H -= (CSP/2); else { /* take care of 'half' CN */ if (linedif[pline] > CSP/2) linedif[pline] -= (CSP/2); else if (linedif[pline] > 0) { H -= (CSP/2-linedif[pline]); linedif[pline]=0; newpos=1; } else { H -= (CSP/2); newpos=1; } } } } else if (H > cRM - CSP*2/3) { newline(pr, 0); return 2; } if (!pr) { inCH=100; if (centraladj && spaceH == -1) spaceH = H; } else { if (centraladj && spaceH == -1) { H -= linedif[pline]; spaceH=1; /**fprintf(stderr, "\tcentraladj: pline=%d, H = %d", pline, H);**/ } addr=Addr(c1, c2); if (PreScanMode && Prntpage) fstring[addr]++; else if (Prntpage) { /**if (ttf_font) ; else if (ptstring[addr]==NULL) { HBFgetBitmap(ch); ptstring[addr=Addr(cspace/256, cspace%256)] = array; }**/ if (vertical && rt != NT && rt != R) { /* rotate & move */ fprintf(out, "%d %d q ", BM-V + CSP/ (rt==RMY ? 6:2), H - CSP/ (rt==RMX ? 6:2) ); newpos=1; /* next char must re-define position */ } else if (newpos || (rt==NT && Rotate) ) { if (newpos==1 || rt==R || (rt==NT && Rotate) ) fprintf(out, (vertical && rt==R)? "%d %d q\n":"%d %d Q\n", BM-V, H); newpos=0; if (vertical && rt==NT) {Rotate=0; newpos=2;} } /* possible problem here for unicode */ if (fstring[addr]>=60000) { j = fstring[addr] - 60000; if (inCH != (j>>8) +1) fprintf(out, "z%d ", (inCH = (j>>8) +1)); j%=256; fprintf(out, (j>='~' || j<' ' || j=='(' || j==')' || j==92)? "<%02x>%c\n" : "(%c)%c\n", j, ((rt==NT)? 'W':'w')); } else if (ttf_font) { fprintf(out, (rt==NT)? "Z" : "z"); TTFgen_PSproc(fpTTF, c1, c2); fprintf(out, "V\n"); } else { fprintf(out, (rt==NT)? "T {<" : "t {<"); HBFgetBitmap(ch); putBitmap(array); /*putBitmap(ptstring[addr]);*/ fprintf(out, ">}M\n"); } if (fstring[addr]>0 && fstring[addr]<60000 && --fstring[addr]==100) { if (ptstring[addr]!=NULL) free(ptstring[addr]); ptstring[addr]=NULL; } } } } else { if (centraladj) { if (centraladj==2 && spaceH == -1) { if (pr) { H -= linedif[pline]; spaceH=1; } else spaceH = H; } else if (pr && spaceH != 1) H -= CSP; } newpos=1; } H+=CSP; frl=rl; return 0; } signature() { time_t time_val; char *msg[]={"\nHave a nice day !\n", "", "", "", "", "\nThank you for using CNPRINT !\n", "", "", ""}; if (mute) return 1; time(&time_val); if (time_val%287 == 2) fprintf(errout, "\nThis version of CNPRINT is about to expire, please contact author.\n"); else if (time_val%131 == 2) fprintf(errout, "\nThank you for using CNPRINT. Please consider contribution to\n\ CNPRINT educational fund, to help kids in rural China get five-\n\ years' basic education. See \"Author\" section of the help file\n\ for details.\n"); else fprintf(errout, "%s", msg[(int)(time_val%8)]); return 1; } void usage(int n) { if (n>10) bell(); fprintf(errout, "%s\n\n", Version); fprintf(errout, "USAGE: cnprint [-h] [-wvlc2x3...] [-f=font] [file1 [file2]...] \ [-o=outfile]\n\n\ -big5(gb)(hz)(zw)(cns)(jis)(euc)(jis8)(ksc)(utf8)(utf7): \ Input is BIG5,\n\ GB, Hz, zW, CNS, JIS, EUC, Shift-JIS, KSC, 8(7)-bit unicode.\n\ -v(-vv): Vertical printing mode.\n\ -c3: Divide one page into 3 Columns.\n\ -w: Convert to PS Without printing.\n\ -l: Paper orientation Landscape.\n\ -i(out)(io): Use standard input (output) (both).\n\ -f=j16 (f24, k24, or full HBF name): Select font.\n"); fprintf(errout, " -x2: Character width/height 1.2 (-y3: h/w 1.3).\n\ -e56: ASCII width = 0.56 CJK width.\n\ -z(-hz2gb): Hz->GB conversion only (-zz or -gb2hz: GB->Hz).\n\ -gb2b5(-hz2b5)(-b52gb)(-b52hz): GB(HZ)<->BIG5 conversions.\n\ -m: Disable/enable Menu (-m5: print 5 copies).\n\ -aa: Special mode for pure English text file.\n\ -b20e34: Print pages 20-34 (-odd, -even: odd or even-numbered pages).\n\ -b18: Set the starting page number as 18.\n"); if (n!=2) { fprintf(errout, "Use -h option for more on-line help. See help file for details.\n"); /* signature(); */ return; } fprintf(errout, "Press RETURN key to continue\n"); n=getchar(); fprintf(errout, " -q=laserps: : System PS print command = 'laserps'.\n"); fprintf(errout, " -t(-tt): Do NOT print time (-tt: print time and input filename).\n\ -55: BIG5 input, adjust horizontal/vertical punctuations.\n\ -c320: 3 Columns on one page with 20 pts space between columns.\n\ -cgap=15: Space between columns (in pts, def: 2.5 char width).\n\ -vgap=15: Vertical space at place of column number change\n\ (in pts, def: 1.5 of document line spacing).\n\ -l#: Special landscape modes for printing HXWZ (#: 1-4) (*).\n\ -a: Print double-byte letters, digits as English ones.\n\ -d: NO special treatment of punctuation marks.\n\ -e(-eps): EPS output (-ems or -epsms: MS format EPS).\n\ -s: Suppress the effects of functional sequences @[**] (*).\n\ -k: When multiple inputs, produce multiple outputs.\n\ -mfeed: Manual feed paper.\n\ -nopage: Do not print page number and date.\n\ -h23: Set English font as Helvetica-Bold (def: Courier, see menu).\n\ -size=14.5: Char size 14.5 points.\n\ -rm(lm)(tm)(bm)=12.3: Paper margin (right, left, top, bottom) \ 12.3mm\n\ -a4(letter)(legal)(a3): Paper size A4 (Letter)(Legal)(A3).\n"); fprintf(errout, "Press RETURN key to continue\n"); n=getchar(); fprintf(errout, " -env: Envelope mode (-envs: small size envelope) (*).\n\ -label: Print address label, also set manual feed (*).\n\ -bk(4): Booklet format with 2 (4) columns.\n\ -fpg(5): Start new page for new input file (if 5 lines to bottom).\n\ -j: Adjust bottom margin if more than one column (*).\n\ -p4: Print/convert 4 pages at a time.\n\ -tab: TAB mode: 4 CJKs <-> 8 ASCIIs, default CJK (ASCII if -aa)\n\ -f: Two-sided format (but does not print on both sides!)\n\ -short: Convert PS file, long lines to short lines\n\ -extr: Extract/print selected pages in a PS file\n\ -mimeqp: Decode mime quoted printables (=A8=D3=C5 like text)\n\ -euro: Disable <-> enable ability of printing European chars.\n\ -n74: Chars per line N 74 (Hz<->GB, JIS/KSC pre-processing *).\n\ -bmps4 0xa1a2 (0xa1a5) -r/l/t/b: Shift bitmap to right/left/\ top/bottom\n\ by 4 pixels for char 0xa1a2 (to 0xa1a5) (*).\n\ -n=256: # of chars in CNdict (default 2048) (*).\n\ -r=600: Device resolution 600 dpi (default 300).\n\ -level1(2): PostScript level (def: level 2, use compression).\n\ -ttt: Word freq statistics excluding \ (-tttt: including) symbols.\n"); fprintf(errout, "Press RETURN key to continue\n"); n=getchar(); fprintf(errout, " Repair functions:\n\ -zzz: Filter out functional sequence like @[**].\n\ -r1: -zzz + ignore EOL when # of char per line > N and < M.\n\ -r2: -zzz + ignore EOL when # of char per line <= N.\n\ -n68(-m120): set N=68 or M=120 (default: N auto-select, M 100).\n\ -r6: -r1 + ignore one of two consecutive EOLs (newline char).\n\ -r7(-r8): -zzz + add (del) space before Chinese char (for CStar).\n\ -r3: -zzz + make # of spaces at beginning of a line to be 4.\n\ -r4: -r3, even there was no space there.\n\ -s: (when r1, r2, r6) also ignore Space\n\ -p: (when r1, r2, r6) match quotation marks.\n\ -m: (when r1, r2, r6) map .,:;?! etc to CJK ones.\n\ -a: Map double-byte letters, digits to English ones.\n\ -t(-tx): (when r1, r2, r6) ignore 'x' (default: '>') in news reply.\n\ -e: (when r1, r2, r6) do NOT ignore EOL.\n\ -k(-k90): (when -zzz or -r#) break big file into ~64K (90K) ones.\n\ * See help file for details.\n"); fprintf(errout, "\n%s\nCopyright Yidao CAI 1992-1999, All Rights Reserved\n\ cai@neurophys.wisc.edu\n", Version); } int isfs(unsigned char *s, int pr) { int j, k, HBFopen(), issfs(); unsigned char c1, c2, c3, st[12]; unsigned char *t; int seqlen; void shade(); t=s; seqlen=1; while (*t && *t!=']' && seqlen<25) {seqlen++; t++;} if (seqlen < 4) return seqlen; /* "[xx]" is minimum */ c1=s[1]; c2=s[2], c3=s[3]; /* if (s[3]!=']' && s[4]!=']' && c1!='L') { / * not LBxx * / if (c1!='M' || c2!='V' || s[9]!=']') return 0; */ /* not LBxx, Fxxxx, Txxxx, or @[###] */ if (seqlen>=5 && c1!='L' && c1!='F' && c1!='T' && c3!=']' && c1!='+' && c1!='-') { if (c1!='M' || c2!='V' || seqlen!=10) return 0; if (suppress) return (suppress>=2)? 0 : 10; for (j=3; j<=8; j++) if (!isdigit(s[j])) return 0; j = 100*(s[3]-'0') + 10*(s[4]-'0') + (s[5]-'0'); k = 100*(s[6]-'0') + 10*(s[7]-'0') + (s[8]-'0'); endAC(pr); if (pr && k!=1) V = k/ppd; if (j!=1) H = j/ppd; return 10; } if (suppress) return (suppress>=2)? 0 : seqlen; switch(c1) { /* line break */ case 'B': if (c2=='R') { clearascbuf(pr, 1); newline(pr, 1); } return 4; /* C: column number */ case 'C': if (c2=='B' || c2=='b' || c2=='E') { /* Central adjust Begin/End */ if (c2=='E' && s[4]==LF) { /* safe: seqlen>=4 */ clearascbuf(pr, 1); newline(pr, 1); centraladj = 0; return 5; } else if (c2=='E') centraladj = 0; else centraladj = (c2=='B')? 1:2; return 4; } if (!pr) return issfs(c1, c2, c3); if (!isdigit(c2)) return 0; k = (c2=='0')? defcolumn : (c2-'0'); PCN++; if (PCN==1) /* do nothing */ /*fprintf(stderr, "PCN = 1\n")*/ ; else { /** H==cLM? @[C#] at start of a line, good Otherwise need to end this line, not yet supported **/ column = k; /* set search mode for next one */ /** V points to bottom of current line image, set back to end of last line **/ V -= lineclp[pline]; /* a safety measure, in case V go beyond cBM */ if (V < cBM) V = cBM; cBM = BM; V = cTM = V + vgap; H = cLM = LM; cRM = LM + columnWidth(); sline = 0; pline = 1; fnewline = 1; /* force search */ SCN = PCN = 1; if (cTM > BM) { endpage(0); V=cTM=TM; pcolumn=1; } } return 4; /* DF: use default settings for font, size, line and char spaces... */ case 'D': if (c2 != 'F') return 0; strcpy((char *) st, "[F0]"); isfs(st, pr); strcpy((char *) st, "[00]"); isfs(st, pr); /* Cx, Cy: changes Ci! so XY must be before I0 */ strcpy((char *) st, "[XY]"); isfs(st, pr); strcpy((char *) st, "[I0]"); isfs(st, pr); strcpy((char *) st, "[A0]"); isfs(st, pr); return 4; /* ASC font */ case 'h': case 'H': case 'q': case 'Q': if (!isdigit(c2)) return 0; k=nEF; nEF=c2-'0'; if (isupper(c1)) nEF += 20; if (c1=='q') nEF += 10; getEfontdata(); nEFs[nEF]++; if (pr && nEF!=k) PSctrl(); return 4; /* CH font: */ case 'f': case 'F': case 'v': case 'V': case 'T': if (seqlen==4 && !isalpha(c2) && c2!='0') return 0; if (seqlen!=5 && c1=='T') return 0; /* only @[Txx] is valid */ if (seqlen==5 && c1=='F') return 0; /* @[Fxx] not valid */ /* not correct!!! as font may affect CSP, leave as it is for now */ if (!pr) return seqlen; /* @[Fxxx]: specify full hbf/htf/ttf name */ if (c1=='F' && seqlen >= 6) { t = s+2; strncpy(HBFname, (char *)t, seqlen-3); } /* true type fonts: @[Txx] */ else if (c1=='T') { sprintf((char *) st, "%c%c.htf", c2, c3); construct_fontname((char *) st); } /* old @[Fx], @[Vx] format */ else { if (c2 == '0') { strcpy(HBFname, defHBFname); HBFclose(); HBFopen(); PSctrl(); return 4; } k = (isupper(c1))? 1:0; k += (isupper(c2))? 1:0; switch(k) { case 0: j = (toupper(c1)=='F')? 16:40; break; case 1: j = (toupper(c1)=='F')? 24:56; break; case 2: j = (toupper(c1)=='F')? 48:64; break; default: break; } sprintf((char *) st, "%c%d.hbf", tolower(c2), j); construct_fontname((char *) st); } HBFclose(); if (!HBFopen()) { strcpy(HBFname, defHBFname); insertEOL(); if (pr && !PreScanMode) fprintf(errout, "Default font used\n\n"); HBFopen(); } PSctrl(); return seqlen; /* shading */ case 'S': if (!isdigit(c2)) return 0; if (!pr) return 4; if (fshade) shade(); fshade=(c2=='0')? 0:1; return 4; /* gray */ case 'G': if (!isdigit(c2)) return 0; endAC(pr); if (pr && Prntpage && !PreScanMode) fprintf(out, "%3.1f setgray\n", gray=(c2-'0')/10.); return 4; /* X, Y expansion */ case 'X': case 'Y': if (!isdigit(c2)) { if (c1=='X' && c2=='Y') {/* [XY], use default */ Cx = defCx; Cy = defCy; } else return 0; } else { if (c1=='X') { Cx = 1.+(c2-'0')/10.; Cy=1.;} else { Cy = 1.+(c2-'0')/10.; Cx=1.;} } Ci = (Cx+Cy < 2.01)? defCi: (Cy+(Cx-1.)/2.); if (!pr) return (ptspc<=99) ? issfs('0'+ptspc/10, '0'+ptspc%10, ']') : issfs('0'+ptspc/100, '0'+(ptspc/10)%10, '0'+ptspc%10); PSctrl(); return 4; /* E: ASC width, line and char space; EP: EPS */ case 'E': if (!isdigit(c2) && c2!='P') return 0; if (c2!='P') { Casc = (c2=='0')? Casc : (c2-'0')/10.; if (!pr) return (ptspc<=99) ? issfs('0'+ptspc/10, '0'+ptspc%10, ']') : issfs('0'+ptspc/100, '0'+(ptspc/10)%10, '0'+ptspc%10); PSctrl(); } else { endAC((int) (pr && Prntpage)); if (pr && Prntpage) { fprintf(out,"%d %d Q ", BM-V, H); IncludeEPS(""); PSctrl(); } } return 4; /* line and char spaces, and envelope */ case 'I': case 'A': if (!isxdigit(c2)) { if (c1=='A' && (c2=='S' || c2=='R')) { /* Envelope, S/R addresses of sender and receiver, move left margin to right by 3.25/2 inch if AR, restore if AS */ if (pr) return 4; j = ((envelope==2)? 2:3.25) * 72./ppd; if (c2=='R') { LM += j; V = 1.25*72/ppd; } else if (LM>=j) LM -= j; H = cLM = LM; return 4; } else return 0; } if (c1=='I') Ci= (c2=='0')? defCi : (isdigit(c2)? (c2-'0')/10. : (c2-'a'+1) ); else Ca= (c2=='0')? defCa : (isdigit(c2)? (c2-'0') : c2-'a'+10); if (!pr) return (ptspc<=99) ? issfs('0'+ptspc/10, '0'+ptspc%10, ']') : issfs('0'+ptspc/100, '0'+(ptspc/10)%10, '0'+ptspc%10); PSctrl(); return 4; case 'P': if (!isdigit(c2)) return 0; if (!pr) return 4; j = c2-'0'; if (!j || (BM-V)/CLP<=j) { V=BM; pline--; newline(1, 0); } return 4; case 'L': /* LBAS is used in preprocessing only */ if (c2!='B') return 0; j=0; if (s[3] != ']') j=2; /* @[LB] or @[LBxx] */ if (pr) { if (s[3]==']') lbn++; else lbn = (s[3]-'0')*10 + (s[4]-'0'); if (lbn > (k=lbnx*lbny)) { lbn -= k; V=BM; pline--; newline(1, 0); /* new page */ } k = lbn-1; H=cLM = ((k/lbny)*lbxinc + lbxp - .1)*72/ppd; V = ((k%lbny)*lbyinc + lbyp - .1)*72/ppd; } cRM = cLM + (lbxinc - lbxp - 0.1)*72/ppd; return 4+j; /* underline */ case 'U': case 'u': if (c2!='B' && c2!='E') return 0; if (!pr) return 4; if (c2=='B') { UDline.x = H; UDline.f = 1; if (c1=='u') UDline.f = 2; /* broken line 10:7 */ } else { endAC(pr); UDline.f = 0; } return 4; case '+': case '-': /* char size increment/decrement */ if (!isdigit(c2)) return 0; k = c2-'0'; if (isdigit(c3)) k = k*10 + (c3-'0'); if (c1 == '+') k = defptsi + k; else k = defptsi - k; /*fprintf(stderr, "%c%c%c: k = %d \n", c1, c2, c3, k);*/ if (k <= 0 || k > 999) k = defptsi; if (pr) { ptspc=k; PSctrl(); /*fprintf(stderr, "ptspc = %d\n", ptspc);*/ } else j = (k <= 99)? issfs('0'+k/10, '0'+k%10, ']') : issfs('0'+k/100, '0'+(k/10)%10, '0'+k%10); return (c3==']')? 4 : 5; default: if (!isdigit(c1) || !isdigit(c2)) return 0; /* char size */ if (!pr) return issfs(c1, c2, c3); ptspc = (c1-'0')*10 + (c2-'0'); if (isdigit(c3)) ptspc = ptspc*10 + (c3-'0'); PSctrl(); return (c3==']')? 4 : 5; } } int issfs(c1, c2, c3) unsigned char c1, c2, c3; { /* now accept @[xx] or @[xxx] for char size */ int k, span(); float y; switch(c1) { /* C: column number */ case 'C': if (!isdigit(c2)) return 0; k = (c2=='0')? defcolumn : (c2-'0'); if (H > cLM) ; if (sline==0) PCN=SCN=0; /* often happens at start of doc */ SCN++; if (SCN==1) { column = k; cTM = V; cRM = LM + columnWidth(); } else { cBM=span(1); cLM = LM; pcolumn = 1; } return 4; default: if (!isdigit(c1) || !isdigit(c2)) return 0; /* char size */ k = (c1-'0')*10 + (c2-'0'); if (c3 != ']') k = k*10 + (c3-'0'); if (k>=1000 || k<=0) { y=defpts; ptspc=defptsi;} else y=ptspc=k; /* ptspc for print has been saved */ charsize(y); /* size ctrl at the beginning of a line, take it */ /* New approach: no adjustment of V here */ if (H==LM || CLP > 1.1*lineclp[sline+1]) lineclp[sline+1] = CLP; if (H==LM || CIP > linecip[sline+1]) linecip[sline+1] = CIP; return 4; } } void shade() { endAC(0); ; } underline() { int y; if (vertical) { y = ((ptspc==defptsi)? defpts : ptspc)*Cy*Cw/ppd + .1; y += BM-V+CLP/9; } else y = BM-V-CLP/9; fprintf(out, "%d %4.1f %d %d %d UDline\n", UDline.f-1, pts/4, H-UDline.x, UDline.x, y); UDline.x = H; return 1; } void endAC(pr) int pr; { if (!inCH) { if (pr && Prntpage && !PreScanMode) { clearascbuf(1, 0); fprintf(out,") S\n"); } inCH=100; } if (UDline.f && pr && Prntpage) underline(); newpos=1; ascbuf.p=0; } clearascbuf(pr, clearall) int pr, clearall; { int j, k, n=0, c; k = clearall? ascbuf.p : ascbuf.pp; if (ascbuf.p0 && !PreScanMode) { for (j=0; j=128) { n+=3; fprintf(out, "\\%03o", c); } if (c=='(' || c==')' || c==92) { n++; fprintf(out, "\\%c", c); } else fprintf(out, "%c", c); n++; if (n>75 && c==' ' || n>78) { n=0; fprintf(out, "\\\n"); /* break line */ } } } if (!clearall && ascbuf.p != ascbuf.pp && ascbuf.p) for (j=ascbuf.pp; j GB", "GB --> Hz", "", "zW --> GB", "", "Trying to repair", "JIS Pre-Processing", "HZ+ --> GB", "HZ+ -->B5", "KSC7 --> KSC8", "UTF7 --> 2-byte unicode", "UTF8 --> 2-byte unicode", "CNS --> BIG5", "GB --> BIG5", "", "BIG5 --> GB", "", "Long lines --> short lines", "Print/extract selected pages", "MIME quoted printable -->8 bit", "Add sender's address", "", ""}; static char *st2[]={"", "GB", "Hz", "Filtered/Repaired", "GB", "8-bit", "Repaired", "7-bit JIS", "GB", "BIG5", "8-bit", "2-byte", "2-byte", "BIG5", "BIG5", "", "GB", "", "Short version", "Selected pages", "8 bit", "", "", ""}; static char ki[]="$B", ko[]="(B"; char st[6], s[80]; FILE *in; if (convcode==FIL) { strcpy(st, "NEW"); if (breakfile) sprintf(st, "%d", filecount++); } /* convcode=FIL, GB/B5/JIS-->GB/B5/JIS, no action here */ else { fprintf(errout, "%s ...\n", st1[convcode]); inf=Rinf; sbufp=0; while ((in = inf->fp) != NULL) { if (inf != Rinf) fputc(EOL, out); switch (convcode) { case HZGB: case HZPGB: case HZPB5: hz2gb(in); strcpy(st, (convcode==HZPB5)? B5str : GBstr); break; case GBHZ: gb2hz(in); strcpy(st, HZstr); break; case ZWGB: zw2gb(in); strcpy(st, GBstr); break; case CNSB5: cns2b5(in); strcpy(st, B5str); break; case B5GB: gbb5conv(in, B5GB); strcpy(st, GBstr); break; case GBB5: gbb5conv(in, GBB5); strcpy(st, B5str); break; case JIS8: jis2jis8(in); strcpy(st, "JS8"); break; /*case KSC8: ksc2ksc8(in);strcpy(st, "KS8"); break;*/ case JISRP: /*jisrepair(in);*/strcpy(st, "RP");break; case JISCVT: switch (code) { case JIS: seven2seven(in, ki, ko); break; case EUC: euc2seven(in, ki, ko); break; case SJIS: shift2seven(in, ki, ko); break; default: break; } strcpy(st, "JS7"); break; case UTF8TOUNI: case UTF7TOUNI: to2byte_unicode(in); strcpy(st, "u2"); break; case MIMEQP: mimeqpdecode(in); strcpy(st, "8b"); break; case ADDLBAS: addLBAS(in); strcpy(st, "lb"); break; #ifdef PSPRINT case TOSHORTPS: toshortline(in); strcpy(st, "sht"); break; case PAGEPRINT: pageprint(in); strcpy(st, "pps"); break; #endif default: break; } fclose(in); if (convcode==JIS8) remove(inf->s); inf->fp=NULL; if ((inf=inf->p) == NULL) break; } inf=Rinf; } if (ferror(out)) { fprintf(stderr, "%s version write error: %s\n", st2[convcode], tempfile); bell(); exit(-5); } fclose(out); if (convOnly) { strcpy(s, PSfile); if (*PSfile==0) { strcpy(PSfile, Rinf->s); FName(PSfile, st); } else if (breakfile) FName(PSfile, st); if (convOnly==10) { /* PSPRINT functions */ outputToDev(tempfile); } else { if (stdoutput) outputToStdout(tempfile); else { RE_name(tempfile, PSfile); fprintf(errout, "%s version: %s\n", st2[convcode], PSfile); } if (breakfile && convOnly==100) { opnfile(OUT); strcpy(PSfile, s); } } } else { FName(Rinf->s, st); RE_name(tempfile, Rinf->s); opnfile(IN); opnfile(OUT); } } to2byte_unicode(in) FILE *in; { unsigned short unichar; if (convcode==UTF7TOUNI) while ((unichar=utf7_getc(in)) != (unsigned short) EOF) { u2byte((int) (unichar/256)); u2byte((int) (unichar%256)); } else while ((unichar=utf_getc(in)) != (unsigned short) EOF) { u2byte((int) (unichar/256)); u2byte((int) (unichar%256)); } return 1; } u2byte(c1) /* output "escaped" u2 byte */ int c1; /*#define U2ESC 0x4D, U2ESC2 0x21, ESCs for 2-byte unicode: */ { /* 4D4D = 4D, 4D21 = 00 */ switch (c1) { case 0x00: fputc(U2ESC, out); fputc(U2ESC2, out); break; case U2ESC: fputc(U2ESC, out); fputc(c1, out); break; default: fputc(c1, out); break; } return 1; } void jis2jis8(in) /* 0x21-0x7E --> 0xA1-0xFE */ FILE *in; { int state, c1, c2, k=0; state = OUT; sbufp=0; while ((c1=sgetc(in)) != EOF) { if (c1 == ESC) { c2 = sgetc(in); /* ESC$B , ESC(B for New & old JIS */ if (c2 == '$' || c2 == '(') { c1 = sgetc(in); k+=3; if (c1=='B') state = (c2=='$')? IN : OUT; else { sungetc(c1); sungetc(c2); k-=2; if (state==OUT) { /* else eat ESC */ fputc(ESC, out); } } } else { /* if IN, bad ESC, ignore */ sungetc(c2); k++; if (state==OUT) fputc(ESC, out); } } else if (state==IN) { c2 = sgetc(in); fprintf(out,"%c%c", c1+128, c2+128); k+=2; } else if (k= IN && c1 != EOL) { c2 = sgetc(in); if (c2==EOL) { /* bad code, turn c1 to 7-bit */ if (!mute) fprintf(errout, "Bad code: 0x%02X%02X\n", c1, c2); fprintf(out, "%c", MSBoff(c1)); state=OUT; k=0; } else if (c2=='~') { /* "#~{" or "#~}": since '{' or '}' is not valid first byte, more likely to be "~{" or "##~{". this correction is optional */ c2=sgetc(in); sungetc(c2); if (c2=='{' || c2=='}') { sungetc('~'); fprintf(out, "%c", c1); } else { fprintf(out, "%c%c", MSBon(c1), MSBon('~')); k+=2; } } else { fprintf(out, "%c%c", MSBon(c1), MSBon(c2)); k+=2; } } else if (k100) nHzline=76; state = OUT; while ((c1=fgetc(in))!=EOF) { /* GB1 */ if (c1>=0xA1) { if ((c2=fgetc(in))==EOF) break; /* GB2 */ else if (c2>=0xA1) { nGB++; if (state==OUT) { if (k >= nHzline-2) { fprintf(out, "~\n"); k=0; } fprintf(out, "~{"); state=IN; k+=2; } else if (k >= nHzline-4) {fprintf(out, "~}~\n~{"); k=2;} fprintf(out, "%c%c", MSBoff(c1), MSBoff(c2)); k+=2; } else { /* keep bad code as it is */ if (!mute) fprintf(errout, "Probably bad code: %02X%02X\n", c1, c2); if (state==IN) { fprintf(out, "~}"); state=OUT; k+=2; } if (k >= nHzline-1 && c1!=EOL && c2!=EOL) { fprintf(out, "~\n"); k=0; } fprintf(out, "%c%c", c1, c2); k+=2; if (c1==EOL) k=1; if (c2==EOL) k=0; } } else { /* ASCII */ /* may also be euro char */ if (c1>=0x80) fprintf(errout, "Probably bad code: %02X\n",c1); if (state==IN) { fprintf(out, "~}"); state=OUT; k+=2; } if (k >= nHzline-1 && c1!=EOL) { fprintf(out, "~\n"); k=0; } fputc(c1, out); if (c1==EOL) k=0; else if (c1=='\t') { k/=8; k = (k+1)*8; } else k++; } } if (state==IN) fprintf(out, "~}"); if (!nGB) fprintf(errout, "Input may not be a GB file\n"); } void zw2gb(in) FILE *in; { int c1, c2, zW=0, Newline=1; while ((c1=fgetc(in)) != EOF) if (!zW) { if (c1==EOL) { fputc(EOL, out); Newline=1; } else if (Newline && c1=='z') { if ((c2=fgetc(in)) == EOF) { fputc(c1, out); break; } else if (c2=='W') zW=1; else fprintf(out, "%c%c", c1, c2); Newline = 0; } else { fputc(c1, out); Newline = 0; } } else if (c1=='\n') { zW=0; Newline=1; /* soft CR */ } else { /* zW mode */ if ((c2=fgetc(in)) == EOF) { fputc(MSBon(c1), out); break; } else if (c2=='\n') { zW=0; Newline=1; if (c1=='#') fputc(EOL, out); else fprintf(out, "%c\n", MSBon(c1)); /*invalid zW seq.*/ } else if (c1=='#' && c2==' ') fputc(' ', out); else if (c1==' ') fputc(c2, out); else fprintf(out, "%c%c", MSBon(c1), MSBon(c2)); } } int span(int mode) /* vertical column gap is uniform, only need to take care of 1st line image */ { int x, y, n, j, kc=1; int cip0; if (mode==0) { if (sline < column) return 0; x = BM-cTM; y = linecip[1]-lineclp[1]; n = 1; cip0 = linecip[1]; for (j=1; j<=sline; j++) { y += lineclp[j]; if (y > x+BMover) { y = linecip[j]-lineclp[j]; if (cip0 < linecip[j]) cip0 = linecip[j]; if (j != n) j--; /** j==n: one line to bottom **/ n = j+1; kc++; } } linecip[0] = cip0; return (kc>column)? 1:0; } else if (mode==10 && AdjAtEndDoc) { /* end of document */ linecip[0] = linecip[1]; return BM; } else { n=0; do { x=0; n++; if (column==1) n=sline; y = x = linecip[1]-lineclp[1]; linecip[0] = cip0 = linecip[1]; for (j=1; j <= n; j++) x += lineclp[j]; if (x+cTM >= BM) return BM; else if (column==1) return (x+cTM); kc=1; for (j=1; j<=sline; j++) { y += lineclp[j]; if (y > x + BMover) { y = linecip[j]-lineclp[j]; if (cip0 < linecip[j]) cip0 = linecip[j]; j--; kc++; if (kc>column) break; } } linecip[0] = cip0; if (kc <= column && y <= x+BMover) return (cTM+x > BM)? BM : (cTM+x); } while (kc>column); } } int CheckLineLen() { int c1, c2, Hz; unsigned int j, k, m=0, N=0; FILE *in; if (nHzline < 9999) return nHzline; else if (nHzline==9999) nHzline=10000; inf=Rinf; sbufp=0; for (j=0; j<=150; j++) linedif[j]=0; while ((in = inf->fp) != NULL) { if (!mute || convcode==FIL) fprintf(errout, " %s\n", inf->s); while ((c1=sgetc(in))!=EOF) { if (c1==EOL) { /* used to determine nHzline */ linedif[(m<150)?m:150]++; N += m; m=0; } else if (c1=='~' && lcode=10000) nHzline++; else if (c2=='{' || c2=='}') { Hz++; m+=2; } else { sungetc(c2); m++; } } else m++; } rewind(in); if (inf->p == NULL) break; else inf = inf->p; } inf=Rinf; if (nHzline<9999) return nHzline; if (Hz && convcode==HZGB) { /* 1% lines has ~\n */ if ((nHzline-10000.)*200./Hz >= 2) return nHzline; } m=0; for (j=0; j<=150; j++) m += linedif[j]; /* long lines: # of lines < # of chars/100 or 20% lines have 150+ chars */ if (m < N/100 || m < linedif[150]*5) return 9999; /* if 25% lines are N to N+3 chars long, set it */ for (j=0; j<=40; j++) { for (k = -1; k<=1; k+=2) { N = 75 + j*k; if ((linedif[N]+linedif[N+1]+linedif[N+2]+linedif[N+3]) > m/4) return (N - (1-k)); } } return 9999; } int yes(int n) { char s[40]; if (stdinput) return n; /* can't read from keyboard, use default */ do { if (n>1) bell(); gets(s); if ((toupper(s[0]))=='Y') return 1; else if ((toupper(s[0]))=='N') return 0; else if (n<=1) return n; else s[0]='\0'; fprintf(errout, "(Y/N) ?\n"); } while (s[0]=='\0'); } #ifdef STAT /* start STAT functions */ #include "cnstat.h" #else /* No STAT functions */ statinit() { fprintf(stderr, "Functions supported by enhanced version only\n\ Please contact author\n"); cleanup(1); exit(0); return 1; } wordstat(d) unsigned int d; { return 1; } statistics(Nchars, NcharAll) unsigned int Nchars, NcharAll; { return 1; } CharBMPshift() { return statinit(); } void stat_prescan() { return; } int CharBitmapShift(fp, addr, a) FILE *fp; unsigned char *a; { unsigned char *c, ON[8]; int j, k, n; ON[0]=128; for (j=1; j<8; j++) ON[j]=ON[j-1]/2; c = (unsigned char *) calloc(CHsize+1, sizeof(unsigned char)); if (c==NULL) MemExit(); for (j=0; jB5 table file -> %s\n", KWfile); exit(0); } return 1; } int gbb5tableinit(dirc, in) int dirc; /* GBB5 or B5GB */ FILE *in; { unsigned char *p, *t, cst[120]; int j, k1, k2, wordmap; while (fgets((char *) cst, 118, in)!=NULL) { /* MSB set for both GB and Big5, minimum line "GBB5\n" */ if (cst[0] < 0xA1 || strlen((char *) cst) < 5) continue; p = &cst[0]; wordmap=0; /* def: char mapping */ k1 = GBPOS(p[0], p[1]); k2 = B5POS(p[2], p[3]); /* "GBGB B5B5\n", use space or tab as seperator, but change * tab to space */ j=strlen((char *) p); if (j >= 10) { while (*++p != '\0') if (*p == ' ' || *p == '\t') { *p = ' '; if (strlen((char *) p) >= 6) wordmap=1; k2 = B5POS(p[1], p[2]); break; } p = &cst[0]; } if (k1<0 || k2<0) continue; /* mapping line not complete */ /* word (phrase) mapping */ if (wordmap) { p[j-1] = ' '; p[j]='\0'; if (dirc==B5GB) k1=k2; /* allow more than one pair */ if (ptstring[k1]!=NULL) j += strlen((char *)ptstring[k1]); t = (unsigned char *) calloc(j+1, sizeof(unsigned char)); /* if not enough space, ignore current pair */ if (t==NULL) continue; t[0]='\0'; if (ptstring[k1]!=NULL) { strcpy((char *) t, (char *) ptstring[k1]); free(ptstring[k1]); } ptstring[k1] = t; strcat((char *) ptstring[k1], (char *) p); /** only one pair is allowed: overwrite previous ones if (ptstring[k1]!=NULL) free(ptstring[k1]); ptstring[k1] = (unsigned char *) calloc(j+1, sizeof(unsigned char)); if (ptstring[k1]==NULL) MemExit(0); else strcpy((char *) ptstring[k1], (char *) p); **/ continue; } /* else: char mapping, overwrite previous ones */ if (dirc==GBB5) fstring[k1]=k2; else { fstring[k2]=k1; /* multiple mapping possible */ p += 4; while (strlen((char *) p) >=3) { /* always terminated with EOL */ if ((k2=B5POS(p[0], p[1])) >= 0) fstring[k2]=k1; p += 2; } } } fclose(in); return 1; } gbb5conv(in, dirc) FILE *in; int dirc; { int c1, c2, idx, matched; unsigned int ch; unsigned char *m, *p, *t, s1[45], s2[45]; sbufp=0; while ((c1=sgetc(in)) != EOF) { if (c1>=0xa1) { if ((c2=sgetc(in))==EOF) break; else if (c2>=0xa1 || (dirc==B5GB && c2>=0x40)) { idx = (dirc==B5GB)? B5POS(c1, c2) : GBPOS(c1, c2); /* consider word mapping first */ if ((m=ptstring[idx]) != NULL) { matched=0; while (strlen((char *)m) >= 9) { p=m; /* k=0; while ((s1[k] = *p++) != ' ') k++; sscanf((char *) p, "%s", (char *) s2); s1[k]=s2[strlen((char *) s2)+1]='\0'; */ sscanf((char *)p, "%s %s", (char *)s1, (char *)s2); /* advance pointer to next word pair */ m += strlen((char *) s1) + strlen((char *) s2) + 2; /* compare with current word pair */ p = (dirc==B5GB)? &s2[1] : &s1[1]; t = p+1; while (*++p != '\0') { if ((c1=sgetc(in)) != *p) { sungetc(c1); while (--p >= t) sungetc(*p); break; } } if (p>t) { /* words match, map word */ p = (dirc==B5GB)? &s1[0] : &s2[0]; while (*p != '\0') fprintf(out, "%c", *p++); matched++; break; } } if (matched) continue; /* while sgetc(in) loop */ /* else words not match, map char */ } /* one to one char mapping */ if (dirc==B5GB) { ch = (fstring[idx]==30000)? GBbox : fstring[idx]; fprintf(out, "%c%c", GBB1(ch), GBB2(ch)); } else { ch = (fstring[idx]==30000)? B5box : fstring[idx]; fprintf(out, "%c%c", B5B1(ch), B5B2(ch)); } } else fprintf(errout, "Bad pair: %02X%02X\n", c1, c2); } else fprintf(out, "%c", c1); } return 1; } convertEOL(unsigned char *t, int *jmax) /* CR or CR-LF to LF, for a unified treatment */ { int nc=0; /* # of CR-LF converted to LF */ unsigned char *s; s=t; while (*t = *s) { if (*s==CR) { *t = LF; if (*++s == LF) nc++; else s--; } s++; t++; } *jmax -= nc; } void CodeConversion() { int conv_code; do { conv_code = convcode; /* save original convcode */ switch(convcode) { case HZGB: if (nHzline==9999) nHzline = CheckLineLen(); break; case HZB5: convcode=HZGB; if (nHzline==9999) nHzline = CheckLineLen(); convers(0); convcode=GBB5; gbb5convinit(GBB5); break; case GBB5: case B5GB: gbb5convinit(convcode); break; case B5HZ: convcode=B5GB; gbb5convinit(B5GB); convers(0); convcode=GBHZ; break; case TOSHORTPS: case PAGEPRINT: /* old PSPRINT function */ convers(10); exit(0); break; default: break; } convers(1); /* 1, conversion only */ convcode = conv_code; /* restore old original convcode */ } while (OIOU((convcode==HZGB || convcode==HZB5)? 1: 0) != NT); if (stdinput) remove(Rinf->t); signature(); cleanup(0); /* ? */ exit(0); } void GetCharUsage() /* prepare char statistics for buliding dict */ { long m; long nchars_doc; /* # of chars in document */ long ndchar_font; /* # of different char/font variations */ long ndchar_font_1; /* # of diff. char/font var. with 1 occur. */ unsigned int i, j; struct FontTag *F; m=0; nchars_doc = ndchar_font = ndchar_font_1 = 0; for (j=0; jp) { /* white space does not count: not 0 addr for GBK/B5P */ F->fstring[Addr(cspace/256, cspace%256)]=0; F->ndchar=0; /* # of different chars used for this font */ for (i=0; i < F->nchar; i++) { if (F->fstring[i] == 0) continue; F->ndchar++; nchars_doc += F->fstring[i]; ndchar_font++; /*N++;*/ if (F->fstring[i]==1) ndchar_font_1++; /*n++;*/ /* usage histogram */ linedif[(F->fstring[i] > MAXLINES-2)? MAXLINES-2 : F->fstring[i] ]++; } F->fdict = (unsigned int *) calloc(F->ndchar, sizeof(unsigned int)); if (F->fdict==NULL) MemExit(); F->k = F->nCN = F->ndchar; } if (nchars_doc > 0) fprintf(stderr, "There are %ld characters in the document (%ld %s)\n\n", nchars_doc, ndchar_font, (Fonts->p==NULL)? "unique characters" : "char/font combinations"); j = (int) (ndchar_font - ndchar_font_1); if (nCN > j) nCN = j; /* # of chars in dict(s) cannot exceed nCN */ m = ndchar_font; j=0; if (ndchar_font > 0) { while (++j <= MAXLINES-2) { if (m<=0) break; if (linedif[j] == 0) continue; else if (j==MAXLINES-2) j=65000; for (F=Fonts; F!=NULL; F=F->p) { for (i=0; i < F->nchar; i++) { if (F->fstring[i]>0 && F->fstring[i]<=j) { F->fdict[--(F->k)]=i; F->fstring[i] += 30000; if ((int) m > nCN) (F->nCN)--; if (--m==0) break; } } if (m==0) break; } } for (F=Fonts; F!=NULL; F=F->p) { if (F->nCN > 0) for (j=0; j < F->nCN; j++) F->fstring[F->fdict[j]] = j+60000; if (F->nCN < F->ndchar) for (j = F->nCN; j < F->ndchar; j++) F->fstring[F->fdict[j]] -= 29900; } } } int print_range_check(int npg) { return (npg>=bp && (!ep || npg<=ep) && (!odd || (odd==1 && npg%2) || (odd>=2 && !(npg%2))))? 1:0; } int set_doc_defaults() /* * restore to original settings after prescan mode */ { int j; PCN=SCN=1; column = defcolumn; Ca=defCa; Ci=defCi; Cx=defCx; Cy=defCy; nEF=defnEF; if (nEF%10 == 2) for (j=0; j<129; j++) Wasc[j] = 1.; ptspc==defptsi; pts=defpts; charsize(defpts); V=TM; H=LM; cRM = RM; cBM = BM; cTM=cLM=0; if (column>1) cRM = LM + columnWidth(); spaceH = -1; Ha = 0; pgpd=0; pgcount=pgcount_bak; Prntpage = print_range_check(pgcount); inCH=100; newpos=1; ascbuf.p=ascbuf.pp=0; return 1; } main(int argc, char **argv) { int j, jmax, c, endfile, buftoosmall; void init(), style(), build_dict(); void gbb5preproc(), jispreproc(), kscpreproc(); unsigned char *s, *p, *doAC(); unsigned int bufsz, bufused; float Cis, Cas, Cascs, Cxs, Cys, ps; int snEF, CSPs, CLPs, CIPs, scnsp, sfrl, inCHs, sctradj; struct FontTag *sFontptr; FILE *in; mRinf=Rinf=NULL; buf=NULL; init(argc, argv); if (bmpshift) CharBMPshift(); /* exit */ if (convcode!=FIL && breakfile>10) { /* multiple input, multiple output */ mRinf = Rinf->p; Rinf->p = NULL; } if (convcode && convcode!=FIL) CodeConversion(); /* exit */ if (timestat>=3) { statinit(); stat_prescan(); statistics(); /* exit */ } if (buf==NULL) { bufsz=BUFSIZE; buf = (unsigned char *) calloc(bufsz, sizeof(unsigned char)); if (buf==NULL) MemExit(); } if (convcode==FIL) { fprintf(errout, (fix)? "Repair ...\n" : "Filter out functional sequences ...\n"); if (nHzline==9999) nHzline = CheckLineLen(); if (nHzline==9999 && fix!=2) nHzline=70; if (nHzline > 160 && fix==2) copies=nHzline=80; nchar=odd=0; if (copies==1) copies=100; } style((convcode==FIL || mute)? 0:1); /* one-input, one-output loop */ do { if (convcode != FIL) { if (addrlabel) { convcode=ADDLBAS; convers(0); } if (lcode==JIS) jispreproc(); else if (lcode==KSC) kscpreproc(); else if (lcode==UTF) unicodepreproc(); else if (lcode==GBK || lcode==B5P) ; else gbb5preproc(); if (!mute) fprintf(errout, "Scanning document(s) ...\n"); } /* Scan/Print mode loop */ for (PreScanMode=1; PreScanMode>=0; PreScanMode--) { set_doc_defaults(); if (convcode!=FIL && !PreScanMode) { GetCharUsage(); if (*PSfile==0) { strcpy(PSfile, Rinf->s); FName(PSfile, PSstr); } if (!mute) fprintf(errout, "%s --> PS ...\n", codename[lcode]); header(); } endfile=0; inf=Rinf; in=inf->fp; buf[0]=fgetc(in); buf[1]='\0'; p = buf; while (p[0]!='\0') { /* reorganize buf */ if (!endfile && strlen((char *) p) < bufsz-2048) { j=0; if (p != buf) while (buf[j++] = *p++) ; jmax=strlen((char *) buf); j=bufsz-jmax-5; while (--j) { if ((c=getc(in)) != EOF) { if (c!='\0') buf[jmax++]=c; } else { if (PreScanMode) rewind(in); else { fclose(in); inf->fp=NULL; if (convcode==ZWGB || convcode==HZGB || convcode==ADDLBAS || convcode==JIS8) remove(inf->s); } if (inf->p == NULL) { endfile=1; break; } /* else */ inf=inf->p; if ((in = inf->fp) == NULL) { endfile=1; break; } else if (breakfile && convcode!=FIL) { buf[jmax++]='@'; buf[jmax++]='['; buf[jmax++]='P'; buf[jmax++]= '0'+(breakfile-1); buf[jmax++]=']'; j -= 5; } else { buf[jmax++]=EOL; j--; } } } buf[jmax]='\0'; /*if (convcode!=FIL)*/ convertEOL(buf, &jmax); p = buf; } s=p; H = LM; /* save status variables that will be used and changed by search */ Cis=Ci; Cas=Ca; Cascs=Casc; Cxs=Cx; Cys=Cy; ps=ptspc; snEF=nEF; CSPs = CSP; CLPs = CLP; CIPs = CIP; scnsp=cnsp; sfrl=frl; inCHs=inCH; sctradj=centraladj; sline=fnewline=0; /*lineclp[0]=*/ lineclp[1]=CLP; /*linecip[0]=*/ linecip[1]=CIP; frl=NT; cnsp=0; inCH=100; ascbuf.p=ascbuf.pp=0; sFontptr=CurrentFont; /* SEARCH */ bufused = (unsigned int) (p - buf); buftoosmall = 0; for (;;) { while (!fnewline && *s!='\0' && (s[1]!='\0' || endfile) ) s=doAC(s, 0); if (SCN==2 || convcode==FIL) break; else if ( span(0) || (endfile && s[0]=='\0') ) { if (endfile && s[0]=='\0') { /* see issfs SCN=2 */ if (s[-1]!=EOL) newline(0, 1); cBM=span(10); } else cBM = BM; cLM = LM; /* this may create problem */ pcolumn = 1; break; } else if (!endfile && (s[0]=='\0' || (s[0]!='\0' && s[1]=='\0')) ) { /* needs to recover all status variables */ buftoosmall = 1; break; } fnewline = 0; } if (convcode==FIL) { p=s; continue;} /* recover status variables */ Ci=Cis; Ca=Cas; Casc=Cascs; Cx=Cxs; Cy=Cys; ptspc=ps; CSP = CSPs; CLP = CLPs; CIP = CIPs; cnsp=scnsp; frl=sfrl; inCH=inCHs; centraladj=sctradj; ascbuf.p=ascbuf.pp=0; if (nEF != snEF) { nEF=snEF; if (!getdata(1)) for (j=0; j<129; j++) Wasc[j]=1.; } if (CurrentFont != sFontptr) { strcpy(HBFname, sFontptr->FontName); HBFopen(); } if (buftoosmall) { if (bufsz>MAXBUFSZ) MemExit(); bufsz += 3072; buf = (unsigned char *) realloc(buf, bufsz); if (buf==NULL) MemExit(); p = buf; p += bufused; continue; } /* PRINT */ pline=1; H=cLM; /*if (V==cTM)*/ V += linecip[1]; if (cTM+linecip[0]*0.75 > BM && cTM+linecip[1] > BM+BMover) { endpage(0); V=cTM=TM; H=cLM=LM; PCN=SCN=1; pcolumn=1; continue; } do { fnewline=0; while (!fnewline && *p!='\0' && (p[1]!='\0' || endfile) ) p=doAC(p, 1); } while (pline<=sline && *p!='\0'); } if (convcode==FIL) { if (sbufp) sbufprint(EOL); convers(1); PreScanMode--; /* bypass */ } else { /* last EOL is ignored, explicit action needed */ if (ascbuf.p) { clearascbuf(1, 1); endAC(1); } endpage(1); } } /* end of PreScanMode loop */ if (booklet) tobooklet(); } while (OIOU(1) != NT); /* one-input, one-output loop */ free(buf); cleanup(0); if (stdinput) remove(Rinf->t); signature(); exit(0); } int OIOU(int fstr_used) /* one input one output: multiple input, seperate output Does not work for convcode=FIL because of "breakfile" */ { int j; struct FontTag *F; if (fstr_used) { /* re-initialize fstring and ptstring */ for (F=Fonts; F!=NULL; F=F->p) { for (j=0; j<=nchar; j++) if (fstring[j]>0 && fstring[j]<60000) { if (ptstring[j]!=NULL) free(ptstring[j]); ptstring[j]=NULL; } } } if (convcode!=FIL && breakfile>10 && mRinf!=NULL) { inf = Rinf = mRinf; mRinf = Rinf->p; Rinf->p = NULL; /* set to default values: there are others affected, not clean */ init(999, NULL); opnfile(OUT); PSfile[0]='\0'; code=codecmd; pgpd=0; pgcount=1; nCN=2048; return 1; } else return NT; } unsigned char *doAC(unsigned char *q, int pr) { int k, j=1; int putCH(), putASC(), isfs(); unsigned char c1, c2; c2=0; c1 = *q++; if (c1>=b1l) { /* b1l=0xa1, or 0x30 if utf */ if (q[0]=='\0') ; else { c2 = *q++; if (lcode==UTF) { /* special handling for unicode */ if (c1=='@' && q[0]=='[') { /* problem for unicode */ if (k=isfs(q, pr)) { q += k; j=0; } } else if (c1==U2ESC) { c1=c2; c2=0; if (c1==U2ESC2) c1=0x00; } if (c2==0) c2 = *q++; if (c2=='\0') ; else { if (c2==U2ESC) { if ((c2 = *q++) == '\0') j=0; else if (c2==U2ESC2) c2=0x00; } if (c1>=b1l) j++; else { c1=c2; c2=0;} /* if byte 1 not 0x00, eat it */ } } /*else if (lcode!=B5 && c2>=0xa1) { */ else if (c2 >= b2l) { if (lcode==GB && alnumadjust) { /* also for JIS ? */ if (c1==0xa3 && isalnum(c2-128)) c1=c2-128; else if (c1==0xa1 && c1==c2 && !inCH && *q>=c1) c1=0x20; /* ascii non-ascii_space ascii */ else j = 2; } else j = 2; } /*else if (lcode==B5 && c2 >= 0x40) j = 2; */ else {q--; c2=0;} } } else if (c1=='@' && q[0]=='[') { if (k=isfs(q, pr)) { q += k; j=0; } } if (j==2) k = putCH(c1, c2, pr); else if (j==1) { if (c1==EOL && *q=='\0' && pr) k=0; /* Don't print the last EOL */ else if (!vgb || !isvgb(c1)) { k = putASC(c1, q[0], pr); } else k = putCH(0xa3, c1+128, pr); } else k=0; if (k==1 && c2!=0) k++; /* (c1, c2) --> c1-128 */ if (convcode==FIL && !k) k = filter(c1, (j==1)? q[0]:c2, q, j); return (q-k); } void MemExit() { fprintf(stderr, "CNPRINT: not enough memory\n"); exit(2); } FILE *Rfopen(char *fn, char *mod) { char cst[100]; struct Roots *rt; FILE *fp; rt=root; do { cst[0]='\0'; if (rt!=NULL) strcpy(cst, rt->s); strcat(cst, fn); /* fprintf(errout, "open: @%s@\n", cst); */ if ((fp=fopen(cst, mod))!=NULL) return fp; if (rt!=NULL) rt = rt->p; } while (rt!=NULL); return NULL; } int filter(c1, c2, q, j) unsigned char c1, c2, *q; int j; { /* filter */ /* now assumes CR or CR/LF has been converted to LF */ int n=0, k; if (c1==LF && breakfile) { if (fnchar >= (breakfile-2)*1024L) { convers(100); /* save into small files */ fnchar = 0; } } switch(fix) { case 0: if (j==1) sbufprint(c1); else if (j==2) { sbufprint(c1); sbufprint(c2); } break; case 3: case 4: if ((j==1 && (c1==' ' || c1=='\t')) || ((c1*256)+c2)==cspace) { for (k=0; k0 || fix==4) ) { if (c1!=EOL) for (k=nchar; k<4; k++) sbufprint(' '); nchar=4; } nchar++; ignorespace=0; sbufprint(c1); if (c1==LF) nchar=0; if (j==2) { sbufprint(c2); nchar++; } } break; case 7: /* for CStar: in V1.3a, if HZ and non-punctuation, add space before CH char, should be more intelligent */ if (j==1) sbufprint(c1); else if (j==2) { if ( (c1==0xA1 && c2<=0xC3) || (c1==0xA3 && !isalnum(c2-0x80)) ) ; /* else if (sbufp==0) ; else if (sbuf[sbufp-1]==' ' || sbuf[sbufp-1]=='\t'); */ else sbufprint(' '); sbufprint(c1); sbufprint(c2); } break; case 8: /* for CStar: if ...HZ HZ..., delete space --> ...HZHZ... */ if (j==1) { if (c1==' ' && c2>=0xA1) { ; /* if (sbufp==0) ; else if (sbuf[sbufp-1]==' ' || sbuf[sbufp-1]=='\t') sbufprint(c1); */ } else sbufprint(c1); } else if (j==2) { sbufprint(c1); sbufprint(c2); } break; default: /* 1 2 6 */ if (j==1) { if (nchar>=nHzline-2 && fix!=2) ignorespace=suppress; /* space */ switch(c1) { case LF: /*case CR: / * CR, LF, or CR+LF * / if (c1==CR && c2==LF) n--; / * advance buf pointer by 1 */ if (nchar0) || (ignoreEOL && nchar==0) )? 1:0; if (ignoreEOL) ignoreEOL=0; /* fix=6, ignore 2nd */ else if (fix!=2 || (fix==2 && nchar==0) || EPS) sbufprint(EOL); /* EPS: keep EOL */ } else { if (fix==2 || EPS || nchar>copies) sbufprint(EOL); if (EPS || fix==2) ignorespace=0; /* copies: nmax */ if (fix==6) ignoreEOL=1; } nchar=0; break; case ' ': case '\t': if (c2==LF) break; if (c1=='\t') nchar = (nchar/8 + 1) * 8; else nchar++; if (!ignorespace) sbufprint(c1); break; case ',': case '.': case ':': case ';': case '(': case ')': case '!': case '?': case '"': if (!mute) { /* mute = map to CH */ nchar++; sbufprint(c1); break; } else if (c1=='.' && c2=='.') { /* .... do not convert */ do { nchar++; sbufprint(c1); n--; } while (*q++ == c1); n++; break; } if (c2==' ') n--; /* advance buffer pointer by 1 */ if (lcode==GB) { if (c1=='.') { c1=0xA1; c2=0xA3; } else if (pausqm && c1=='"') {/* quot. mark pair? */ c2=0xB0+odd; c1=0xA1; odd=(odd)? 0:1; } else { c2=c1+0x80; c1=0xA3; } } else if (lcode==B5) { switch (c1) { case '"': if (pausqm && c1=='"') { c2=0xA7+odd; odd=(odd)? 0:1; } else c2 = 0xB2; break; case ',': c2=0x41; break; case '.': c2=0x43; break; case ':': c2=0x52; break; case ';': c2=0x51; break; case '(': c2=0x5D; break; case ')': c2=0x5E; break; case '?': c2=0x48; break; case '!': c2=0x54; break; default: break; } c1=0xA1; } else if (lcode==JIS) { switch (c1) { case '"': if (pausqm && c1=='"') { c2=0xC8+odd; odd=(odd)? 0:1; } else c2 = 0xED; break; case ',': c2=0xA4; break; case '.': c2=0xA3; break; case ':': c2=0xA7; break; case ';': c2=0xA8; break; case '(': c2=0xCA; break; case ')': c2=0xCB; break; case '?': c2=0xA9; break; case '!': c2=0xAA; break; default: break; } c1=0xA1; } nchar += (1-n); sbufprint(c1); sbufprint(c2); break; default: nchar++; /* ignore news head char '>' */ if (nchar==1 && c1==newshd && timestat) break; if (isprint(c1)) sbufprint(c1); break; } } if (j==2) { if (pausqm) switch((c1*256)+c2) { case 0xA1B0: case 0xA1B1: case 0xA1E5: case 0xA3B2: c1=0xA1; c2=0xB0+odd; odd=(odd)? 0:1; break; case 0xA3AE: c1=0xA1; c2=0xA3; break; default: break; } if (!ignorespace || ((c1*256)+c2)!=cspace) { sbufprint(c1); sbufprint(c2); } nchar+=2; } /* j=0, ignore */ break; } fnchar += (j-n); return n; } sbufprint(int c) { int j = -1; ignoreEOL=0; sbuf[sbufp++]=c; if (c==EOL) { j=sbufp; while(--j) if (sbuf[j-1] != ' ' && sbuf[j-1] != '\t') break; if (j != sbufp-1) { sbuf[j]=EOL; sbufp=j+1; } } if (sbufp>SBUFSIZE-1 || c==EOL) { for (j=0; j0)? sbuf[--sbufp] : getc(in); } sungetc(int c) { if (sbufp>=SBUFSIZE) fprintf(stderr, "sungetc: too many chars\n"); else sbuf[sbufp++]=c; return 1; } bell() { fprintf(stderr, "%c", 7); return 1; } int SkipESCSeq(in, c, state) FILE *in; int c, *state; { int temp = *state; if (c == '$' || c == '(') sgetc(in); *state = (c == 'K' || c == '$')? 1 : 0; return (temp == *state)? 0 : 1; } int DetectJPCodeType() { int c = 0, dct = ASCII; /* detected code type */ FILE *in; inf=Rinf; while ((in = inf->fp) != NULL) { while (dct==EUCORSJIS || dct==ASCII) { if ((c=sgetc(in)) == EOF) break; if (c==ESC) { if ((c=sgetc(in)) == '$') { c=sgetc(in); if (c=='B' || c=='@') dct=JIS; /* B: NEW, @: OLD */ } else if (c=='K') dct=JIS; /* NEC */ } else if ((c>=129 && c<=141) || (c>=143 && c<=159)) dct=SJIS; else if (c==SS2) { c=sgetc(in); if ((c>=64 && c<=126) || (c>=128 && c<=160) || (c>=224 && c<=252)) dct=SJIS; else if (c>=161 && c<=223) dct=EUCORSJIS; } else if (c>=161 && c<=223) { c=sgetc(in); if (c>=240 && c<=254) dct=EUC; else if (c >= 161 && c <= 223) dct = EUCORSJIS; else if (c >= 224 && c <= 239) { dct = EUCORSJIS; while (c >= 64 && c != EOF && dct == EUCORSJIS) { if (c >= 129) { if (c <= 141 || (c >= 143 && c <= 159)) dct = SJIS; else if (c >= 253 && c <= 254) dct = EUC; } c = sgetc(in); } } else if (c <= 159) dct = SJIS; } else if (c >= 240 && c <= 254) dct = EUC; else if (c >= 224 && c <= 239) { c = sgetc(in); if ((c >= 64 && c <= 126) || (c >= 128 && c <= 160)) dct = SJIS; else if (c >= 253 && c <= 254) dct = EUC; else if (c >= 161 && c <= 252) dct = EUCORSJIS; } } rewind(in); if ((inf=inf->p) == NULL) break; } inf=Rinf; return dct; } void han2zen(in, p1, p2, codein) FILE *in; int *p1, *p2, codein; { int tmp = *p1, junk, maru = 0, nigori = 0; static int mtable[][2] = { {129,66},{129,117},{129,118},{129,65},{129,69},{131,146},{131,64}, {131,66},{131,68},{131,70},{131,72},{131,131},{131,133},{131,135}, {131,98},{129,91},{131,65},{131,67},{131,69},{131,71},{131,73}, {131,74},{131,76},{131,78},{131,80},{131,82},{131,84},{131,86}, {131,88},{131,90},{131,92},{131,94},{131,96},{131,99},{131,101}, {131,103},{131,105},{131,106},{131,107},{131,108},{131,109}, {131,110},{131,113},{131,116},{131,119},{131,122},{131,125}, {131,126},{131,128},{131,129},{131,130},{131,132},{131,134}, {131,136},{131,137},{131,138},{131,139},{131,140},{131,141}, {131,143},{131,147},{129,74},{129,75} }; if (codein == SJIS) { *p2 = sgetc(in); if (*p2 == 222) { if (ISNIGORI(*p1)) nigori = 1; else sungetc(*p2); } else if (*p2 == 223) { if (ISMARU(*p1)) maru = 1; else sungetc(*p2); } else sungetc(*p2); } else if (codein == EUC) { junk = sgetc(in); if (junk == SS2) { *p2 = sgetc(in); if (*p2 == 222) { if (ISNIGORI(*p1)) nigori = 1; else { sungetc(*p2); sungetc(junk); } } else if (*p2 == 223) { if (ISMARU(*p1)) maru = 1; else { sungetc(*p2); sungetc(junk); } } else { sungetc(*p2); sungetc(junk); } } else sungetc(junk); } if (*p1 >= 161 && *p1 <= 223) { *p1 = mtable[tmp - 161][0]; *p2 = mtable[tmp - 161][1]; } if (nigori) { if ((*p2>=74 && *p2<=103) || (*p2>=110 && *p2<=122)) (*p2)++; else if (*p1 == 131 && *p2 == 69) *p2 = 148; } else if (maru && *p2 >= 110 && *p2 <= 122) *p2 += 2; } void sjis2jis(p1, p2) int *p1, *p2; { unsigned char c1, c2; int adjust, rowOffset, cellOffset; c1 = *p1; c2 = *p2; adjust = c2 < 159; rowOffset = c1 < 160 ? 112 : 176; cellOffset = adjust ? (c2 > 127 ? 32 : 31) : 126; *p1 = ((c1 - rowOffset) << 1) - adjust; *p2 -= cellOffset; } void shift2seven(in, ki, ko) FILE *in; char *ki, *ko; { int p1, p2, state = OUT; while ((p1 = sgetc(in)) != EOF) { if (p1 == EOL || p1 == CR) { if (state==IN) { state = OUT; fprintf(out, "%c%s", ESC, ko); } fprintf(out, "%c", p1); } else if (SJIS1(p1)) { p2 = sgetc(in); if (SJIS2(p2)) { sjis2jis(&p1, &p2); if (state==OUT) { state=IN; fprintf(out, "%c%s", ESC, ki); } } fprintf(out, "%c%c", p1, p2); } else if (HANKATA(p1)) { han2zen(in, &p1, &p2, SJIS); sjis2jis(&p1, &p2); if (state==OUT) { state=IN; fprintf(out, "%c%s", ESC, ki); } fprintf(out, "%c%c", p1, p2); } else { if (state==IN) { state = OUT; fprintf(out, "%c%s", ESC, ko); } fprintf(out, "%c", p1); } } if (state==IN) fprintf(out, "%c%s", ESC, ko); } void euc2seven(in, ki, ko) FILE *in; char *ki, *ko; { int p1, p2, state = OUT; while ((p1 = sgetc(in)) != EOF) { if (p1 == EOL || p1 == CR) { if (state==IN) { state = OUT; fprintf(out, "%c%s", ESC, ko); } fprintf(out,"%c",p1); } else { if (ISEUC(p1)) { p2 = sgetc(in); if (ISEUC(p2)) { p1 -= 128; p2 -= 128; if (state==OUT) { state=IN; fprintf(out, "%c%s", ESC, ki); } } fprintf(out, "%c%c", p1, p2); } else if (p1 == SS2) { p2 = sgetc(in); if (HANKATA(p2)) { p1 = p2; han2zen(in, &p1, &p2, EUC); sjis2jis(&p1, &p2); if (state==OUT) { state=IN; fprintf(out, "%c%s", ESC, ki); } } fprintf(out, "%c%c", p1, p2); } else { if (state==IN) { state = OUT; fprintf(out, "%c%s", ESC, ko); } fprintf(out, "%c", p1); } } } if (state==IN) fprintf(out, "%c%s", ESC, ko); } void seven2seven(in, ki, ko) FILE *in; char *ki, *ko; { int temp, p1, p2, change, state = OUT; while ((p1 = sgetc(in)) != EOF) { if (p1 == ESC) { temp = sgetc(in); change = SkipESCSeq(in, temp, &state); if (change) fprintf(out, "%c%s", ESC, (state==IN)? ki : ko); } else if (p1 == EOL || p1 == CR) { if (state==IN) { state = OUT; fprintf(out, "%c%s", ESC, ko); } fprintf(out, "%c", p1); } else { if (state==IN) { p2 = sgetc(in); fprintf(out, "%c%c", p1, p2); } else fprintf(out, "%c", p1); } } if (state==IN) fprintf(out, "%c%s", ESC, ko); } void jispreproc() /* convert to 7-bit, then to 8-bit */ { if (code==UNKNOWN || (code==JIS && defcode!=JIS)) { code = DetectJPCodeType(); if (!mute) fprintf(errout, "Detected input code: %s\n", codename[code]); } switch (code) { case EUCORSJIS : if (!mute) { fprintf(stderr, "Treat as Shift-JIS, OK ? (Y/N)\n"); bell(); if (yes(0)) code=SJIS; else exit(0); } else code=SJIS; break; case ASCII : if (mute) { break; } fprintf(errout, "Might be damaged New- or Old-JIS, repair? (Y/N)\n"); bell(); if (yes(1)) { convcode=JISRP; convers(0); fprintf(errout, "Repaired version saved: %s\n", Rinf->s); } else return; break; default: break; } /* convert to 7-bit JIS according to input code type */ convcode=JISCVT; convers(0); /* convert to 8-bit for unified GB/B5/JIS/KSC processing */ nHzline = CheckLineLen(); convcode=JIS8; convers(0); } void kscpreproc() { ; } void gbb5preproc() { int dct=UNKNOWN; if (code==UNKNOWN || (code==GB && defcode!=GB)) { dct = DetectCNCodeType(); if (!mute) fprintf(errout, "Detected input code: %s\n", codename[dct]); } else dct=code; switch (dct) { case UNKNOWN: break; case GB: break; case GBORB5: if (dct==code) break; else if (mute) code=defcode; else if (code==GB || defcode==GB) { fprintf(errout, "Treat as GB\n"); code=GB; } else { fprintf(stderr, "Please supply code type at command-line.\n"); cleanup(1); exit(0); } break; case B5: if (defcode!=B5 && code!=B5 && !mute) { fprintf(stderr, "Is that right (Y/N)?\n"); bell(); if (yes(1)) code=dct; else if (code==UNKNOWN) { fprintf(stderr, "Please supply code type at command-line.\n"); cleanup(1); exit(0); } } else if (code==UNKNOWN) code=dct; break; case ZW: case HZ: case CNS: if (mute) code=dct; else if (dct != code) { fprintf(stderr, "Is that right (Y/N)?\n"); bell(); if (yes(1)) code=dct; else fprintf(errout, "Treat as %s\n", codename[(code==UNKNOWN)? (code=defcode) : code]); } else if (code==UNKNOWN) code=dct; if (code==CNS) convcode=CNSB5; else convcode=(code==ZW)? ZWGB : HZGB; break; case ASCII: code = defcode; break; default: exit(0); break; } switch(code) { case GB: case HZ: case ZW: if (lcode!=GB) init(999, NULL); break; case B5: case CNS: if (lcode!=B5) init(999, NULL); break; default: break; } if (convcode) { nHzline = CheckLineLen(); convers(0); } } int DetectCNCodeType() { int c = 0, n=0, dct = ASCII; /* detected code type */ FILE *in; inf=Rinf; while ((in = inf->fp) != NULL) { while (dct==ASCII || dct==GBORB5) { if ((c=fgetc(in)) == EOF) break; else if (c==ESC) { n++; if ((c=sgetc(in)) == '$') { n++; if ((c=sgetc(in)) == 'C') { c=sgetc(in); if (c=='G' || c=='H') dct=CNS; } } } else if (c>=0xA1) { c = fgetc(in); if (c>=0x40 && c<=0x7E) dct=B5; else if (c>=0xA1) dct=GBORB5; else sungetc(c); /* bad codes */ n+=2; } else if (c == '~') { c = fgetc(in); if (c=='{' || c=='}') dct=HZ; n+=2; } else if (c=='z' && n==0) { c = fgetc(in); if (c=='W') dct=ZW; n+=2; } else if (c==EOL) n=0; } rewind(in); if ((inf=inf->p) == NULL) break; } inf=Rinf; return dct; } unicodepreproc() { if (code==UNKNOWN) code=lcode; if (code>UTF) { /* not 2-byte unicode */ convcode = (code==UTF8)? UTF8TOUNI : UTF7TOUNI; convers(0); } return 1; } long utf_getc(fp) /* utf8 to 2-byte unicode */ FILE *fp; { int c, extras; long wc; unsigned bit; if ((c = getc(fp)) == EOF) return EOF; if ((c & 0x80) == 0) /* ASCII character */ return c; if ((c & 0xc0) == 0x80) /* unexpected tail character */ return CODE_ERROR; /* how many extra bytes? */ extras = 1; for (bit = 0x20; (c & bit) != 0; bit >>= 1) extras++; if (extras > 5) return CODE_ERROR; /* put all the bits together */ wc = c & (bit-1); while (extras-- > 0) { if ((c = getc(fp)) == EOF) return EOF; if ((c & 0xc0) != 0x80) { /* unexpected head character */ ungetc(c, fp); return CODE_ERROR; } wc = (wc<<6) | (c&0x3f); } return wc; } static void invert() { int i; unsigned char *s; utf_initzd = IN; for (i = 0; i < NUMBYTES; i++) char_type[i] = 0; for (s = base64; *s != '\0'; s++) { char_type[*s] |= BASE64; inv_base64[*s] = s - base64; } for (s = safe; *s != '\0'; s++) char_type[*s] |= SAFE; for (s = optional; *s != '\0'; s++) char_type[*s] |= OPTIONAL; for (s = space; *s != '\0'; s++) char_type[*s] |= SPACE; } long utf7_getc(fp) /* utf7 to 2-byte unicode */ FILE *fp; { int c; if (! utf_initzd) invert(); for (;;) { if ((c = getc(fp)) == EOF) return EOF; if (! in_base64) { if (c != '+') return c; if ((c = getc(fp)) == EOF) return EOF; if (c == '-') return '+'; in_base64 = IN; nbits = 0; } /* now we're in Base64 mode */ while (char_type[c]&BASE64) { bit_buffer <<= 6; bit_buffer |= inv_base64[c]; nbits += 6; if (nbits >= 16) { nbits -= 16; return ((bit_buffer >> nbits)&0xffffL); } if ((c = getc(fp)) == EOF) return EOF; } in_base64 = OUT; if (c != '-') return c; } } getroot() { char *s, *t; int n, c = ':'; /* unix */ struct Roots *rt; /*char defpath[50];*/ #ifdef VMS c = ','; #endif root = (struct Roots *) calloc(1, sizeof(struct Roots)); if (root == NULL) MemExit(); rt = root; root->p = NULL; root->s=NULL; s=getenv("HBFPATH"); /* fprintf(errout, "s=.%s.\n", s); */ /* if (s==NULL) { defpath[0]='\0'; #ifdef unix strcpy(defpath, "/usr/local/src/cnprint"); #endif s=defpath; } */ do { if (root->s!=NULL && rt->p==NULL) { rt->p = (struct Roots *) calloc(1, sizeof(struct Roots)); if (rt->p==NULL) MemExit(); rt = rt->p; rt->p = NULL; } if (s!=NULL) t = strchr(s, c); else t = NULL; if (t!=NULL) n = (int) (t-s); else n = (s==NULL)? 0 : strlen(s); if ( (rt->s = (char *) calloc(n+2, sizeof(char))) == NULL) MemExit(); if (n) { strncpy (rt->s, s, n); s += n; if (t!=NULL) s++; #ifdef unix if (rt->s[n-1] != '/') strcat(rt->s, "/"); #endif } else { (rt->s)[0] = '\0'; s=NULL; } /* fprintf(errout, "s=.%s. .%s.\n", s, rt->s);*/ } while (s!=NULL); /* rt=root; do { fprintf(errout, "rt->s: .%s.\n", rt->s); if (rt!=NULL) rt = rt->p; } while (rt!=NULL); */ return 1; } void FName(char *s, char *t) /** compose a file name based on *s with surfix *t **/ { int j, k; #ifdef VMS j=strlen(s); while (s[j]!=';' && j) j--; if (j>1) s[j]='\0'; #endif strcat(s, t); } RE_name(char *old, char *new) { char p[100]; #ifdef unix # ifdef MUSER sprintf(p, "cp %s %s", old, new); system(p); remove(old); # else sprintf(p, "mv %s %s", old, new); system(p); # endif #else if (rename(old, new)!=0) { sprintf(p, "copy %s %s", old, new); system(p); remove(old); } #endif return 0; } tobooklet() { int j, k, xpos[17]; int Nppg; /* physical pages */ int npg; /* nominal page number */ long filepos; FILE *in; if (!mute) fprintf(errout, "Convert PS file to booklet format...\n"); Nppg = (pgpd+2*booklet-1)/(booklet*2); Nppg *= 2; /* positions of each page on a physical page (sheet of paper) */ for (j=1; j<=booklet/2; j++) { /* booklet must be even number */ xpos[j] = xpos[j+3*booklet/2] = Xa*j + RM*(j-1); xpos[j+booklet/2] = xpos[j+booklet] = Xa*(j+1+booklet/2) + RM*(j+booklet/2-1); } FName(Rinf->s, "bk"); RE_name(tempfile, Rinf->s); opnfile(IN); opnfile(OUT); in=Rinf->fp; copypage(0, 0, 1, in, &filepos); /* copy header */ for (j=1; j<=Nppg; j++) { for (k=booklet; k>=1; k--) { if (k <= booklet/2) npg = (Nppg*booklet - (j-1)*booklet/2) - (booklet/2-k); else npg = (j-1)*booklet/2 + (k-booklet/2); if (k==booklet) fprintf(out, "\n%%%%Page: %d %d\nCN31Dict begin\n", j, npg); if (npg<=pgpd) copypage(npg, xpos[k + booklet*((j+1)%2)], 0, in, &filepos); if (k==1) fprintf(out, "SP end %% CN31Dict\n"); } fprintf(errout, (j%5 == 0 || j==Nppg)? "%5d\n" : "%5d", j); } trailer(Nppg); remove(Rinf->s); if (ferror(out)) { fprintf(stderr, "WARNING: PS file %s write error, possibly out of memory.\n", tempfile); bell(); exit(-5); } fclose(out); outputToDev(); return 1; } copypage(npg, xp, ht, in, pfilepos) long *pfilepos; /* copy selected page to output, for booklet */ int npg, xp, ht; /* xp: x-position; ht: -1 trailer; 1, header */ FILE *in; { int j, k, Prntpage=0; char cst[256]; if (npg > 0) fseek(in, *pfilepos, 0); if (ht==1) Prntpage=2; /* ht==1, copy header */ while (fgets(cst, 255, in)!=NULL) { if (Prntpage>=2) { if (strncmp(cst, "EP", 2)==0) { fprintf(out, "EP\n"); break; } else fprintf(out, "%s", cst); if (npg<=0) { if (strncmp(cst, "%%EndSetup", 10)==0) { *pfilepos = ftell(in); break; } } } else if (Prntpage) { if (strncmp(cst, "BP", 2)==0) { /* BP -2550 LRT 180 186 translate */ sscanf(cst, "%*s%d%*s%*d%d", &j, &k); fprintf(out, "BP %d LRT %d %d translate\n", j, xp, k); Prntpage++; } } else if (strncmp(cst, "%%Page:", 7)==0) { /* Prntpage=0; */ sscanf(cst, "%*s%d%d", &k, &j); if (j==npg) { Prntpage=1; fprintf(out, "%%face page: %d %d\n", k, npg); continue; } } } return 1; } #ifdef PSPRINT toshortline(FILE *in) /* break long lines to short ones: some printer has problem with long lines */ { int c; int hexd=0; /* # of continuous Hexidecimal digits */ int comment=0; /* PS comment lines */ int bop=0; /* 1: (; 0: ) */ int charcount=0; while ( (c=fgetc(in)) != EOF) { if (c=='(') bop=1; else if (c==')') bop=0; if (c==LF || c==CR) { c=getc(in); if (c!=LF && c!=EOF) ungetc(c, in); charcount=0; comment=hexd=0; fputc(EOL, out); } else if (c=='\\') { c=getc(in); if (charcount > MAXLENGTH-6 && c!=EOL) { if (bop) fputc('\\', out); fputc(EOL, out); if (comment) fputc('%', out); charcount=0; hexd=0; } fputc('\\', out); fputc(c, out); if (c==EOL) { charcount=comment=0; c=getc(in); if (c==EOL) ; else ungetc(c, in); } } else if (charcount>MAXLENGTH && (isbreaka(c) || isbreakb(c))) { if (isbreakb(c)) fputc(c, out); /* if inside a char string, add line-continuation mark */ if (bop) fputc('\\', out); fputc(EOL, out); if (comment) fputc('%', out); if (isbreaka(c)) fputc(c, out); charcount=1; hexd=0; } else if (charcount>MAXLENGTHA && c=='/' && !bop) { /* not inside () */ fputc(EOL, out); if (comment) fputc('%', out); fputc(c, out); charcount=1; hexd=0; } else if (charcount>MAXLENGTHB) { if (hexd==0 || hexd==10) { /* line-continuation */ if(hexd==0) fputc('\\', out); fputc(EOL, out); if (comment) fputc('%', out); charcount=0; hexd=0; } if (isxdigit(c)) hexd++; else hexd=0; charcount++; fputc(c, out); } else { if (c=='%' && !bop) comment++; fputc(c, out); charcount++; if (isxdigit(c)) hexd++; else hexd=0; if (hexd==78) { fputc(EOL, out); if (comment) fputc('%', out); charcount=hexd=0; } } } } #endif /* PSPRINT */ #ifdef PSPRINT pageprint(FILE *in) /* print selected pages, must be DSC conforming, no error checking. * by standard, EPS file must be bracketed with %%BeginDocument %%EndDocument * pair. Ignore the "##Page: " comments in EPS file. * Note: it does not adjust the page numbers and # of pages. */ { int j, npg=0, EPSlevel=0; char cst[256]; int Prntpage=1; while (fgets(cst, 255, in)!=NULL) { if (EPSlevel) { if (strncmp(cst, "%%EndDocument", 13)==0) EPSlevel--; } else if (strncmp(cst, "%%BeginDocument", 15)==0) { EPSlevel++; } else if (strncmp(cst, "%%Page:", 7)==0) { sscanf(cst, "%*s%*s%d", &j); if (j>npg) npg=j; if (npg>0) { if (npg>=bp && (ep==0 || npg<=ep)) { if (odd==0 || ((odd%2)==(npg%2))) Prntpage=1; else Prntpage=0; } else Prntpage=0; } if (Prntpage) fprintf(stderr, "%s\tYES\n", cst); } else if (strncmp(cst, "%%Trailer", 9)==0) { Prntpage=1; } if (Prntpage) fprintf(out, "%s", cst); } } #endif /* PSPRINT */ /* for decoding of mime quoted printable */ int hex(int x) { return (isdigit(x)? (x-'0') : (islower(x) ? (x-'a'+10):(x-'A'+10)) ); } void mimeqpdecode(FILE *in) { int c1, c2; sbufp=0; while ((c1=sgetc(in)) != EOF) { if (c1 != '=') fputc(c1, out); else { c1 = sgetc(in); c2 = sgetc(in); if (c1==CR || c1==LF) { if (c1==LF || (c1==CR && c2 != LF)) sungetc(c2); continue; } else if (!isxdigit(c1) || !isxdigit(c2)) { sungetc(c2); sungetc(c1); fputc('=', out); continue; } fputc(hex(c1)*16+hex(c2), out); } } } /* end of MIME handling */ int strfilecmp(char *s, FILE *fp) /* if EQ, eat the str, otherwise, use sungetc() */ { int c, j, len; len = strlen(s); j = 0; while (j < len && (c=sgetc(fp)) != EOF) { if (c == s[j]) j++; else { sungetc(c); while (--j >= 0) sungetc(s[j]); break; } } return (j==len)? 0:1; /* like strcmp(), EQ=0 */ } void addLBAS(FILE *in) { int j, nlbas=0, c1, c2; unsigned char *lbas; lbas = (unsigned char *) calloc(LBASMAX, sizeof(char)); if (lbas==NULL) MemExit(0); sbufp=0; while ((c1=sgetc(in)) != EOF) { if (c1=='@' && strfilecmp("[LBAS]", in)==EQ) break; else fputc(c1, out); } while ((c1=sgetc(in)) != EOF) { if (c1 == '@' && strfilecmp("[LB", in)==EQ) { sungetc('B'); sungetc('L'); sungetc('['); sungetc(c1); break; } else lbas[nlbas++] = c1; } lbas[nlbas]='\0'; while ((c1=sgetc(in)) != EOF) { fputc(c1, out); if (c1 == '@' && strfilecmp("[LB", in)==EQ) { fprintf(out, "%s", "[LB"); fputc(c1=sgetc(in), out); j=0; if (c1==']') j=nlbas; else if (isdigit(c1)) { fputc(c2=sgetc(in), out); if (isdigit(c2)) { fputc(c1=sgetc(in), out); if (c1==']') j=nlbas; } } if (j==nlbas) for (j=0; j