295 lines · 7.4 KB · C
RawDownload
/*  * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #include <u.h>#include <libc.h>#include <bio.h>#include "../common/common.h"#include "tr2post.h" int hpos = 0, vpos = 0;int fontsize, fontpos; #define MAXSTR	128int trindex;			/* index into trofftab of current troff font */static int expecthmot = 0; voidinitialize(void) {} voidhgoto(int x) {	hpos = x;	if (pageon()) {		endstring();/*		Bprint(Bstdout, "%d %d m\n", hpos, vpos); */	}} voidvgoto(int y) {	vpos = y;	if (pageon()) {		endstring();/*		Bprint(Bstdout, "%d %d m\n", hpos, vpos); */	}} voidhmot(int x) {	int delta; 	if ((x<expecthmot-1) || (x>expecthmot+1)) {		delta = x - expecthmot;		if (curtrofffontid <0 || curtrofffontid >= troffontcnt) {			fprint(2, "troffontcnt=%d curtrofffontid=%d\n",				troffontcnt, curtrofffontid);			exits("");		}		if (delta == troffontab[curtrofffontid].spacewidth*fontsize/10 &&		    isinstring()) {			if (pageon())				runeout(' ');		} else {			if (pageon()) {				endstring();				/* Bprint(Bstdout, " %d 0 rmoveto ", delta); *//*				Bprint(Bstdout, " %d %d m ", hpos+x, vpos); */				if (debug)					fprint(2, "x=%d expecthmot=%d\n",						x, expecthmot);			}		}	}	hpos += x;	expecthmot = 0;} voidvmot(int y) {	endstring();/*	Bprint(Bstdout, " 0 %d rmoveto ", -y); */	vpos += y;} struct charent **findglyph(int trfid, Rune rune, char *stoken) {	struct charent **cp; 	for (cp = &(troffontab[trfid].charent[RUNEGETGROUP(rune)][RUNEGETCHAR(rune)]); *cp != 0; cp = &((*cp)->next)) {		if ((*cp)->name) {			if (debug) fprint(2, "looking for <%s>, have <%s> in font %s\n", stoken, (*cp)->name, troffontab[trfid].trfontid);			if (strcmp((*cp)->name, stoken) == 0)				break;		}	}	return(cp);} /* output glyph.  Use first rune to look up character (hash) * then use stoken UTF string to find correct glyph in linked * list of glyphs in bucket. */voidglyphout(Rune rune, char *stoken, BOOLEAN specialflag) {	struct charent **cp;	struct troffont *tfp;	struct psfent *psfp;	int i, t, mi, wid;	int fontid;	/* this is the troff font table index, not the mounted font table index */	Rune r; 	mi = 0;	settrfont(); 	/* check current font for the character, special or not */	fontid = curtrofffontid;	if (debug)		fprint(2, "\tlooking through current font: trying %s\n",			troffontab[fontid].trfontid);	cp = findglyph(fontid, rune, stoken);	if (*cp != 0)		goto foundit; 	if (specialflag) {		if (expecthmot)			hmot(0); 		/* check special fonts for the special character */		/* cycle through the (troff) mounted fonts starting at the next font */		for (mi=0; mi<fontmnt; mi++) {			if (troffontab[fontid].trfontid==0)				error(WARNING, "glyphout:troffontab[%d].trfontid=0x%x, botch!\n",					fontid, troffontab[fontid].trfontid);			if (fontmtab[mi]==0) {				if (debug)					fprint(2, "fontmtab[%d]=%#p, fontmnt=%d\n",						mi, fontmtab[mi], fontmnt);				continue;			}			if (strcmp(troffontab[fontid].trfontid, fontmtab[mi])==0)				break;		}		if (mi==fontmnt)			error(FATAL, "current troff font is not mounted, botch!\n");		for (i=(mi+1)%fontmnt; i!=mi; i=(i+1)%fontmnt) {			if (fontmtab[i]==0) {				if (debug)					fprint(2, "fontmtab[%d]=%#p, fontmnt=%d\n",						i, fontmtab[i], fontmnt);				continue;			}			fontid = findtfn(fontmtab[i], TRUE);if (debug) fprint(2, "	looking through special fonts: trying %s\n", troffontab[fontid].trfontid);			if (troffontab[fontid].special) {				cp = findglyph(fontid, rune, stoken);				if (*cp != 0)					goto foundit;			}		} 		/* check font 1 (if current font is not font 1) for the special character */		if (mi != 1) {				fontid = findtfn(fontmtab[1], TRUE);;if (debug) fprint(2, "	looking through font at position 1: trying %s\n", troffontab[fontid].trfontid);				cp = findglyph(fontid, rune, stoken);				if (*cp != 0) goto foundit;		}	} 	if (*cp == 0) {		error(WARNING, "cannot find glyph, rune=0x%x stoken=<%s> troff font %s\n", rune, stoken,			troffontab[curtrofffontid].trfontid);		expecthmot = 0;	} 	/* use the peter face in lieu of the character that we couldn't find */	rune = 'p';	stoken = "pw";	for (i=(mi+1)%fontmnt; i!=mi; i=(i+1)%fontmnt) {		if (fontmtab[i]==0) {			if (debug) fprint(2, "fontmtab[%d]=%#p\n", i, fontmtab[i]);			continue;		}		fontid = findtfn(fontmtab[i], TRUE);if (debug) fprint(2, "	looking through special fonts: trying %s\n", troffontab[fontid].trfontid);		if (troffontab[fontid].special) {			cp = findglyph(fontid, rune, stoken);			if (*cp != 0) goto foundit;		}	} 	if (*cp == 0) {		error(WARNING, "cannot find glyph, rune=0x%x stoken=<%s> troff font %s\n",			rune, stoken, troffontab[curtrofffontid].trfontid);		expecthmot = 0;		return;	} foundit:	t = (((*cp)->postfontid&0xff)<<8) | ((*cp)->postcharid&0xff);	if (debug)		fprint(2, "runeout(0x%x)<%C> postfontid=0x%x postcharid=0x%x troffcharwidth=%d\n",			rune, rune, (*cp)->postfontid, (*cp)->postcharid,			(*cp)->troffcharwidth); 	tfp = &troffontab[fontid];	psfp = nil;	for (i=0; i<tfp->psfmapsize; i++) {		psfp = &(tfp->psfmap[i]);		if(t>=psfp->start && t<=psfp->end)			break;	}	if (i >= tfp->psfmapsize)		error(FATAL, "character <0x%x> does not have a Postscript font defined.\n", rune); 	setpsfont(psfp->psftid, fontsize); 	if (t == 0x0001) {	/* character is in charlib */		endstring();		if (pageon()) {			Bprint(Bstdout, "%d %d m ", hpos, vpos);			/* if char is unicode character rather than name, clean up for postscript */			wid = chartorune(&r, (*cp)->name);			if(' '<r && r<0x7F)				Bprint(Bstdout, "%d build_%s\n",					(*cp)->troffcharwidth, (*cp)->name);			else{				if((*cp)->name[wid] != 0)					error(FATAL, "character <%s> badly named\n", (*cp)->name);				Bprint(Bstdout, "%d build_X%.4x\n",					(*cp)->troffcharwidth, r);			} 			/*			 * stash charent pointer in a list so that we can			 * print these character definitions in the prologue.			 */			for (i=0; i<build_char_cnt; i++)				if (*cp == build_char_list[i])					break;			if (i == build_char_cnt) {				build_char_list = galloc(build_char_list,					sizeof(struct charent *)*++build_char_cnt,					"build_char_list");				build_char_list[build_char_cnt-1] = *cp;			}		}		expecthmot = (*cp)->troffcharwidth * fontsize / unitwidth;	} else if (isinstring() || rune != ' ') {		startstring();		if (pageon())			if (rune == ' ')				Bprint(Bstdout, " ");			else				Bprint(Bstdout, "%s", charcode[RUNEGETCHAR(t)].str);		expecthmot = (*cp)->troffcharwidth * fontsize / unitwidth;	}} /* * runeout puts a symbol into a string (queue) to be output. * It also has to keep track of the current and last symbol * output to check that the spacing is correct by default * or needs to be adjusted with a spacing operation. */ voidruneout(Rune rune) {	char stoken[UTFmax+1];	int i; 	i = runetochar(stoken, &rune);	stoken[i] = '\0';	glyphout(rune, stoken, TRUE);} voidspecialout(char *stoken) {	Rune rune; 	chartorune(&rune, stoken);	glyphout(rune, stoken, TRUE);} voidgraphfunc(Biobufhdr *bp) {	USED(bp);} longnametorune(char *name) {	USED(name);	return(0);} voidnotavail(char *msg) {	fprint(2, "%s is not available at this time.\n", msg);}