Beispiel #1
0
void
draw(Biobufhdr *Bp) {

	int r, x1, y1, x2, y2, i;
	int d1, d2;

	drawflag = TRUE;
	r = Bgetrune(Bp);
	switch(r) {
	case 'l':
		if (Bgetfield(Bp, 'd', &x1, 0)<=0 || Bgetfield(Bp, 'd', &y1, 0)<=0 || Bgetfield(Bp, 'r', &i, 0)<=0)
			error(FATAL, "draw line function, destination coordinates not found.\n");

		endstring();
		if (pageon())
			Bprint(Bstdout, "%d %d %d %d Dl\n", hpos, vpos, hpos+x1, vpos+y1);
		hpos += x1;
		vpos += y1;
		break;
	case 'c':
		if (Bgetfield(Bp, 'd', &d1, 0)<=0)
			error(FATAL, "draw circle function, diameter coordinates not found.\n");

		endstring();
		if (pageon())
			Bprint(Bstdout, "%d %d %d %d De\n", hpos, vpos, d1, d1);
		hpos += d1;
		break;
	case 'e':
		if (Bgetfield(Bp, 'd', &d1, 0)<=0 || Bgetfield(Bp, 'd', &d2, 0)<=0)
			error(FATAL, "draw ellipse function, diameter coordinates not found.\n");

		endstring();
		if (pageon())
			Bprint(Bstdout, "%d %d %d %d De\n", hpos, vpos, d1, d2);
		hpos += d1;
		break;
	case 'a':
		if (Bgetfield(Bp, 'd', &x1, 0)<=0 || Bgetfield(Bp, 'd', &y1, 0)<=0 || Bgetfield(Bp, 'd', &x2, 0)<=0 || Bgetfield(Bp, 'd', &y2, 0)<=0)
			error(FATAL, "draw arc function, coordinates not found.\n");

		endstring();
		if (pageon())
			Bprint(Bstdout, "%d %d %d %d %d %d Da\n", hpos, vpos, x1, y1, x2, y2);
		hpos += x1 + x2;
		vpos += y1 + y2;
		break;
	case 'q':
		drawspline(Bp, 1);
		break;
	case '~':
		drawspline(Bp, 2);
		break;
	default:
		error(FATAL, "unknown draw function <%c>\n", r);
		break;
	}
}
Beispiel #2
0
static char *fm_strbrk(OBJECT *start,WORD maxnum,WORD maxlen,char *alert,
                           WORD *pnum,WORD *plen)
{
    int i, j, len;
    OBJECT *obj;
    char *p;

    *plen = 0;

    if (*alert == '[')              /* ignore a leading [ */
        alert++;

    for (i = 0, obj = start; i < maxnum; i++, obj++, alert++) {
        p = (char *)obj->ob_spec;
        for (j = 0; j < maxlen; j++) {
            if (endsubstring(*alert))
                break;
            *p++ = *alert++;
        }
        *p = '\0';

        len = p - (char *)obj->ob_spec;
        if (len > *plen)            /* track max substring length */
            *plen = len;

        if (!endsubstring(*alert)) {/* substring was too long */
#if DBG_ALERT
            kprintf("form_alert(): substring > %d bytes long\n",maxlen);
#endif
            while(1) {              /* eat rest of substring */
                if (endsubstring(*alert))
                    break;
                alert++;
            }
        }
        if (endstring(*alert))      /* end of all substrings */
            break;
    }
#if DBG_ALERT
    if (i >= maxnum)                /* too many substrings */
        kprintf("form_alert(): more than %d substrings\n",maxnum);
#endif

    while(1) {                      /* eat any remaining characters */
        if (endstring(*alert))
            break;
        alert++;
    }

    *pnum = (i<maxnum)?(i+1):maxnum;/* count of substrings found */

    if (*alert)                     /* if not at null byte, */
        alert++;                    /* point to next one    */

    return alert;
}
Beispiel #3
0
void
beginpath(char *buf, int copy) {

/*
 * Called from devcntrl() whenever an "x X BeginPath" command is read. It's used
 * to mark the start of a sequence of drawing commands that should be grouped
 * together and treated as a single path. By default the drawing procedures in
 * *drawfile treat each drawing command as a separate object, and usually start
 * with a newpath (just as a precaution) and end with a stroke. The newpath and
 * stroke isolate individual drawing commands and make it impossible to deal with
 * composite objects. "x X BeginPath" can be used to mark the start of drawing
 * commands that should be grouped together and treated as a single object, and
 * part of what's done here ensures that the PostScript drawing commands defined
 * in *drawfile skip the newpath and stroke, until after the next "x X DrawPath"
 * command. At that point the path that's been built up can be manipulated in
 * various ways (eg. filled and/or stroked with a different line width).
 *
 * Color selection is one of the options that's available in parsebuf(),
 * so if we get here we add *colorfile to the output file before doing
 * anything important.
 *
 */
	if (inpath == FALSE) {
		endstring();
	/*	getdraw();	*/
	/*	getcolor(); */
		Bprint(Bstdout, "gsave\n");
		Bprint(Bstdout, "newpath\n");
		Bprint(Bstdout, "%d %d m\n", hpos, vpos);
		Bprint(Bstdout, "/inpath true def\n");
		if ( copy == TRUE )
			Bprint(Bstdout, "%s\n", buf);
		inpath = TRUE;
	}
}
Beispiel #4
0
void
hmot(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;
}
Beispiel #5
0
void
vgoto(int y) {
	vpos = y;
	if (pageon()) {
		endstring();
/*		Bprint(Bstdout, "%d %d m\n", hpos, vpos); */
	}
}
Beispiel #6
0
void
hgoto(int x) {
	hpos = x;
	if (pageon()) {
		endstring();
/*		Bprint(Bstdout, "%d %d m\n", hpos, vpos); */
	}
}
Beispiel #7
0
static void
oput(int ch)

    /* int		ch;			/ * next output character */

