|
|
1.1 ! root 1: /* ! 2: * ! 3: * Typesetter font tables routines - for postprocessors. ! 4: * ! 5: */ ! 6: ! 7: /* ! 8: * A slightly modified version of the dpost original -- DBK ! 9: */ ! 10: ! 11: #include <stdio.h> ! 12: #include <ctype.h> ! 13: ! 14: #include "font.h" /* font table definitions */ ! 15: ! 16: TrFont *mount[MAXFONTS+1]; /* mount table - pointers into fonts[] */ ! 17: TrFont fonts[MAXFONTS+2]; /* font data - guarantee one empty slot */ ! 18: ! 19: int fcount; /* entries in fonts[] */ ! 20: int mcount; /* fonts currently in memory */ ! 21: int mlimit = MAXFONTS+1; /* and the most we'll allow */ ! 22: ! 23: char *chnames[MAXCH]; /* special character hash table */ ! 24: int nchnames; /* number of entries in chnames[] */ ! 25: ! 26: extern int devres; ! 27: extern int unitwidth; ! 28: extern int nfonts; ! 29: extern char **lfonts; ! 30: ! 31: /*****************************************************************************/ ! 32: ! 33: getdesc(path) ! 34: ! 35: char *path; ! 36: ! 37: { ! 38: ! 39: char buf[150]; ! 40: FILE *fp; ! 41: int n; ! 42: ! 43: /* ! 44: * ! 45: * Read a typesetter description file. Font and size lists are discarded. Only ! 46: * used to get to the start of the next command. ! 47: * ! 48: */ ! 49: ! 50: if ( (fp = fopen(path, "r")) == NULL ) ! 51: return(-1); ! 52: ! 53: while ( fscanf(fp, "%s", buf) != EOF ) { ! 54: if ( strcmp(buf, "res") == 0 ) ! 55: fscanf(fp, "%d", &devres); ! 56: else if ( strcmp(buf, "unitwidth") == 0 ) ! 57: fscanf(fp, "%d", &unitwidth); ! 58: else if ( strcmp(buf, "sizes") == 0 ) ! 59: while ( fscanf(fp, "%d", &n) != EOF && n != 0 ) ; ! 60: else if ( strcmp(buf, "inmemory") == 0 ) ! 61: fscanf(fp, "%d", &mlimit); ! 62: else if ( strcmp(buf, "fonts") == 0 ) { ! 63: fscanf(fp, "%d", &nfonts); ! 64: if (nfonts > 0) ! 65: lfonts = (char **) malloc(nfonts * sizeof (char *)); ! 66: for ( n = 0; n < nfonts; n++ ) { ! 67: fscanf(fp, "%s", buf); ! 68: lfonts[n] = strsave(buf); ! 69: } ! 70: } else if ( strcmp(buf, "charset") == 0 ) { ! 71: while ( fscanf(fp, "%s", buf) != EOF ) ! 72: chadd(buf); ! 73: break; ! 74: } /* End if */ ! 75: skipline(fp); ! 76: } /* End while */ ! 77: ! 78: fclose(fp); ! 79: return(1); ! 80: ! 81: } /* End of getdesc */ ! 82: ! 83: /*****************************************************************************/ ! 84: ! 85: getfont(path, fpos) ! 86: ! 87: char *path; ! 88: TrFont *fpos; ! 89: ! 90: { ! 91: ! 92: FILE *fin; ! 93: Chwid chtemp[MAXCH]; ! 94: static Chwid chinit; ! 95: int i, nw, n, wid, code; ! 96: int nospace = 1; ! 97: char buf[150], ch[20], s1[10], s2[10], s3[10], cmd[30]; ! 98: ! 99: ! 100: /* ! 101: * ! 102: * Read a width table from path into *fpos. Skip unnamed characters, spacewidth, ! 103: * ligatures, ascender/descender entries, and anything else not recognized. All ! 104: * calls should come through mountfont(). ! 105: * ! 106: */ ! 107: ! 108: if ( fpos->state == INMEMORY ) ! 109: return(1); ! 110: ! 111: if ( (fin = fopen(path, "r")) == NULL ) ! 112: return(-1); ! 113: ! 114: if ( fpos->state == NEWFONT ) { ! 115: if ( ++fcount > MAXFONTS+1 ) ! 116: return(-1); ! 117: fpos->path = strsave(path); ! 118: } /* End if */ ! 119: ! 120: if ( ++mcount > mlimit && mcount > nfonts+1 ) ! 121: freefonts(); ! 122: ! 123: for ( i = 0; i < 128-32; i++ ) ! 124: chtemp[i] = chinit; ! 125: ! 126: while ( fscanf(fin, "%s", cmd) != EOF ) { ! 127: if ( strcmp(cmd, "name") == 0 ) { ! 128: release(fpos->name); ! 129: fscanf(fin, "%s", buf); ! 130: fpos->name = strsave(buf); ! 131: } else if ( strcmp(cmd, "fontname") == 0 ) { ! 132: release(fpos->fontname); ! 133: fscanf(fin, "%s", buf); ! 134: fpos->fontname = strsave(buf); ! 135: } else if ( strcmp(cmd, "special") == 0 ) ! 136: fpos->specfont = 1; ! 137: else if ( strcmp(cmd, "named") == 0 ) /* in prologue or somewhere else */ ! 138: fpos->flags |= NAMED; ! 139: else if (strcmp(cmd, "spacewidth") == 0) { ! 140: fscanf(fin, "%d", &wid); ! 141: chtemp[0].wid = wid; ! 142: chtemp[0].num = ' '; ! 143: nospace = 0; ! 144: } ! 145: else if ( strcmp(cmd, "charset") == 0 ) { ! 146: skipline(fin); ! 147: nw = 128-32; ! 148: while ( fgets(buf, sizeof(buf), fin) != NULL ) { ! 149: sscanf(buf, "%s %s %s %s", ch, s1, s2, s3); ! 150: if ( s1[0] != '"' ) { /* not a synonym */ ! 151: sscanf(s1, "%d", &wid); ! 152: if (s3[0] == '0') ! 153: sscanf(s3, "%o", &code); ! 154: else sscanf(s3, "%d", &code); ! 155: } /* End if */ ! 156: if ( strlen(ch) == 1 ) { /* it's ascii */ ! 157: n = ch[0] - 32; /* origin omits non-graphics */ ! 158: chtemp[n].num = ch[0]; ! 159: chtemp[n].wid = wid; ! 160: chtemp[n].code = code; ! 161: } else if ( strcmp(ch, "---") != 0 ) { /* ignore unnamed chars */ ! 162: if ( (n = chindex(ch)) == -1 ) /* global? */ ! 163: n = chadd(ch); ! 164: chtemp[nw].num = n; ! 165: chtemp[nw].wid = wid; ! 166: chtemp[nw].code = code; ! 167: nw++; ! 168: } /* End else */ ! 169: } /* End while */ ! 170: break; ! 171: } /* End else */ ! 172: skipline(fin); ! 173: } /* End while */ ! 174: ! 175: fclose(fin); ! 176: ! 177: if (nospace) { ! 178: chtemp[0].wid = 25; ! 179: chtemp[0].num = ' '; ! 180: } ! 181: ! 182: fpos->wp = (Chwid *)allocate(nw * sizeof(Chwid)); ! 183: for ( i = 0; i < nw; i++ ) ! 184: fpos->wp[i] = chtemp[i]; ! 185: ! 186: fpos->nchars = nw; ! 187: fpos->state = INMEMORY; ! 188: ! 189: return(1); ! 190: ! 191: } /* End of getfont */ ! 192: ! 193: /*****************************************************************************/ ! 194: ! 195: mountfont(path, m) ! 196: ! 197: char *path; ! 198: int m; ! 199: ! 200: { ! 201: ! 202: TrFont *fpos; ! 203: ! 204: /* ! 205: * ! 206: * Mount font table from file path at position m. Mounted fonts are guaranteed ! 207: * to be in memory. ! 208: * ! 209: */ ! 210: ! 211: if ( m < 0 || m > MAXFONTS ) ! 212: return(-1); ! 213: ! 214: if ( mount[m] != NULL ) { ! 215: if ( strcmp(path, mount[m]->path) == 0 ) { ! 216: if ( mount[m]->state == INMEMORY ) ! 217: return(1); ! 218: } else { ! 219: mount[m]->mounted--; ! 220: mount[m] = NULL; ! 221: } /* End else */ ! 222: } /* End if */ ! 223: ! 224: mount[m] = fpos = &fonts[findfont(path)]; ! 225: mount[m]->mounted++; ! 226: return(getfont(path, fpos)); ! 227: ! 228: } /* End of mountfont */ ! 229: ! 230: /*****************************************************************************/ ! 231: ! 232: freefonts() ! 233: ! 234: { ! 235: ! 236: int n; ! 237: ! 238: /* ! 239: * ! 240: * Release memory used by all unmounted fonts - except for the path string. ! 241: * ! 242: */ ! 243: ! 244: for ( n = 0; n < MAXFONTS+2; n++ ) ! 245: if ( fonts[n].state == INMEMORY && fonts[n].mounted == 0 ) { ! 246: release(fonts[n].wp); ! 247: fonts[n].wp = NULL; ! 248: fonts[n].state = RELEASED; ! 249: mcount--; ! 250: } /* End if */ ! 251: ! 252: } /* End of freefonts */ ! 253: ! 254: /*****************************************************************************/ ! 255: ! 256: findfont(path) ! 257: ! 258: char *path; ! 259: ! 260: { ! 261: ! 262: register n; ! 263: ! 264: /* ! 265: * ! 266: * Look for path in the fonts table. Returns the index where it was found or can ! 267: * be inserted (if not found). ! 268: * ! 269: */ ! 270: ! 271: for ( n = hash(path, MAXFONTS+2); fonts[n].state != NEWFONT; n = (n+1) % (MAXFONTS+2) ) ! 272: if ( strcmp(path, fonts[n].path) == 0 ) ! 273: break; ! 274: return(n); ! 275: ! 276: } /* End of findfont */ ! 277: ! 278: /*****************************************************************************/ ! 279: ! 280: mounted(m) ! 281: ! 282: int m; ! 283: ! 284: { ! 285: ! 286: /* ! 287: * ! 288: * Return 1 if a font is mounted at position m. ! 289: * ! 290: */ ! 291: ! 292: return((m >= 0 && m <= MAXFONTS && mount[m] != NULL) ? 1 : 0); ! 293: ! 294: } /* End of mounted */ ! 295: ! 296: /*****************************************************************************/ ! 297: ! 298: onfont(c, m) ! 299: ! 300: int c; ! 301: int m; ! 302: ! 303: { ! 304: ! 305: register TrFont *fp; ! 306: register Chwid *cp, *ep; ! 307: ! 308: /* ! 309: * ! 310: * Returns the position of character c in the font mounted at m, or -1 if the ! 311: * character is not found. ! 312: * ! 313: */ ! 314: ! 315: if ( mounted(m) ) { ! 316: fp = mount[m]; ! 317: if ( c < 128 ) { ! 318: if ( fp->wp[c-32].num == c ) /* ascii at front */ ! 319: return c - 32; ! 320: else return -1; ! 321: } /* End if */ ! 322: ! 323: cp = &fp->wp[128-32]; ! 324: ep = &fp->wp[fp->nchars]; ! 325: for ( ; cp < ep; cp++ ) /* search others */ ! 326: if ( cp->num == c ) ! 327: return cp - &fp->wp[0]; ! 328: } /* End if */ ! 329: ! 330: return -1; ! 331: ! 332: } /* End of onfont */ ! 333: ! 334: /*****************************************************************************/ ! 335: ! 336: chwidth(n, m) ! 337: ! 338: int n; ! 339: int m; ! 340: ! 341: { ! 342: ! 343: /* ! 344: * ! 345: * Return width of the character at position n in the font mounted at m. Skip ! 346: * bounds checks - assume it's already been done. ! 347: * ! 348: */ ! 349: ! 350: return(mount[m]->wp[n].wid); ! 351: ! 352: } /* End of chwidth */ ! 353: ! 354: /*****************************************************************************/ ! 355: ! 356: chcode(n, m) ! 357: ! 358: int n; ! 359: int m; ! 360: ! 361: { ! 362: ! 363: /* ! 364: * ! 365: * Return typesetter code for the character at position n in the font mounted ! 366: * at m. Skip bounds checks - assume it's already been done. ! 367: * ! 368: */ ! 369: ! 370: return(mount[m]->wp[n].code); ! 371: ! 372: } /* End of chcode */ ! 373: ! 374: /*****************************************************************************/ ! 375: ! 376: chindex(s) ! 377: ! 378: char *s; ! 379: ! 380: { ! 381: ! 382: register i; ! 383: ! 384: /* ! 385: * ! 386: * Look for s in global character name table. Hash table is guaranteed to have ! 387: * at least one empty slot (by chadd()) so the loop terminate. ! 388: * ! 389: */ ! 390: ! 391: for ( i = hash(s, MAXCH); chnames[i] != NULL; i = (i+1) % MAXCH ) ! 392: if ( strcmp(s, chnames[i]) == 0 ) ! 393: return(i+128); ! 394: return(-1); ! 395: ! 396: } /* End of chindex */ ! 397: ! 398: /*****************************************************************************/ ! 399: ! 400: chadd(s) ! 401: ! 402: char *s; ! 403: ! 404: { ! 405: ! 406: register i; ! 407: ! 408: /* ! 409: * ! 410: * Add s to the global character name table. Leave one empty slot so loops ! 411: * terminate. ! 412: * ! 413: */ ! 414: ! 415: if ( nchnames >= MAXCH - 1 ) ! 416: yyerror("out of table space adding character %s", s); ! 417: ! 418: for ( i = hash(s, MAXCH); chnames[i] != NULL; i = (i+1) % MAXCH ) ; ! 419: ! 420: nchnames++; ! 421: chnames[i] = strsave(s); ! 422: ! 423: return(i+128); ! 424: ! 425: } /* End of chadd */ ! 426: ! 427: /*****************************************************************************/ ! 428: ! 429: char *chname(n) ! 430: ! 431: int n; ! 432: ! 433: { ! 434: ! 435: /* ! 436: * ! 437: * Returns string for the character with index n. ! 438: * ! 439: */ ! 440: ! 441: return(chnames[n-128]); ! 442: ! 443: } /* End of chname */ ! 444: ! 445: /*****************************************************************************/ ! 446: ! 447: hash(s, l) ! 448: ! 449: char *s; ! 450: int l; ! 451: ! 452: { ! 453: ! 454: register i; ! 455: ! 456: /* ! 457: * ! 458: * Return the hash index for string s in a table of length l. Probably should ! 459: * make i unsigned and mod once at the end. ! 460: * ! 461: */ ! 462: ! 463: for ( i = 0; *s != '\0'; s++ ) ! 464: i = (i * 10 + *s) % l; ! 465: return(i); ! 466: ! 467: } /* End of hash */ ! 468: ! 469: /*****************************************************************************/ ! 470: ! 471: char *strsave(s) ! 472: ! 473: char *s; ! 474: ! 475: { ! 476: ! 477: char *ptr = NULL; ! 478: ! 479: /* ! 480: * ! 481: * Make a permanent copy of string s. ! 482: * ! 483: */ ! 484: ! 485: if ( s != NULL ) { ! 486: ptr = (char *)allocate(strlen(s)+1); ! 487: strcpy(ptr, s); ! 488: } /* End if */ ! 489: return(ptr); ! 490: ! 491: } /* End of strsave */ ! 492: ! 493: /*****************************************************************************/ ! 494: ! 495: char *allocate(count) ! 496: ! 497: int count; ! 498: ! 499: { ! 500: ! 501: char *ptr; ! 502: ! 503: /* ! 504: * ! 505: * Allocates count bytes. Free unmounted fonts if the first attempt fails. To ! 506: * be absolutely correct all memory allocation should be done by this routine. ! 507: * ! 508: */ ! 509: ! 510: if ( (ptr = (char *)malloc(count)) == NULL ) { ! 511: freefonts(); ! 512: if ( (ptr = (char *)malloc(count)) == NULL ) ! 513: yyerror("out of space in allocate (font.c)"); ! 514: } /* End if */ ! 515: return(ptr); ! 516: ! 517: } /* End of allocate */ ! 518: ! 519: /*****************************************************************************/ ! 520: ! 521: release(ptr) ! 522: ! 523: char *ptr; ! 524: ! 525: { ! 526: ! 527: /* ! 528: * ! 529: * Free memory provided ptr isn't NULL. ! 530: * ! 531: */ ! 532: ! 533: if ( ptr != NULL ) ! 534: free(ptr); ! 535: ! 536: } /* End of release */ ! 537: ! 538: /*****************************************************************************/ ! 539: ! 540: dumpmount(m) ! 541: ! 542: int m; ! 543: ! 544: { ! 545: ! 546: /* ! 547: * ! 548: * Dumps the font mounted at position n. ! 549: * ! 550: */ ! 551: ! 552: if ( mount[m] != NULL ) ! 553: dumpfont((mount[m] - &fonts[0])); ! 554: else fprintf(stderr, "no font mounted at %d\n", m); ! 555: ! 556: } /* End of dumpmount */ ! 557: ! 558: /*****************************************************************************/ ! 559: ! 560: dumpfont(n) ! 561: ! 562: int n; ! 563: ! 564: { ! 565: ! 566: int i; ! 567: TrFont *fpos; ! 568: char *str; ! 569: ! 570: /* ! 571: * ! 572: * Dump of everything known about the font saved at fonts[n]. ! 573: * ! 574: */ ! 575: ! 576: fpos = &fonts[n]; ! 577: ! 578: if ( fpos->state ) { ! 579: fprintf(stderr, "path %s\n", fpos->path); ! 580: fprintf(stderr, "state %d\n", fpos->state); ! 581: fprintf(stderr, "flags %d\n", fpos->flags); ! 582: fprintf(stderr, "mounted %d\n", fpos->mounted); ! 583: fprintf(stderr, "nchars %d\n", fpos->nchars); ! 584: fprintf(stderr, "special %d\n", fpos->specfont); ! 585: fprintf(stderr, "name %s\n", fpos->name); ! 586: fprintf(stderr, "fontname %s\n", fpos->fontname); ! 587: if ( fpos->state == INMEMORY ) { ! 588: fprintf(stderr, "charset\n"); ! 589: for ( i = 0; i < fpos->nchars; i++ ) { ! 590: if ( fpos->wp[i].num > 0 ) { ! 591: if ( fpos->wp[i].num < 128 ) ! 592: fprintf(stderr, "%c\t%d\t%d\n", fpos->wp[i].num, ! 593: fpos->wp[i].wid, fpos->wp[i].code); ! 594: else { ! 595: str = chname(fpos->wp[i].num); ! 596: if ( *str == '#' && isdigit(*(str+1)) && isdigit(*(str+2)) ) ! 597: str = "---"; ! 598: fprintf(stderr, "%s\t%d\t%d\n", str, fpos->wp[i].wid, ! 599: fpos->wp[i].code); ! 600: } /* End else */ ! 601: } /* End if */ ! 602: } /* End for */ ! 603: } else fprintf(stderr, "charset: not in memory\n"); ! 604: } else fprintf(stderr, "empty font: %d\n", n); ! 605: ! 606: putc('\n', stderr); ! 607: ! 608: } /* End of dumpfont */ ! 609: ! 610: /*****************************************************************************/ ! 611:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.