/* ************************************************** * CNPRINT.C For CNPRINT Version 3.30b (VMS & UNIX) * * ************************************************** Copyright YIDAO CAI (~{2LR@5@~}), 1992-2001 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, UTF16, UTF8 and UTF7 are supported. *** PLEASE read CNPRINT.HELP first EVEN if you have used CNPRINT before *** YIDAO CAI cai@neurophys.wisc.edu MAY-11-2001 **************************************************** */ /*#define STAT*/ /*#define CNS_SUPPORT*/ #define PSPRINT #define TIME #ifdef VMS #else # ifdef unix /* */ # else # define unix # endif /* for multi-users on unix */ # define MUSER #endif #include #include #include #include #include #ifdef MUSER #include #endif #define GBstr "_gb" #define B5str "_b5" #define PSstr "_ps" #define HZstr "_hz" #define JISstr "_jis" #define Version "CNPRINT V3.30b (VMS & UNIX) MAY-11-2001" #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 #define RINIT 999 /* re-init */ /* 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 /* 2-byte unicode, also UTF16BE */ #define UTF7 18 /* 7-bit unicode */ #define UTF8 19 /* 8-bit unicode */ #define UTF16 20 /* 16-bit unicode, particularly 16LE */ 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", "UTF16LE", "", ""}; /* conversion codes */ #define HZGB 1 #define GBHZ 2 #define FILT 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 /* convert to escaped 2-byte */ #define UTF8TOUNI 12 #define UTF16BETOUNI 13 #define UTF16LETOUNI 14 #define CNSB5 15 /* CNS planes 1/2 to Big5 */ #define GBB5 16 /* GB to B5 */ #define HZB5 17 #define B5GB 18 #define B5HZ 19 #define TOSHORTPS 20 #define PAGEPRINT 21 #define MIMEQP 22 /* decoding mime quoted printable */ #define MIME64 23 /* decoding mime base64 */ #define ADDLBAS 24 /* filter input file, add sender's address */ #define UNIGB 25 /* unicode to GB */ #define UNIB5 26 #define UNIKSC 27 #define UNIJIS 28 #define UTF8CJK 29 /* unicode type to CJK */ #define UTF7CJK 30 #define UTF16CJK 31 /* BE */ #define UTF16LECJK 32 #define GBUNI 33 /* GB to unicode */ #define B5UNI 34 #define KSCUNI 35 #define JISUNI 36 #define CJKUTF8 37 /* CJK to unicode type */ #define CJKUTF7 38 #define CJKUTF16 39 /* BE */ #define CJKUTF16LE 40 #define STATS 41 /* statistics output */ #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 int LM, RM, TM, BM, CSP, CLP, CIP, H, V; int indentL=0, indentR=0; /* left or right indent in dots */ 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], EPSHDfile[80], KWfile[80], G2Bfileb[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 input_file_layer=0; /* control deletion of intermediate files */ 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 */ /* gray level: 0=black, 1=white; by default, use color mode if rgb>0 */ struct ColorGrayStr { float gray, red, green, blue; } color; int linewidth=1, deflinewidth=1; 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 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 tabascii=0; /* set tab width according to CH (0) or ASCII(1) default 0 (1 if ASCII file selected) */ /* mode for printing address labels */ #define LBASMAX 512 /* max # of chars for sender's address */ int addrlabel=0; int lbn=0, lbnx=2, lbny=5; int lb_eat_EOL=1; /* EOL after @[LBAS], @[LB] or @[LB##] is ignored */ float lbxp=.5, lbyp=1.0, lbxinc=4.25, lbyinc=2.0; void addLBAS(FILE *); /* 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; int euro=0; /* European chars, def: auto-detect; -1, disable */ float Wasc[129]; /* width of ASC char re Courier */ char **EFontnames, **EFmetricfiles; int nEFmax=40, nEFfamily=10; /* default in old version */ char *zerolenstr=""; 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"}; void getEfontdata(int); int getEfontlist(void); int isASCfont(char *); /* for search */ #define MAXLINES 350 /* max # of lines, affect multiple column options */ #define ASCBUFSIZE 300 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]; struct {unsigned char s[ASCBUFSIZE]; int p, pp, Hp;} ascbuf; /* for efficient multiple font/language handling */ int PreScanMode=1; struct FontTag { char FontName[100]; /* 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, *CurrentFont; unsigned int *fstring, *fdict, nchar; unsigned int cspace, b1l, b2l; /* space char, lowerest byte-1(2) */ unsigned int b2h_range1, b2gap, b2span; unsigned char **ptstring, *array; /* 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 */ int HBFopen(void); void HBFclose(void); int HBFgetBitmap(unsigned int); 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; int UnicodeTTF=0; /* can be used by all lcode through mapping */ unsigned short **UNItablemap; void loadUNImappingtable(int, int); void mapToUnicode(unsigned char *, unsigned char *); /* defined in ttfb.c */ void TTFclose(FILE *); void TTFgen_PSproc(FILE *, unsigned int, unsigned int); /* 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 or CJK */ 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; /* should use chars that are rarely used (control chars) and not the high-byte of CJK */ #define U2ESC 0x28 /* ESCs for 2-byte unicode */ #define U2ESC2 0x29 /* 0x2828 = 0x28, 0x2829 () = 0x00 */ #define isUnicodeASCII(c1, c2) ((c1) == 0x00 && (c2) <= 0x7E) void unicodepreproc(void); int DetectUnicodeType(void); void to2byte_unicode(FILE *); void u2byte(int); void utf16to2byte_unicode(FILE *); void unicode2cjk(FILE *); void unicode2cjk16(FILE *); void cjk2unicode(FILE *); long utf16_getc(FILE *);/* utf16 to 2-byte unicode (escaped) */ long utf8_getc(FILE *); /* utf8 to 2-byte unicode */ long utf7_getc(FILE *); /* utf7 to 2-byte unicode */ static void invert(void); int unicode_isfs(unsigned char *, int); /* -----------------------------*/ void RegisterFont(void); void UnRegisterFont(struct FontTag *); int columnWidth(void); void charsize(float); float getnew(float, int); void newline(int, int); void endpage(int); void outputToStdout(char *); void outputToDev(void); void trailer(int); void pagesetup(void); void putnpagetime(void); void header(void); void putBitmap(unsigned char *); void putBitmap85(unsigned char *, int); void PSctrl(void); void CNdict(int, int); unsigned int Addr(int, int); /* char level handling --- page layout related */ int isrlasc(int); int isrlch(unsigned char, unsigned char); unsigned char tovhb5(unsigned char); int vchange(unsigned char *, unsigned char *); int rtch(unsigned char, unsigned char); int isfs(unsigned char *, int); int issfs(unsigned char, unsigned char, unsigned char); int putASC(int, int, int); int putCH(unsigned char, unsigned char, int); void shade(void); void underline(void); void endAC(int); void clearascbuf(int, int); int span(int); int CheckLineLen(void); /* stat */ int charstat=1; /* char/word statistics */ void statistics(unsigned int, unsigned int); extern void statinit(void); void stat_prescan(void); void wordstat(unsigned int); /* non-printing related */ void CharBMPshift(void); /* bitmap shift for char */ int CharBitmapShift(FILE *, long, unsigned char *); void Addchar(int, int); void sbufprint(int); void convertEOL(unsigned char *, int *); void GetCharUsage(void); int print_range_check(int); void set_doc_defaults(void); void style(int); int filter(unsigned char, unsigned char, unsigned char *, int); int OIOU(int); unsigned char *doAC(unsigned char *, int); unsigned char *doAC_unicode(unsigned char *, int); /* code detection, conversion, etc */ int convt_and_print=0; void CodeConversion(void); void convers(int); void nullfilter(FILE *); /* JIS-related */ #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)) void jispreproc(void); /* convert to 7-bit, then to 8-bit */ void jis2jis8(FILE *); /* 0x21-0x7E --> 0xA1-0xFE */ int SkipESCSeq(FILE *, int, int *); int DetectJPCodeType(void); void han2zen(FILE *, int *, int *, int); void sjis2jis(int *, int *); void shift2seven(FILE *, char *, char *); void euc2seven(FILE *, char *, char *); void seven2seven(FILE *, char *, char *); void jisrepair(void); /* KSC */ void kscpreproc(void); /* GB/HZ, B5 */ #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 */ unsigned int *gbb5_fstr; unsigned char **gbb5_ptstr; void gbb5preproc(void); int DetectCNCodeType(void); void hz2gb(FILE *); void gb2hz(FILE *); void zw2gb(FILE *); void cns2b5(FILE *, FILE *); void gbb5convinit(int); void gbb5conv(FILE *, int); void gbb5tableinit(int, FILE *); /* MIME type */ int mimeqp_hex(int); int DetectMIMEType(void); void mimeqpdecode(FILE *); /* general, init, file handling, time, etc */ void opnfile(int); FILE *Rfopen(char *, char *); int sgetc(FILE *); int sungetc(int); void bell(void); void signature(void); void usage(int); void MemExit(void); void getroot(void); void FName(char *, char *); void RE_name(char *, char *); int yes(int); void cleanup(int); void init(int, char **); char *readstr(char **v, char *s); float readfv(char **v, char *s); int isstr(char *s, char **v); int num(char **v, int n); int getdata(int); void header(void), PSctrl(void); void charsize(float); void endpage(int); void putBitmap(unsigned char *); /* ============================= */ /* functions */ float hex2float1(char, char); int int3pts2dot(unsigned char *); void insertEOL(void); int IncludeEPS(char *); char *gets_stdin(char *, int); void pageprint(FILE *); int copypage(int, int, int, FILE *, long *); int strfilecmp(char *, FILE *); void RegisterFont(void); void tobooklet(void); void toshortline(FILE *); 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 */ void cns2b5(FILE *in, FILE *out) /* 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"); } #endif /* CNS support */ char *gets_stdin(char *s, int n) { int k; fgets(s, n, stdin); k = strlen(s); if (s[k-1]=='\n') s[k-1] = '\0'; return s; } void insertEOL() /* print an EOL, to put message between page numbers */ { if (extraEOL) fputc('\n', errout); extraEOL = 0; } int IncludeEPS(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_stdin(feps, 79); } 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" **** */ FontCa=0.; /* reset font-specific parameters */ FontptsScale=1.; while (fgets(cst, 119, HBF) != NULL) { if (strncmp(cst, "COMMENT", 7) == EQ) continue; else 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; if ( (fpTTF=TTFopen_init(TTFfile)) == NULL) { ttf_font = 0; if (*defHBFname==0) exit(-3); else return 0; } /* 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 requires PostScript language level 2, this PS file may not work.\n\ Please use -level option on command line\n"); } RegisterFont(); if (UnicodeTTF && lcode != UTF) loadUNImappingtable(lcode, 1); return 1; } /* else: YES, found HBF */ break; } /* 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; if (UnicodeTTF && lcode != UTF) { for (j=0; j<=0xFF-b1l; j++) free(UNItablemap[j]); free(UNItablemap); UnicodeTTF=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(char **v, char *s) { v[0]++; sscanf(*v, "%s", s); v[0] += (strlen(s)-1); return s; } float readfv(char **v, char *s) { float x; sscanf(readstr(v, s), "%f", &x); return x; } int initinputfile(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) + 10, 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) + 20, 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]; int m, j=0, ASCfile=0; float ptscmd, Cxcmd, Cycmd, Cicmd, Cacmd, Casccmd; float rmcmd, lmcmd, tmcmd, bmcmd; int columncmd=0, eurocmd=0, fputnpagecmd = -2; int papersize=UNKNOWN; if (argc==RINIT) goto B5INIT; prntcmd[0]='\0'; EPSHDfile[0]='\0'; KWfile[0]='\0'; tempfile[0]='\0'; *HBFname=0; *defHBFname=0; *PSfile=0; *G2Bfileb=0; Fonts=NULL; errout = stderr; ptscmd=Cxcmd=Cycmd=0.; Cicmd=Cacmd=Casccmd=0.; rmcmd=lmcmd=tmcmd=bmcmd=0.; color.gray = color.red = color.green = color.blue = 0.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("b52uni", v)) convcode=B5UNI; 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 = (int) 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("envs", v)) { envelope = 2; /* small size */ Casccmd = 0.6; } else if (isstr("env", v)) { envelope = 1; Casccmd = 0.6; } else if (isstr("epsheader=", v)) { strcpy(EPSHDfile, readstr(v, cst)); IncEPS=1; } 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("gb2uni", v)) convcode=GBUNI; 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("jis2uni", v)) convcode=JISUNI; else if (isstr("jis", v)) code=JIS; else AdjAtEndDoc=0; break; case 'k': if (isstr("ksc2uni", v)) convcode=KSCUNI; else if (isstr("ksc", v)) code=KSC; else if (isstr("keeptempfile", v)) input_file_layer = -99; 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)) { if ((m=num(v, 3)) > 0) addrlabel=m; else 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<=6000) 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': if (isstr("print", v)) { convt_and_print=1; break; } 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=FILT; 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 = (int) 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("utf16le", v)) code=UTF16; else if (isstr("utf16", v)) code=UTF; else if (isstr("utf", v)) code=UTF; else if (isstr("uni2gb", v)) convcode=UNIGB; else if (isstr("uni2b5", v)) convcode=UNIB5; else if (isstr("uni2ksc", v)) convcode=UNIKSC; else if (isstr("uni2jis", v)) convcode=UNIJIS; 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!=RINIT) 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==RINIT) { lcode=UNKNOWN; UnRegisterFont(Fonts); HBFclose(); Fonts=NULL; /*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<=UTF16) lcode=UTF; else if (code==KSC || code==GBK || code==B5P) lcode=code; else lcode=defcode; /* else use default */ if ( (convcode==GBB5 || convcode==B5GB || convcode==HZB5) && convt_and_print) lcode=code= (convcode==B5GB)? GB:B5; 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==B5HZ) return; else if (convcode==UNIGB || convcode==UNIB5 || convcode==UNIKSC || convcode==UNIJIS) return; else if (convcode==GBUNI || convcode==B5UNI || convcode==KSCUNI || convcode==JISUNI) { if (code==defcode && code!=UTF) code=UTF; return; } else if ((convcode==GBB5 || convcode==B5GB || convcode==HZB5) && !convt_and_print) return; if (!HBFopen()) exit(0); /* if (lcode==KSC) adjust=0; */ if (argc==RINIT || 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 */ LM-=20; 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; /* 2.54 mm, 0.1 inch */ fputnpage=0; manualfeed++; Ci=.5; Casc=.6; if (nEF<0) nEF=3; column=lbnx; } 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=(int)(rmcmd*10); if (lmcmd>0.01) LM=(int)(lmcmd*10); if (tmcmd>0.01) TM=(int)(tmcmd*10); if (bmcmd>0.01) BM=(int)(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 */ if (!getEfontlist()) { EFontnames = EFname; EFmetricfiles = NULL; } nEFs = (int *) calloc(nEFmax+1, sizeof(int)); if (nEFs == NULL) MemExit(); getEfontdata(1); /* 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); } void 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(1, sizeof(struct FontTag)); 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 should be 0x01 or 0x00, not 0x30 */ b1l=0x00; b2l=0x00; b2h_range1=0xFF; nchar = (unsigned int) 61440; /* 240*256 */ 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; } void UnRegisterFont(struct FontTag *F) { int j; if (F==NULL) return ; UnRegisterFont(F->p); if (F->fdict != NULL) free(F->fdict); if (F->fstring != NULL) free(F->fstring); if (F->ptstring != NULL) { if (F->nchar > 0) for (j=0; j < F->nchar; j++) if (F->ptstring[j] != NULL && F->ptstring[j] != dummy) free(F->ptstring[j]); free(F->ptstring); } free(F); } int getdata(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(EFontnames[nEF])<=2) return 0; while (fgets(t, 98, cmd)!=NULL) { if (strncmp(EFontnames[nEF], t, strlen(EFontnames[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<=30) 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 = (int) (x1*10); RM = (int) (x2*10); TM = (int) (x3*10); BM = (int) (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 %d", &j, &k, &x1, &x2, &x3, &x4, &lb_eat_EOL); 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=UTF; 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, G2Bfileb); 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, k; 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 = (int) (XX*72/ppd); Yh = (int) (YY*72/ppd); pr = (int) (Xw*Ck); pb = (int) (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, EFontnames[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(EPSHDfile)? EPSHDfile : "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 = (int) (10.*(pb-bm-tm + (CLP-CIP)*Ck)/(CLP*Ck)); if (booklet) b = (int) (10.*(pr-rm*(column+2))/(CSP*Ck)/column); else { b = (int) (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_stdin(cst, 99); /*fprintf(stderr, "cst = :%s:\n", 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 = (int) 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_stdin(EPSHDfile, 79); fprintf(errout, "Page header on the first page (Y/N)?\n"); gets_stdin(s, 99); 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_stdin(s, 99); 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_stdin(s, 99); 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_stdin(s, 99); } 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_stdin(s, 99); 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", EFontnames[nEF]); for (j=0; j= 2) fprintf(errout, "%4d: %s\n", j, EFontnames[j]); fprintf(errout, "0-%d: Normal %d-%d: Oblique/Italic %d-%d: Bold %d-%d: Bold & Oblique\n", nEFfamily-1, nEFfamily, 2*nEFfamily-1, 2*nEFfamily, 3*nEFfamily-1, 3*nEFfamily, 4*nEFfamily-1); j = nEF; k = nEF = (int) getnew(nEF+0.1, 3); if (k==j) break; getEfontdata(0); /* fall back to original if selection not available */ if (nEF != k) { fprintf(errout, "Metric data not available for selected font, keep original font\n"); nEF = j; getEfontdata(0); } 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 = (int) (defpts+0.5); defCa=Ca; defCi=Ci; defcolumn=column; defCx=Cx; defCy=Cy; defnEF=nEF; cgap = (int) (gap/Ck); if (vgap==0) vgap = (int) (1.5*(CLP-CIP)); else vgap = (int) (vgap/ppd); if (booklet) { j = (int) ((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 = (int) ((pr/Ck-column*RM)/(column+2)); RM += LM; booklet = column; /* in case it is changed */ column = 1; } else { LM = (int) (lm/Ck); RM = (int) ((pr - rm)/Ck); } TM = (int) ((tm + os)/Ck); BM = (int) ((pb - bm - os)/Ck); BM = (BM - TM + (CLP-CIP) + CLP/2) / CLP * CLP + TM; x = (RM - LM - cgap*(column-1)) / (float) CSP / column; j = (int) x; if (column>1) { /* & not booklet */ if (x-j > 0.65) { x = (1 - x + j++) * CSP*column; RM += (int) (x*0.45); LM -= (int) (x*0.15); } else if ((x=(x-j)*CSP*column) > 0.3*cgap*(column-1)) { RM -= (int) (x*0.45); LM += (int) (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 += (int) (x*0.651); LM -= (int) (x*0.35); } else { x = (x - j) * CSP; RM -= (int) (x*0.65); LM += (int) (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=129) { fclose(fp); return; } } fclose(fp); } /* no metric file or data not complete, try "cnprint.cmd" */ if (!getdata(1)) nEF=2; } if ((nEF%nEFfamily)==2) for (j=0; j<129; j++) Wasc[j]=1.; if (nEF!=nEF0 && displaymessage) { insertEOL(); bell(); fprintf(errout, "No metric data available for selected font, use Courier\n"); } } int columnWidth() { /* int n; float x; if (column==1) return (RM-LM); x = (cgap)? cgap : (2.*pts*(Cw*Cx + (Ca+FontCa-1.)/25.)*25./24./ppd +.65); n = (RM-LM-x*(column-1))/column; return (ptspc==defptsi)? ((n/CSP)*CSP) : n; */ /* use doc default: do not use current char size based */ return (RM-LM-cgap*(column-1))/column; } void charsize(float x) { CSP = (int) (x*(Cw*Cx + (Ca+FontCa-1.)/25.)*25./24./ppd +.65); pts = CSP/((Cw*Cx + (Ca+FontCa-1.)/25.)*25./24./ppd); CLP = (int) (pts*(Cw*Cy - 1./25. + (1.0 - Cw + 1./25.)*Ci)*25./24./ppd); CIP = (int) (pts*Cw*Cy/ppd); /* an estimate */ } float getnew(float y, int n) { float x = -1.; char s[40]; fprintf(errout, " Please enter your desired value, or press RETURN to continue\n"); if (n==0) fprintf(errout, " ~~~~~~ ONLY VALUE IN --pts-- IS ACCEPTABLE ~~~~~~\n"); else if (n==1) fprintf(errout, " ~~~~~~ inch OR mm ~~~~~~\n"); gets_stdin(s, 39); if (s[0]=='\0') return y; sscanf(s,"%f",&x); if (x<=5. && n==1) x *= 25.4; /* 5mm < Margin <= 127 mm (5 in) */ if (n==0 && x<100. && x>=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= -1e-8) 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) { 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 + indentL; cnsp=0; spaceH = -1; return; } /* print */ /*ascbuf.p=0;*/ if (fshade) shade(); else endAC(pr); spaceH = -1; V += lineclp[++pline]; H = cLM + indentL; if (V > cBM+BMover || pline > sline) { /*pline--;*/ x = columnWidth(); if (++pcolumn <= column) { V = cTM + linecip[pline]; cLM=LM+(x+(RM-LM-x*column)/(column-1))*(pcolumn-1); H = cLM + indentL; } else if (V > BM+BMover) { endpage(0); V=cTM=TM; cLM=LM; H = cLM + indentL; 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]; 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_stdin(s, 79); } filecount++; if (!endDoc) { opnfile(OUT); header(); pgpd=0; } } else if (Prntpage) pagesetup(); } void 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); } } void 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_stdin(s, 79); } 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); } } void trailer(int Nppg) /* # of pages (booklet), use pgpd if 0 (regular) */ { int j; struct FontTag *F; fprintf(out, "%%%%Trailer\n"); if (!EPS) fprintf(out, "%%%%Pages: %d\n", (Nppg==0)? pgpd : Nppg); j=0; while (j0) { fprintf(out, "%%%%DocumentNeededResources: font %s\n", EFontnames[j-1]); break; } while (j0) fprintf(out, "%%%%+: font %s\n", EFontnames[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(EPSHDfile)) { if (pgcount==1 && !IncEPS) return; fprintf(out, "%d 0 Q\n", BM); IncludeEPS(EPSHDfile); } } void putnpagetime() { struct tm *time_str; int i=0, pnp, px, py, tx, ty; time_t time_val; char s1[120], s2[40]; 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)? (int) (RM+4.5*BSO) : (int) (LM-4*BSO); if (pnp==1 || pnp==4) { /* left */ py = (int) (BM-4*BSO); ty = (int) (TM + 4*BSO); } else if (pnp==2 || pnp==5) { /*middle */ ty = py = (int) ((BM-TM+3*BSO)/2); tx = (pnp<3)? (int) (RM+4.5*BSO) : (int) (LM-4*BSO); } else { /*right */ py = (int) (TM + 4*BSO); ty = (int) (BM - 4*BSO); } } else { py = ty = (pnp>3)? (int) (BM+4.5*BSO) : (int) (TM-4*BSO); if (pnp==1 || pnp==4) { /* left */ px = LM; tx = RM; } else if (pnp==2 || pnp==5) { /*middle */ tx = px = (int) ((RM-LM-3*BSO)/2); ty = (pnp<3)? (int) (BM+4.5*BSO) : (int) (TM-4*BSO); } else { /*right */ px = (int) (RM - 6*BSO); tx = LM; } } /* use document default font/size for page number */ i = (int) (0.8338*(defpts*Cw*defCx/ppd)*20.*Casc); fprintf(out, "/%s [%g 0 0 %d 0 0] SF\n", EFontnames[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 (timestat==1) return; #ifdef TIME time(&time_val); time_str = localtime(&time_val); strftime(s2, 39, "%a %d-%b-%Y %H:%M:%S %Z", time_str); for (i=0; i<40 && (s2[i]=toupper(s2[i])) != '\0'; i++) ; if (timestat != 2) strcpy(s1, "CNPRINT"); else { char *fns; fns = (inf==Rinf)? inf->t : inf->s; if (strlen(fns) <= 119) strcpy(s1, fns); else strncpy(s1, fns, 119); } s1[119]=s2[39]='\0'; i = (int) ((strlen(s1)+strlen(s2))*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) S grestore\n" : "/Courier %d SF %d %d Qa (%s %s) S\n", (int) (6./ppd), BM-ty, tx, s1, s2); #endif } void header() { int j, n, urx, ury; time_t time_val; 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 = (int) ((Yh-(Ya+BM+2*CLP))*ppd); if (j<=0) j=0; urx = Xw-RM-Xa; n=Xa; if (twoside) { n=(urx=2) fprintf(out, "/U{uappend fill}B\n\ /V{U grestore p 0 rmoveto}B\n"); fprintf(out, "/BeginEPSF{currentpoint /cpy exch def /cpx exch def\n\ /b4_Inc_state save def /dict_count countdictstack def\n\ /op_count count 1 sub def userdict begin /showpage{}def\n\ 0 setgray 0 setlinecap 1 setlinewidth 0 setlinejoin 10 setmiterlimit\n\ [] 0 setdash newpath /languagelevel where {pop languagelevel 1 ne\n\ {false setstrokeadjust false setoverprint}if}if}B\n\ /EndEPSF {count op_count sub {pop} repeat countdictstack\n\ dict_count sub {end} repeat b4_Inc_state restore }B\n"); fprintf(out, "/Shade{setgray RF setgray}B\n"); fprintf (out, /* redefine font using ISOLatin1 */ "/ILE {findfont dup length dict begin\n\ {1 index /FID ne {def}{pop pop} ifelse}forall\n\ /Encoding ISOLatin1Encoding def currentdict end\n\ /ILfont exch definefont pop /ILfont}B\n\ /linedraw {gsave moveto lineto stroke grestore}B\n\ /UDline {gsave moveto 0 rlineto setlinewidth 1 eq\n\ {[p 2.5 div dpi 300 div mul dup .7 mul]} {[]} ifelse\n\ 0 setdash stroke grestore}B\n"); fprintf(out, "/RD{ gsave newpath 4 -2 roll moveto dup 0 exch rlineto exch 0 rlineto\n\ neg 0 exch rlineto closepath stroke grestore}B\n"); fprintf(out, "/code 256 array def /str 3 string def /s00 (00) def\n\ code 0 [0 1 255 {dup 16 str cvrs exch 16 lt\n\ {s00 exch 1 exch putinterval s00} if cvn} for] putinterval\n"); fprintf(out, "end %% CN31%sDict\n", DictExt); fprintf(out, "%%%%EndResource\n\ %%%%EndProlog\n\ %%%%BeginSetup\n"); fprintf(out, "%sstatusdict begin /manualfeed true def end\n", (manualfeed)? "":"% "); fprintf(out, "CN31%sDict begin\n", DictExt); fprintf(out, "/dpi %d def\n", (int) (72./ppd+.2)); if (copies>1 && !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; unsigned char c1, c2; int nch; long jn; float x; /*jn = (mx/24.)*/ jn = (long) ( (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 [%8.6f 0 0 %8.6f 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); if (UnicodeTTF && lcode != UTF) mapToUnicode(&c1, &c2); 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) { int j; if (PSLlevel>=2) { putBitmap85(a, CHsize); return; } for (j=0; j 4) mlen = 4; base256 = 0; for (kb=0; 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, nsx, nsy; int j, 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; j = (int) (ns*Cx*10); nsx = j/10.; j = (int) (ns*Cy*10); nsy = j/10.; nx = (int) ((0.8338*CSP)*2.*Casc*10); ny = (int) (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{%g %g 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 [%g 0 0 %g 0 0] SF}B\n", j, CurrentFont->FontID, mx, j, DictExt, nsx, nsy); else fprintf(out, "/z%d{/CN%df%d%d%s %g 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", EFontnames[nEF], (euro>=1)? " ILE":"", nx/10, nx%10, ny); if (color.red + color.green + color.blue > 0.001) fprintf(out, "%g %g %g setrgbcolor\n", color.red, color.green, color.blue); else fprintf(out, "%g setgray\n", color.gray); } int isrlasc(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(unsigned char c1, unsigned char 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 */ /* this will never be true if (isUnicodeASCII(c1, c2)) return isrlasc(c2); */ if (c1 != 0x30) return NT; switch (c2) { case 0x08 : case 0x0A : case 0x0C : case 0x0E : case 0x10 : case 0x14 : case 0x16 : case 0x1D : return L; case 0x09 : case 0x0B : case 0x0D : case 0x0F : case 0x11 : case 0x15 : case 0x17 : case 0x1E : case 0x1F : case 0x01 : case 0x02 : return R; default: return NT; } break; default: break; } return NT; } unsigned char tovhb5(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(unsigned char *c1, unsigned char *c2) /* * substitutions under vertical mode */ { 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(unsigned char c1, unsigned char 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 != 0x30) return R; if (c2 >= 0x08 && c2 <= 0x11 || c2 >= 0x14 && c2 <= 0x1B) return NT; else return R; default: break; } return NT; } int putASC(int c, int c2, int pr) { int p, k, ASP, 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 && pr) { /* a quick and dirty way */ 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 = (int) (x + 8.5); k = (int) ((k/8)*8); H += (int) ( (k-x)*CSP*((tabascii)? Casc: 0.5) ); return 0; } k = (c>=' ' && c<=160)? (c-' ') : 0; /* change 126 to 160 */ ASP = (int) (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-indentR-ASP*3/2 && rl==L && adjust) { clearascbuf(pr, 1); newline(pr, 0); return 1; } else if (H > cRM-indentR-ASP/2) { if (!adjust || H > cRM-indentR+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-indentR-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: but not for unicode !!! */ 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 = (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(unsigned char c1, unsigned char c2, int pr) { int j, rl, rt, newl=0; unsigned int ch, addr; 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-indentR-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-indentR-2*CSP) { cnsp=1; newpos=1; if (H < cRM-indentR-CSP*5/4) { H -= ((frl==R)? CSP: CSP/2); if (frl==R) frl=NT; if (H < cRM-indentR-2*CSP) H=cRM-indentR-2*CSP; } else if (H < cRM-indentR-CSP*3/4 && frl==R) { H -= CSP; if (H < cRM-indentR-2*CSP) H=cRM-indentR-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-indentR-CSP && H <=cRM-indentR-CSP/4 && !cnsp) { newpos=1; H = (H > cRM-indentR-CSP/2)? (H-CSP/2) : (cRM-indentR-CSP); } else if (newl || (H>cRM-indentR-CSP*2/3 && rl!=R) || H>cRM-indentR+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 - indentR - 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; } addr=Addr(c1, c2); if (PreScanMode && Prntpage) fstring[addr]++; else if (Prntpage) { 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"); if (UnicodeTTF && lcode != UTF) mapToUnicode(&c1, &c2); 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 (CurrentFont->ptstring[addr] != NULL) free(CurrentFont->ptstring[addr]); ptstring[addr]=CurrentFont->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; } void signature() { time_t time_val; char *msg[]={"\nHave a nice day !\n", "", "", "", "", "\nThank you for using CNPRINT !\n", "", "", ""}; if (mute) return ; 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)]); } void usage(int n) { /* unlisted: -keeptempfile */ 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)(utf)(utf8)(utf7)(utf16)\n\ (utf16le): Specify input code type.\n\ -v(-vv): Vertical printing mode.\n\ -c3: Divide one page into 3 Columns.\n\ -w: Generate PS file Without printing it.\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\ -gb2b5(hz2b5)(b52gb)(b52hz)(hz2gb)(gb2hz): code conversion only.\n\ -print: use with gb2b5 etc, also print or generate PS file.\n\ -uni2gb(-gb2uni)(b5)(ksc)(jis): unicode<->CJK (utf type: -utf16 etc)\n\ -m: Disable/enable Menu (-m5: print 5 copies).\n\ -aa: Special mode for pure ASCII 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\ -epsheader=EPSfile: specify EPS header file\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-2001, All Rights Reserved\n\ cai@neurophys.wisc.edu\n", Version); } int isfs(unsigned char *s, int pr) { int j, k; float x; unsigned char c1, c2, c3, st0[100]; unsigned char *t; int seqlen; t=s; seqlen=1; while (*t && *t!=']' && seqlen<51) {seqlen++; t++;} /* ignore string too short or too long: "[xx]" is minimum */ if (seqlen < 4 || s[seqlen-1]!=']') return 0; c1=s[1]; c2=s[2], c3=s[3]; if (suppress) return (suppress>=2)? 0 : seqlen; switch(c1) { /* RGB */ case 'R': if (c2!='G' || c3!='B' || seqlen!=11) return 0; for (j=4; j<=9; j++) if (!isxdigit(s[j])) return 0; color.red = hex2float1(s[4], s[5]); color.green = hex2float1(s[6], s[7]); color.blue = hex2float1(s[8], s[9]); if (color.red + color.green + color.blue > 0.001) { color.gray = 0.0; if (pr && Prntpage && !PreScanMode) { fprintf(out, "%g %g %g setrgbcolor\n", color.red, color.green, color.blue); } } return 11; /* move to */ case 'M': if (c2!='V' || seqlen!=10) return 0; 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); /* V position is one line off */ if (pr && k!=1) V = (int) (k/ppd + linecip[1]); if (j!=1) H = (int) (j/ppd); return 10; /* line break and BOX draw/fill */ case 'B': if (c2!='O' && c3!='X' && seqlen > 4) return 0; if (c2=='R') { clearascbuf(pr, 1); newline(pr, 1); return 4; } /* BOXDRAW/FILL: def fill */ for (j=8; j=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 { column = k; /* set search mode for next one */ 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 *) st0, "[F0]"); isfs(st0, pr); strcpy((char *) st0, "[00]"); isfs(st0, pr); /* Cx, Cy: changes Ci! so XY must be before I0 */ strcpy((char *) st0, "[XY]"); isfs(st0, pr); strcpy((char *) st0, "[I0]"); isfs(st0, pr); strcpy((char *) st0, "[A0]"); isfs(st0, pr); return 4; /* ASC font by number */ case 'h': case 'H': case 'q': case 'Q': if (!isdigit(c2)) return 0; k=nEF; nEF=c2-'0'; if (isdigit(c3)) { nEF=nEF*10 + (c3-'0'); if (c1=='h' && isdigit(s[4])) nEF=nEF*10 + (s[4]-'0'); } if (c1=='H' || c1=='Q') nEF += 2*nEFfamily; if (c1=='q' || c1=='Q') nEF += nEFfamily; if (nEF != k) { getEfontdata(pr && !PreScanMode); nEFs[nEF]++; if (pr /*&& nEF!=k*/) PSctrl(); } return seqlen; /* CH font: or ASC font by name (F) */ 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/ASCfont name */ if (c1=='F' && seqlen >= 6) { t = s+2; strncpy((char *) st0, (char *) t, seqlen-3); st0[seqlen-3] = '\0'; k=nEF; if ((nEF = isASCfont((char *) st0)) >= 0) { if (nEF != k) { getEfontdata(pr && !PreScanMode); nEFs[nEF]++; if (pr /*&& nEF!=k*/) PSctrl(); } return seqlen; } else { nEF = k; strcpy(HBFname, (char *) st0); } } /* true type fonts: @[Txx] */ else if (c1=='T') { sprintf((char *) st0, "%c%c.htf", c2, c3); construct_fontname((char *) st0); } /* 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 *) st0, "%c%d.hbf", tolower(c2), j); construct_fontname((char *) st0); } 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 (seqlen==4) { if (isdigit(c2)) color.gray = (c2-'0')/10.; else return 0; } else if (strncmp((char *) s, "[GRAY", 5)==EQ) { if (sscanf((char *) s, "[GRAY%f]", &x) != 1) return 0; if (x>=0.0 && x<=1.0) color.gray = x; } else return 0; color.red = color.green = color.blue = 0.0; endAC(pr); if (pr && Prntpage && !PreScanMode) fprintf(out, "%g setgray\n", color.gray); return seqlen; /* 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 (seqlen==4) { x = 1.0 + (c2-'0')/10.0; } else { /* allow [X1.32] format */ if (sscanf((char *) s, "[%c%f]", &x) != 1) return 0; } if (x==0.0) { /* use default */ Cx = defCx; Cy = defCy; } else if (c1=='X') { Cx = x; Cy=1.0; } else { Cy = x; Cx=1.0; } } 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 seqlen; /* E: ASC width, line and char space; EP: EPS */ case 'E': if (!isdigit(c2) && c2!='P') return 0; if (isdigit(c2)) { 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(); return 4; } else if (c2=='P') { /* EP or EPS */ endAC((int) (pr && Prntpage)); if (pr && Prntpage && !PreScanMode) { fprintf(out,"%d %d Q ", BM-V, H); if (c3=='S' && seqlen>7) { strncpy((char *) st0, (char *) (s+4), seqlen-5); st0[seqlen-5] = '\0'; IncludeEPS((char *) st0); } else IncludeEPS(""); PSctrl(); } return seqlen; } else return 0; /* line spaces, indent */ case 'I': if (c1=='I' && c2=='N' && c3=='D') { /* INDL/R/E */ if (s[4]=='E') { if (H==indentL) H -= indentL; indentL=indentR=0; /* end */ } else if (seqlen>6) { if (sscanf((char *) s, "[IND%*c%d]", &k) != 1) return 0; k = (int) (k/ppd); if (s[4]=='R') indentR = k; else { indentL = k; if (H==0) H += indentL; } } else return 0; return seqlen; } else { Ci = (c2=='0')? defCi : (isdigit(c2)? (c2-'0')/10. : (c2-'a'+1) ); 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; } /* char space, envelope address */ 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 = (int) ( ((envelope==2)? 2 : 3.25) * 72./ppd ); if (c2=='R') { LM += j; V = (int) (1.25*72/ppd); } else if (LM>=j) LM -= j; H = cLM = LM; return 4; } else return 0; } 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 (addLBAS) */ /* Linedraw */ if (strncmp((char *) s, "[LINEDRAW", 9) == EQ) { for (j=9; j (k=lbnx*lbny)) { lbn -= (k+1); V=BM; /*pline--;*/ pcolumn=column; newline(1, 0); /* force a new page */ /* also push back '@', potential problem here, esp. with unicode */ return -1; } k = lbn-1; H=cLM = (int) ( ((k/lbny)*lbxinc + lbxp - .1)*72/ppd ); V = (int) ( ((k%lbny)*lbyinc + lbyp - .1)*72/ppd ); } cRM = (int) ( 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(unsigned char c1, unsigned char c2, unsigned char c3) { /* now accept @[xx] or @[xxx] for char size */ int k; 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); ; } void underline() { int y; if (vertical) { y = (int) ( ((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; } void endAC(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; } void clearascbuf(int pr, int 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", "UTF-16BE --> CJK", "UTF-16LE --> CJK", "CNS --> BIG5", "GB --> BIG5", "", "BIG5 --> GB", "", "Long lines --> short lines", "Print/extract selected pages", "MIME quoted printable --> 8 bit", "MIME base64 --> 8 bit", "Add sender's address", "unicode --> GB", "unicode --> Big5", "unicode --> KSC", "unicode --> JIS", "UTF-8 --> CJK", "UTF-7 --> CJK", "UTF-16 --> CJK", "", "", "", "", "", "", "", "", "", "Stat", ""}; static char *st2[]={"", "GB", "Hz", "Filtered/Repaired", "GB", "8-bit", "Repaired", "7-bit JIS", "GB", "BIG5", "8-bit", "2-byte", "2-byte", "2-byte", "2-byte", "BIG5", "BIG5", "", "GB", "", "Short version", "Selected pages", "8 bit", "8 bit", "", "GB", "Big5", "KSC", "JIS", "CJK", "CJK", "CJK", "CJK", "", "", "", "", "", "", "", "", "Statistic output", ""}; static char ki[]="$B", ko[]="(B"; char st[20], s[80]; FILE *in; if (convcode==FILT) { strcpy(st, "NEW"); if (breakfile) sprintf(st, "%d", filecount++); } else if (convcode==STATS) { strcpy(st, "stt"); } /* GB/B5/JIS-->GB/B5/JIS */ 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, out); 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, "uni"); break; case UTF16BETOUNI: case UTF16LETOUNI: utf16to2byte_unicode(in); strcpy(st, "uni"); break; case CJKUTF8: case CJKUTF7: case CJKUTF16: case CJKUTF16LE: cjk2unicode(in); strcpy(st, "uni"); break; case UTF8CJK: case UTF7CJK: unicode2cjk(in); strcpy(st, "cjk"); break; case UTF16CJK: case UTF16LECJK: unicode2cjk16(in); strcpy(st, "cjk"); break; case UNIGB: nullfilter(in); strcpy(st, "gb"); break; case UNIB5: nullfilter(in); strcpy(st, "b5"); break; case UNIKSC: nullfilter(in); strcpy(st, "ksc"); break; case UNIJIS: nullfilter(in); strcpy(st, "jis"); 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); 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(); } 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 { if (input_file_layer > 0) remove(Rinf->s); else input_file_layer++; FName(Rinf->s, st); RE_name(tempfile, Rinf->s); opnfile(IN); opnfile(OUT); } } void nullfilter(FILE *in) { int c; while ((c=fgetc(in)) != EOF) fputc(c, out); } void unicode2cjk(FILE *in) { unsigned short uni, cjk; for (;;) { uni = (convcode==UTF7CJK)? utf7_getc(in) : utf8_getc(in); if (uni == (unsigned short) EOF) break; /* not good ! */ if (uni <= 0x007F) { fputc(uni, out); /* ASCII */ continue; } cjk= UNItablemap[(int)(uni/256)][(int)(uni%256)]; fputc((int)(cjk/256), out); fputc((int)(cjk%256), out); } } void cjk2unicode(FILE *in) { unsigned short uni; int c1, c2; if (convcode==CJKUTF8) { fputc(0xEF, out); fputc(0xBB, out); fputc(0xBF, out); } else if (convcode==CJKUTF16LE) { fputc(0xFF, out); fputc(0xFE, out); } else { fputc(0xFE, out); fputc(0xFF, out); } for (;;) { if ((c1= fgetc(in)) == EOF) break; if (c1 < b1l) { c2=c1; c1=0x00; /* 0x80 */ } else { c2 = fgetc(in); if (c2==EOF) break; uni = UNItablemap[c1-b1l][c2-b2l]; c1 = (unsigned char) (uni/256); c2 = (unsigned char) (uni%256); } switch (convcode) { case CJKUTF16LE: fputc(c2, out); fputc(c1, out); break; case CJKUTF8: /* utf_fputc(c1, c2, out) */ break; default: fputc(c1, out); fputc(c2, out); break; } } } void unicode2cjk16(FILE *in) /* 16 bit only */ { unsigned short cjk; int c1, c2, c3; for (;;) { c1 = fgetc(in); c2 = fgetc(in); if (c1==EOF || c2==EOF) break; if (convcode==UTF16LECJK) { c3=c1; c1=c2; c2=c3; } if (isUnicodeASCII(c1, c2)) { fputc(c2, out); /* ASCII */ continue; } cjk= UNItablemap[c1][c2]; fputc((int)(cjk/256), out); fputc((int)(cjk%256), out); } } void to2byte_unicode(FILE *in) { long uni; int c1, c2, c3; /* UTF-8: EF BB BF */ sbufp = 0; c1 = sgetc(in); c2 = sgetc(in); c3 = sgetc(in); if (c1 != 0xEF || c2 != 0xBB || c3 != 0xBF) { sungetc(c3); sungetc(c2); sungetc(c1); } while ((uni = (convcode==UTF7TOUNI)? utf7_getc(in) : utf8_getc(in) ) != EOF) { u2byte((int)(uni/256)); u2byte((int)(uni%256)); } } void utf16to2byte_unicode(FILE *in) { int c1, c2; sbufp = 0; c1 = sgetc(in); c2 = sgetc(in); if (c1+c2 != 0x01FD) { sungetc(c2); sungetc(c1); } while ((c1=sgetc(in)) != EOF) { c2 = sgetc(in); if (c2==EOF) break; if (convcode==UTF16LETOUNI) { u2byte(c2); u2byte(c1); } else { u2byte(c1); u2byte(c2); } } } void u2byte(int ch) /* * output "escaped" u2 byte *#define U2ESC 0x4D, U2ESC2 0x21, ESCs for 2-byte unicode: */ { /* 4D4D = 4D, 4D21 = 00 */ switch (ch) { case 0x00: fputc(U2ESC, out); fputc(U2ESC2, out); break; case U2ESC: fputc(U2ESC, out); fputc(ch, out); break; default: fputc(ch, out); break; } } void jis2jis8(FILE *in) /* 0x21-0x7E --> 0xA1-0xFE */ { 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(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--; 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; int i; 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==FILT) 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 (i = -1; i<=1; i+=2) { N = 75 + j*i; if ((linedif[N]+linedif[N+1]+linedif[N+2]+linedif[N+3]) > m/4) return ( N - (1 - i) ); } } 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_stdin(s, 39); 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 */ void statinit() { fprintf(stderr, "Functions supported by enhanced version only\n\ Please contact author\n"); cleanup(1); exit(0); } void wordstat(unsigned int d) { return ; } void statistics(unsigned int Nchars, unsigned int NcharAll) { return ; } void stat_scan_output() { return; } #endif /* end STAT functions */ void CharBMPshift() /* bitmap shift for char */ { unsigned int chl; if (mx%8 > 0) fprintf(errout, "Width %d pixels not supported\n", mx); else if (bmpshift >= mx) fprintf(errout, "Request shift %d >= char width %d\n", bmpshift, mx); else { fprintf(errout, "Please make a COPY of the original bitmap file(s)\n\ Bitmap shift: %d pixels, %d (1-4, R/L/T/B) 0X%04X-0X%04X\n\ Continue (Y/N)?\n", bmpshift, bmpshift_dir, bmpshift_ch, bmpshift_ch2); if (yes(0)) { for (chl=bmpshift_ch; chl<=bmpshift_ch2; chl++) { fprintf(errout, "0X%04X: ", chl); HBFgetBitmap(chl); } } else fprintf(errout, "Aborted\n"); } cleanup(1); exit(0); } int CharBitmapShift(FILE *fp, long addr, 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; j= CHsize) k -= CHsize; if (bmpshift_dir==T) c[j] = a[k]; else c[k] = a[j]; } /* for (j=n; j= n) k -= n; } else if ((k=j-bmpshift) < 0) k += n; if (a[k/8] & ON[k%8]) c[j/8] += ON[j%8]; } break; case RMIRROR: /* rotate a mirror bitmap: matrix transpose, Cij = Aji */ for (j=0; jB5 table file -> %s\n", KWfile); exit(0); } } void gbb5tableinit(int dirc, FILE *in) /* dirc: GBB5 or B5GB */ { 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 (gbb5_ptstr[k1]!=NULL) j += strlen((char *)gbb5_ptstr[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 (gbb5_ptstr[k1]!=NULL) { strcpy((char *) t, (char *) gbb5_ptstr[k1]); free(gbb5_ptstr[k1]); } gbb5_ptstr[k1] = t; strcat((char *) gbb5_ptstr[k1], (char *) p); continue; } /* else: char mapping, overwrite previous ones */ if (dirc==GBB5) gbb5_fstr[k1]=k2; else { gbb5_fstr[k2]=k1; /* multiple mapping possible */ p += 4; while (strlen((char *) p) >=3) { /* always terminated with EOL */ if ((k2=B5POS(p[0], p[1])) >= 0) gbb5_fstr[k2]=k1; p += 2; } } } fclose(in); } void gbb5conv(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=gbb5_ptstr[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 = (gbb5_fstr[idx]==30000)? GBbox : gbb5_fstr[idx]; fprintf(out, "%c%c", GBB1(ch), GBB2(ch)); } else { ch = (gbb5_fstr[idx]==30000)? B5box : gbb5_fstr[idx]; fprintf(out, "%c%c", B5B1(ch), B5B2(ch)); } } else fprintf(errout, "Bad pair: %02X%02X\n", c1, c2); } else fprintf(out, "%c", c1); } } void 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; if (lcode==UTF) return; /* don't do this for unicode */ 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, n; 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 GBUNI: case B5UNI: case KSCUNI: case JISUNI: if (convcode==GBUNI) n = GB; else if (convcode==B5UNI) n = B5; else n = (convcode==KSCUNI)? KSC : JIS; loadUNImappingtable(n, 1); if (code==UTF8) convcode=CJKUTF8; else if (code==UTF7) convcode=CJKUTF7; else convcode = (code==UTF16)? CJKUTF16LE : CJKUTF16; break; case UNIGB: case UNIB5: case UNIKSC: case UNIJIS: /* assume 16-bit, 8-bit or 7-bit utf */ if (convcode==UNIGB) n = GB; else if (convcode==UNIB5) n = B5; else n = (convcode==UNIKSC)? KSC : JIS; loadUNImappingtable(n, 0); /* first convert to UTF-16BE then to proper code */ if (code==UTF7) convcode = UTF7CJK; else if (code==UTF8) convcode = UTF8CJK; else convcode = (code==UTF16)? UTF16LECJK : UTF16CJK; convers(0); convcode = conv_code; /* restore old original convcode */ break; case TOSHORTPS: case PAGEPRINT: /* old PSPRINT function */ convers(10); exit(0); break; default: break; } convers(convt_and_print? 0:1); /* 1 = conversion only */ convcode = conv_code; /* restore old original convcode */ } while (OIOU(0) != NT); } void GetCharUsage() /* prepare char statistics for buliding dict */ { 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. */ long m; 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; } void 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; if (nEF != defnEF) { nEF=defnEF; getEfontdata(1); } /*if (nEF%nEFfamily == 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; indentL=indentR=0; color.gray = color.red = color.green = color.blue = 0.0; } main(int argc, char **argv) { int j, jmax, c, endfile, buftoosmall; unsigned char *s, *p; unsigned char *mbuf; /* main buffer */ unsigned int mbufsz, bufused; float Cis, Cas, Cascs, Cxs, Cys; int ptspcs; int snEF, CSPs, CLPs, CIPs, scnsp, sfrl, inCHs, sctradj; int indentRs, indentLs; struct FontTag *sFontptr; struct ColorGrayStr colors; int linewidths; FILE *in; mRinf=Rinf=NULL; mbuf=NULL; init(argc, argv); if (bmpshift) CharBMPshift(); /* exit */ if (convcode!=FILT && breakfile>10) { /* multiple input, multiple output */ mRinf = Rinf->p; Rinf->p = NULL; } if (convcode && convcode!=FILT) { CodeConversion(); if (convt_and_print) convcode = NT; else { if (stdinput) remove(Rinf->t); signature(); exit(0); } } if (timestat>=3) { statinit(); stat_scan_output(); /* exit */ } if (mbuf==NULL) { mbufsz=BUFSIZE; mbuf = (unsigned char *) calloc(mbufsz, sizeof(unsigned char)); if (mbuf==NULL) MemExit(); } if (convcode==FILT) { 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==FILT || mute)? 0:1); /* one-input, one-output loop */ do { if (convcode != FILT) { if (DetectMIMEType() == 1) { j = convcode; convcode=MIMEQP; convers(0); convcode = j; } if (addrlabel) { j = convcode; convcode=ADDLBAS; convers(0); convcode = j; } 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!=FILT && !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; mbuf[0]=fgetc(in); mbuf[1]='\0'; p = mbuf; while (p[0]!='\0') { /* reorganize buf */ if (!endfile && strlen((char *) p) < mbufsz-2048) { j=0; if (p != mbuf) while (mbuf[j++] = *p++) ; jmax=strlen((char *) mbuf); j=mbufsz-jmax-5; while (--j) { if ((c=getc(in)) != EOF) { if (c!='\0') mbuf[jmax++]=c; } else { if (PreScanMode) rewind(in); else { fclose(in); inf->fp=NULL; if (input_file_layer > 0) 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!=FILT) { /* does not work with unicode */ mbuf[jmax++]='@'; mbuf[jmax++]='['; mbuf[jmax++]='P'; mbuf[jmax++]= '0'+(breakfile-1); mbuf[jmax++]=']'; j -= 5; } else { mbuf[jmax++]=EOL; j--; } } } mbuf[jmax]='\0'; /*if (convcode!=FILT)*/ convertEOL(mbuf, &jmax); p = mbuf; } s=p; H = LM+indentL; /* save status variables that will be used and changed by search */ Cis=Ci; Cas=Ca; Cascs=Casc; Cxs=Cx; Cys=Cy; ptspcs=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; indentRs=indentR; indentLs=indentL; colors.gray = color.gray; colors.red = color.red; colors.green = color.green; colors.blue = color.blue; linewidths = linewidth; /* SEARCH */ bufused = (unsigned int) (p - mbuf); buftoosmall = 0; for (;;) { while (!fnewline && *s!='\0' && (s[1]!='\0' || endfile) ) s = (lcode==UTF)? doAC_unicode(s, 0) : doAC(s, 0); if (SCN==2 || convcode==FILT) 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==FILT) { p=s; continue;} /* recover status variables */ Ci=Cis; Ca=Cas; Casc=Cascs; Cx=Cxs; Cy=Cys; ptspc=ptspcs; CSP = CSPs; CLP = CLPs; CIP = CIPs; cnsp=scnsp; frl=sfrl; inCH=inCHs; centraladj=sctradj; ascbuf.p=ascbuf.pp=0; indentR=indentRs; indentL=indentLs; color.gray = colors.gray; color.red = colors.red; color.green = colors.green; color.blue = colors.blue; linewidth = linewidths; if (nEF != snEF) { nEF=snEF; getEfontdata(0); } if (CurrentFont != sFontptr) { strcpy(HBFname, sFontptr->FontName); HBFopen(); } if (buftoosmall) { if (mbufsz>MAXBUFSZ) MemExit(); mbufsz += 3072; mbuf = (unsigned char *) realloc(mbuf, mbufsz); if (mbuf==NULL) MemExit(); p = mbuf; p += bufused; continue; } /* PRINT */ pline=1; H=cLM+indentL; /*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 = (lcode==UTF)? doAC_unicode(p, 1) : doAC(p, 1); } while (pline<=sline && *p!='\0'); } if (convcode==FILT) { 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(mbuf); 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=FILT 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 < F->nchar; j++) { if (F->fstring[j]>0 && F->fstring[j]<60000) { if (F->ptstring[j] != NULL && F->ptstring[j] != dummy) free(F->ptstring[j]); F->ptstring[j]=NULL; } F->fstring[j]=0; } } } if (convcode!=FILT && breakfile>10 && mRinf!=NULL) { inf = Rinf = mRinf; mRinf = Rinf->p; Rinf->p = NULL; /* set to default values: there are others affected, not clean */ init(RINIT, 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; 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 (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==FILT && !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(unsigned char c1, unsigned char c2, unsigned char *q, int j) /* * now assumes CR or CR/LF has been converted to LF * does not handle unicode */ { 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; } void 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); } int sungetc(int c) { if (sbufp>=SBUFSIZE) { fprintf(stderr, "sungetc: too many chars\n"); return -1; } else sbuf[sbufp++]=c; return c; } void bell() { fprintf(stderr, "%c", 7); } int SkipESCSeq(FILE *in, int c, int *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; sbufp=0; 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(FILE *in, int *p1, int *p2, int 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(int *p1, int *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(FILE *in, char *ki, char *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(FILE *in, char *ki, char *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(FILE *in, char *ki, char *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(RINIT, NULL); break; case B5: case CNS: if (lcode!=B5) init(RINIT, 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; sbufp=0; while ((in = inf->fp) != NULL) { while (dct==ASCII || dct==GBORB5) { if ((c=sgetc(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 = sgetc(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 = sgetc(in); if (c=='{' || c=='}') dct=HZ; n+=2; } else if (c=='z' && n==0) { c = sgetc(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; } int DetectMIMEType() /* * this is independent of language/encoding type. It is another layer. * It can be either quoted printable (QP) or base64. In either case, * we need to get back the original. * Right now we only care about QP. We look for "=B7 =C3", "=B7=C3" * or "=\n" pattern ("=B7s3" will not count) */ { int c=0, n=0; /* code type */ FILE *in; inf=Rinf; sbufp=0; while ((in = inf->fp) != NULL) { while (n < 5) { if ((c=sgetc(in)) == EOF) break; else if (c == '=') { if ((c=sgetc(in)) == EOL) n++; /* =\n */ else if (c == '=') sungetc(c); else if (isxdigit(c)) { c = sgetc(in); if (c == '=') sungetc(c); else if (isxdigit(c)) { /* OK =B4 */ c=sgetc(in); if (c == ' ' || c == '=') n++; sungetc(c); } } } } rewind(in); if ((inf=inf->p) == NULL) break; } inf=Rinf; return (n<5)? 0:1; } void unicodepreproc() { if (code==UNKNOWN || code==UTF) code=DetectUnicodeType(); switch(code) { case UTF7: case UTF8: convcode = (code==UTF7)? UTF7TOUNI : UTF8TOUNI; break; case UTF16: convcode = UTF16LETOUNI; break; default: code = UTF; convcode = UTF16BETOUNI; break; } if (!mute) fprintf(errout, "Code type is %s\n", codename[code]); convers(0); } int DetectUnicodeType() { int c1, c2, dct=UNKNOWN; FILE *in; in = Rinf->fp; c1 = fgetc(in); c2 = fgetc(in); switch(c1) { case 0xFE: if (c2==0xFF) dct=UTF; break; case 0xFF: if (c2==0xFE) dct=UTF16; break; case 0xEF: if (c2==0xBB && 0xBF==fgetc(in)) dct=UTF8; break; default: break; } rewind(in); return dct; } long utf8_getc(FILE *fp) /* utf8 to 2-byte unicode */ { 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(FILE *fp) /* utf7 to 2-byte unicode */ { 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; } } void 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"); 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; } } while (s!=NULL); /* rt=root; do { fprintf(errout, "rt->s: .%s.\n", rt->s); if (rt!=NULL) rt = rt->p; } while (rt!=NULL); */ } void FName(char *s, char *t) { int j, k; #ifdef VMS j=strlen(s); while (s[j]!=';' && j) j--; if (j>1) s[j]='\0'; #endif strcat(s, t); } void RE_name(char *fn_old, char *fn_new) { char p[100]; #ifdef unix # ifdef MUSER sprintf(p, "cp %s %s", fn_old, fn_new); system(p); remove(fn_old); # else sprintf(p, "mv %s %s", fn_old, fn_new); system(p); # endif #else if (rename(fn_old, fn_new)!=0) { sprintf(p, "copy %s %s", fn_old, fn_new); system(p); remove(fn_old); } #endif } void 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(); } int copypage(int npg, int xp, int ht, FILE *in, long *pfilepos) /* * pfilepos: copy selected page to output, for booklet * xp: x-position; ht: -1 trailer; 1, header */ { 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 void 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 void 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 mimeqp_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(mimeqp_hex(c1)*16 + mimeqp_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) /* * add sender information to every label, forming sender-receiver pair * if addrlabel>1, fill the whole page with everything before the first * @[LB as receiver address */ { int nlbas=0, nlbar=0, nlabel=0; int j, c1, c2; unsigned char *lbas, *lbar; lbas = (unsigned char *) calloc(LBASMAX, sizeof(char)); lbar = (unsigned char *) calloc(LBASMAX, sizeof(char)); if (lbas==NULL || lbar==NULL) MemExit(); sbufp=0; if (addrlabel > 1) { while ((c1=sgetc(in)) != EOF) { if (c1=='@' && strfilecmp("[LB", in)==EQ) { sungetc('B'); sungetc('L'); sungetc('['); sungetc(c1); break; } else lbar[nlbar++] = c1; if (nlbar >= LBASMAX-1) break; } lbar[nlbar]='\0'; } while ((c1=sgetc(in)) != EOF) { if (c1=='@' && strfilecmp("[LBAS]", in)==EQ) { if (lb_eat_EOL && (c1=sgetc(in)) != LF) sungetc(c1); break; } else if (c1=='@' && strfilecmp("[LB", in)==EQ) { nlabel++; fprintf(out, "%s", "@[LB"); } 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; if (nlbas >= LBASMAX-1) break; } lbas[nlbas]='\0'; while ((c1=sgetc(in)) != EOF) { fputc(c1, out); if (c1 == '@' && strfilecmp("[LB", in)==EQ) { nlabel++; 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 (nlbas>0 && j==nlbas) { for (j=0; j 0) { fprintf(out, "%s", "@[LB]"); for (j=0; j UNI */ if (b1l == 0x00) { b1l = 0xA1; b2l = (chcode==B5)? 0x40 : 0xA1; } b1low = b1l; b2low = b2l; spacechar = 0x3000; } else { /* convert UNI to CJK */ b1low=b2low=0; spacechar = (chcode==B5)? 0xA140 : 0xA1A1; } UNItablemap = (unsigned short **) calloc((0xFF-b1low+1), sizeof(unsigned short *)); if (UNItablemap==NULL) MemExit(); for (j=0; j<=0xFF-b1low; j++) { UNItablemap[j] = (unsigned short *) calloc((0xFF-b2low+1), sizeof(unsigned short)); if (UNItablemap[j]==NULL) MemExit(); for (k=0; k<=0xFF-b2low; k++) UNItablemap[j][k] = spacechar; } if ((fp=Rfopen(tablefile, "r"))==NULL) { fprintf(stderr, "Can't open unicode mapping file --- %s\n", tablefile); exit(0); } p = tablefile; while (fgets(p, 99, fp) != NULL) { if (p[0]=='0' && p[1]=='X') { sscanf(p, "%i%i", &j, &k); if (dire == 1) UNItablemap[j/256-b1low][j%256-b2low] = (unsigned short) k; else UNItablemap[k/256][k%256] = (unsigned short) j; } } fclose(fp); } void mapToUnicode(unsigned char *c1, unsigned char *c2) /*if (UnicodeTTF && lcode != UTF) mapToUnicode(&c1, &c2);*/ { unsigned short k = UNItablemap[*c1-b1l][*c2-b2l]; *c1 = (unsigned char) (k/256); *c2 = (unsigned char) (k%256); } int getcode_unicode(unsigned char *p, int *c1, int *c2) /* * get a 16-bit code of unicode, return # of bytes used: a positive value for success. zero or a negative value for end of line in char string *p, * The code value is returned via pointers */ { int c3, n=2; if ((*c1 = *p++) == '\0') return 0; if ((*c2 = *p++) == '\0') return -1; if (*c1 == U2ESC) { /* we trust the escaped 2-byte file: no error handling */ if (*c2 == U2ESC2) *c1 = 0x00; /* now we need to get a new *c2 */ if ((*c2 = *p++) == '\0') return -2; n++; } if (*c2 == U2ESC) { if ((c3 = *p++) == '\0') return -n; n++; if (c3 == U2ESC2) *c2 = 0x00; } return n; } int unicode_isfs(unsigned char *q, int pr) /* * convert unicode seq to ASCII seq, and call isfs() return # of bytes used * limitation: @[xxx], use of codes > 0x00FF is limited */ { int c1, c2, m, j; unsigned char fsq[50], *ps1; ps1 = q; for (j=0; j<49; j++) { m = getcode_unicode(q, &c1, &c2); if (m < 0) return 0; /* EOF */ q += m; /*else if (c1 != 0x00) return 0; / * only allow ASCII */ if (j==0 && c1!=0x00 && c2!='[') return 0; else if (isUnicodeASCII(c1, c2)) { fsq[j] = c2; if (c2==']') { /* end of @[...], stop */ fsq[++j]='\0'; m = isfs(fsq, pr); /* m<0: push back chars (e.g. '@'), assume each ASCII is 2 bytes in unicode */ return (m > 0)? (int)(q-ps1) : m*2; } } else { /* allow some Unicode chars */ fsq[j++] = c1; fsq[j] = c2; } } return 0; /* pattern @[...] not found */ } unsigned char *doAC_unicode(unsigned char *q, int pr) /* * for unicode only * since everything is two-byte with unicode, functional sequence like @[C2] would not work. This implementation tries to build an ASCII version of the sequence so that it will work with isfs. * filter() will not work for unicode too */ { unsigned char *ps1, *ps2; int k, j, m; int c1, c2, c3, c4; /* we work with unicode, there is no ASCII code here. However, we still * need to convert "ASCII" chars to ASCII and use putASC() to process. */ ps1 = q; m = getcode_unicode(q, &c1, &c2); if (m < 0) return (q-m); ps2 = q = q + m; if (c1==0x00 && c2=='@') { k = unicode_isfs(q, pr); if (k > 0) return (q+k); /* used */ } if (isUnicodeASCII(c1, c2)) { getcode_unicode(q, &c3, &c4); if (c3 >= 0x01) c4 = 0xB4; k = putASC(c2, c4, pr); if (k > 0) { if (k==1) return ps1; else { /* push back those in ascbuf: ps1 - 3*(k-1) */ k--; m = 3*k; for (; k>0; k--) if (ascbuf.s[k] == U2ESC) m++; return (ps1-m); } } } else { k = putCH(c1, c2, pr); return (k==0)? ps2 : ps1; /* k: 0 (used) or 2 */ } return q; } int isASCfont(char *fn) /* * find the font number for an ASC font */ { int j; for (j=0; j0 && k>0 && j >= k*4) { nEFmax = j; nEFfamily = k; break; } else { fclose(fp); return 0; } } } EFontnames = (char **) calloc(nEFmax, sizeof(char *)); if (EFontnames==NULL) MemExit(); EFmetricfiles = (char **) calloc(nEFmax, sizeof(char *)); if (EFmetricfiles==NULL) MemExit(); for (j=0; j=0) { EFontnames[j] = (char *) calloc(strlen(s1)+1, sizeof(char)); if (EFontnames[j]==NULL) MemExit(); EFmetricfiles[j] = (char *) calloc(strlen(s2)+1, sizeof(char)); if (EFmetricfiles[j]==NULL) MemExit(); strcpy(EFontnames[j], s1); strcpy(EFmetricfiles[j], s2); k++; } } fclose(fp); return k; }