{

/*
 *
 * Responsible for adding all printing characters from the input file to the
 * open string on top of the stack. The only other characters that end up in
 * that string are the quotes required for special characters. Reverse printing
 * mode hasn't been tested but it should be close. hpos and lastx should disagree
 * each time (except after startline() does something), and that should force a
 * call to endstring() for every character.
 *
 */

    if ( stringcount > 100 )		/* don't put too much on the stack */
	endline();

    if ( vpos != lasty )
	endline();

    if ( advance == -1 )		/* for reverse printing - move first */
	hmot(hmi);

    startline();

    if ( lastc != ch || hpos != prevx )  {
	if ( lastx != hpos )
	    endstring();

	if ( isascii(ch) && isprint(ch) ) {
	    if ( ch == '\\' || ch == '(' || ch == ')' )
		putc('\\', fp_out);
	    putc(ch, fp_out);
	} else fprintf(fp_out, "\\%.3o", ch & 0377);

	lastc = ch;
	prevx = hpos;
	lastx += lasthmi;
    }	/* End if */

    if ( advance != -1 )
	hmot(hmi);

    markedpage = TRUE;

}   /* End of oput */
Beispiel #8
0
void
drawspline(Biobufhdr *Bp, int flag) {	/* flag!=1 connect end points */
	int x[100], y[100];
	int i, N;
/*
 * Spline drawing routine for Postscript printers. The complicated stuff is
 * handled by procedure Ds, which should be defined in the library file. I've
 * seen wrong implementations of troff's spline drawing, so fo the record I'll
 * write down the parametric equations and the necessary conversions to Bezier
 * cubic splines (as used in Postscript).
 *
 * Parametric equation (x coordinate only):
 *
 *	    (x2 - 2 * x1 + x0)    2                    (x0 + x1)
 *	x = ------------------ * t   + (x1 - x0) * t + ---------
 *		    2					   2
 *
 * The coefficients in the Bezier cubic are,
 *
 *	A = 0
 *	B = (x2 - 2 * x1 + x0) / 2
 *	C = x1 - x0
 *
 * while the current point is,
 *
 *	current-point = (x0 + x1) / 2
 *
 * Using the relationships given in the Postscript manual (page 121) it's easy to
 * see that the control points are given by,
 *
 *	x0' = (x0 + 5 * x1) / 6
 *	x1' = (x2 + 5 * x1) / 6
 *	x2' = (x1 + x2) / 2
 *
 * where the primed variables are the ones used by curveto. The calculations
 * shown above are done in procedure Ds using the coordinates set up in both
 * the x[] and y[] arrays.
 *
 * A simple test of whether your spline drawing is correct would be to use cip
 * to draw a spline and some tangent lines at appropriate points and then print
 * the file.
 */
	for (N=2; N<sizeof(x)/sizeof(x[0]); N++)
		if (Bgetfield(Bp, 'd', &x[N], 0)<=0 || Bgetfield(Bp, 'd', &y[N], 0)<=0)
			break;

	x[0] = x[1] = hpos;
	y[0] = y[1] = vpos;

	for (i = 1; i < N; i++) {
		x[i+1] += x[i];
		y[i+1] += y[i];
	}

	x[N] = x[N-1];
	y[N] = y[N-1];

	for (i = ((flag!=1)?0:1); i < ((flag!=1)?N-1:N-2); i++) {
		endstring();
		if (pageon())
			Bprint(Bstdout, "%d %d %d %d %d %d Ds\n", x[i], y[i], x[i+1], y[i+1], x[i+2], y[i+2]);
/*		if (dobbox == TRUE) {		/* could be better */
/*	    		cover((double)(x[i] + x[i+1])/2,(double)-(y[i] + y[i+1])/2);
/*	    		cover((double)x[i+1], (double)-y[i+1]);
/*	    		cover((double)(x[i+1] + x[i+2])/2, (double)-(y[i+1] + y[i+2])/2);
/*		}
 */
	}

	hpos = x[N];			/* where troff expects to be */
	vpos = y[N];
}
Beispiel #9
0
void
devcntl(Biobufhdr *inp) {
	char cmd[50], buf[256], str[MAXTOKENSIZE], *line;
	int c, n;

/*
 *
 * Interpret device control commands, ignoring any we don't recognize. The
 * "x X ..." commands are a device dependent collection generated by troff's
 * \X'...' request.
 *
 */

	Bgetfield(inp, 's', cmd, 50);
	if (debug) Bprint(Bstderr, "devcntl(cmd=%s)\n", cmd);
	switch (cmd[0]) {
	case 'f':		/* mount font in a position */
		Bgetfield(inp, 'd', &n, 0);
		Bgetfield(inp, 's', str, 100);
		mountfont(n, str);
		break;

	case 'i':			/* initialize */
		initialize();
		break;

	case 'p':			/* pause */
		break;

	case 'r':			/* resolution assumed when prepared */
		Bgetfield(inp, 'd', &resolution, 0);
		Bgetfield(inp, 'd', &minx, 0);
		Bgetfield(inp, 'd', &miny, 0);
		break;

	case 's':			/* stop */
	case 't':			/* trailer */
		/* flushtext(); */
		break;

	case 'H':			/* char height */
		Bgetfield(inp, 'd', &n, 0);
		t_charht(n);
		break;

	case 'S':			/* slant */
		Bgetfield(inp, 'd', &n, 0);
		t_slant(n);
		break;

	case 'T':			/* device name */
		Bgetfield(inp, 's', devname, 16);
		if (debug) Bprint(Bstderr, "devname=%s\n", devname);
		break;

	case 'E':			/* input encoding - not in troff yet */
		Bgetfield(inp, 's', str, 100);
/*
		if (strcmp(str, "UTF") == 0)
			reading = UTFENCODING;
		else
			reading = ONEBYTE;
 */
		break;

	case 'X':			/* copy through - from troff */
		if (Bgetfield(inp, 's', str, MAXTOKENSIZE-1) <= 0)
			error(FATAL, "incomplete devcntl line\n");
		if ((line = Brdline(inp, '\n')) == 0)
			error(FATAL, "incomplete devcntl line\n");
		strncpy(buf, line, Blinelen(inp)-1);
		buf[Blinelen(inp)-1] = '\0';
		Bungetc(inp);

		if (strncmp(str, "PI", sizeof("PI")-1) == 0 || strncmp(str, "PictureInclusion", sizeof("PictureInclusion")-1) == 0) {
			picture(inp, str);
		} else if (strncmp(str, "InlinePicture", sizeof("InlinePicture")-1) == 0) {
			error(FATAL, "InlinePicture not implemented yet.\n");
/*			inlinepic(inp, buf);			*/
		} else if (strncmp(str, "BeginPath", sizeof("BeginPath")-1) == 0) {
			beginpath(buf, FALSE);
		} else if (strncmp(str, "DrawPath", sizeof("DrawPath")-1) == 0) {
			drawpath(buf, FALSE);
		} else if (strncmp(str, "BeginObject", sizeof("BeginObject")-1) == 0) {
			beginpath(buf, TRUE);
		} else if (strncmp(str, "EndObject", sizeof("EndObject")-1) == 0) {
			drawpath(buf, TRUE);
		} else if (strncmp(str, "NewBaseline", sizeof("NewBaseline")-1) == 0) {
			error(FATAL, "NewBaseline not implemented yet.\n");
/*			newbaseline(buf);			*/
		} else if (strncmp(str, "DrawText", sizeof("DrawText")-1) == 0) {
			error(FATAL, "DrawText not implemented yet.\n");
/*			drawtext(buf);				*/
		} else if (strncmp(str, "SetText", sizeof("SetText")-1) == 0) {
			error(FATAL, "SetText not implemented yet.\n");
/*			settext(buf);				*/
		} else if (strncmp(str, "SetColor", sizeof("SetColor")-1) == 0) {
			error(FATAL, "SetColor not implemented yet.\n");
/*			newcolor(buf);				*/
/*			setcolor();					*/
		} else if (strncmp(str, "INFO", sizeof("INFO")-1) == 0) {
			error(FATAL, "INFO not implemented yet.\n");
/*			flushtext();				*/
/*			Bprint(outp, "%%INFO%s", buf);	*/
		} else if (strncmp(str, "PS", sizeof("PS")-1) == 0 || strncmp(str, "PostScript", sizeof("PostScript")-1) == 0) {
			if(pageon()) {
				endstring();
				Bprint(Bstdout, "%s\n", buf);
			}
		} else if (strncmp(str, "ExportPS", sizeof("ExportPS")-1) == 0) {	/* dangerous!! */
			error(FATAL, "ExportPS not implemented yet.\n");
/*			if (Bfildes(outp) == 1) {		*/
/*				restore();				*/
/*				Bprint(outp, "%s", buf);	*/
/*				save();				*/
/*			}						*/
		}
/*		 else
			error(WARNING, "Unknown string <%s %s> after x X\n", str, buf);
*/

		break;
	}
	while ((c = Bgetc(inp)) != '\n' && c != Beof);
	inputlineno++;
}
Beispiel #10
0
/* 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.
 */
void
glyphout(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;
	}
}
Beispiel #11
0
void
vmot(int y) {
	endstring();
/*	Bprint(Bstdout, " 0 %d rmoveto ", -y); */
	vpos += y;
}