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