1 /* Unicode | PostScript 2 * start end | offset font name 3 * 0x0000 0x00ff 0x00 LucidaSansUnicode00 4 */ 5 #include <u.h> 6 #include <libc.h> 7 #include <bio.h> 8 #include "common.h" 9 #include "tr2post.h" 10 #include "comments.h" 11 #include "path.h" 12 13 /* Postscript font names, e.g., `LucidaSansUnicode00' 14 * names may only be added because reference to the 15 * names is made by indexing into this table. 16 */ 17 static struct pfnament *pfnafontmtab = 0; 18 static int pfnamcnt = 0; 19 int curpostfontid = -1; 20 int curfontsize = -1; 21 int curtrofffontid = -1; 22 static int curfontpos = -1; 23 24 /* This is troffs mounted font table. It is an anachronism resulting 25 * from the design of the APS typesetter. fontmnt is the 26 * number of positions available. fontmnt is really 11, but 27 * should not be limited. 28 */ 29 int fontmnt = 0; 30 char **fontmtab; 31 32 struct troffont *troffontab = 0; 33 34 int troffontcnt = 0; 35 36 void 37 mountfont(int pos, char *fontname) { 38 int i; 39 40 if (debug) Bprint(Bstderr, "mountfont(%d, %s)\n", pos, fontname); 41 if (pos < 0 || pos >= fontmnt) 42 error(FATAL, "cannot mount a font at position %d,\n can only mount into postions 0-%d\n", 43 pos, fontmnt-1); 44 45 i = strlen(fontname); 46 fontmtab[pos] = galloc(fontmtab[pos], i+1, "mountfont():fontmtab"); 47 strcpy(fontmtab[pos], fontname); 48 if (curfontpos == pos) curfontpos = -1; 49 } 50 51 void 52 settrfont(void) { 53 if (curfontpos == fontpos) return; 54 55 if (fontmtab[fontpos] == 0) 56 error(FATAL, "Font at position %d was not initialized, botch!\n", fontpos); 57 58 curtrofffontid = findtfn(fontmtab[fontpos], 1); 59 if (debug) Bprint(Bstderr, "settrfont()-> curtrofffontid=%d\n", curtrofffontid); 60 curfontpos = fontpos; 61 if (curtrofffontid < 0) { 62 int i; 63 64 error(WARNING, "fontpos=%d\n", fontpos); 65 for (i=0; i<fontmnt; i++) 66 if (fontmtab[i] == 0) 67 error(WARNING, "fontmtab[%d]=0x0\n", i); 68 else 69 error(WARNING, "fontmtab[%d]=%s\n", i, fontmtab[i]); 70 exits("settrfont()"); 71 } 72 } 73 74 void 75 setpsfont(int psftid, int fontsize) { 76 if (psftid == curpostfontid && fontsize == curfontsize) return; 77 if (psftid >= pfnamcnt) 78 error(FATAL, "Postscript font index=%d used but not defined, there are only %d fonts\n", 79 psftid, pfnamcnt); 80 81 endstring(); 82 if (pageon()) { 83 Bprint(Bstdout, "%d /%s f\n", fontsize, pfnafontmtab[psftid].str); 84 pfnafontmtab[psftid].used = 1; 85 curpostfontid = psftid; 86 curfontsize = fontsize; 87 } 88 } 89 90 /* find index of PostScript font name in table 91 * returns -1 if name is not in table 92 * If insflg is not zero 93 * and the name is not found in the table, insert it. 94 */ 95 int 96 findpfn(char *fontname, int insflg) { 97 char *tp; 98 int i; 99 100 for (i=0; i<pfnamcnt; i++) { 101 if (strcmp(pfnafontmtab[i].str, fontname) == 0) 102 return(i); 103 } 104 if (insflg) { 105 tp = galloc(pfnafontmtab, sizeof(struct pfnament)*(pfnamcnt+1), "findpfn():pfnafontmtab"); 106 if (tp == 0) 107 return(-2); 108 pfnafontmtab = (struct pfnament *)tp; 109 i = strlen(fontname); 110 pfnafontmtab[pfnamcnt].str = galloc(0, i+1, "findpfn():pfnafontmtab[].str"); 111 strncpy(pfnafontmtab[pfnamcnt].str, fontname, i); 112 pfnafontmtab[pfnamcnt].str[i] = '\0'; 113 return(pfnamcnt++); 114 } 115 return(-1); 116 } 117 118 char postroffdirname[] = "/sys/lib/postscript/troff"; /* "/sys/lib/postscript/troff/"; */ 119 char troffmetricdirname[] = "/sys/lib/troff/font"; /* "/sys/lib/troff/font/devutf/"; */ 120 121 int 122 readpsfontdesc(char *fontname, int trindex) { 123 static char *filename = 0; 124 Biobuf *bfd; 125 Biobufhdr *Bfd; 126 int warn = 0, errorflg = 0, line =1, rv; 127 int start, end, offset; 128 int startfont, endfont, startchar, endchar, i, pfid; 129 char psfontnam[128]; 130 struct troffont *tp; 131 struct charent *cp[]; 132 133 if (debug) Bprint(Bstderr, "readpsfontdesc(%s,%d)\n", fontname, trindex); 134 filename=galloc(filename, strlen(postroffdirname)+1+strlen(fontname)+1, "readpsfontdesc: cannot allocate memory\n"); 135 sprint(filename, "%s/%s", postroffdirname, fontname); 136 137 bfd = Bopen(filename, OREAD); 138 if (bfd == 0) { 139 error(WARNING, "cannot open file %s\n", filename); 140 return(0); 141 } 142 Bfd = &(bfd->Biobufhdr); 143 144 do { 145 offset = 0; 146 if ((rv=Bgetfield(Bfd, 'd', &start, 0)) == 0) { 147 errorflg = 1; 148 error(WARNING, "file %s:%d illegal start value\n", filename, line); 149 } else if (rv < 0) break; 150 if ((rv=Bgetfield(Bfd, 'd', &end, 0)) == 0) { 151 errorflg = 1; 152 error(WARNING, "file %s:%d illegal end value\n", filename, line); 153 } else if (rv < 0) break; 154 if ((rv=Bgetfield(Bfd, 'd', &offset, 0)) < 0) { 155 errorflg = 1; 156 error(WARNING, "file %s:%d illegal offset value\n", filename, line); 157 } 158 if ((rv=Bgetfield(Bfd, 's', psfontnam, 128)) == 0) { 159 errorflg = 1; 160 error(WARNING, "file %s:%d illegal fontname value\n", filename, line); 161 } else if (rv < 0) break; 162 Brdline(Bfd, '\n'); 163 if (!errorflg) { 164 struct psfent *psfentp; 165 startfont = RUNEGETGROUP(start); 166 startchar = RUNEGETCHAR(start); 167 endfont = RUNEGETGROUP(end); 168 endchar = RUNEGETCHAR(end); 169 pfid = findpfn(psfontnam, 1); 170 if (startfont != endfont) { 171 error(WARNING, "font descriptions must not cross 256 glyph block boundary\n"); 172 errorflg = 1; 173 break; 174 } 175 tp = &(troffontab[trindex]); 176 tp->psfmap = galloc(tp->psfmap, ++(tp->psfmapsize)*sizeof(struct psfent), "readpsfontdesc():psfmap"); 177 if (debug) Bprint(Bstderr, "\tpsfentp=0x%x\n", psfentp); 178 psfentp = &(tp->psfmap[tp->psfmapsize-1]); 179 psfentp->start = start; 180 psfentp->end = end; 181 psfentp->offset = offset; 182 psfentp->psftid = pfid; 183 /* 184 for (i=startchar; i<=endchar; i++) { 185 tp->charent[startfont][i].postfontid = pfid; 186 tp->charent[startfont][i].postcharid = i + offset - startchar; 187 } 188 */ 189 if (debug) { 190 Bprint(Bstderr, "%x %x ", start, end); 191 if (offset) Bprint(Bstderr, "%x ", offset); 192 Bprint(Bstderr, "%s\n", psfontnam); 193 } 194 line++; 195 } 196 } while(errorflg != 1); 197 Bterm(Bfd); 198 return(1); 199 } 200 201 int 202 readtroffmetric(char *fontname, int trindex) { 203 static char *filename = 0; 204 Biobuf *bfd; 205 Biobufhdr *Bfd; 206 int warn = 0, errorflg = 0, line =1, rv; 207 struct troffont *tp; 208 struct charent **cp; 209 char stoken[128], *str; 210 int ntoken; 211 Rune troffchar, quote; 212 int width, flag, charnum, thisfont, thischar; 213 BOOLEAN specharflag; 214 215 if (debug) Bprint(Bstderr, "readtroffmetric(%s,%d)\n", fontname, trindex); 216 filename=galloc(filename, strlen(troffmetricdirname)+4+strlen(devname)+1+strlen(fontname)+1, "readtroffmetric():filename"); 217 sprint(filename, "%s/dev%s/%s", troffmetricdirname, devname, fontname); 218 219 bfd = Bopen(filename, OREAD); 220 if (bfd == 0) { 221 error(WARNING, "cannot open file %s\n", filename); 222 return(0); 223 } 224 Bfd = &(bfd->Biobufhdr); 225 do { 226 /* deal with the few lines at the beginning of the 227 * troff font metric files. 228 */ 229 if ((rv=Bgetfield(Bfd, 's', stoken, 128)) == 0) { 230 errorflg = 1; 231 error(WARNING, "file %s:%d illegal token\n", filename, line); 232 } else if (rv < 0) break; 233 if (debug) { 234 Bprint(Bstderr, "%s\n", stoken); 235 } 236 237 if (strcmp(stoken, "name") == 0) { 238 if ((rv=Bgetfield(Bfd, 's', stoken, 128)) == 0) { 239 errorflg = 1; 240 error(WARNING, "file %s:%d illegal token\n", filename, line); 241 } else if (rv < 0) break; 242 } else if (strcmp(stoken, "named") == 0) { 243 Brdline(Bfd, '\n'); 244 } else if (strcmp(stoken, "fontname") == 0) { 245 if ((rv=Bgetfield(Bfd, 's', stoken, 128)) == 0) { 246 errorflg = 1; 247 error(WARNING, "file %s:%d illegal token\n", filename, line); 248 } else if (rv < 0) break; 249 } else if (strcmp(stoken, "spacewidth") == 0) { 250 if ((rv=Bgetfield(Bfd, 'd', &ntoken, 0)) == 0) { 251 errorflg = 1; 252 error(WARNING, "file %s:%d illegal token\n", filename, line); 253 } else if (rv < 0) break; 254 troffontab[trindex].spacewidth = ntoken; 255 thisfont = RUNEGETGROUP(' '); 256 thischar = RUNEGETCHAR(' '); 257 for (cp = &(troffontab[trindex].charent[thisfont][thischar]); *cp != 0; cp = &((*cp)->next)) 258 if ((*cp)->name) 259 if (strcmp((*cp)->name, " ") == 0) 260 break; 261 262 if (*cp == 0) *cp = galloc(0, sizeof(struct charent), "readtroffmetric:charent"); 263 (*cp)->postfontid = thisfont; 264 (*cp)->postcharid = thischar; 265 (*cp)->troffcharwidth = ntoken; 266 (*cp)->name = galloc(0, 2, "readtroffmetric: char name"); 267 (*cp)->next = 0; 268 strcpy((*cp)->name, " "); 269 } else if (strcmp(stoken, "special") == 0) { 270 troffontab[trindex].special = TRUE; 271 } else if (strcmp(stoken, "charset") == 0) { 272 line++; 273 break; 274 } 275 if (!errorflg) { 276 line++; 277 } 278 } while(!errorflg && rv>=0); 279 while(!errorflg && rv>=0) { 280 if ((rv=Bgetfield(Bfd, 's', stoken, 128)) == 0) { 281 errorflg = 1; 282 error(WARNING, "file %s:%d illegal rune token <0x%x> rv=%d\n", filename, line, troffchar, rv); 283 } else if (rv < 0) break; 284 if (utflen(stoken) > 1) specharflag = TRUE; 285 else specharflag = FALSE; 286 /* if this character is a quote we have to use the previous characters info */ 287 if ((rv=Bgetfield(Bfd, 'r', "e, 0)) == 0) { 288 errorflg = 1; 289 error(WARNING, "file %s:%d illegal width or quote token <0x%x> rv=%d\n", filename, line, quote, rv); 290 } else if (rv < 0) break; 291 if (quote == '"') { 292 /* need some code here */ 293 294 goto flush; 295 } else { 296 Bungetrune(Bfd); 297 } 298 299 if ((rv=Bgetfield(Bfd, 'd', &width, 0)) == 0) { 300 errorflg = 1; 301 error(WARNING, "file %s:%d illegal width token <0x%x> rv=%d\n", filename, line, troffchar, rv); 302 } else if (rv < 0) break; 303 if ((rv=Bgetfield(Bfd, 'd', &flag, 0)) == 0) { 304 errorflg = 1; 305 error(WARNING, "file %s:%d illegal flag token <0x%x> rv=%d\n", filename, line, troffchar, rv); 306 } else if (rv < 0) break; 307 if ((rv=Bgetfield(Bfd, 'd', &charnum, 0)) == 0) { 308 errorflg = 1; 309 error(WARNING, "file %s:%d illegal character number token <0x%x> rv=%d\n", filename, line, troffchar, rv); 310 } else if (rv < 0) break; 311 flush: 312 str = Brdline(Bfd, '\n'); 313 /* stash the crap from the end of the line for debugging */ 314 if (debug) { 315 if (str == 0) { 316 Bprint(Bstderr, "premature EOF\n"); 317 return(0); 318 } 319 str[Blinelen(Bfd)-1] = '\0'; 320 } 321 line++; 322 chartorune(&troffchar, stoken); 323 if (specharflag) { 324 if (debug) 325 Bprint(Bstderr, "%s %d %d 0x%x %s # special\n",stoken, width, flag, charnum, str); 326 } 327 if (strcmp(stoken, "---") == 0) { 328 thisfont = RUNEGETGROUP(charnum); 329 thischar = RUNEGETCHAR(charnum); 330 stoken[0] = '\0'; 331 } else { 332 thisfont = RUNEGETGROUP(troffchar); 333 thischar = RUNEGETCHAR(troffchar); 334 } 335 for (cp = &(troffontab[trindex].charent[thisfont][thischar]); *cp != 0; cp = &((*cp)->next)) 336 if ((*cp)->name) { 337 if (debug) Bprint(Bstderr, "installing <%s>, found <%s>\n", stoken, (*cp)->name); 338 if (strcmp((*cp)->name, stoken) == 0) 339 break; 340 } 341 if (*cp == 0) *cp = galloc(0, sizeof(struct charent), "readtroffmetric:charent"); 342 (*cp)->postfontid = RUNEGETGROUP(charnum); 343 (*cp)->postcharid = RUNEGETCHAR(charnum); 344 (*cp)->troffcharwidth = width; 345 (*cp)->name = galloc(0, strlen(stoken)+1, "readtroffmetric: char name"); 346 (*cp)->next = 0; 347 strcpy((*cp)->name, stoken); 348 if (debug) { 349 if (specharflag) 350 Bprint(Bstderr, "%s", stoken); 351 else 352 Bputrune(Bstderr, troffchar); 353 Bprint(Bstderr, " %d %d 0x%x %s # psfontid=0x%x pscharid=0x%x thisfont=0x%x thischar=0x%x\n", 354 width, flag, charnum, str, 355 (*cp)->postfontid, 356 (*cp)->postcharid, 357 thisfont, thischar); 358 } 359 } 360 Bterm(Bfd); 361 Bflush(Bstderr); 362 return(1); 363 } 364 365 /* find index of troff font name in table 366 * returns -1 if name is not in table 367 * returns -2 if it cannot allocate memory 368 * returns -3 if there is a font mapping problem 369 * If insflg is not zero 370 * and the name is not found in the table, insert it. 371 */ 372 int 373 findtfn(char *fontname, BOOLEAN insflg) { 374 struct troffont *tp; 375 int i, j; 376 377 if (debug) { 378 if (fontname==0) fprint(2, "findtfn(0x%x,%d)\n", fontname, insflg); 379 else fprint(2, "findtfn(%s,%d)\n", fontname, insflg); 380 } 381 for (i=0; i<troffontcnt; i++) { 382 if (troffontab[i].trfontid==0) { 383 error(WARNING, "findtfn:troffontab[%d].trfontid=0x%x, botch!\n", 384 i, troffontab[i].trfontid); 385 continue; 386 } 387 if (strcmp(troffontab[i].trfontid, fontname) == 0) 388 return(i); 389 } 390 if (insflg) { 391 tp = (struct troffont *)galloc(troffontab, sizeof(struct troffont)*(troffontcnt+1), "findtfn: struct troffont:"); 392 if (tp == 0) 393 return(-2); 394 troffontab = tp; 395 tp = &(troffontab[troffontcnt]); 396 i = strlen(fontname); 397 tp->trfontid = galloc(0, i+1, "findtfn: trfontid:"); 398 399 /* initialize new troff font entry with name and numeric fields to 0 */ 400 strncpy(tp->trfontid, fontname, i); 401 tp->trfontid[i] = '\0'; 402 tp->special = FALSE; 403 tp->spacewidth = 0; 404 tp->psfmapsize = 0; 405 tp->psfmap = 0; 406 for (i=0; i<NUMOFONTS; i++) 407 for (j=0; j<FONTSIZE; j++) 408 tp->charent[i][j] = 0; 409 troffontcnt++; 410 if (!readtroffmetric(fontname, troffontcnt-1)) 411 return(-3); 412 if (!readpsfontdesc(fontname, troffontcnt-1)) 413 return(-3); 414 return(troffontcnt-1); 415 } 416 return(-1); 417 } 418 419 void 420 finish(void) { 421 int i; 422 423 Bprint(Bstdout, "%s", TRAILER); 424 Bprint(Bstdout, "done\n"); 425 Bprint(Bstdout, "%s", DOCUMENTFONTS); 426 427 for (i=0; i<pfnamcnt; i++) 428 if (pfnafontmtab[i].used) 429 Bprint(Bstdout, " %s", pfnafontmtab[i].str); 430 Bprint(Bstdout, "\n"); 431 432 Bprint(Bstdout, "%s %d\n", PAGES, pages_printed); 433 434 } 435