xref: /plan9/sys/src/cmd/postscript/tr2post/utils.c (revision 456a8764e4ea95d7aa2c2cf34e5112293070bc84)
1219b2ee8SDavid du Colombier #include <u.h>
2219b2ee8SDavid du Colombier #include <libc.h>
3219b2ee8SDavid du Colombier #include <bio.h>
4219b2ee8SDavid du Colombier #include "../common/common.h"
5219b2ee8SDavid du Colombier #include "tr2post.h"
6219b2ee8SDavid du Colombier 
7219b2ee8SDavid du Colombier int hpos = 0, vpos = 0;
8219b2ee8SDavid du Colombier int fontsize, fontpos;
9219b2ee8SDavid du Colombier 
10219b2ee8SDavid du Colombier #define MAXSTR	128
11219b2ee8SDavid du Colombier int trindex;			/* index into trofftab of current troff font */
12219b2ee8SDavid du Colombier static int expecthmot = 0;
13219b2ee8SDavid du Colombier 
14219b2ee8SDavid du Colombier void
initialize(void)15219b2ee8SDavid du Colombier initialize(void) {
16219b2ee8SDavid du Colombier }
17219b2ee8SDavid du Colombier 
18219b2ee8SDavid du Colombier void
hgoto(int x)19219b2ee8SDavid du Colombier hgoto(int x) {
20219b2ee8SDavid du Colombier 	hpos = x;
21219b2ee8SDavid du Colombier 	if (pageon()) {
22219b2ee8SDavid du Colombier 		endstring();
23219b2ee8SDavid du Colombier /*		Bprint(Bstdout, "%d %d m\n", hpos, vpos); */
24219b2ee8SDavid du Colombier 	}
25219b2ee8SDavid du Colombier }
26219b2ee8SDavid du Colombier 
27219b2ee8SDavid du Colombier void
vgoto(int y)28219b2ee8SDavid du Colombier vgoto(int y) {
29219b2ee8SDavid du Colombier 	vpos = y;
30219b2ee8SDavid du Colombier 	if (pageon()) {
31219b2ee8SDavid du Colombier 		endstring();
32219b2ee8SDavid du Colombier /*		Bprint(Bstdout, "%d %d m\n", hpos, vpos); */
33219b2ee8SDavid du Colombier 	}
34219b2ee8SDavid du Colombier }
35219b2ee8SDavid du Colombier 
36219b2ee8SDavid du Colombier void
hmot(int x)37219b2ee8SDavid du Colombier hmot(int x) {
38219b2ee8SDavid du Colombier 	int delta;
39219b2ee8SDavid du Colombier 
40219b2ee8SDavid du Colombier 	if ((x<expecthmot-1) || (x>expecthmot+1)) {
41219b2ee8SDavid du Colombier 		delta = x - expecthmot;
42219b2ee8SDavid du Colombier 		if (curtrofffontid <0 || curtrofffontid >= troffontcnt) {
43*456a8764SDavid du Colombier 			fprint(2, "troffontcnt=%d curtrofffontid=%d\n",
44*456a8764SDavid du Colombier 				troffontcnt, curtrofffontid);
45219b2ee8SDavid du Colombier 			exits("");
46219b2ee8SDavid du Colombier 		}
47*456a8764SDavid du Colombier 		if (delta == troffontab[curtrofffontid].spacewidth*fontsize/10 &&
48*456a8764SDavid du Colombier 		    isinstring()) {
49*456a8764SDavid du Colombier 			if (pageon())
50*456a8764SDavid du Colombier 				runeout(' ');
51219b2ee8SDavid du Colombier 		} else {
52219b2ee8SDavid du Colombier 			if (pageon()) {
53219b2ee8SDavid du Colombier 				endstring();
54219b2ee8SDavid du Colombier 				/* Bprint(Bstdout, " %d 0 rmoveto ", delta); */
55219b2ee8SDavid du Colombier /*				Bprint(Bstdout, " %d %d m ", hpos+x, vpos); */
56*456a8764SDavid du Colombier 				if (debug)
57*456a8764SDavid du Colombier 					fprint(2, "x=%d expecthmot=%d\n",
58*456a8764SDavid du Colombier 						x, expecthmot);
59219b2ee8SDavid du Colombier 			}
60219b2ee8SDavid du Colombier 		}
61219b2ee8SDavid du Colombier 	}
62219b2ee8SDavid du Colombier 	hpos += x;
63219b2ee8SDavid du Colombier 	expecthmot = 0;
64219b2ee8SDavid du Colombier }
65219b2ee8SDavid du Colombier 
66219b2ee8SDavid du Colombier void
vmot(int y)67219b2ee8SDavid du Colombier vmot(int y) {
68219b2ee8SDavid du Colombier 	endstring();
69219b2ee8SDavid du Colombier /*	Bprint(Bstdout, " 0 %d rmoveto ", -y); */
70219b2ee8SDavid du Colombier 	vpos += y;
71219b2ee8SDavid du Colombier }
72219b2ee8SDavid du Colombier 
73219b2ee8SDavid du Colombier struct charent **
findglyph(int trfid,Rune rune,char * stoken)74219b2ee8SDavid du Colombier findglyph(int trfid, Rune rune, char *stoken) {
75219b2ee8SDavid du Colombier 	struct charent **cp;
76219b2ee8SDavid du Colombier 
77219b2ee8SDavid du Colombier 	for (cp = &(troffontab[trfid].charent[RUNEGETGROUP(rune)][RUNEGETCHAR(rune)]); *cp != 0; cp = &((*cp)->next)) {
78219b2ee8SDavid du Colombier 		if ((*cp)->name) {
79*456a8764SDavid du Colombier 			if (debug) fprint(2, "looking for <%s>, have <%s> in font %s\n", stoken, (*cp)->name, troffontab[trfid].trfontid);
80219b2ee8SDavid du Colombier 			if (strcmp((*cp)->name, stoken) == 0)
81219b2ee8SDavid du Colombier 				break;
82219b2ee8SDavid du Colombier 		}
83219b2ee8SDavid du Colombier 	}
84219b2ee8SDavid du Colombier 	return(cp);
85219b2ee8SDavid du Colombier }
86219b2ee8SDavid du Colombier 
87219b2ee8SDavid du Colombier /* output glyph.  Use first rune to look up character (hash)
88219b2ee8SDavid du Colombier  * then use stoken UTF string to find correct glyph in linked
89219b2ee8SDavid du Colombier  * list of glyphs in bucket.
90219b2ee8SDavid du Colombier  */
91219b2ee8SDavid du Colombier void
glyphout(Rune rune,char * stoken,BOOLEAN specialflag)92219b2ee8SDavid du Colombier glyphout(Rune rune, char *stoken, BOOLEAN specialflag) {
93219b2ee8SDavid du Colombier 	struct charent **cp;
94219b2ee8SDavid du Colombier 	struct troffont *tfp;
95219b2ee8SDavid du Colombier 	struct psfent *psfp;
96*456a8764SDavid du Colombier 	int i, t, mi, wid;
97219b2ee8SDavid du Colombier 	int fontid;	/* this is the troff font table index, not the mounted font table index */
98219b2ee8SDavid du Colombier 	Rune r;
99219b2ee8SDavid du Colombier 
100*456a8764SDavid du Colombier 	mi = 0;
101219b2ee8SDavid du Colombier 	settrfont();
102219b2ee8SDavid du Colombier 
103219b2ee8SDavid du Colombier 	/* check current font for the character, special or not */
104219b2ee8SDavid du Colombier 	fontid = curtrofffontid;
105*456a8764SDavid du Colombier 	if (debug)
106*456a8764SDavid du Colombier 		fprint(2, "\tlooking through current font: trying %s\n",
107*456a8764SDavid du Colombier 			troffontab[fontid].trfontid);
108219b2ee8SDavid du Colombier 	cp = findglyph(fontid, rune, stoken);
109*456a8764SDavid du Colombier 	if (*cp != 0)
110*456a8764SDavid du Colombier 		goto foundit;
111219b2ee8SDavid du Colombier 
112219b2ee8SDavid du Colombier 	if (specialflag) {
113*456a8764SDavid du Colombier 		if (expecthmot)
114*456a8764SDavid du Colombier 			hmot(0);
115219b2ee8SDavid du Colombier 
116219b2ee8SDavid du Colombier 		/* check special fonts for the special character */
117219b2ee8SDavid du Colombier 		/* cycle through the (troff) mounted fonts starting at the next font */
118219b2ee8SDavid du Colombier 		for (mi=0; mi<fontmnt; mi++) {
119*456a8764SDavid du Colombier 			if (troffontab[fontid].trfontid==0)
120*456a8764SDavid du Colombier 				error(WARNING, "glyphout:troffontab[%d].trfontid=0x%x, botch!\n",
121219b2ee8SDavid du Colombier 					fontid, troffontab[fontid].trfontid);
122219b2ee8SDavid du Colombier 			if (fontmtab[mi]==0) {
123*456a8764SDavid du Colombier 				if (debug)
124*456a8764SDavid du Colombier 					fprint(2, "fontmtab[%d]=%#p, fontmnt=%d\n",
125*456a8764SDavid du Colombier 						mi, fontmtab[mi], fontmnt);
126219b2ee8SDavid du Colombier 				continue;
127219b2ee8SDavid du Colombier 			}
128*456a8764SDavid du Colombier 			if (strcmp(troffontab[fontid].trfontid, fontmtab[mi])==0)
129*456a8764SDavid du Colombier 				break;
130219b2ee8SDavid du Colombier 		}
131*456a8764SDavid du Colombier 		if (mi==fontmnt)
132*456a8764SDavid du Colombier 			error(FATAL, "current troff font is not mounted, botch!\n");
133219b2ee8SDavid du Colombier 		for (i=(mi+1)%fontmnt; i!=mi; i=(i+1)%fontmnt) {
134219b2ee8SDavid du Colombier 			if (fontmtab[i]==0) {
135*456a8764SDavid du Colombier 				if (debug)
136*456a8764SDavid du Colombier 					fprint(2, "fontmtab[%d]=%#p, fontmnt=%d\n",
137*456a8764SDavid du Colombier 						i, fontmtab[i], fontmnt);
138219b2ee8SDavid du Colombier 				continue;
139219b2ee8SDavid du Colombier 			}
140219b2ee8SDavid du Colombier 			fontid = findtfn(fontmtab[i], TRUE);
141219b2ee8SDavid du Colombier if (debug) fprint(2, "	looking through special fonts: trying %s\n", troffontab[fontid].trfontid);
142219b2ee8SDavid du Colombier 			if (troffontab[fontid].special) {
143219b2ee8SDavid du Colombier 				cp = findglyph(fontid, rune, stoken);
144*456a8764SDavid du Colombier 				if (*cp != 0)
145*456a8764SDavid du Colombier 					goto foundit;
146219b2ee8SDavid du Colombier 			}
147219b2ee8SDavid du Colombier 		}
148219b2ee8SDavid du Colombier 
149219b2ee8SDavid du Colombier 		/* check font 1 (if current font is not font 1) for the special character */
150219b2ee8SDavid du Colombier 		if (mi != 1) {
151219b2ee8SDavid du Colombier 				fontid = findtfn(fontmtab[1], TRUE);;
152219b2ee8SDavid du Colombier if (debug) fprint(2, "	looking through font at position 1: trying %s\n", troffontab[fontid].trfontid);
153219b2ee8SDavid du Colombier 				cp = findglyph(fontid, rune, stoken);
154219b2ee8SDavid du Colombier 				if (*cp != 0) goto foundit;
155219b2ee8SDavid du Colombier 		}
156219b2ee8SDavid du Colombier 	}
157219b2ee8SDavid du Colombier 
158219b2ee8SDavid du Colombier 	if (*cp == 0) {
159219b2ee8SDavid du Colombier 		error(WARNING, "cannot find glyph, rune=0x%x stoken=<%s> troff font %s\n", rune, stoken,
160219b2ee8SDavid du Colombier 			troffontab[curtrofffontid].trfontid);
161219b2ee8SDavid du Colombier 		expecthmot = 0;
162219b2ee8SDavid du Colombier 	}
163219b2ee8SDavid du Colombier 
164219b2ee8SDavid du Colombier 	/* use the peter face in lieu of the character that we couldn't find */
165219b2ee8SDavid du Colombier 	rune = 'p';	stoken = "pw";
166219b2ee8SDavid du Colombier 	for (i=(mi+1)%fontmnt; i!=mi; i=(i+1)%fontmnt) {
167219b2ee8SDavid du Colombier 		if (fontmtab[i]==0) {
168*456a8764SDavid du Colombier 			if (debug) fprint(2, "fontmtab[%d]=%#p\n", i, fontmtab[i]);
169219b2ee8SDavid du Colombier 			continue;
170219b2ee8SDavid du Colombier 		}
171219b2ee8SDavid du Colombier 		fontid = findtfn(fontmtab[i], TRUE);
172219b2ee8SDavid du Colombier if (debug) fprint(2, "	looking through special fonts: trying %s\n", troffontab[fontid].trfontid);
173219b2ee8SDavid du Colombier 		if (troffontab[fontid].special) {
174219b2ee8SDavid du Colombier 			cp = findglyph(fontid, rune, stoken);
175219b2ee8SDavid du Colombier 			if (*cp != 0) goto foundit;
176219b2ee8SDavid du Colombier 		}
177219b2ee8SDavid du Colombier 	}
178219b2ee8SDavid du Colombier 
179219b2ee8SDavid du Colombier 	if (*cp == 0) {
180*456a8764SDavid du Colombier 		error(WARNING, "cannot find glyph, rune=0x%x stoken=<%s> troff font %s\n",
181*456a8764SDavid du Colombier 			rune, stoken, troffontab[curtrofffontid].trfontid);
182219b2ee8SDavid du Colombier 		expecthmot = 0;
183219b2ee8SDavid du Colombier 		return;
184219b2ee8SDavid du Colombier 	}
185219b2ee8SDavid du Colombier 
186219b2ee8SDavid du Colombier foundit:
187219b2ee8SDavid du Colombier 	t = (((*cp)->postfontid&0xff)<<8) | ((*cp)->postcharid&0xff);
188*456a8764SDavid du Colombier 	if (debug)
189*456a8764SDavid du Colombier 		fprint(2, "runeout(0x%x)<%C> postfontid=0x%x postcharid=0x%x troffcharwidth=%d\n",
190*456a8764SDavid du Colombier 			rune, rune, (*cp)->postfontid, (*cp)->postcharid,
191*456a8764SDavid du Colombier 			(*cp)->troffcharwidth);
192219b2ee8SDavid du Colombier 
193*456a8764SDavid du Colombier 	tfp = &troffontab[fontid];
194*456a8764SDavid du Colombier 	psfp = nil;
195219b2ee8SDavid du Colombier 	for (i=0; i<tfp->psfmapsize; i++) {
196219b2ee8SDavid du Colombier 		psfp = &(tfp->psfmap[i]);
197*456a8764SDavid du Colombier 		if(t>=psfp->start && t<=psfp->end)
198*456a8764SDavid du Colombier 			break;
199219b2ee8SDavid du Colombier 	}
200219b2ee8SDavid du Colombier 	if (i >= tfp->psfmapsize)
201219b2ee8SDavid du Colombier 		error(FATAL, "character <0x%x> does not have a Postscript font defined.\n", rune);
202219b2ee8SDavid du Colombier 
203219b2ee8SDavid du Colombier 	setpsfont(psfp->psftid, fontsize);
204219b2ee8SDavid du Colombier 
205219b2ee8SDavid du Colombier 	if (t == 0x0001) {	/* character is in charlib */
206219b2ee8SDavid du Colombier 		endstring();
207219b2ee8SDavid du Colombier 		if (pageon()) {
208219b2ee8SDavid du Colombier 			Bprint(Bstdout, "%d %d m ", hpos, vpos);
209219b2ee8SDavid du Colombier 			/* if char is unicode character rather than name, clean up for postscript */
210219b2ee8SDavid du Colombier 			wid = chartorune(&r, (*cp)->name);
211219b2ee8SDavid du Colombier 			if(' '<r && r<0x7F)
212*456a8764SDavid du Colombier 				Bprint(Bstdout, "%d build_%s\n",
213*456a8764SDavid du Colombier 					(*cp)->troffcharwidth, (*cp)->name);
214219b2ee8SDavid du Colombier 			else{
215219b2ee8SDavid du Colombier 				if((*cp)->name[wid] != 0)
216219b2ee8SDavid du Colombier 					error(FATAL, "character <%s> badly named\n", (*cp)->name);
217*456a8764SDavid du Colombier 				Bprint(Bstdout, "%d build_X%.4x\n",
218*456a8764SDavid du Colombier 					(*cp)->troffcharwidth, r);
219219b2ee8SDavid du Colombier 			}
220219b2ee8SDavid du Colombier 
221*456a8764SDavid du Colombier 			/*
222*456a8764SDavid du Colombier 			 * stash charent pointer in a list so that we can
223*456a8764SDavid du Colombier 			 * print these character definitions in the prologue.
224219b2ee8SDavid du Colombier 			 */
225219b2ee8SDavid du Colombier 			for (i=0; i<build_char_cnt; i++)
226*456a8764SDavid du Colombier 				if (*cp == build_char_list[i])
227*456a8764SDavid du Colombier 					break;
228219b2ee8SDavid du Colombier 			if (i == build_char_cnt) {
229*456a8764SDavid du Colombier 				build_char_list = galloc(build_char_list,
230*456a8764SDavid du Colombier 					sizeof(struct charent *)*++build_char_cnt,
231219b2ee8SDavid du Colombier 					"build_char_list");
232219b2ee8SDavid du Colombier 				build_char_list[build_char_cnt-1] = *cp;
233219b2ee8SDavid du Colombier 			}
234219b2ee8SDavid du Colombier 		}
235219b2ee8SDavid du Colombier 		expecthmot = (*cp)->troffcharwidth * fontsize / unitwidth;
236219b2ee8SDavid du Colombier 	} else if (isinstring() || rune != ' ') {
237219b2ee8SDavid du Colombier 		startstring();
238*456a8764SDavid du Colombier 		if (pageon())
239219b2ee8SDavid du Colombier 			if (rune == ' ')
240219b2ee8SDavid du Colombier 				Bprint(Bstdout, " ");
241219b2ee8SDavid du Colombier 			else
242219b2ee8SDavid du Colombier 				Bprint(Bstdout, "%s", charcode[RUNEGETCHAR(t)].str);
243219b2ee8SDavid du Colombier 		expecthmot = (*cp)->troffcharwidth * fontsize / unitwidth;
244219b2ee8SDavid du Colombier 	}
245219b2ee8SDavid du Colombier }
246219b2ee8SDavid du Colombier 
247*456a8764SDavid du Colombier /*
248*456a8764SDavid du Colombier  * runeout puts a symbol into a string (queue) to be output.
249219b2ee8SDavid du Colombier  * It also has to keep track of the current and last symbol
250219b2ee8SDavid du Colombier  * output to check that the spacing is correct by default
251219b2ee8SDavid du Colombier  * or needs to be adjusted with a spacing operation.
252219b2ee8SDavid du Colombier  */
253219b2ee8SDavid du Colombier 
254219b2ee8SDavid du Colombier void
runeout(Rune rune)255219b2ee8SDavid du Colombier runeout(Rune rune) {
256219b2ee8SDavid du Colombier 	char stoken[UTFmax+1];
257219b2ee8SDavid du Colombier 	int i;
258219b2ee8SDavid du Colombier 
259219b2ee8SDavid du Colombier 	i = runetochar(stoken, &rune);
260219b2ee8SDavid du Colombier 	stoken[i] = '\0';
261219b2ee8SDavid du Colombier 	glyphout(rune, stoken, TRUE);
262219b2ee8SDavid du Colombier }
263219b2ee8SDavid du Colombier 
264219b2ee8SDavid du Colombier void
specialout(char * stoken)265219b2ee8SDavid du Colombier specialout(char *stoken) {
266219b2ee8SDavid du Colombier 	Rune rune;
267219b2ee8SDavid du Colombier 
268*456a8764SDavid du Colombier 	chartorune(&rune, stoken);
269219b2ee8SDavid du Colombier 	glyphout(rune, stoken, TRUE);
270219b2ee8SDavid du Colombier }
271219b2ee8SDavid du Colombier 
272219b2ee8SDavid du Colombier void
graphfunc(Biobufhdr * bp)273219b2ee8SDavid du Colombier graphfunc(Biobufhdr *bp) {
274*456a8764SDavid du Colombier 	USED(bp);
275219b2ee8SDavid du Colombier }
276219b2ee8SDavid du Colombier 
277219b2ee8SDavid du Colombier long
nametorune(char * name)278219b2ee8SDavid du Colombier nametorune(char *name) {
279*456a8764SDavid du Colombier 	USED(name);
280219b2ee8SDavid du Colombier 	return(0);
281219b2ee8SDavid du Colombier }
282219b2ee8SDavid du Colombier 
283219b2ee8SDavid du Colombier void
notavail(char * msg)284219b2ee8SDavid du Colombier notavail(char *msg) {
285*456a8764SDavid du Colombier 	fprint(2, "%s is not available at this time.\n", msg);
286219b2ee8SDavid du Colombier }
287