|
|
1.1 ! root 1: /* ! 2: * ! 3: * Typesetter font tables routines - for postprocessors. ! 4: * ! 5: */ ! 6: ! 7: #include <stdio.h> ! 8: #include <ctype.h> ! 9: ! 10: #include "gen.h" ! 11: #include "rune.h" ! 12: #include "ext.h" ! 13: #include "font.h" ! 14: ! 15: Font *mount[MAXFONTS+1]; /* mount table - pointers into fonts[] */ ! 16: Font fonts[MAXFONTS+2]; /* font data - guarantee one empty slot */ ! 17: ! 18: int fcount; /* entries in fonts[] */ ! 19: int mcount; /* fonts currently in memory */ ! 20: int mlimit = MAXFONTS+1; /* and the most we'll allow */ ! 21: ! 22: char *chnames[SPECIALCHARS]; /* special character hash table */ ! 23: int nchnames; /* number of entries in chnames[] */ ! 24: ! 25: extern int devres; ! 26: extern int unitwidth; ! 27: extern int nfonts; ! 28: ! 29: /*****************************************************************************/ ! 30: ! 31: checkdesc(path) ! 32: ! 33: char *path; ! 34: ! 35: { ! 36: ! 37: char buf[150]; ! 38: FILE *fp; ! 39: int val = 0; ! 40: ! 41: /* ! 42: * ! 43: * Return non-zero if the typesetter description file path includes, ! 44: * ! 45: * PDL PostScript ! 46: * ! 47: * before the charset table. ! 48: * ! 49: */ ! 50: ! 51: if ( (fp = fopen(path, "r")) != NULL ) { ! 52: while ( fscanf(fp, "%s", buf) != EOF ) { ! 53: if ( strcmp(buf, "PDL") == 0 ) { ! 54: fscanf(fp, "%s", buf); ! 55: val = strcmp(buf, "PostScript") == 0; ! 56: break; ! 57: } else if ( strcmp(buf, "charset") == 0 ) ! 58: break; ! 59: skipline(fp); ! 60: } /* End while */ ! 61: fclose(fp); ! 62: } /* End if */ ! 63: ! 64: return(val); ! 65: ! 66: } /* End of checkdesc */ ! 67: ! 68: /*****************************************************************************/ ! 69: ! 70: getdesc(path) ! 71: ! 72: char *path; ! 73: ! 74: { ! 75: ! 76: char buf[150]; ! 77: FILE *fp; ! 78: int n; ! 79: ! 80: if ( (fp = fopen(path, "r")) == NULL ) ! 81: return(-1); ! 82: ! 83: while ( fscanf(fp, "%s", buf) != EOF ) { ! 84: if ( strcmp(buf, "res") == 0 ) ! 85: fscanf(fp, "%d", &devres); ! 86: else if ( strcmp(buf, "unitwidth") == 0 ) ! 87: fscanf(fp, "%d", &unitwidth); ! 88: else if ( strcmp(buf, "sizes") == 0 ) ! 89: while ( fscanf(fp, "%d", &n) != EOF && n != 0 ) ; ! 90: else if ( strcmp(buf, "inmemory") == 0 ) ! 91: fscanf(fp, "%d", &mlimit); ! 92: else if ( strcmp(buf, "Encoding") == 0 ) { ! 93: fscanf(fp, "%s", buf); ! 94: fontencoding = strsave(buf); ! 95: } else if ( strcmp(buf, "fonts") == 0 ) { ! 96: fscanf(fp, "%d", &nfonts); ! 97: for ( n = 0; n < nfonts; n++ ) ! 98: fscanf(fp, "%s", buf); ! 99: } else if ( strcmp(buf, "charset") == 0 ) { ! 100: while ( fscanf(fp, "%s", buf) != EOF ) ! 101: chadd(buf); ! 102: break; ! 103: } /* End if */ ! 104: skipline(fp); ! 105: } /* End while */ ! 106: ! 107: fclose(fp); ! 108: return(1); ! 109: ! 110: } /* End of getdesc */ ! 111: ! 112: /*****************************************************************************/ ! 113: ! 114: getfont(path, fpos) ! 115: ! 116: char *path; ! 117: Font *fpos; ! 118: ! 119: { ! 120: ! 121: FILE *fin; ! 122: Chwid chtemp[LARGESTFONT]; ! 123: int next; ! 124: int i, n, num, wid, code; ! 125: char buf[300], ch[100], s1[100], s2[100], s3[100], cmd[100]; ! 126: ! 127: ! 128: /* ! 129: * ! 130: * Read a font width table. Skip unnamed characters, spacewidth, ligatures, ! 131: * ascender/descender entries, and anything else not recognized. Charset ! 132: * entries for a new font are first stacked in chtemp[] and later copied ! 133: * to correct slots in a newly allocated wp array. All calls should come ! 134: * through mountfont(). ! 135: * ! 136: */ ! 137: ! 138: if ( fpos->state == INMEMORY ) ! 139: return(1); ! 140: ! 141: if ( (fin = fopen(path, "r")) == NULL ) ! 142: return(-1); ! 143: ! 144: if ( fpos->state == NEWFONT ) { ! 145: if ( ++fcount > MAXFONTS+1 ) ! 146: return(-1); ! 147: fpos->path = strsave(path); ! 148: } /* End if */ ! 149: ! 150: if ( ++mcount > mlimit && mcount > nfonts+1 ) ! 151: freefonts(); ! 152: ! 153: while ( fscanf(fin, "%s", cmd) != EOF ) { ! 154: if ( strcmp(cmd, "name") == 0 ) { ! 155: release(fpos->name); ! 156: fscanf(fin, "%s", buf); ! 157: fpos->name = strsave(buf); ! 158: } else if ( strcmp(cmd, "fontname") == 0 ) { ! 159: release(fpos->fontname); ! 160: fscanf(fin, "%s", buf); ! 161: fpos->fontname = strsave(buf); ! 162: } else if ( strcmp(cmd, "special") == 0 ) ! 163: fpos->specfont = 1; ! 164: else if ( strcmp(cmd, "named") == 0 ) /* in prologue or somewhere else */ ! 165: fpos->flags |= NAMED; ! 166: else if ( strcmp(cmd, "charset") == 0 ) { ! 167: skipline(fin); ! 168: next = 0; ! 169: fpos->nchars = 0; /* special characters */ ! 170: fpos->first = LASTCODE; ! 171: fpos->last = FIRSTCODE; ! 172: while ( fgets(buf, sizeof(buf), fin) != NULL ) { ! 173: num = -1; ! 174: sscanf(buf, "%s %s %s %s", ch, s1, s2, s3); ! 175: if ( s1[0] != '"' ) { /* not a synonym */ ! 176: sscanf(s1, "%d", &wid); ! 177: code = strtol(s3, 0, 0); /* dec/oct/hex */ ! 178: } /* End if */ ! 179: if ( strlen(ch) == 1 ) /* it's ascii */ ! 180: num = ch[0]; ! 181: else if ( ch[0] == '\\' && ch[1] == '0' ) ! 182: num = strtol(ch+1, 0, 0); ! 183: /* ! 184: * Eventually consider something like, ! 185: * ! 186: * else if ( strlen(ch) == chartorune(&r, ch) ) ! 187: * num = r; ! 188: */ ! 189: else if ( strcmp(ch, "---") != 0 ) { /* ignore unnamed chars */ ! 190: if ( (num = chindex(ch)) == INVALIDCODE ) ! 191: num = chadd(ch); ! 192: } /* End else */ ! 193: if ( ValidChar(num) ) { ! 194: if ( next < LARGESTFONT ) { ! 195: chtemp[next].num = num; ! 196: chtemp[next].wid = wid; ! 197: chtemp[next++].code = code; ! 198: if ( ValidCode(num) ) { ! 199: fpos->first = (num < fpos->first) ? num : fpos->first; ! 200: fpos->last = (num > fpos->last) ? num : fpos->last; ! 201: } else fpos->nchars++; ! 202: } else error(FATAL, "font %s too large", path); ! 203: } else if ( num != -1 ) ! 204: error(FATAL, "invalid character in font %s\n", path); ! 205: } /* End while */ ! 206: break; ! 207: } /* End else */ ! 208: skipline(fin); ! 209: } /* End while */ ! 210: ! 211: fclose(fin); ! 212: ! 213: if ( fpos->first > fpos->last ) ! 214: fpos->last = fpos->first - 1; ! 215: fpos->nchars += fpos->last - fpos->first + 1; ! 216: fpos->wp = (Chwid *)allocate(fpos->nchars * sizeof(Chwid)); ! 217: ! 218: for ( i = 0; i < fpos->nchars; i++ ) ! 219: fpos->wp[i].num = INVALIDCODE; ! 220: ! 221: for ( i = 0, n = 1; i < next; i++ ) { ! 222: if ( chtemp[i].num <= fpos->last ) ! 223: fpos->wp[chtemp[i].num - fpos->first] = chtemp[i]; ! 224: else fpos->wp[fpos->last - fpos->first + n++] = chtemp[i]; ! 225: } /* End for */ ! 226: ! 227: fpos->state = INMEMORY; ! 228: return(1); ! 229: ! 230: } /* End of getfont */ ! 231: ! 232: /*****************************************************************************/ ! 233: ! 234: mountfont(path, m) ! 235: ! 236: char *path; ! 237: int m; ! 238: ! 239: { ! 240: ! 241: Font *fpos; ! 242: ! 243: if ( m < 0 || m > MAXFONTS ) ! 244: return(-1); ! 245: ! 246: if ( mount[m] != NULL ) { ! 247: if ( mount[m]->path != NULL && strcmp(path, mount[m]->path) == 0 ) { ! 248: if ( mount[m]->state == INMEMORY ) ! 249: return(1); ! 250: } else { ! 251: mount[m]->mounted--; ! 252: mount[m] = NULL; ! 253: } /* End else */ ! 254: } /* End if */ ! 255: ! 256: mount[m] = fpos = &fonts[findfont(path)]; ! 257: mount[m]->mounted++; ! 258: return(getfont(path, fpos)); ! 259: ! 260: } /* End of mountfont */ ! 261: ! 262: /*****************************************************************************/ ! 263: ! 264: freefonts() ! 265: ! 266: { ! 267: ! 268: int n; ! 269: ! 270: /* ! 271: * ! 272: * Don't release the path without resetting state to NEWFONT - findfont() ! 273: * assumes path is available. ! 274: * ! 275: */ ! 276: ! 277: for ( n = 0; n < MAXFONTS+2; n++ ) ! 278: if ( fonts[n].state == INMEMORY && fonts[n].mounted == 0 ) { ! 279: release(fonts[n].wp); ! 280: fonts[n].wp = NULL; ! 281: fonts[n].state = RELEASED; ! 282: mcount--; ! 283: } /* End if */ ! 284: ! 285: } /* End of freefonts */ ! 286: ! 287: /*****************************************************************************/ ! 288: ! 289: findfont(path) ! 290: ! 291: char *path; ! 292: ! 293: { ! 294: ! 295: register n; ! 296: ! 297: for ( n = hash(path, MAXFONTS+2); fonts[n].state != NEWFONT; n = (n+1) % (MAXFONTS+2) ) ! 298: if ( strcmp(path, fonts[n].path) == 0 ) ! 299: break; ! 300: return(n); ! 301: ! 302: } /* End of findfont */ ! 303: ! 304: /*****************************************************************************/ ! 305: ! 306: mounted(m) ! 307: ! 308: int m; ! 309: ! 310: { ! 311: ! 312: return(m >= 0 && m <= MAXFONTS && mount[m] != NULL); ! 313: ! 314: } /* End of mounted */ ! 315: ! 316: /*****************************************************************************/ ! 317: ! 318: onfont(c, m) ! 319: ! 320: int c; ! 321: int m; ! 322: ! 323: { ! 324: ! 325: Font *fp; ! 326: Chwid *cp, *ep; ! 327: ! 328: /* ! 329: * ! 330: * Returns the position of character c in the font mounted at m, or -1 if the ! 331: * character is not found. ! 332: * ! 333: */ ! 334: ! 335: if ( mounted(m) ) { ! 336: fp = mount[m]; ! 337: if ( c >= fp->first && c <= fp->last ) { ! 338: if ( fp->wp[c-fp->first].num == c ) ! 339: return(c - fp->first); ! 340: else return(-1); ! 341: } /* End if */ ! 342: ! 343: if ( ValidSpecial(c) ) { ! 344: cp = &fp->wp[fp->last - fp->first + 1]; ! 345: ep = &fp->wp[fp->nchars]; ! 346: for ( ; cp < ep; cp++ ) /* search others */ ! 347: if ( cp->num == c ) ! 348: return(cp - &fp->wp[0]); ! 349: } /* End if */ ! 350: } /* End if */ ! 351: ! 352: return(-1); ! 353: ! 354: } /* End of onfont */ ! 355: ! 356: /*****************************************************************************/ ! 357: ! 358: chindex(s) ! 359: ! 360: char *s; ! 361: ! 362: { ! 363: ! 364: register i; ! 365: ! 366: /* ! 367: * ! 368: * Return the code assigned to special character s or INVALIDCODE if s ! 369: * is not currently defined. ! 370: * ! 371: */ ! 372: ! 373: for ( i = hash(s, SPECIALCHARS); chnames[i] != NULL; i = (i+1) % SPECIALCHARS ) ! 374: if ( strcmp(s, chnames[i]) == 0 ) ! 375: return(i+FIRSTSPECIAL); ! 376: return(INVALIDCODE); ! 377: ! 378: } /* End of chindex */ ! 379: ! 380: /*****************************************************************************/ ! 381: ! 382: chadd(s) ! 383: ! 384: char *s; ! 385: ! 386: { ! 387: ! 388: register i; ! 389: ! 390: if ( nchnames >= SPECIALCHARS - 1 ) /* guarantee one empty slot */ ! 391: error(FATAL, "out of table space adding character %s", s); ! 392: ! 393: for ( i = hash(s, SPECIALCHARS); chnames[i] != NULL; i = (i+1) % SPECIALCHARS ) ; ! 394: ! 395: nchnames++; ! 396: chnames[i] = strsave(s); ! 397: return(i+FIRSTSPECIAL); ! 398: ! 399: } /* End of chadd */ ! 400: ! 401: /*****************************************************************************/ ! 402: ! 403: char *chname(n) ! 404: ! 405: int n; ! 406: ! 407: { ! 408: ! 409: return(chnames[n-FIRSTSPECIAL]); ! 410: ! 411: } /* End of chname */ ! 412: ! 413: /*****************************************************************************/ ! 414: ! 415: hash(s, l) ! 416: ! 417: char *s; ! 418: int l; ! 419: ! 420: { ! 421: ! 422: unsigned i; ! 423: ! 424: for ( i = 0; *s; s++ ) ! 425: i = i*10 + *s; ! 426: return(i % l); ! 427: ! 428: } /* End of hash */ ! 429: ! 430: /*****************************************************************************/ ! 431: ! 432: char *strsave(s) ! 433: ! 434: char *s; ! 435: ! 436: { ! 437: ! 438: char *ptr = NULL; ! 439: ! 440: if ( s != NULL ) { ! 441: ptr = (char *)allocate(strlen(s)+1); ! 442: strcpy(ptr, s); ! 443: } /* End if */ ! 444: return(ptr); ! 445: ! 446: } /* End of strsave */ ! 447: ! 448: /*****************************************************************************/ ! 449: ! 450: char *allocate(count) ! 451: ! 452: int count; ! 453: ! 454: { ! 455: ! 456: char *ptr; ! 457: ! 458: if ( (ptr = (char *)malloc(count)) == NULL ) { ! 459: freefonts(); ! 460: if ( (ptr = (char *)malloc(count)) == NULL ) ! 461: error(FATAL, "no memory"); ! 462: } /* End if */ ! 463: return(ptr); ! 464: ! 465: } /* End of allocate */ ! 466: ! 467: /*****************************************************************************/ ! 468: ! 469: release(ptr) ! 470: ! 471: char *ptr; ! 472: ! 473: { ! 474: ! 475: if ( ptr != NULL ) ! 476: free(ptr); ! 477: ! 478: } /* End of release */ ! 479: ! 480: /*****************************************************************************/ ! 481: ! 482: dumpmount(m) ! 483: ! 484: int m; ! 485: ! 486: { ! 487: ! 488: if ( mount[m] != NULL ) ! 489: dumpfont((mount[m] - &fonts[0])); ! 490: else fprintf(stderr, "no font mounted at %d\n", m); ! 491: ! 492: } /* End of dumpmount */ ! 493: ! 494: /*****************************************************************************/ ! 495: ! 496: dumpfont(n) ! 497: ! 498: int n; ! 499: ! 500: { ! 501: ! 502: int i; ! 503: Font *fpos; ! 504: char *str; ! 505: ! 506: fpos = &fonts[n]; ! 507: ! 508: if ( fpos->state ) { ! 509: fprintf(stderr, "path %s\n", fpos->path); ! 510: fprintf(stderr, "state %d\n", fpos->state); ! 511: fprintf(stderr, "flags %d\n", fpos->flags); ! 512: fprintf(stderr, "mounted %d\n", fpos->mounted); ! 513: fprintf(stderr, "first %d\n", fpos->first); ! 514: fprintf(stderr, "last %d\n", fpos->last); ! 515: fprintf(stderr, "nchars %d\n", fpos->nchars); ! 516: fprintf(stderr, "special %d\n", fpos->specfont); ! 517: fprintf(stderr, "name %s\n", fpos->name); ! 518: fprintf(stderr, "fontname %s\n", fpos->fontname); ! 519: if ( fpos->state == INMEMORY ) { ! 520: fprintf(stderr, "charset\n"); ! 521: for ( i = 0; i < fpos->nchars; i++ ) { ! 522: if ( fpos->wp[i].num > 0 ) { ! 523: if ( fpos->wp[i].num <= fpos->last ) ! 524: fprintf(stderr, "%c\t%d\t%d\n", fpos->wp[i].num, ! 525: fpos->wp[i].wid, fpos->wp[i].code); ! 526: else { ! 527: str = chname(fpos->wp[i].num); ! 528: if ( *str == '#' && isdigit(*(str+1)) && isdigit(*(str+2)) ) ! 529: str = "---"; ! 530: fprintf(stderr, "%s\t%d\t%d\n", str, fpos->wp[i].wid, ! 531: fpos->wp[i].code); ! 532: } /* End else */ ! 533: } /* End if */ ! 534: } /* End for */ ! 535: } else fprintf(stderr, "charset: not in memory\n"); ! 536: } else fprintf(stderr, "empty font: %d\n", n); ! 537: ! 538: putc('\n', stderr); ! 539: ! 540: } /* End of dumpfont */ ! 541: ! 542: /*****************************************************************************/ ! 543:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.