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 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 67 vmot(int y) { 68 endstring(); 69 /* Bprint(Bstdout, " 0 %d rmoveto ", -y); */ 70 vpos += y; 71 } 72 73 struct charent ** 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 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 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 265 specialout(char *stoken) { 266 Rune rune; 267 268 chartorune(&rune, stoken); 269 glyphout(rune, stoken, TRUE); 270 } 271 272 void 273 graphfunc(Biobufhdr *bp) { 274 USED(bp); 275 } 276 277 long 278 nametorune(char *name) { 279 USED(name); 280 return(0); 281 } 282 283 void 284 notavail(char *msg) { 285 fprint(2, "%s is not available at this time.\n", msg); 286 } 287