/************************************* * CNPRINT.C For CNPRINT Version 2.22* ************************************* Copyright YIDAO CAI, 1992 All Rights Reserved. Free for non-commercial purpose only. CNPRINT, a utility to print Chinese text under UNIX and VAX/VMS systems. It works just as a print command on your system. Currently GB and Hz format are supported. Functions and Features: ( Nov. 17, 1992) 1. Print GB and Hz format Chinese text or pure English text. 2. Hz to GB conversion. 3. Use compressed fonts (takes at least 50% less memory). 4. Support several fonts and character sizes. 5. Change font (character size) for a whole document, set font (character size) for a group of characters. 6. Multicolumn for a page or part of a page. 7. Treatment of punctuation marks. 8. Set gray level for a whole document or a group of characters. 8. Page numbering, change of margins. 9. Set paper orientation: Portrait or Landscape. 10. Friendly designed so that even if you make a mistake the program would take care for you in most cases. USAGE: For normal usage, just type: cnprint filename The extended usages: cnprint [-h] [-z] [-w] [-x] [-y] [-p] [-l] [-c font] filename -h: Help message -z: Hz to GB conversion only -w: Print, Do NOT keep PS files -x2: Set character width/height 1.2 -y3: Set character height/width 1.3 -p4: Stop and print at every 4 pages -c font: Select font -l: Set paper orientation Landscape -s: suppress the effects of the functional sequences @[**] -m: Do NOT display menu -a: Input is a Hz file and CNPRINT would not ask for conformation 1. To set margins or set character size for the WHOLE document, run CNPRINT and follow the menu instructions. 2. To select font and character width-height ratio for the WHOLE document, use -c, -x -y options above. The use of -c option is -c k24 for 24x24 Kaishu font -c f16 for 16x16 Fanti font (see fonts for meaning of k24, f16, etc) 3. To select font, character size, width-height ratio for part of the document (or a group of characters, even one character), or divide a page/part of a page into several columns, insert the sequence @[**] in the text. The meaning of **: @[18] pure number for character size in points. 1 point = 0.355mm @[X2] Set character width/height 1.2 @[Y3] Set character height/width 1.3 @[G2] Set gray level 0.2, 0=black; 1=white @[C2] Select columns, i.e. divide the text into two columns, just like that in a newspaper f# or F# select font a. C, G, X, Y must be in upper case. b. Each of the above sequence would takes effect immediately and stop only after the same nature of selection is encountered. For example, if you select a character size 12 by @[12], it would remain 12 points until you select another size, say 15 by @[15]. c. Column marker must begin at the begining of a paragraph and must end at the end of a paragraph right after the hard return (i.e. the begining of next line, even if it is a blank line). d. To select font, you must specify font style by j, f, n, k, h or J, F, N, K, H in the place of # in f# or F#. The meaning of j, f... is j/J for Jianti, f/F for Fanti, etc (say below). The font size are small (16x16), middle (24x24) and large (48x48). Currently we do not have 48x48 fonts but this program is capable of using it. To specify small font, both f# must be in lower case; to specify middle size font, one and only one of f# or F# should be in lower case, the other in upper case. For example, @[Fh] or @[fH] both select 24x24 Heiti font, and @[ff] select 16x16 Fanti font. e. The program will use whatever character size, width/height ratio right before the column maker @[C#] setting the parameters for the columns, so it is best to select the character size and width/height ratio for most of the multicolumn portion right before the column marker @[C#]. 4. If the input file is a Hz document, a GB version will be generated and preserved on the disk. 5. If you use -l to change paper orientation to Landscape, the default character size is 12.3 pts (if width/height=1) or 10.3 (otherwise). Also, the page will be divided into 2 columns. 6. If you use -a to tell CNPRINT that the input is a Hz file, CNPRINT would not ask for conformation. You are NOT required to supply this when printing a Hz file. 7. The default setting: Font: Jianti 24x24 Character Size: 15 pts (if width/height=1) 13.5 pts (otherwise) Character Width/Height: 1.0 Paper Orientation: Portrait CHINESE FONT FILES: cclib.j24 (compressed version of csong24.plib) cclib.j16 cclib.f16 (non-simplified) cclib.f24 (compressed version of cfan.ccf, Fanti) cclib.n24 (compressed version of cfang.ccf, Fangsong) cclib.k24 (compressed version of ckai.ccf, Kaishu) cclib.h24 (compressed version of chei.ccf, Heiti) AUTHOR: cai@neurophys.wisc.edu Yidao Cai Department of Neurophysiology University of Wisconsin Medical School 1300 University Ave Madison, WI 53705 USA Acknowledgement: Some of the initial ideas come from the GB2PS Version 1.00 of Dr. Wei Sun at william@anucsd.anu.edu.au, Department of Computer Science, the Australian National University, Canberra, ACT 2601 Australia. Most of the fonts are modified from those in Dr. Sun's package. *****************************************************************************/ #include #include #include #ifndef CN2PSLIB #define CN2PSLIB "cclib.j24" #endif #ifndef PRINT_COMMAND /*#define PRINT_COMMAND "lp -dcga4m "*/ #define PRINT_COMMAND "cat " #endif #define EOL '\n' #define IN 1 #define OUT 0 /* define CCLIB as a string holding the default font path */ char CCLIB[100] = CN2PSLIB; /* define environment variable CN2PSFNT for the font path */ static char CN2PSFNT[] = "CN2PSFNT"; /* define margins, line space (CLP) and char spaces */ int LM =770, RM =5554, TM =820, BM =7270; int CSP, ASP, CLP, maxCLP, H, V; float pts=15.0; /* 1 pts = 10 div = 1/72 inch */ float Ck=0.035555556; /* ~~~ mm/div ~~~ */ float Cw=7.0; /* char width/line space */ int nCNdict=160; /* # of entries in CNdict */ char prntcmd[50]; char cclib_name[100]; char filename[100], PSfile[100], INfile[100], tempfile[20]; char inbuf[10240]; char fext[100], cst[100]; char chp1=0, chp2=0; /* for holding chars at newline */ int pts0, ptspc=100; /* pts0 = INT(pts), ptspc is from PC */ char defFontStlSz[10], StlSz[10]; int defFont=1; int defCHsize, CHsize=72; /* default 24x24, size 72 bytes */ int inASC=0, whitespace=1; int filecount=1; float charcount=0; int fputnpage=1, pagecount=1; int flag=0; /* 1: open another output file */ char frl; /* right-left */ int fnewline=1; int cnsp=0; /* special CH char */ int fstring[8180]; /* 8178 = 94*87 */ unsigned char *ptstring[8180]; float gray=.0; /* 0 black, .9 white */ float Cx=1., Cy=1.; int fshade=0; struct {int X; int Y; int *C; int g;} point; int Hzfile=0, HZa=0, HZb=0, hz_to_gb=0; int fprntfile=0; int pause=0, pp=4; /* pause at every pp pages */ int landscape=0; int suppress=0; int mute=0, keepPS=0; /* for search */ int PCN=0, SCN=0; int scnsp=0; char sfrl; /* right-left for search */ int ASPs, Hs, CSPs, CLPs, clptmp; int cTM, cBM, cLM, cRM; float scharcount=0; char chs1=0, chs2=0; int sinASC=0; int pline=0, pcolumn=1; int sline=0, column=1; int lineclp[500], linedif[500], fsnewline=0; FILE *in, *out, *cclib, *cclibs[79], *cmd; int init(arg,arglist) int arg; char **arglist; { char** i; int m, k=0, j=0; *cclib_name=0; strcpy(tempfile, "cnprint.out_tmp"); strcpy(StlSz, "JM"); /* default font style & size: Jianti, Middle */ sfrl=frl=NULL; for (i=arglist+1; i48 && fext[2]<=57) pp=fext[2]-48; break; case 'x': case 'y': strcpy(fext, *i); if (isdigit(fext[2]) && (m=fext[2]-'0') > 0) { StlSz[2]=toupper(fext[1]); StlSz[3]=fext[2]; StlSz[4]='\0'; if (fext[1]=='x') Cx += (m/10.); else Cy += (m/10.); pts=(landscape)? 12.3/(Cx+Cy-1): 13; } break; case 'm': mute=1; break; case 'u': keepPS=1; break; case 'w': fprntfile=1; break; case 'a': Hzfile=1; break; case 'z': hz_to_gb=1; break; case 's': suppress=1; break; case 'l': landscape=1; column=2; m=BM; BM=RM; RM=m; m=TM; TM=LM; LM=m; pts=(Cx+Cy>2.05)? 10.3: 12.3; break; default: usage(); exit(0); } break; default: if (k==0) { strcpy (INfile, *i); opnfile(IN); } k++; break; } if (k==1) opnfile(OUT); else { usage(); if (k>1) fclose(in); exit (1); } if (hz_to_gb) return k; if (*cclib_name!=0) { m=0; strcpy(fext, cclib_name); for (j=(strlen(cclib_name) - 3); j >= 0 ; j--) { if (cclib_name[j+1]=='4' && cclib_name[j+2]=='8') { StlSz[1]='L'; m=j; } else if (cclib_name[j+1]=='1' && cclib_name[j+2]=='6') { StlSz[1]='S'; m=j; } /* default M: 24x24 */ else if (cclib_name[j+1]=='2' && cclib_name[j+2]=='4') m=j; } switch (fext[m]) { case 'j': case 'f': case 'k': case 'n': case 'h': StlSz[0] = fext[m] + 'A' - 'a'; if (m==0) { strcpy(cclib_name,CCLIB); cclib_name[strlen(cclib_name) - 3] = '\0'; strcat(cclib_name,fext); } break; default: break; } } else strcpy(cclib_name, CCLIB); if ((cclib = fopen (cclib_name, "r"))==NULL) { fprintf(stderr,"Cannot open the Chinese font file -> %s\n", cclib_name); bell(); exit (-1); } else fprintf(stderr, "Chinese font file %s opened;\n\n", cclib_name); if (StlSz[1]=='S') CHsize = 32; else if (StlSz[1]=='L') CHsize = 288; else CHsize = 72; for (j=0; j<79; j++) cclibs[j]=0; j = StlSz[0] - 'A' + 1; if (StlSz[1]=='M') j += 26; else if (StlSz[1]=='L') j += 52; cclibs[0]=cclibs[j]=cclib; strcpy (defFontStlSz, StlSz); defCHsize=CHsize; strcpy(prntcmd, PRINT_COMMAND); strcpy(fext, CCLIB); fext[strlen(fext)-9]='\0'; strcat(fext, "cnprint.cmd"); if (strlen(prntcmd) <= 2) if ((cmd=fopen(fext, "r"))!=NULL) { fgets(prntcmd, 49, cmd); fclose(cmd); } if ((j=strlen(prntcmd)) > 2) { prntcmd[j++]=' '; prntcmd[j]='\0'; } else prntcmd[fprntfile=0]='\0'; return k; } opnfile(n) int n; { if (n==IN) { if ((in=fopen(INfile, "r"))==NULL) { fprintf(stderr, "Can't open input file -> %s\n", INfile); bell(); exit (-2); } } else if ((out=fopen(tempfile, "w"))==NULL) { fprintf(stderr, "Can't open output file\n"); bell(); exit (-3); } } style () { int n; float lm, rm, tm, bm, offset=0; float x, pr=215.9, pb=279.4; float mg_change(); if (landscape) { x=pr; pr=pb; pb=x; } charsize(); lm = LM*Ck; rm = pr - RM*Ck; tm = TM*Ck -(offset + CLP*Cw*Ck/10.); bm = pb - (BM*Ck - (offset + CLP*Ck) ); if (!mute) do { if (fputnpage) fprintf(stderr, "\ \tN: Page Numbering. Current: Yes. Start at %d\n", pagecount); else fprintf(stderr, "\ \tN: Page Numbering. Current: No.\n"); fprintf(stderr, fprntfile? "\tP: Print PS file? Current: Yes.\n" : "\tP: Print PS file? Current: No.\n"); fprintf(stderr, "\ \tS: Character Size. Current: %7.2f mm (%.1f pts)\n\ \tL: Left Margin. Current: %6.1f mm\n\ \tR: Right Margin. Current: %6.1f mm\n\ \tT: Top Margin. Current: %6.1f mm\n\ \tB: Bottom Margin. Current: %6.1f mm\n\ \tQ: Quit.\n\n", CSP*Ck, pts, lm, rm, tm, bm); fprintf(stderr, "\ There are about %.1f lines in a page and %.1f words in a line\n\n\ To change, type one of the following:\n\n\tN, P, S, L, R, T, B, Q\n\n\ or press RETURN key to continue\n", (pb-bm-tm + .3*Ck*CLP)/(CLP*Ck), (pr-rm-lm)/(CSP*Ck)); gets(cst); if ( cst[0] != '\0') switch (toupper(cst[0])) { case 'N': fprintf(stderr, "\ \tPage Numbering. Current: Yes. Start at %d\n\n", pagecount); fprintf(stderr, "(Y/N ?) If NO, type < N >;\n\ If YES, enter your number to change OR press RETURN to continue;\n"); gets(fext); if (toupper(fext[0]) == 'N') fputnpage=0; else { if (toupper(fext[0])!='Y') sscanf(fext,"%d", &pagecount); fputnpage=1; } break; case 'P': fprintf(stderr, fprntfile? "\tPrint PS file ? Current: Yes. [Yes]?\n\n" : "\tPrint PS file ? Current: No. [No]?\n\n"); if (strlen(prntcmd)<=2) { fprintf(stderr, "Print command invalid/not found, OK !?\n"); bell(); gets(fext); } else fprntfile=yes(fprntfile); break; case 'S': fprintf(stderr, "\ \tCharacter Size. Current: %7.2f mm (%.1f pts)\n\ \t\t****** 1 pts = 3.556 mm ******\n", CSP*Ck, pts); pts=mg_change(pts,0); charsize(); break; case 'L': fprintf(stderr, " \tLeft Margin. Current: %6.1f mm\n\n", lm); lm=mg_change(lm,1); break; case 'R': fprintf(stderr, " \tRight Margin. Current: %6.1f mm\n\n", rm); rm=mg_change (rm,1); break; case 'T': fprintf(stderr, " \tTop Margin. Current: %6.1f mm\n\n", tm); tm=mg_change (tm,1); break; case 'B': fprintf(stderr, " \tBottom Margin. Current: %6.1f mm\n\n", bm); bm=mg_change (bm,1); break; case 'Q': cleanup(); fclose(out); remove(tempfile); exit(0); default: break; } } while (cst[0] != '\0'); charsize(); if (ptspc >= 100) ptspc=pts0; LM = lm/Ck; RM = (pr - rm)/Ck; TM = (tm +(offset + CSP*Ck))/Ck; BM = (pb - bm + (offset + CLP*Ck))/Ck; RM = ((RM-LM)%CSP < CSP/2)? (RM-LM)/CSP*CSP+LM : (RM-LM)/CSP*CSP+CSP+LM; BM = ((BM-TM)%CLP < CLP/2)? (BM-TM)/CLP*CLP+TM : (BM-TM)/CLP*CLP+CLP+TM; fprintf(stderr, " There are %d lines in a page and %d words in a line\n\n", (BM - TM)/CLP, (RM - LM)/CSP); cLM = LM; cRM = RM; cTM = TM; cBM = BM; CLPs = CLP; ASPs = ASP; CLPs = CLP; if (column>1) { n = (RM-LM-2*Cw*pts*(column-1))/column; cRM = cLM + (n/CSP)*CSP; } } charsize () { CLP = pts*10.0*(Cy+(Cx-1)/2.); CSP = pts*Cw*Cx; ASP = CSP*.6; pts0 = pts; maxCLP = clptmp = CLP; } float mg_change(y, n) float y; int n; { float xy=0; fprintf(stderr, (n==1)? " Please enter your desired margin," : " Please enter your desired character size,"); fprintf(stderr, " or press RETURN to continue\n"); bell(); fprintf(stderr, (n==1)? " ~~~~~~ inch OR mm ~~~~~~\n": " ~~~~~~ ONLY VALUE IN --pts-- IS ACCEPTABLE ~~~~~~\n"); gets(fext); if (fext[0] != EOL) { sscanf(fext,"%f",&xy); if (xy <=5 && n==1) xy *= 25.4; } /* 5mm < Margin <= 127 mm (5 in) */ if ( ((xy < 5 || xy > 130) && n==1) || ((xy < 1 || xy > 100) && n==0) ) { fprintf(stderr, "\n**** WARNING: input value out of range, ignored ! ****\n\n"); bell(); return y; } else return xy; } cleanup() { int i; fclose(in); for (i=0; i<79; i++) if(cclibs[i]) fclose(cclibs[i]); bell(); } newline() { if (fshade) shade(); else endASC(); charcount=0; if (column==1) { V += CLP; H=LM; if (V>= BM) { end_page (); V=TM; fprintf(out,"save\n"); } maxCLP = clptmp = CLP; } else { V += lineclp[++pline]; H = cLM; if (V >= cBM) { int x; x = (RM-LM-2*Cw*pts*(column-1))/column; x = (x/CSP)*CSP; if (++pcolumn <= column) { V = cTM; H=cLM=LM+(x+(RM-LM-x*column)/(column-1))*(pcolumn-1); } else if (V >= BM) { end_page (); fprintf(out,"save\n"); V=cTM=TM; H=Hs=cLM=LM; PCN=SCN=1; /* see print_ctrl, PCN=2 */ pline=1; sline=0; /* force goto search */ pcolumn=1; } cRM = cLM + x; } } fnewline=1; if (fshade) { point.X=H; point.Y=V; point.C=(column==1)? &maxCLP:&lineclp[pline]; } } end_page() { int j; /* bell(); */ fprintf(stderr, "*** Page %d has been done ***\n",pagecount); put_npagetime (); pagecount++; fprintf(out,"endpage\n"); if (flag) { fprintf(out,"%%%%Trailer\n"); fprintf(out,"%%%%Pages: %d\n", pagecount - 1); } else fprintf(out,"%%%%Page: %d %d\n", pagecount, pagecount); if (flag || (pause && !(pagecount%pp)) ) { if (ferror(out)) { fprintf(stderr, "WARNING: PS file %s write error, possibly out of memory.\n\ PS file might NOT be complete.\n\ Suggestion: delete PS file and run CNPRINT again, use the -p[number] option\n\ or select smaller number\n", tempfile); bell(); exit(-4); } fclose(out); sprintf(fext,"%d",filecount); strcpy(filename, PSfile); if (pause) strcat(filename, fext); rename(tempfile, filename); if (fprntfile) { strcpy(cst, prntcmd); strcat(cst, filename); system(cst); fprintf(stderr,"Job has been sent to printer\n"); if (!keepPS) { fprintf(stderr,"Please press RETURN after print job is finished\n"); gets(fext); remove(filename); } } filecount++; if (!flag) { opnfile(OUT); ps_header(); } } } put_npagetime () { struct tm *time_str; int i=0, time_val; endASC(); if (fputnpage) fprintf(out, "%d %d GO R (%d) S\n", LM+(int)((RM-LM)/2), BM+(int)(1.5*CLP), pagecount); /* if (fputnpage) { fprintf(out, "%d %d GO R (%6d) S\n", RM-300-3*CSP, BM+CLP, pagecount); time(&time_val); time_str = localtime(&time_val); strftime(cst, 48, "%a %d-%b-%y %H:%M:%S %Z", time_str); while ( (cst[i]=toupper(cst[i])) != '\0') ++i; fprintf(out, "/Courier findfont 6 scalefont setfont\n%d %d GO R (%s) S\n", LM, BM+CLP, cst); } */ } ps_header () { float ns, nx, ny, ntx, nty; int m=24; ns = pts*Cw*24./25/10; nx = pts*0.5775; ny = nx*1.45; nx *= 1.2; nty = nx/9.; ntx = -0.1*nty; fprintf(out, "%%!PS-Adobe-2.0\n"); fprintf(out, "%%%%Creator: (cnprint 2.22)\n"); fprintf(out, "%%%%Title: %s -> %s\n", INfile, PSfile); fprintf(out, "%%%%Pages: (atend)\n"); fprintf(out, "%%%%EndComments\n"); fprintf(out, "%%%%BeginProlog\n"); fprintf(out, "/endpage {restore showpage} def\n\ /M {imagemask grestore} def\n\ /S {show grestore} def\n\ /CSP %.1f def\n", CSP/10.); fprintf(out, (landscape)? "/GO {10 div exch 10 div CSP sub moveto} def\n\ /R {0 CSP rmoveto gsave currentpoint translate 90 rotate} def\n" : "/GO {exch 10 div CSP sub exch 10 div 792 sub neg moveto} def\n\ /R {CSP 0 rmoveto gsave currentpoint translate} def\n"); if (CHsize==32) m=16; else if (CHsize==288) m=48; fprintf(out, "/T {R %.1f %.1f scale %d %d true [%d 0 0 -%d 0 %d] } def\n", (StlSz[0]=='F')? ns*0.95*Cx:ns*Cx, ns*Cy, m, m, m, m, m); fprintf(out, "/Courier findfont [%.1f 0 0 %.1f %.1f %.1f] makefont setfont\n", nx*Cx, ny*Cy, ntx, nty); fprintf(out, "/Shade {newpath 10 div exch 10 div exch moveto 10 div dup 0 exch rlineto\n\ exch 10 div dup 0 rlineto exch neg 0 exch rlineto neg 0 rlineto closepath\n\ 10 div setgray fill setgray} def\n"); CNdict(); fprintf(out,"%%%%EndProlog\n"); } CNdict() /* dictionary for frequently used characters with nCNdict entries */ { int j, m, byte; unsigned char array[300]; char st3[600]; for (m=1; m<8180; m++) if (fstring[m] < 0) { st3[0]='\0'; fseek(cclib, m*CHsize, 0); byte=fread(array, CHsize, 1, cclib); if (byte < CHsize) for (j=0; j < CHsize-byte; ++j) read(cclib, &array[j+byte], 1); for (j=0; j < CHsize; ++j) { sprintf(fext, (j==40)?"\n%02x":"%02x", array[j]); strcat(st3, fext); } fprintf(out,"/C%x { {<%s>} M } def\n", m, st3); ptstring[m] = &array[0]; } } char isrlasc(c) int c; { /* l=left; r=right; NULL=none */ switch (c) { case 40 : case 60 : case 91 : case 123 : return 'l'; break; case 33 : case 41 : case 44 : case 46 : case 58 : case 59 : case 62 : case 63 : case 93 : case 125 : return 'r'; break; default: return NULL; break; } } char isrlch(c1, c2) unsigned char c1, c2; { /* l=left; r=right; NULL=none */ switch (c1) { case 0xA1: if (c2>=0xAE && c2<=0xBF) c2%=2; switch (c2) { case 0: return 'l'; break; case 1: case 0xA2 : case 0xA3 : case 0xC3 : case 0xE3 : case 0xE4 : case 0xE5 : return 'r'; break; default : return NULL; break; } case 0xA3: switch (c2) { case 0xA8 : case 0xDB : case 0xFB : case 0xE0 : return 'l'; break; case 0xA1 : case 0xA7 : case 0xA9 : case 0xAC : case 0xAE : case 0xBA : case 0xBB : case 0xBF : case 0xDD : case 0xDF : case 0xFD : return 'r'; break; default : return NULL; break; } default : return NULL; break; } } putASC(c) int c; { int k, k1, newl=0; char isrlasc(), rl; if (c==13 || c==26) return; cnsp=0; if (c==EOL) { newline(); return; } else if (c=='\t' || c==' ') { k=1+charcount; k1=(c==' ')? 1:(8-k%8); if (inASC) for (k=1; k<=k1; k++) fprintf(out, " "); else whitespace = 1; H += (k1*ASP); charcount += (1.2*k1); return; } else if ((rl=isrlasc(c))=='l') if (H > cRM - ASP*3/2) newl=1; if (newl || (H > cRM-ASP/2 && rl != 'r') ) { chp1=c; newline(); return; } if (!inASC) { fprintf(out,"%d %d GO\nR (", H, V); inASC=IN; } fprintf(out, (c=='(' || c==')' || c==92) ? "\\%c":"%c", c); charcount += 1.2; H+=ASP; } putCH(ch1, ch2) unsigned char ch1, ch2; { long addr; int i, j, byte, newl=0; char isrlch(), rl, st3[600]; unsigned char array[300]; rl=NULL; st3[0]='\0'; if (ch1>=0xA4) cnsp=0; else { cnsp++; if ( (rl=isrlch(ch1, ch2))==NULL ) cnsp=0; else if (rl=='l') { if (H > cRM-2*CSP) { cnsp=1; whitespace=1; if (H < cRM-CSP*5/4) { H -= ((frl=='r')? CSP: CSP/2); if (frl=='r') frl=NULL; charcount--; if (H < cRM-2*CSP) H=cRM-2*CSP; } else if (H < cRM-CSP*3/4 && frl=='r') { H -= CSP; charcount-=2; if (H < cRM-2*CSP) H=cRM-2*CSP; } else newl=1; } } else if (rl=='r' && frl=='l') cnsp=1; } if (addr=(ch1-0xA1)*94+ch2-0xA1) { if (frl=='r' && H > cRM-CSP && H <=cRM-CSP/4 && !cnsp) { whitespace = 1; H = (H > cRM-CSP/2)? (H-CSP/2):(cRM-CSP); } else if (newl || ( (H > cRM - CSP*2/3) && rl!='r' ) ) { chp1=ch1; chp2=ch2; newline(); return; } if (cnsp >= 2) { /* 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; whitespace=1; } else { H -= (CSP/2); charcount--; whitespace=1; } } if (inASC) endASC(); if (whitespace) fprintf(out,"%d %d GO\n", H, V); /* skip 6 empty symbol sections - Do NOT skip for cclib.24 */ /* if (addr>=1410) addr -= 564; */ if ((defFont && ptstring[addr]==NULL) || !defFont) { fseek(cclib, addr*CHsize, 0); byte=fread(array, CHsize, 1, cclib); if (byte < CHsize) for (j=0; j < CHsize-byte; ++j) read(cclib, &array[j+byte], 1); if (defFont) { /* allocate memory for bitmap array */ ptstring[addr] = (unsigned char *) calloc(CHsize+2, sizeof(unsigned char)); if (ptstring[addr]!=NULL) for (j=0; j} M\n", st3); } whitespace = 0; if (--fstring[addr]==100) { cfree(ptstring[addr]); ptstring[addr]=NULL; } } else if (inASC) { putASC(' '); return; } else whitespace = 1; H+=CSP; charcount+=2; frl=rl; } bell() { int bel=7; fprintf(stderr, "%c", bel); } usage() { fprintf(stderr, "USAGE: cnprint [-h] [-z] ... [-c font] filename\n\ -h: This message.\n\ -z: Hz to GB conversion only.\n\ -w: Print, Do NOT keep PS files.\n\ -x2: Set Character width/height 1.2.\n\ -y3: Set Character height/width 1.3.\n\ -p4: Stop and print at every 4 pages.\n\ -l: Set paper Orientation Landscape.\n\ -m: Do NOT display menu.\n\ -c font: Select font (k24, f16, ...)\n"); } charsize_ctrl() { float ns, nx, ny, ntx, nty; int m=24; endASC(); if (ptspc <= 0 || ptspc >= 100) { ptspc=pts0; CLP = pts*10.0*(Cy+(Cx-1)/2.); CSP = pts*Cw*Cx; } else { CLP = ptspc*10.0*(Cy+(Cx-1)/2.); CSP = ptspc*Cw*Cx; } ASP = CSP*.6; ns = ptspc*Cw*24./25/10; nx = ptspc*0.5775; ny = nx*1.45; nx *= 1.2; nty = nx/9.; ntx = -0.1*nty; if (CHsize==32) m=16; else if (CHsize==288) m=48; fprintf(out, "/T {R %.1f %.1f scale %d %d true [%d 0 0 -%d 0 %d] } def\n", (StlSz[0]=='F')? ns*0.95*Cx:ns*Cx, ns*Cy, m, m, m, m, m); fprintf(out, "/Courier findfont [%.1f 0 0 %.1f %.1f %.1f] makefont setfont\n", nx*Cx, ny*Cy, ntx, nty); fprintf(out, "/CSP %.1f def\n", CSP/10.); } int print_ctrl(c1, c2) unsigned char c1, c2; { int j, k, x; if(suppress) return 0; /* char size */ if (isdigit(c1) && isdigit(c2)) { ptspc = (c1-48)*10 + (c2-48); charsize_ctrl(); return 1; } /* C: column number */ else if (c1=='C' && isdigit(c2)) { k = (c2==48)? 1 : (c2-48); PCN++; if (PCN==1) { if (column==1 && k==1) PCN=0; return 1; } else { column = k; /* set search mode for next one */ fnewline = 1; sline = 0; pline = 1; V = cBM; cBM = BM; Hs = cLM = H = LM; if (column > 1) { SCN = 1; PCN = 1; cTM = V; x = (RM-LM-2*Cw*pts*(column-1))/column; x = (x/CSP)*CSP; cRM = LM + x; } else { SCN = 0; PCN = 0; cRM = RM; cTM = TM; } } return 1; } /* font change */ else if (c1=='f' || c1=='F') { switch (c2) { case 'j': case 'f': case 'h': case 'k': case 'n': case 'J': case 'F': case 'H': case 'K': case 'N': StlSz[0] = toupper(c2); break; default: return 0; break; } fext[0] = tolower(StlSz[0]); fext[1] = '\0'; j = StlSz[0] - 'A' + 1; if (c1=='f' && islower(c2)) { StlSz[1] = 'S'; CHsize = 32; strcat (fext, "16"); } else if (c1=='F' && isupper(c2)) { StlSz[1] = 'L'; CHsize = 288; j += 52; strcat (fext, "48"); } else { StlSz[1] = 'M'; CHsize = 72; j += 26; strcat (fext, "24"); } if (!cclibs[j]) { strcpy (cclib_name,CCLIB); cclib_name[strlen(cclib_name) - 3] = '\0'; strcat (cclib_name,fext); if ((cclib = fopen (cclib_name, "r"))==NULL) { fprintf(stderr, "\ Cannot open the Chinese font file -> %s\n\ Default font used\n", cclib_name); bell(); CHsize = defCHsize; StlSz[0] = defFontStlSz[0]; StlSz[1] = defFontStlSz[1]; cclib = cclibs[0]; } else cclibs[j] = cclib; } else cclib = cclibs[j]; defFont = (cclib==cclibs[0])? 1:0; if (!defFont) charsize_ctrl(); return 1; } /* shading */ else if (c1=='S' && isdigit(c2) ) { if (fshade) shade(); fshade=(c2=='0')? 0:1; point.X=H; point.Y=V; point.g=c2-'0'; point.C=(column==1)? &maxCLP:&lineclp[pline]; return 1; } /* gray */ else if (c1=='G' && isdigit(c2) ) { endASC(); fprintf(out, "%3.1f set gray\n", gray=(c2-'0')/10.); return 1; } /* X, Y expansion */ else if ( (c1=='X'||c1=='Y') && isdigit(c2) ) { if (c2 > '0') { StlSz[2]=c1; StlSz[3]=c2; StlSz[4]='\0'; } else StlSz[2]='\0'; if (c1=='X') { Cx=1.+(c2-'0')/10.; Cy=1;} else { Cy=1.+(c2-'0')/10.; Cx=1;} charsize_ctrl(); return 1; } else return 0; } int search_ctrl(c1, c2) unsigned char c1, c2; { int k, x, span(); if(suppress) return 0; /* char size */ if (isdigit(c1) && isdigit(c2)) { k = (c1-48)*10 + (c2-48); if (k >= 100 || k <=0) k=pts; CSPs = Cw*k*Cx; ASPs = .6*CSPs; CLPs = k*10.0*(Cy+(Cx-1)/2.); /* size ctrl at the begin of a line, take it */ if (column==1) { if (Hs==LM || CLPs > 1.2*clptmp) { V += (CLPs - maxCLP); maxCLP = CLPs; } } else if (Hs==LM || CLPs > 1.2*clptmp) { if (sline==0) V += (CLPs-lineclp[sline+1]); lineclp[sline+1] = CLPs; } return 1; } /* column number */ else if (c1=='C' && isdigit(c2)) { k = (c2==48)? 1:(c2-48); SCN++; if (SCN==1) { column = k; if (column==1) SCN = 0; cTM = V; x = (RM-LM-2*Cw*pts*(column-1))/column; x = (x/CSP)*CSP; cRM = LM + x; } else { cBM=span(0); cLM = LM; H = LM; pcolumn = 1; } return 1; } /* font */ else if (c1=='f' || c1=='F') { switch (c2 = tolower(c2)) { case 'j': case 'f': case 'h': case 'k': case 'n': return 1; break; default: return 0; break; } } /* shading & gray */ else if ((c1=='S' || c1=='G') && isdigit(c2) ) return 1; /* X, Y expansion */ else if ( (c1=='X'||c1=='Y') && isdigit(c2) ) { if (c1=='X') Cx = 1+ (c2-'0')/10.; else Cy = 1+ (c2-'0')/10.; return search_ctrl('0'+ptspc/10, '0'+ptspc%10); } else return 0; } shade() { endASC(); /* g g x y X Y shade */ fprintf(out, "%3.1f %d %d %d %d %d Shade\n", gray, point.g, (H-point.X), *point.C, point.X, (point.Y - (*point.C)*.15)); } endASC() { if (inASC) fprintf(out,") S\n"); inASC=OUT; whitespace=1; } scanASC(c) int c; { int k, newl=0; char isrlasc(), rl; if (c==13 || c==26) return; scnsp=0; if (c==EOL) { snewline(1); return; } else if (c=='\t') { k=1+scharcount; k=8-k%8; Hs += (k*ASPs); scharcount += (1.2*k); return; } else if ((rl=isrlasc(c))=='l') if (Hs > cRM - ASPs*3/2) newl=1; scharcount += 1.2; if (newl || (Hs > cRM-ASPs/2 && rl != 'r') ) { chs1=c; snewline(0); return; } sinASC=IN; Hs+=ASPs; } scanCH(ch1, ch2) unsigned char ch1, ch2; { int k, newl=0; char isrlch(), rl; rl=NULL; if (ch1>=0xA4) scnsp=0; else { scnsp++; if ( (rl=isrlch(ch1, ch2))==NULL) scnsp=0; else if (rl=='l') { if (Hs > cRM-2*CSPs) { scnsp=1; if (Hs < cRM-CSPs*5/4) { Hs -= ((sfrl=='r')? CSPs: CSPs/2); if (sfrl=='r') sfrl=NULL; scharcount--; if (Hs < cRM-2*CSPs) Hs=cRM-2*CSPs; } else if (Hs < cRM-CSPs*3/4 && sfrl=='r') { Hs -= CSPs; scharcount-=2; if (Hs < cRM-2*CSPs) Hs=cRM-2*CSPs; } else newl=1; } } else if (rl=='r' && sfrl=='l') scnsp=1; } if (ch1!=0xA1||ch2!=0xA1) { if (sfrl=='r' && Hs > cRM-CSPs && Hs <=cRM-CSPs/4 && !scnsp) Hs = (Hs > cRM-CSPs/2)? (Hs-CSPs/2):(cRM-CSPs); else if (newl || ( (Hs > cRM - CSPs*2/3) && rl != 'r') ) { chs1=ch1; chs2=ch2; snewline(0); return; } if (scnsp >= 2) { Hs -= (CSPs/2); scharcount--; } sinASC=OUT; } else if (sinASC) { scanASC(' '); return; } Hs+=CSPs; scharcount+=2; sfrl=rl; } snewline(ret) int ret; { fsnewline=1; scharcount=0; sinASC=OUT; lineclp[1+(++sline)]=clptmp=CLPs; linedif[sline]=(Hs GB ...\n"); while ( (cin=fgetc(in) )!=EOF) { if (cin < 0) break; else if (cin=='~') { if ( (cin2=fgetc(in)) < 0) break; else if (cin2 == '{') state = IN; else if (cin2 == '}') state = OUT; else if (cin2 == '\n') fprintf (out, "\n"); else fprintf (out, "%c%c", cin+(state==IN?128:0), cin2+(state==IN?128:0)); } else { if (state == IN) { cin2 = fgetc(in); if (cin2 < 0) break; fprintf (out,"%c%c", cin+128, cin2+128); } else fprintf (out, "%c", cin); } } fclose(in); if (ferror(out)) { fprintf(stderr, " GB version %s write error\n", tempfile); bell(); exit(-4); } fclose(out); } ishz(c) int c; { if (c=='{') HZa++; else if (c=='}') HZb++; } int span(m) int m; { int x, y, n, j, k=1; if (m==1) { x = BM-V+lineclp[0]; y=0; for (j=1; j<=sline; j++) { y += lineclp[j]; if (y >= x) { y=0; j--; k++; } } return (k>column)? 1:0; } else { n=1; x=lineclp[0]; do { x += lineclp[n++]; y=0; k=1; for (j=1; j<=sline; j++) { y += lineclp[j]; if (y >= x) { y=0; j--; k++; } } if (k==column && yBM)? BM :(x-lineclp[0]+cTM); } while (k>column); } } prescan() { int i, m, n, ch1, ch2; long addr; for (i=0; i<8180; i++) fstring[i]=0; fprintf(stderr, "Scanning document ...\n"); while ((ch1=fgetc(in))!=EOF) { if (ch1>=0xA1) { if ((ch2=fgetc(in))==EOF) break; else if (ch1==0xa3 && isalnum(ch2-128)) continue; else if (ch2>=0xA1) { addr=(ch1-0xA1)*94+ch2-0xA1; /* fstring[(addr>=1410)? (addr-564):addr]++; */ /* Do NOT skip for cclib.24 */ fstring[addr]++; } else if (ch2=='~') if ((ch1=fgetc(in))!=EOF) ishz(ch1); } else if (ch1=='~') if ((ch2=fgetc(in))!=EOF) ishz(ch2); } fclose (in); opnfile(IN); /* strcpy(PSfile, INfile); */ i = 0; while ((INfile[i] != '.') && (i < strlen(INfile))) { PSfile[i] = INfile[i]; i++; } PSfile[i]='\0'; #if VMS i=strlen(PSfile); while (PSfile[i]!=';' && i) i--; if (i>1) PSfile[i]='\0'; #endif strcat(PSfile, ".ps"); if (HZa>0 && HZb>0 && !hz_to_gb) { if (!Hzfile) fprintf(stderr, "Input file is in Hz format, is that right (Y/N)?\n"); hz_to_gb=(Hzfile)? 1:(yes(2)? 1:0); HZa=HZb=0; if (hz_to_gb) { hz2gb(); strcat(INfile, "_GB"); rename(tempfile, INfile); opnfile(IN); opnfile(OUT); return; } } if (!HZa || !HZb) { fstring[0]=m=n=0; for (i=0; i<8180; i++) { if (fstring[i]) n++; m += fstring[i]; ptstring[i]=NULL; } fprintf(stderr, "There are %d different words and total %d words in this document\n", n, m); n=0; do { m=0; n++; for (i=1; i<8180; i++) if (fstring[i]>n) m++; } while (m > nCNdict); nCNdict=m; for (i=1; i<8180; i++) fstring[i] += ((fstring[i]>n)? -5000:100); } } int yes(n) int n; { char csx[50]; do { bell(); gets(csx); if ((toupper(csx[0]))=='Y') return 1; else if ((toupper(csx[0]))=='N') return 0; else if (n<=1) return n; else csx[0]='\0'; fprintf(stderr, "(Y/N) ?\n"); } while (csx[0]=='\0'); } main (argc,argv) int argc; char **argv; { int i, k, k1, j, jmax, c; int m, n, endfile=0; int search_ctrl(), print_ctrl(), span(); unsigned char ch1, ch2; /* get environment variable */ if(getenv(CN2PSFNT) != NULL) strcpy(CCLIB, getenv(CN2PSFNT)); i=init(argc,argv); if (hz_to_gb) { hz2gb(); strcat(INfile, "_GB"); rename(tempfile, INfile); bell(); exit(0); } style(); prescan(); if (hz_to_gb) prescan(); fprintf(stderr, "GB --> PS ...\n"); ps_header(); V=TM; H=LM; fprintf(out,"%%%%Page: %d %d\n", pagecount, pagecount); fprintf(out,"save\n"); inbuf[j=0]=getc(in); jmax=1; while (j < jmax) { /* reorganize inbuf */ if (!endfile && (jmax-j) < 8000) { jmax=jmax-j; if (j>0) for (n=0; n <= jmax; n++) inbuf[n]=inbuf[n+j]; j=0; n=10200-jmax; while (--n>0 && (c=getc(in))!=EOF) inbuf[jmax++]=c; inbuf[jmax]='\0'; if (c==EOF) endfile=1; } ASPs = ASP; CSPs = CSP; CLPs = CLP; Hs = LM; sline=fsnewline=0; lineclp[0]=lineclp[1]=clptmp=CLPs; m=j; if (chp1 !=0 && chp2 != 0) scanCH(chp1, chp2); else if (chp1 != 0) scanASC(chp1); SEARCH: while (!fsnewline && (m < (jmax-1) || (endfile && m= 0xA1) { if (m==jmax) scanASC(ch1); else if ( (ch2=inbuf[m++]) >= 0xa1) { if (ch1==0xa3 && isalnum(ch2-128)) scanASC(ch2-128); else scanCH(ch1,ch2); } else { scanASC(ch1); if (ch2=='@' && inbuf[m]=='[' && inbuf[m+3]==']') { if (search_ctrl(inbuf[m+1], inbuf[m+2])) m += 4; else scanASC('@'); } } } else if (ch1=='@' && inbuf[m]=='[' && inbuf[m+3]==']') { if (search_ctrl(inbuf[m+1], inbuf[m+2])) m += 4; else scanASC('@'); } else scanASC(ch1); } if (column==1) goto PRINTa; else { if (SCN==2) goto PRINTa; if ( (k1=span(1))==1 || (endfile && m==jmax) ) { if (endfile && m==jmax) { /* see search_ctrl SCN=2 */ snewline(1); cBM=span(0); } else cBM = BM; cLM = LM; H = LM; pcolumn = 1; goto PRINTa; } } fsnewline = 0; goto SEARCH; PRINTa: chs1=chs2=0; pline=1; PRINTb: fnewline=0; if (chp1 !=0 && chp2 != 0) putCH(chp1, chp2); else if (chp1 != 0) putASC(chp1); chp1=chp2=0; while (!fnewline && (j < (jmax-1) || (endfile && j= 0xa1) { if (j==jmax) putASC(ch1); else if ( (ch2=inbuf[j++]) >= 0xa1) { if (ch1==0xa3 && isalnum(ch2-128)) putASC(ch2-128); else putCH(ch1, ch2); } else { putASC(ch1); if (ch2=='@' && inbuf[j]=='[' && inbuf[j+3]==']') { if (print_ctrl(inbuf[j+1], inbuf[j+2])) j += 4; else putASC('@'); } } } else if (ch1=='@' && inbuf[j]=='[' && inbuf[j+3]==']') { if (print_ctrl(inbuf[j+1], inbuf[j+2])) j += 4; else putASC('@'); } else putASC(ch1); } if (column==1) sline = 0; if (pline <=sline && j < jmax) goto PRINTb; } flag=1; end_page (); cleanup(); if (hz_to_gb) fprintf(stderr, "A GB version of the Hz document is preserved: %s\n", INfile); exit(0); }