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