plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

chartab.c (13686B)


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