134114Skarels #ifndef lint
234114Skarels static char Notice[] = "Copyright (c) 1985 Adobe Systems Incorporated";
334114Skarels static char *RCSID="$Header: pscatmap.c,v 2.1 85/11/24 11:50:07 shore Rel $";
434114Skarels #endif
534114Skarels /* pscatmap.c
634114Skarels *
734114Skarels * Copyright (C) 1985 Adobe Systems Incorporated
834114Skarels *
934114Skarels * Build font width files for troff and correspondence tables
1034114Skarels * for pscat.
1134114Skarels *
1234114Skarels * Edit History:
1334114Skarels * Andrew Shore: Sat Nov 9 15:37:04 1985
1434114Skarels * End Edit History.
1534114Skarels *
1634114Skarels * The correspondence tables are intended to be created by humans for
1734114Skarels * describing a set of 4 fonts to be used by troff: detailing the
1834114Skarels * mapping from troff & C/A/T codes to output actions for pscat
1934114Skarels * These actions take one of three forms:
2034114Skarels * PFONT - map to a character in a PostScript font
2134114Skarels * PLIG - map to a "fake" ligature
2234114Skarels * PPROC - map to a named PostScript procedure
2334114Skarels * PNONE - no action
2434114Skarels *
2534114Skarels * PFONT is straightforward, the mapping specifies which character in
2634114Skarels * which PostScript font is desired and the character width is
2734114Skarels * collected from the PostScript "afm" font metrics file format.
2834114Skarels * Note that ascender and descender information is "wired in" to the code;
2934114Skarels * it might be a better idea to "compute" it from the character
3034114Skarels * bounding box information.
3134114Skarels *
3234114Skarels * PLIG is provided so that the correct width for the ligature may
3334114Skarels * be "computed" by this program, rather than hand done by the user.
3434114Skarels * There are 3 ligature types:
3534114Skarels * 0126 - build "ff" out of "f" and "f"
3634114Skarels * 0131 - build "ffi" out of "f" and "fi"
3734114Skarels * 0130 - build "ffl" out of "f" and "fl"
3834114Skarels * This list should probably be expanded to span the space.
3934114Skarels *
4034114Skarels * PPROC provides a general callback mechanism so that users can
4134114Skarels * create and character definition with a PostScript procedure.
4234114Skarels * The procedures are "named" with user-specified numbers, and are
4334114Skarels * called with all information available to them (current position,
4434114Skarels * font size, intended width, railmag, ...). Such procedures are used
4534114Skarels * for troff characters not in any PostScript font (rules, boxes,
4634114Skarels * constructed braces, etc.), but may also be used as a general
4734114Skarels * "escape hatch" for incorporating ANY PostScript routine into a
4834114Skarels * troff document -- a logo, a scanned image, etc. The exact
4934114Skarels * calling rules are:
5034114Skarels * an absolute moveto is performed to the position for this character
5134114Skarels * The following numbers are pushed on the PS stack:
5234114Skarels * pointsize
5334114Skarels * troff character code
5434114Skarels * "railmag"
5534114Skarels * character width
5634114Skarels * procedure "number"
5734114Skarels * x offset
5834114Skarels * y offset
5934114Skarels * width
6034114Skarels *
6134114Skarels * then a procedure named "PSn" where n is the procedure number
6234114Skarels * is executed. It is that procedure's responsibility to image
6334114Skarels * the character and move by the appropriate width.
6434114Skarels *
6534114Skarels * RCSLOG:
6634114Skarels * $Log: pscatmap.c,v $
6734114Skarels * Revision 2.1 85/11/24 11:50:07 shore
6834114Skarels * Product Release 2.0
6934114Skarels *
7034114Skarels * Revision 1.3 85/11/20 00:32:45 shore
7134114Skarels * support for System V
7234114Skarels * short names, non ".c" output, better arith.
7334114Skarels *
7434114Skarels * Revision 1.2 85/05/14 11:24:04 shore
7534114Skarels *
7634114Skarels *
7734114Skarels *
7834114Skarels */
7934114Skarels
8034114Skarels #include <stdio.h>
8134114Skarels #ifdef SYSV
8234114Skarels #include <string.h>
8334114Skarels #else
8434114Skarels #include <strings.h>
8534114Skarels #endif
8634114Skarels #include "transcript.h"
8734114Skarels #include "action.h"
8834114Skarels
8934114Skarels #define LFONT 1
9034114Skarels #define LMAP 2
9134114Skarels #define LNONE 3
9234114Skarels
9334114Skarels private char linebuf[200];
9434114Skarels private char *libdir; /* place for AFM files */
9534114Skarels
9634114Skarels private struct chAction chAction [] = {
9734114Skarels PFONT, "PFONT", /* character in PostScript font */
9834114Skarels PLIG, "PLIG", /* fake ligatures: ff ffi ffl */
9934114Skarels PPROC, "PPROC", /* PostScript procedure outcall */
10034114Skarels PNONE, "0", /* null action */
10134114Skarels 0, 0
10234114Skarels };
10334114Skarels
10434114Skarels #define MAXFONTS 25
10534114Skarels private int nfonts;
10634114Skarels private struct font {
10734114Skarels char mapname[20]; /* short name in map file e.g., "ROMAN" */
10834114Skarels char afmname[80]; /* name of AFM file for this font (in map file) */
10934114Skarels char psname[80]; /* PS font name from AFM file */
11034114Skarels int widths[256]; /* PostScript widths of encoded chars (1000/em) */
11134114Skarels /* more here */
11234114Skarels } fonts[MAXFONTS];
11334114Skarels private char faces[] = "RIBS0"; /* order important! */
11434114Skarels
11534114Skarels private char familyname[80];
11634114Skarels private char facenames[4][80];
11734114Skarels
11834114Skarels /* there should be on the order of 4 * 128 characters, so 1000 is generous */
11934114Skarels
12034114Skarels #define MAXCHARS 1000
12134114Skarels private struct ctab {
12234114Skarels int trcode; /* troff char code */
12334114Skarels int catcode; /* CAT char code */
12434114Skarels int wid; /* table-driven width */
12534114Skarels int action; /* action type */
12634114Skarels int x, y; /* x and y offset */
12734114Skarels int font; /* PostScript font */
12834114Skarels int pschar; /* PS character code */
12934114Skarels int pswidth; /* PS width (/1000) */
13034114Skarels char *descr; /* short print description */
13134114Skarels } ctab[MAXCHARS];
13234114Skarels private int nchars;
13334114Skarels
13434114Skarels
BuildTable()13534114Skarels private BuildTable()
13634114Skarels {
13734114Skarels char *c;
13834114Skarels int status;
13934114Skarels int gotfamily, gotfaces, gotfonts, gotmap;
14034114Skarels
14134114Skarels gotfamily = gotfaces = gotfonts = gotmap = 0;
14234114Skarels
14334114Skarels while(fgets(linebuf, sizeof linebuf, stdin) != NULL) {
14434114Skarels /* strip off newline */
14534114Skarels if ((c = INDEX(linebuf, '\n')) == 0) {
14634114Skarels fprintf(stderr, "line too long \"%s\"\n",linebuf);
14734114Skarels exit(1);
14834114Skarels }
14934114Skarels *c = '\0';
15034114Skarels /* ignore blank or comment (%) lines */
15134114Skarels if ((*linebuf == '%') || (*linebuf == '\0')) continue;
15234114Skarels if (*linebuf == '@') {
15334114Skarels /* "command" line */
15434114Skarels /* printf("C: %s\n", linebuf); */
15534114Skarels if (strncmp(&linebuf[1], "FAMILYNAME", 10) == 0) {
15634114Skarels if (sscanf(linebuf,"@FAMILYNAME %s",familyname) != 1) {
15734114Skarels fprintf(stderr,"bad familyname %s\n",familyname);
15834114Skarels exit(1);
15934114Skarels }
16034114Skarels gotfamily++;
16134114Skarels }
16234114Skarels if (strncmp(&linebuf[1], "FACENAMES", 9) == 0) {
16334114Skarels if (sscanf(linebuf,"@FACENAMES %s %s %s %s",
16434114Skarels facenames[0],facenames[1],
16534114Skarels facenames[2],facenames[3]) != 4) {
16634114Skarels fprintf(stderr,"must be four facenames\n");
16734114Skarels exit(1);
16834114Skarels }
16934114Skarels gotfaces++;
17034114Skarels }
17134114Skarels if (strcmp(&linebuf[1], "BEGINFONTS") == 0) {
17234114Skarels if ((!gotfamily) || (!gotfaces)) {
17334114Skarels fprintf(stderr,"FAMILYNAME and FACENAMES must come before BEGINFONTS\n");
17434114Skarels exit(1);
17534114Skarels }
17634114Skarels VOIDC strcpy(fonts[0].mapname,"0");
17734114Skarels VOIDC strcpy(fonts[0].afmname,"0");
17834114Skarels VOIDC strcpy(fonts[0].psname,"0");
17934114Skarels nfonts = 1;
18034114Skarels status = LFONT;
18134114Skarels continue;
18234114Skarels }
18334114Skarels if (strcmp(&linebuf[1], "ENDFONTS") == 0) {
18434114Skarels gotfonts++;
18534114Skarels status = LNONE;
18634114Skarels continue;
18734114Skarels }
18834114Skarels if (strcmp(&linebuf[1], "BEGINMAP") == 0) {
18934114Skarels if (!gotfonts) {
19034114Skarels fprintf(stderr,"BEGINFONTS/ENDFONTS must come before map\n");
19134114Skarels exit(1);
19234114Skarels }
19334114Skarels status = LMAP;
19434114Skarels continue;
19534114Skarels }
19634114Skarels if (strcmp(&linebuf[1], "ENDMAP") == 0) {
19734114Skarels status = LNONE;
19834114Skarels gotmap++;
19934114Skarels continue;
20034114Skarels }
20134114Skarels }
20234114Skarels switch (status) {
20334114Skarels case LFONT:
20434114Skarels GetFont();
20534114Skarels break;
20634114Skarels case LMAP:
20734114Skarels GetMap();
20834114Skarels break;
20934114Skarels default:
21034114Skarels break;
21134114Skarels }
21234114Skarels }
21334114Skarels if (!gotmap) {
21434114Skarels fprintf(stderr,"missing @ENDMAP\n");
21534114Skarels exit(1);
21634114Skarels }
21734114Skarels }
21834114Skarels
GetFont()21934114Skarels private GetFont () {
22034114Skarels char *eqp;
22134114Skarels register int i;
22234114Skarels char afmpath[200];
22334114Skarels #ifdef SYSV
22434114Skarels char shortname[40];
22534114Skarels #endif
22634114Skarels
22734114Skarels if ((eqp = INDEX(linebuf, '=')) == 0) {
22834114Skarels fprintf(stderr, "bad FONTS line:%s\n",linebuf);
22934114Skarels exit(1);
23034114Skarels }
23134114Skarels *eqp++ = '\0';
23234114Skarels for (i = 0; i < nfonts; i++) {
23334114Skarels if (strcmp (fonts[i].mapname, linebuf) == 0) {
23434114Skarels fprintf(stderr, "duplicate entry for font %s\n", linebuf);
23534114Skarels exit(1);
23634114Skarels }
23734114Skarels }
23834114Skarels if (nfonts >= MAXFONTS) {
23934114Skarels fprintf(stderr, "Too many FONTS\n");
24034114Skarels exit(1);
24134114Skarels }
24234114Skarels if (strlen(linebuf) > (sizeof fonts[0].mapname)) {
24334114Skarels fprintf(stderr, "FONT name too long %s\n", linebuf);
24434114Skarels exit(1);
24534114Skarels }
24634114Skarels if (strlen(eqp) > (sizeof fonts[0].afmname)) {
24734114Skarels fprintf(stderr, "FONT name too long %s\n", eqp);
24834114Skarels exit(1);
24934114Skarels }
25034114Skarels VOIDC strcpy(fonts[nfonts].mapname, linebuf);
25134114Skarels VOIDC strcpy(fonts[nfonts].afmname, eqp);
25234114Skarels
25334114Skarels /* read the font's .afm file to get real widths */
25434114Skarels if (*eqp == '/') {
25534114Skarels VOIDC strcpy(afmpath,eqp);
25634114Skarels }
25734114Skarels else {
25834114Skarels VOIDC strcpy(afmpath,libdir);
25934114Skarels VOIDC strcat(afmpath,"/");
26034114Skarels #ifdef SYSV
26134114Skarels mapname(eqp,shortname);
26234114Skarels VOIDC strcat(afmpath,shortname);
26334114Skarels #else
26434114Skarels VOIDC strcat(afmpath, eqp);
26534114Skarels #endif
26634114Skarels VOIDC strcat(afmpath,".afm");
26734114Skarels }
26834114Skarels ReadAFM(afmpath);
26934114Skarels nfonts++;
27034114Skarels return;
27134114Skarels }
27234114Skarels
27334114Skarels
ReadAFM(afmfile)27434114Skarels private ReadAFM(afmfile) char *afmfile; {
27534114Skarels char *c;
27634114Skarels FILE *afm;
27734114Skarels int gotMetrics, gotName, inChars, ccode, cwidth;
27834114Skarels char afmbuf[1000];
27934114Skarels
28034114Skarels if ((afm = fopen(afmfile, "r")) == NULL) {
28134114Skarels fprintf(stderr,"Can't open afm file %s\n",afmfile);
28234114Skarels exit(1);
28334114Skarels }
28434114Skarels inChars = gotMetrics = gotName = 0;
28534114Skarels while(fgets(afmbuf, sizeof afmbuf, afm) != NULL) {
28634114Skarels /* strip off newline */
28734114Skarels if ((c = INDEX(afmbuf, '\n')) == 0) {
28834114Skarels fprintf(stderr, "AFM line too long %s\n", afmbuf);
28934114Skarels exit(1);
29034114Skarels }
29134114Skarels *c = '\0';
29234114Skarels /* ignore blank lines */
29334114Skarels if (*afmbuf == '\0') continue;
294*34115Skarels if (strcmp(afmbuf,"StartFontMetrics 2.0") == 0) {
29534114Skarels gotMetrics++;
29634114Skarels continue;
29734114Skarels }
29834114Skarels if (strncmp(afmbuf,"FontName ", 9) == 0) {
29934114Skarels VOIDC sscanf(afmbuf,"FontName %s",fonts[nfonts].psname);
30034114Skarels gotName++;
30134114Skarels continue;
30234114Skarels }
30334114Skarels if (strcmp(afmbuf,"EndCharMetrics") == 0) {
30434114Skarels if (!inChars) {
30534114Skarels fprintf(stderr,"AFM: %s without StartCharMetrics\n",afmbuf);
30634114Skarels exit(1);
30734114Skarels }
30834114Skarels inChars++;
30934114Skarels break;
31034114Skarels }
31134114Skarels if (strcmp(afmbuf,"StartCharMetrics") == 0) {
31234114Skarels inChars++;
31334114Skarels continue;
31434114Skarels }
31534114Skarels if (inChars == 1) {
31634114Skarels if (sscanf(afmbuf,"C %d ; WX %d ;",&ccode, &cwidth) != 2) {
31734114Skarels fprintf(stderr, "Bad Character in AFM file %s\n",afmbuf);
31834114Skarels exit(1);
31934114Skarels }
32034114Skarels if (ccode == -1) continue; /* skip unencoded chars */
32134114Skarels if (ccode > 255) {
32234114Skarels fprintf(stderr, "Bad Character Code skipped %s\n", afmbuf);
32334114Skarels continue;
32434114Skarels }
32534114Skarels fonts[nfonts].widths[ccode] = cwidth;
32634114Skarels continue;
32734114Skarels }
32834114Skarels }
32934114Skarels if ((inChars != 2) || (!gotMetrics) || (!gotName)) {
33034114Skarels fprintf(stderr,"improper AFM file %s\n",afmfile);
33134114Skarels exit(1);
33234114Skarels }
33334114Skarels VOIDC fclose(afm);
33434114Skarels }
33534114Skarels
33634114Skarels
GetMap()33734114Skarels private GetMap(){
33834114Skarels int trcode;
33934114Skarels char trfont;
34034114Skarels int catcode;
34134114Skarels int wid;
34234114Skarels char action[10];
34334114Skarels int x,y;
34434114Skarels char psfont[20];
34534114Skarels int pschar;
34634114Skarels char descr[100];
34734114Skarels
34834114Skarels char *fp;
34934114Skarels int trface; /* 0 - 3 : R I B S */
35034114Skarels int pf;
35134114Skarels struct ctab *ch;
35234114Skarels struct chAction *act;
35334114Skarels
35434114Skarels if (sscanf(linebuf,"%o %c %o %d %s %d %d %s %o \"%[^\"]\"",
35534114Skarels &trcode, &trfont, &catcode, &wid, action, &x, &y,
35634114Skarels psfont, &pschar, descr) != 10) {
35734114Skarels fprintf(stderr,"Bad line %s",linebuf);
35834114Skarels }
35934114Skarels
36034114Skarels /* verify the integrity of the data we got */
36134114Skarels if ((fp = INDEX(faces, trfont)) == 0) {
36234114Skarels fprintf(stderr, "Bad face code in %s\n", linebuf);
36334114Skarels exit(1);
36434114Skarels }
36534114Skarels trface = fp - faces;
36634114Skarels for (act = chAction; act->actName != 0; act++) {
36734114Skarels if (strcmp(action, act->actName) == 0) break;
36834114Skarels }
36934114Skarels if (act->actName == 0) {
37034114Skarels fprintf(stderr, "Bad action in %s\n", linebuf);
37134114Skarels exit(1);
37234114Skarels }
37334114Skarels for (pf = 0; pf < nfonts; pf++) {
37434114Skarels if (strcmp(fonts[pf].mapname, psfont) == 0) goto gotfont;
37534114Skarels }
37634114Skarels fprintf(stderr, "Bad font (%s) name %s\n", linebuf, psfont);
37734114Skarels exit(1);
37834114Skarels
37934114Skarels gotfont:
38034114Skarels
38134114Skarels if (nchars >= MAXCHARS) {
38234114Skarels fprintf(stderr,"Too many character definitions\n");
38334114Skarels exit(1);
38434114Skarels }
38534114Skarels ch = &ctab[nchars];
38634114Skarels ch->trcode = trcode;
38734114Skarels ch->catcode = (trface << 7) | catcode;
38834114Skarels ch->action = act->actCode;
38934114Skarels ch->x = x;
39034114Skarels ch->y = y;
39134114Skarels ch->font = pf;
39234114Skarels ch->pschar = pschar;
39334114Skarels if (descr[0]) {
39434114Skarels if ((ch->descr = malloc((unsigned) (strlen(descr)+1))) == NULL) {
39534114Skarels fprintf(stderr,"malloc failed\n");
39634114Skarels exit(1);
39734114Skarels }
39834114Skarels VOIDC strcpy(ch->descr, descr);
39934114Skarels }
40034114Skarels
40134114Skarels /* calculate width in cat units (432 per inch) of 6 pt
40234114Skarels * character (the way troff wants them).
40334114Skarels * 6 pts = 36 cat units
40434114Skarels */
40534114Skarels
40634114Skarels if (ch->action == PLIG) {/* fake ligature, fake width */
40734114Skarels switch (catcode) {
40834114Skarels case 0126: /* ff = f f */
40934114Skarels ch->pswidth = fonts[pf].widths['f'] * 2;
41034114Skarels break;
41134114Skarels case 0131: /* ffi = f fi */
41234114Skarels ch->pswidth = fonts[pf].widths['f'] + fonts[pf].widths[0256];
41334114Skarels break;
41434114Skarels case 0130: /* ffl = f fl */
41534114Skarels ch->pswidth = fonts[pf].widths['f'] + fonts[pf].widths[0257];
41634114Skarels break;
41734114Skarels default:
41834114Skarels fprintf(stderr,"Unknown ligature 0%o\n",catcode);
41934114Skarels exit(1);
42034114Skarels }
42134114Skarels }
42234114Skarels else {
42334114Skarels ch->pswidth = fonts[pf].widths[pschar];
42434114Skarels }
42534114Skarels ch->wid = (wid >= 0) ? wid :
42634114Skarels (int) ( (((float) ch->pswidth * 36.0 ) / 1000.0) + 0.5);
42734114Skarels if (ch->wid > 255) {
42834114Skarels fprintf(stderr,"Scaled width too big!\n");
42934114Skarels exit(1);
43034114Skarels }
43134114Skarels nchars++;
43234114Skarels }
43334114Skarels
43434114Skarels
compCTent(a,b)43534114Skarels private int compCTent(a,b)
43634114Skarels struct ctab *a, *b;
43734114Skarels {
43834114Skarels if (a->catcode < b->catcode) return -1;
43934114Skarels if (a->catcode > b->catcode) return 1;
44034114Skarels return 0;
44134114Skarels }
44234114Skarels
44334114Skarels
WriteTable()44434114Skarels private WriteTable() {
44534114Skarels int i, curcode;
44634114Skarels struct ctab *ct;
44734114Skarels struct map map, emptymap;
44834114Skarels char outname[84];
44934114Skarels FILE *mapfile;
45034114Skarels
45134114Skarels /* write out font mapping */
45234114Skarels if (familyname[0] == 0) {
45334114Skarels fprintf(stderr,"No FAMILYNAME specified!\n");
45434114Skarels exit(1);
45534114Skarels }
45634114Skarels VOIDC strcpy(outname, familyname);
45734114Skarels VOIDC strcat(outname, ".ct");
45834114Skarels if ((mapfile = fopen(outname, "w")) == NULL) {
45934114Skarels fprintf(stderr,"can't open output file %s\n", mapfile);
46034114Skarels exit(1);
46134114Skarels }
46234114Skarels VOIDC putw(nfonts, mapfile);
46334114Skarels for (i = 0; i < nfonts; i++) {
46434114Skarels VOIDC fwrite(fonts[i].psname, sizeof fonts[0].psname, 1, mapfile);
46534114Skarels }
46634114Skarels /* sort ctab by catcode */
46734114Skarels qsort((char *) ctab, nchars, sizeof (struct ctab), compCTent);
46834114Skarels /* write it out */
46934114Skarels VOIDC putw(ctab[nchars-1].catcode,mapfile);
47034114Skarels VOIDC fflush(mapfile);
47134114Skarels emptymap.wid = emptymap.x = emptymap.y = emptymap.font =
47234114Skarels emptymap.pschar = emptymap.action = emptymap.pswidth = 0;
47334114Skarels
47434114Skarels ct = &ctab[0];
47534114Skarels curcode = 0;
47634114Skarels for (i = 0; i < MAXCHARS; i++) {
47734114Skarels while (curcode < ct->catcode) {
47834114Skarels VOIDC write(fileno(mapfile), &emptymap, sizeof map);
47934114Skarels curcode++;
48034114Skarels }
48134114Skarels while ((ct->catcode < curcode) && (ct <= &ctab[nchars])) {
48234114Skarels ct++;
48334114Skarels i++;
48434114Skarels }
48534114Skarels if (ct >= &ctab[nchars]) break;
48634114Skarels map.wid = ct->wid;
48734114Skarels map.pswidth = ct->pswidth;
48834114Skarels map.x = ct->x;
48934114Skarels map.y = ct->y;
49034114Skarels map.action = ct->action;
49134114Skarels map.pschar = ct->pschar;
49234114Skarels map.font = ct->font;
49334114Skarels VOIDC write(fileno(mapfile), &map, sizeof map);
49434114Skarels ct++;
49534114Skarels curcode++;
49634114Skarels }
49734114Skarels VOIDC fclose(mapfile);
49834114Skarels }
49934114Skarels
50034114Skarels
50134114Skarels /* called by qsort to compare troff codes */
50234114Skarels /* if troff codes are the same, use facecode to decide */
50334114Skarels
compTRcode(a,b)50434114Skarels private compTRcode(a,b)struct ctab *a, *b;
50534114Skarels {
50634114Skarels register int i;
50734114Skarels i = a->trcode - b->trcode;
50834114Skarels if (i == 0) return ((a->catcode>>7) - (b->catcode>>7));
50934114Skarels return(i);
51034114Skarels }
51134114Skarels
51234114Skarels
DoWidths()51334114Skarels private DoWidths() {
51434114Skarels int f; /* font index 0-3 */
51534114Skarels
51634114Skarels qsort((char *) ctab, nchars, sizeof(struct ctab), compTRcode);
51734114Skarels for (f = 0; f < 4; f++) {
51834114Skarels dofont(f);
51934114Skarels }
52034114Skarels }
52134114Skarels
52234114Skarels
52334114Skarels #define ASCENDER 0200
52434114Skarels #define DESCENDER 0100
52534114Skarels
52634114Skarels /* note that both is 0300 */
52734114Skarels /* ascenders are:
52834114Skarels * b d f h i j k l t beta gamma delta zeta theta lambda xi
52934114Skarels * phi psi Gamma Delta Theta Lambda Xi Pi Sigma
53034114Skarels * Upsilon Phi Psi Omega gradient
53134114Skarels */
53234114Skarels
53334114Skarels private char Ascenders[] = "bdfhijklt\231\232\233\235\237\242\245\254\256\260\261\262\263\264\264\265\266\270\271\272\273\326";
53434114Skarels
53534114Skarels /* descenders are:
53634114Skarels * g j p q y beta zeta eta mu xi
53734114Skarels * rho phi chi psi terminal-sigma
53834114Skarels */
53934114Skarels
54034114Skarels private char Descenders[] = "gjpqy\231\235\236\243\245\250\254\255\256\275";
54134114Skarels
54234114Skarels
dofont(fontno)54334114Skarels private dofont(fontno)
54434114Skarels int fontno; /* troff font number 0-3 */
54534114Skarels {
54634114Skarels char ftfilename[100];
54734114Skarels FILE *ftfile; /* generated font widths file */
54834114Skarels int wid, curcode;
54934114Skarels struct ctab *ct, *cc;
55034114Skarels int asde;
55134114Skarels
55234114Skarels #ifdef SYSV
55334114Skarels VOIDC sprintf(ftfilename, "ft%s", facenames[fontno]);
55434114Skarels #else
55534114Skarels VOIDC sprintf(ftfilename, "ft%s.c", facenames[fontno]);
55634114Skarels #endif
55734114Skarels if ((ftfile = fopen(ftfilename, "w")) == NULL) {
55834114Skarels perror(ftfilename);
55934114Skarels exit(1);
56034114Skarels }
56134114Skarels #ifdef BSD
56234114Skarels fprintf(ftfile, "/* troff width file for %s - %s (%c) */\n",
56334114Skarels familyname, facenames[fontno], faces[fontno]);
56434114Skarels fprintf(ftfile, "char ft%s[256-32] = {\n", facenames[fontno]);
56534114Skarels #endif
56634114Skarels
56734114Skarels /* write out entry for each troff character code */
56834114Skarels /* codes 0-31 (decimal) are not used */
56934114Skarels /* the first interesting code is 32 (040) - space */
57034114Skarels
57134114Skarels ct = ctab;
57234114Skarels for (curcode = 32; curcode < 256; curcode++) {
57334114Skarels while ((ct < &ctab[nchars]) && (ct->trcode < curcode) ||
57434114Skarels ((ct->trcode == curcode) && ((ct->catcode>>7) < fontno))) {
57534114Skarels ct++;
57634114Skarels }
57734114Skarels asde = 0;
57834114Skarels if ((ct >= &ctab[nchars]) || (curcode != ct->trcode) ||
57934114Skarels ((ct->catcode>>7) != fontno)) {
58034114Skarels /* not found */
58134114Skarels wid = 0;
58234114Skarels cc = 0;
58334114Skarels }
58434114Skarels else {
58534114Skarels wid = ct->wid;
58634114Skarels cc = ct;
58734114Skarels /* calculate ascender/descender info (heuristic) */
58834114Skarels if (((curcode >= '0') && (curcode <= '9')) ||
58934114Skarels ((curcode >= 'A') && (curcode <= 'Z'))) asde |= ASCENDER;
59034114Skarels if (INDEX(Ascenders, curcode)) asde |= ASCENDER;
59134114Skarels if (INDEX(Descenders, curcode)) asde |= DESCENDER;
59234114Skarels }
59334114Skarels #ifdef SYSV
59434114Skarels /* for system V we write a binary file of the width bytes */
59534114Skarels putc(0377&(wid+asde),ftfile);
59634114Skarels #else
59734114Skarels /* for BSD we write a "c" array to be compiled */
59834114Skarels fprintf(ftfile, "%d", wid);
59934114Skarels if (asde) fprintf(ftfile,"+0%o",asde);
60034114Skarels fprintf(ftfile, ",\t%s/* %s */\n",
60134114Skarels asde?"":"\t",cc?cc->descr:"NULL");
60234114Skarels #endif
60334114Skarels }
60434114Skarels #ifdef BSD
60534114Skarels fprintf(ftfile,"};\n");
60634114Skarels #endif
60734114Skarels VOIDC fclose(ftfile);
60834114Skarels }
60934114Skarels
61034114Skarels
main(argc,argv)61134114Skarels main(argc, argv)
61234114Skarels int argc;
61334114Skarels char **argv;
61434114Skarels {
61534114Skarels if (argc != 2) {
61634114Skarels fprintf(stderr,"usage: pscatmap mapfile\n");
61734114Skarels exit(1);
61834114Skarels }
61934114Skarels if (freopen(*++argv,"r",stdin) == NULL) {
62034114Skarels perror("pscatmap");
62134114Skarels exit(1);
62234114Skarels }
62334114Skarels
62434114Skarels if ((libdir = envget("PSLIBDIR")) == NULL) libdir = LibDir;
62534114Skarels
62634114Skarels BuildTable();
62734114Skarels WriteTable();
62834114Skarels DoWidths();
62934114Skarels }
63034114Skarels
631