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