xref: /plan9-contrib/sys/src/cmd/postscript/tr2post/utils.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1*219b2ee8SDavid du Colombier #include <u.h>
2*219b2ee8SDavid du Colombier #include <libc.h>
3*219b2ee8SDavid du Colombier #include <bio.h>
4*219b2ee8SDavid du Colombier #include "../common/common.h"
5*219b2ee8SDavid du Colombier #include "tr2post.h"
6*219b2ee8SDavid du Colombier 
7*219b2ee8SDavid du Colombier int hpos = 0, vpos = 0;
8*219b2ee8SDavid du Colombier int fontsize, fontpos;
9*219b2ee8SDavid du Colombier 
10*219b2ee8SDavid du Colombier #define MAXSTR	128
11*219b2ee8SDavid du Colombier int trindex;			/* index into trofftab of current troff font */
12*219b2ee8SDavid du Colombier static int expecthmot = 0;
13*219b2ee8SDavid du Colombier 
14*219b2ee8SDavid du Colombier void
15*219b2ee8SDavid du Colombier initialize(void) {
16*219b2ee8SDavid du Colombier }
17*219b2ee8SDavid du Colombier 
18*219b2ee8SDavid du Colombier void
19*219b2ee8SDavid du Colombier hgoto(int x) {
20*219b2ee8SDavid du Colombier 	hpos = x;
21*219b2ee8SDavid du Colombier 	if (pageon()) {
22*219b2ee8SDavid du Colombier 		endstring();
23*219b2ee8SDavid du Colombier /*		Bprint(Bstdout, "%d %d m\n", hpos, vpos); */
24*219b2ee8SDavid du Colombier 	}
25*219b2ee8SDavid du Colombier }
26*219b2ee8SDavid du Colombier 
27*219b2ee8SDavid du Colombier void
28*219b2ee8SDavid du Colombier vgoto(int y) {
29*219b2ee8SDavid du Colombier 	vpos = y;
30*219b2ee8SDavid du Colombier 	if (pageon()) {
31*219b2ee8SDavid du Colombier 		endstring();
32*219b2ee8SDavid du Colombier /*		Bprint(Bstdout, "%d %d m\n", hpos, vpos); */
33*219b2ee8SDavid du Colombier 	}
34*219b2ee8SDavid du Colombier }
35*219b2ee8SDavid du Colombier 
36*219b2ee8SDavid du Colombier void
37*219b2ee8SDavid du Colombier hmot(int x) {
38*219b2ee8SDavid du Colombier 	int delta;
39*219b2ee8SDavid du Colombier 
40*219b2ee8SDavid du Colombier 	if ((x<expecthmot-1) || (x>expecthmot+1)) {
41*219b2ee8SDavid du Colombier 		delta = x - expecthmot;
42*219b2ee8SDavid du Colombier 		if (curtrofffontid <0 || curtrofffontid >= troffontcnt) {
43*219b2ee8SDavid du Colombier 			Bprint(Bstderr, "troffontcnt=%d curtrofffontid=%d\n", troffontcnt, curtrofffontid);
44*219b2ee8SDavid du Colombier 			Bflush(Bstderr);
45*219b2ee8SDavid du Colombier 			exits("");
46*219b2ee8SDavid du Colombier 		}
47*219b2ee8SDavid du Colombier 		if (delta == troffontab[curtrofffontid].spacewidth*fontsize/10 && isinstring()) {
48*219b2ee8SDavid du Colombier 			if (pageon()) runeout(' ');
49*219b2ee8SDavid du Colombier 		} else {
50*219b2ee8SDavid du Colombier 			if (pageon()) {
51*219b2ee8SDavid du Colombier 				endstring();
52*219b2ee8SDavid du Colombier 				/* Bprint(Bstdout, " %d 0 rmoveto ", delta); */
53*219b2ee8SDavid du Colombier /*				Bprint(Bstdout, " %d %d m ", hpos+x, vpos); */
54*219b2ee8SDavid du Colombier 				if (debug) Bprint(Bstderr, "x=%d expecthmot=%d\n", x, expecthmot);
55*219b2ee8SDavid du Colombier 			}
56*219b2ee8SDavid du Colombier 		}
57*219b2ee8SDavid du Colombier 	}
58*219b2ee8SDavid du Colombier 	hpos += x;
59*219b2ee8SDavid du Colombier 	expecthmot = 0;
60*219b2ee8SDavid du Colombier }
61*219b2ee8SDavid du Colombier 
62*219b2ee8SDavid du Colombier void
63*219b2ee8SDavid du Colombier vmot(int y) {
64*219b2ee8SDavid du Colombier 	endstring();
65*219b2ee8SDavid du Colombier /*	Bprint(Bstdout, " 0 %d rmoveto ", -y); */
66*219b2ee8SDavid du Colombier 	vpos += y;
67*219b2ee8SDavid du Colombier }
68*219b2ee8SDavid du Colombier 
69*219b2ee8SDavid du Colombier struct charent **
70*219b2ee8SDavid du Colombier findglyph(int trfid, Rune rune, char *stoken) {
71*219b2ee8SDavid du Colombier 	struct charent **cp;
72*219b2ee8SDavid du Colombier 
73*219b2ee8SDavid du Colombier 	for (cp = &(troffontab[trfid].charent[RUNEGETGROUP(rune)][RUNEGETCHAR(rune)]); *cp != 0; cp = &((*cp)->next)) {
74*219b2ee8SDavid du Colombier 		if ((*cp)->name) {
75*219b2ee8SDavid du Colombier 			if (debug) Bprint(Bstderr, "looking for <%s>, have <%s> in font %s\n", stoken, (*cp)->name, troffontab[trfid].trfontid);
76*219b2ee8SDavid du Colombier 			if (strcmp((*cp)->name, stoken) == 0)
77*219b2ee8SDavid du Colombier 				break;
78*219b2ee8SDavid du Colombier 		}
79*219b2ee8SDavid du Colombier 	}
80*219b2ee8SDavid du Colombier 	return(cp);
81*219b2ee8SDavid du Colombier }
82*219b2ee8SDavid du Colombier 
83*219b2ee8SDavid du Colombier /* output glyph.  Use first rune to look up character (hash)
84*219b2ee8SDavid du Colombier  * then use stoken UTF string to find correct glyph in linked
85*219b2ee8SDavid du Colombier  * list of glyphs in bucket.
86*219b2ee8SDavid du Colombier  */
87*219b2ee8SDavid du Colombier void
88*219b2ee8SDavid du Colombier glyphout(Rune rune, char *stoken, BOOLEAN specialflag) {
89*219b2ee8SDavid du Colombier 	struct charent **cp;
90*219b2ee8SDavid du Colombier 	struct troffont *tfp;
91*219b2ee8SDavid du Colombier 	struct psfent *psfp;
92*219b2ee8SDavid du Colombier 	int i, t;
93*219b2ee8SDavid du Colombier 	int fontid;	/* this is the troff font table index, not the mounted font table index */
94*219b2ee8SDavid du Colombier 	int mi, fi, wid;
95*219b2ee8SDavid du Colombier 	Rune r;
96*219b2ee8SDavid du Colombier 
97*219b2ee8SDavid du Colombier 	settrfont();
98*219b2ee8SDavid du Colombier 
99*219b2ee8SDavid du Colombier 	/* check current font for the character, special or not */
100*219b2ee8SDavid du Colombier 	fontid = curtrofffontid;
101*219b2ee8SDavid du Colombier if (debug) fprint(2, "	looking through current font: trying %s\n", troffontab[fontid].trfontid);
102*219b2ee8SDavid du Colombier 	cp = findglyph(fontid, rune, stoken);
103*219b2ee8SDavid du Colombier 	if (*cp != 0) goto foundit;
104*219b2ee8SDavid du Colombier 
105*219b2ee8SDavid du Colombier 	if (specialflag) {
106*219b2ee8SDavid du Colombier 		if (expecthmot) hmot(0);
107*219b2ee8SDavid du Colombier 
108*219b2ee8SDavid du Colombier 		/* check special fonts for the special character */
109*219b2ee8SDavid du Colombier 		/* cycle through the (troff) mounted fonts starting at the next font */
110*219b2ee8SDavid du Colombier 		for (mi=0; mi<fontmnt; mi++) {
111*219b2ee8SDavid du Colombier 			if (troffontab[fontid].trfontid==0) error(WARNING, "glyphout:troffontab[%d].trfontid=0x%x, botch!\n",
112*219b2ee8SDavid du Colombier 				fontid, troffontab[fontid].trfontid);
113*219b2ee8SDavid du Colombier 			if (fontmtab[mi]==0) {
114*219b2ee8SDavid du Colombier 				if (debug) fprint(2, "fontmtab[%d]=0x%x, fontmnt=%d\n", mi, fontmtab[mi], fontmnt);
115*219b2ee8SDavid du Colombier 				continue;
116*219b2ee8SDavid du Colombier 			}
117*219b2ee8SDavid du Colombier 			if (strcmp(troffontab[fontid].trfontid, fontmtab[mi])==0) break;
118*219b2ee8SDavid du Colombier 		}
119*219b2ee8SDavid du Colombier 		if (mi==fontmnt) error(FATAL, "current troff font is not mounted, botch!\n");
120*219b2ee8SDavid du Colombier 		for (i=(mi+1)%fontmnt; i!=mi; i=(i+1)%fontmnt) {
121*219b2ee8SDavid du Colombier 			if (fontmtab[i]==0) {
122*219b2ee8SDavid du Colombier 				if (debug) fprint(2, "fontmtab[%d]=0x%x, fontmnt=%d\n", i, fontmtab[i], fontmnt);
123*219b2ee8SDavid du Colombier 				continue;
124*219b2ee8SDavid du Colombier 			}
125*219b2ee8SDavid du Colombier 			fontid = findtfn(fontmtab[i], TRUE);
126*219b2ee8SDavid du Colombier if (debug) fprint(2, "	looking through special fonts: trying %s\n", troffontab[fontid].trfontid);
127*219b2ee8SDavid du Colombier 			if (troffontab[fontid].special) {
128*219b2ee8SDavid du Colombier 				cp = findglyph(fontid, rune, stoken);
129*219b2ee8SDavid du Colombier 				if (*cp != 0) goto foundit;
130*219b2ee8SDavid du Colombier 			}
131*219b2ee8SDavid du Colombier 		}
132*219b2ee8SDavid du Colombier 
133*219b2ee8SDavid du Colombier 		/* check font 1 (if current font is not font 1) for the special character */
134*219b2ee8SDavid du Colombier 		if (mi != 1) {
135*219b2ee8SDavid du Colombier 				fontid = findtfn(fontmtab[1], TRUE);;
136*219b2ee8SDavid du Colombier if (debug) fprint(2, "	looking through font at position 1: trying %s\n", troffontab[fontid].trfontid);
137*219b2ee8SDavid du Colombier 				cp = findglyph(fontid, rune, stoken);
138*219b2ee8SDavid du Colombier 				if (*cp != 0) goto foundit;
139*219b2ee8SDavid du Colombier 		}
140*219b2ee8SDavid du Colombier 	}
141*219b2ee8SDavid du Colombier 
142*219b2ee8SDavid du Colombier 	if (*cp == 0) {
143*219b2ee8SDavid du Colombier 		error(WARNING, "cannot find glyph, rune=0x%x stoken=<%s> troff font %s\n", rune, stoken,
144*219b2ee8SDavid du Colombier 			troffontab[curtrofffontid].trfontid);
145*219b2ee8SDavid du Colombier 		expecthmot = 0;
146*219b2ee8SDavid du Colombier 	}
147*219b2ee8SDavid du Colombier 
148*219b2ee8SDavid du Colombier 	/* use the peter face in lieu of the character that we couldn't find */
149*219b2ee8SDavid du Colombier 	rune = 'p';	stoken = "pw";
150*219b2ee8SDavid du Colombier 	for (i=(mi+1)%fontmnt; i!=mi; i=(i+1)%fontmnt) {
151*219b2ee8SDavid du Colombier 		if (fontmtab[i]==0) {
152*219b2ee8SDavid du Colombier 			if (debug) fprint(2, "fontmtab[%d]=0x%x\n", i, fontmtab[i]);
153*219b2ee8SDavid du Colombier 			continue;
154*219b2ee8SDavid du Colombier 		}
155*219b2ee8SDavid du Colombier 		fontid = findtfn(fontmtab[i], TRUE);
156*219b2ee8SDavid du Colombier if (debug) fprint(2, "	looking through special fonts: trying %s\n", troffontab[fontid].trfontid);
157*219b2ee8SDavid du Colombier 		if (troffontab[fontid].special) {
158*219b2ee8SDavid du Colombier 			cp = findglyph(fontid, rune, stoken);
159*219b2ee8SDavid du Colombier 			if (*cp != 0) goto foundit;
160*219b2ee8SDavid du Colombier 		}
161*219b2ee8SDavid du Colombier 	}
162*219b2ee8SDavid du Colombier 
163*219b2ee8SDavid du Colombier 	if (*cp == 0) {
164*219b2ee8SDavid du Colombier 		error(WARNING, "cannot find glyph, rune=0x%x stoken=<%s> troff font %s\n", rune, stoken,
165*219b2ee8SDavid du Colombier 			troffontab[curtrofffontid].trfontid);
166*219b2ee8SDavid du Colombier 		expecthmot = 0;
167*219b2ee8SDavid du Colombier 		return;
168*219b2ee8SDavid du Colombier 	}
169*219b2ee8SDavid du Colombier 
170*219b2ee8SDavid du Colombier foundit:
171*219b2ee8SDavid du Colombier 	t = (((*cp)->postfontid&0xff)<<8) | ((*cp)->postcharid&0xff);
172*219b2ee8SDavid du Colombier 	if (debug) {
173*219b2ee8SDavid du Colombier 		Bprint(Bstderr, "runeout(0x%x)<%C> postfontid=0x%x postcharid=0x%x troffcharwidth=%d\n",
174*219b2ee8SDavid du Colombier 			rune, rune, (*cp)->postfontid, (*cp)->postcharid, (*cp)->troffcharwidth);
175*219b2ee8SDavid du Colombier 	}
176*219b2ee8SDavid du Colombier 
177*219b2ee8SDavid du Colombier 	tfp = &(troffontab[fontid]);
178*219b2ee8SDavid du Colombier 	for (i=0; i<tfp->psfmapsize; i++) {
179*219b2ee8SDavid du Colombier 		psfp = &(tfp->psfmap[i]);
180*219b2ee8SDavid du Colombier 		if(t>=psfp->start && t<=psfp->end) break;
181*219b2ee8SDavid du Colombier 	}
182*219b2ee8SDavid du Colombier 	if (i >= tfp->psfmapsize)
183*219b2ee8SDavid du Colombier 		error(FATAL, "character <0x%x> does not have a Postscript font defined.\n", rune);
184*219b2ee8SDavid du Colombier 
185*219b2ee8SDavid du Colombier 	setpsfont(psfp->psftid, fontsize);
186*219b2ee8SDavid du Colombier 
187*219b2ee8SDavid du Colombier 	if (t == 0x0001) {	/* character is in charlib */
188*219b2ee8SDavid du Colombier 		endstring();
189*219b2ee8SDavid du Colombier 		if (pageon()) {
190*219b2ee8SDavid du Colombier 			struct charent *tcp;
191*219b2ee8SDavid du Colombier 
192*219b2ee8SDavid du Colombier 			Bprint(Bstdout, "%d %d m ", hpos, vpos);
193*219b2ee8SDavid du Colombier 			/* if char is unicode character rather than name, clean up for postscript */
194*219b2ee8SDavid du Colombier 			wid = chartorune(&r, (*cp)->name);
195*219b2ee8SDavid du Colombier 			if(' '<r && r<0x7F)
196*219b2ee8SDavid du Colombier 				Bprint(Bstdout, "%d build_%s\n", (*cp)->troffcharwidth, (*cp)->name);
197*219b2ee8SDavid du Colombier 			else{
198*219b2ee8SDavid du Colombier 				if((*cp)->name[wid] != 0)
199*219b2ee8SDavid du Colombier 					error(FATAL, "character <%s> badly named\n", (*cp)->name);
200*219b2ee8SDavid du Colombier 				Bprint(Bstdout, "%d build_X%.4x\n", (*cp)->troffcharwidth, r);
201*219b2ee8SDavid du Colombier 			}
202*219b2ee8SDavid du Colombier 
203*219b2ee8SDavid du Colombier 			/* stash charent pointer in a list so that we can print these character definitions
204*219b2ee8SDavid du Colombier 			 * in the prologue.
205*219b2ee8SDavid du Colombier 			 */
206*219b2ee8SDavid du Colombier 			for (i=0; i<build_char_cnt; i++)
207*219b2ee8SDavid du Colombier 				if (*cp == build_char_list[i]) break;
208*219b2ee8SDavid du Colombier 			if (i == build_char_cnt) {
209*219b2ee8SDavid du Colombier 				build_char_list = galloc(build_char_list, sizeof(struct charent *) * ++build_char_cnt,
210*219b2ee8SDavid du Colombier 				"build_char_list");
211*219b2ee8SDavid du Colombier 				build_char_list[build_char_cnt-1] = *cp;
212*219b2ee8SDavid du Colombier 			}
213*219b2ee8SDavid du Colombier 		}
214*219b2ee8SDavid du Colombier 		expecthmot = (*cp)->troffcharwidth * fontsize / unitwidth;
215*219b2ee8SDavid du Colombier 	} else if (isinstring() || rune != ' ') {
216*219b2ee8SDavid du Colombier 		startstring();
217*219b2ee8SDavid du Colombier 		if (pageon()) {
218*219b2ee8SDavid du Colombier 			if (rune == ' ')
219*219b2ee8SDavid du Colombier 				Bprint(Bstdout, " ");
220*219b2ee8SDavid du Colombier 			else
221*219b2ee8SDavid du Colombier 				Bprint(Bstdout, "%s", charcode[RUNEGETCHAR(t)].str);
222*219b2ee8SDavid du Colombier 		}
223*219b2ee8SDavid du Colombier 		expecthmot = (*cp)->troffcharwidth * fontsize / unitwidth;
224*219b2ee8SDavid du Colombier 	}
225*219b2ee8SDavid du Colombier }
226*219b2ee8SDavid du Colombier 
227*219b2ee8SDavid du Colombier /* runeout puts a symbol into a string (queue) to be output.
228*219b2ee8SDavid du Colombier  * It also has to keep track of the current and last symbol
229*219b2ee8SDavid du Colombier  * output to check that the spacing is correct by default
230*219b2ee8SDavid du Colombier  * or needs to be adjusted with a spacing operation.
231*219b2ee8SDavid du Colombier  */
232*219b2ee8SDavid du Colombier 
233*219b2ee8SDavid du Colombier void
234*219b2ee8SDavid du Colombier runeout(Rune rune) {
235*219b2ee8SDavid du Colombier 	char stoken[UTFmax+1];
236*219b2ee8SDavid du Colombier 	int i;
237*219b2ee8SDavid du Colombier 
238*219b2ee8SDavid du Colombier 	i = runetochar(stoken, &rune);
239*219b2ee8SDavid du Colombier 	stoken[i] = '\0';
240*219b2ee8SDavid du Colombier 	glyphout(rune, stoken, TRUE);
241*219b2ee8SDavid du Colombier }
242*219b2ee8SDavid du Colombier 
243*219b2ee8SDavid du Colombier void
244*219b2ee8SDavid du Colombier specialout(char *stoken) {
245*219b2ee8SDavid du Colombier 	Rune rune;
246*219b2ee8SDavid du Colombier 	int i;
247*219b2ee8SDavid du Colombier 
248*219b2ee8SDavid du Colombier 	i = chartorune(&rune, stoken);
249*219b2ee8SDavid du Colombier 	glyphout(rune, stoken, TRUE);
250*219b2ee8SDavid du Colombier }
251*219b2ee8SDavid du Colombier 
252*219b2ee8SDavid du Colombier void
253*219b2ee8SDavid du Colombier graphfunc(Biobufhdr *bp) {
254*219b2ee8SDavid du Colombier }
255*219b2ee8SDavid du Colombier 
256*219b2ee8SDavid du Colombier long
257*219b2ee8SDavid du Colombier nametorune(char *name) {
258*219b2ee8SDavid du Colombier 	return(0);
259*219b2ee8SDavid du Colombier }
260*219b2ee8SDavid du Colombier 
261*219b2ee8SDavid du Colombier void
262*219b2ee8SDavid du Colombier notavail(char *msg) {
263*219b2ee8SDavid du Colombier 	Bprint(Bstderr, "%s is not available at this time.\n", msg);
264*219b2ee8SDavid du Colombier }
265