Example #1
0
static void
linefeed(void)

{

    int		line = 0;		/* current line - based on ovmi */

/*
 *
 * Adjust our current vertical position. If we've passed the bottom of the page
 * or exceeded the number of lines per page, print it and go to the upper left
 * corner of the next page. This routine is also called from carriage() if crislf
 * is ON.
 *
 */

    vmot(vmi);

    if ( lfiscr == ON )
	hgoto(leftmargin);

    if ( linespp > 0 )			/* means something so see where we are */
	line = vpos / ovmi + 1;

    if ( vpos > bottommargin || line > linespp )
	formfeed();

}   /* End of linefeed */
Example #2
0
void
drawellip (
    int a,
    int b,			/* axes lengths for the ellipse */
    int c
)


{


/*
 *
 * Draws an ellipse having axes lengths horizontally and vertically of a and
 * b. The left side of the ellipse is at the current point. After we're done
 * drawing the path we move the current position to the right side.
 *
 */


    if ( a == 0 && b == 0 )
	return;

    fprintf(tf, "%d %d %d %d D%c\n", hpos, vpos, a, b, c);

    hgoto(hpos + a);			/* where troff expects to be */
    vgoto(vpos);

    resetpos();				/* not sure where the printer is */

}   /* End of drawellip */
Example #3
0
static void
htab(void)

{

    int		col;			/* 'column' we'll be at next */
    int		i;			/* loop index */

/*
 *
 * Tries to figure out where the next tab stop is. Wasn't positive about this
 * one, since hmi can change. I'll assume columns are determined by the original
 * value of hmi. That fixes them on the page, which seems to make more sense than
 * letting them float all over the place.
 *
 */

    endline();

    col = hpos/ohmi + 1;
    for ( i = col; i < ROWS; i++ )
	if ( htabstops[i] == ON )  {
	    col = i;
	    break;
	}   /* End if */

    hgoto(col * ohmi);
    lastx = hpos;

}   /* End of htab */
Example #4
0
void
drawline (
    int dx,
    int dy			/* endpoint is (hpos+dx, vpos+dy) */
)


{


/*
 *
 * Draws a line from (hpos, vpos) to (hpos+dx, vpos+dy), and leaves the current
 * position at the endpoint.
 *
 */


    if ( dx == 0 && dy == 0 )
	drawcirc(1, 'c');
    else fprintf(tf, "%d %d %d %d Dl\n", hpos + dx, vpos + dy, hpos, vpos);

    hgoto(hpos+dx);			/* where troff expects to be */
    vgoto(vpos+dy);

    resetpos();				/* not sure where the printer is */

}   /* End of drawline */
Example #5
0
File: draw.c Project: aksr/heirloom
void
drawellip(int a, int b)
{
	int xc, yc;

	xc = hpos;
	yc = vpos;
	conicarc(hpos + a/2, -vpos, hpos, -vpos, hpos, -vpos, a/2, b/2);
	hgoto(xc + a);
	vgoto(yc);
}
Example #6
0
File: draw.c Project: aksr/heirloom
void
drawcirc(int d)
{
	int xc, yc;

	xc = hpos;
	yc = vpos;
	conicarc(hpos + d/2, -vpos, hpos, -vpos, hpos, -vpos, d/2, d/2);
	hgoto(xc + d);	/* circle goes to right side */
	vgoto(yc);
}
Example #7
0
File: draw.c Project: aksr/heirloom
void
drawwig(char *s)	/* draw wiggly line */
{
	int x[50], y[50], xp, yp, pxp, pyp;
	float t1, t2, t3, w;
	int i, j, numdots, N;
	int osize;
	char temp[50], *p;

	osize = size;
	setsize(t_size(pstab[osize-1] / drawsize));
	p = s;
	for (N = 2; (p=getstr(p,temp)) != NULL && N < sizeof(x)/sizeof(x[0]); N++) {
		x[N] = atoi(temp);
		p = getstr(p, temp);
		y[N] = atoi(temp);
	}
	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];
	pxp = pyp = -9999;
	for (i = 0; i < N-1; i++) {	/* interval */
		numdots = (dist(x[i],y[i], x[i+1],y[i+1]) + dist(x[i+1],y[i+1], x[i+2],y[i+2])) / 2;
		numdots /= DX;
		numdots = min(numdots, maxdots);
		for (j = 0; j < numdots; j++) {	/* points within */
			w = (float) j / numdots;
			t1 = 0.5 * w * w;
			w = w - 0.5;
			t2 = 0.75 - w * w;
			w = w - 0.5;
			t3 = 0.5 * w * w;
			xp = t1 * x[i+2] + t2 * x[i+1] + t3 * x[i] + 0.5;
			yp = t1 * y[i+2] + t2 * y[i+1] + t3 * y[i] + 0.5;
			if (xp != pxp || yp != pyp) {
				hgoto(xp);
				vgoto(yp);
				put1(drawdot);
				pxp = xp;
				pyp = yp;
			}
		}
	}
	setsize(osize);
}
Example #8
0
static void
formfeed(void)

{

/*
 *
 * Called whenever we've finished with the last page and want to get ready for the
 * next one. Also used at the beginning and end of each input file, so we have to
 * be careful about what's done. I've added a simple test before the showpage that
 * should eliminate the extra blank page that was put out at the end of many jobs,
 * but the PAGES comments may be wrong.
 *
 */

    if ( fp_out == stdout )		/* count the last page */
	printed++;

    endline();				/* print the last line */

    fprintf(fp_out, "cleartomark\n");
    if ( feof(fp_in) == 0 || markedpage == TRUE )
	fprintf(fp_out, "showpage\n");
    fprintf(fp_out, "saveobj restore\n");
    fprintf(fp_out, "%s %d %d\n", ENDPAGE, page, printed);

    if ( ungetc(getc(fp_in), fp_in) == EOF )
	redirect(-1);
    else redirect(++page);

    fprintf(fp_out, "%s %d %d\n", PAGE, page, printed+1);
    fprintf(fp_out, "/saveobj save def\n");
    fprintf(fp_out, "mark\n");
    writerequest(printed+1, fp_out);
    fprintf(fp_out, "%d pagesetup\n", printed+1);

    vgoto(topmargin);
    hgoto(leftmargin);

    markedpage = FALSE;

}   /* End of formfeed */
Example #9
0
static void
backspace(void)

{

/*
 *
 * Moves backwards a distance equal to the current value of hmi, but don't go
 * past the left margin.
 *
 */

    endline();

    if ( hpos - leftmargin >= hmi )
	hmot(-hmi);
    else hgoto(leftmargin);		/* maybe just ignore the backspace?? */

    lastx = hpos;

}   /* End of backspace */
Example #10
0
void
drawarc (
    int dx1,
    int dy1,		/* vector from current pos to center */
    int dx2,
    int dy2,		/* from center to end of the arc */
    int c			/* clockwise if c is A */
)


{


/*
 *
 * If c isn't set to 'A' a counter-clockwise arc is drawn from the current point
 * (hpos, vpos) to (hpos+dx1+dx2, vpos+dy1+dy2). The center of the circle is the
 * point (hpos+dx1, vpos+dy1). If c is 'A' the arc goes clockwise from the point
 * (hpos+dx1+dx2, vpos+dy1+dy2) to (hpos, vpos). Clockwise arcs are only needed
 * if we're building a larger path out of pieces that include arcs, and want to
 * have PostScript manage the path for us. Arguments (for a clockwise arc) are
 * what would have been supplied if the arc was drawn in a counter-clockwise
 * direction, and are converted to values suitable for use with PostScript's arcn
 * operator.
 *
 */


    if ( (dx1 != 0 || dy1 != 0) && (dx2 != 0 || dy2 != 0) )
    {
        fprintf(tf, "%d %d %d %d %d %d D%c\n", hpos, vpos, dx1, dy1, dx2, dy2, c);
    }

    hgoto(hpos + dx1 + dx2);		/* where troff expects to be */
    vgoto(vpos + dy1 + dy2);

    resetpos();				/* not sure where the printer is */

}   /* End of drawarc */
Example #11
0
static void
carriage(void)

{

/*
 *
 * Handles carriage return character. If crislf is ON we'll generate a line feed
 * every time we get a carriage return character.
 *
 */

    if ( shadowprint == ON )		/* back to normal mode */
	changefont(fontname);

    advance = 1;
    shadowprint = OFF;

    hgoto(leftmargin);

    if ( crislf == ON )
	linefeed();

}   /* End of carriage */
Example #12
0
static void
escape(void)

{

    int		ch;			/* control character */

/*
 *
 * Handles special codes that are expected to follow an escape character. The
 * initial escape character is followed by one or two bytes.
 *
 */

    switch ( ch = getc(fp_in) ) {
	case 'T':			/* top margin */
		topmargin = vpos;
		break;

	case 'L':			/* bottom margin */
		bottommargin = vpos;
		break;

	case 'C':			/* clear top and bottom margins */
		bottommargin = BOTTOMMARGIN;
		topmargin = TOPMARGIN;
		break;

	case '9':			/* left margin */
		leftmargin = hpos;
		break;

	case '0':			/* right margin */
		rightmargin = hpos;
		break;

	case '1':			/* set horizontal tab */
		htabstops[hpos/ohmi] = ON;
		break;

	case '8':			/* clear horizontal tab at hpos */
		htabstops[hpos/ohmi] = OFF;
		break;

	case '-':			/* set vertical tab */
		vtabstops[vpos/ovmi] = ON;
		break;

	case '2':			/* clear all tabs */
		cleartabs();
		break;

	case '\014':			/* set lines per page */
		linespp = getc(fp_in);
		break;

	case '\037':			/* set hmi to next byte minus 1 */
		hmi = HSCALE * (getc(fp_in) - 1);
		break;

	case 'S':			/* reset hmi to default */
		hmi = ohmi;
		break;

	case '\011':			/* move to column given by next byte */
		hgoto((getc(fp_in)-1) * ohmi);
		break;

	case '?':			/* do carriage return after line feed */
		lfiscr = ON;
		break;

	case '!':			/* don't generate carriage return */
		lfiscr = OFF;
		break;

	case '5':			/* forward print mode */
		advance = 1;
		break;

	case '6':			/* backward print mode */
		advance = -1;
		break;

	case '\036':			/* set vmi to next byte minus 1 */
		vmi = VSCALE * (getc(fp_in) - 1);
		break;

	case '\013':			/* move to line given by next byte */
		vgoto((getc(fp_in)-1) * ovmi);
		break;

	case 'U':			/* positive half line feed */
		vmot(vmi/2);
		break;

	case 'D':			/* negative half line feed */
		vmot(-vmi/2);
		break;

	case '\012':			/* negative line feed */
		vmot(-vmi);
		break;

	case '\015':			/* clear all margins */
		bottommargin = BOTTOMMARGIN;
		topmargin = TOPMARGIN;
		leftmargin = BOTTOMMARGIN;
		rightmargin = RIGHTMARGIN;
		break;

	case 'E':			/* auto underscore - use italic font */
		changefont("/Courier-Oblique");
		break;

	case 'R':			/* disable auto underscore */
		changefont(fontname);
		break;

	case 'O':			/* bold/shadow printing */
	case 'W':
		changefont("/Courier-Bold");
		shadowprint = ON;
		break;

	case '&':			/* disable bold printing */
		changefont(fontname);
		shadowprint = OFF;
		break;

	case '/':			/* ignored 2 byte escapes */
	case '\\':
	case '<':
	case '>':
	case '%':
	case '=':
	case '.':
	case '4':
	case 'A':
	case 'B':
	case 'M':
	case 'N':
	case 'P':
	case 'Q':
	case 'X':
	case '\010':
		break;

	case ',':			/* ignored 3 byte escapes */
	case '\016':
	case '\021':
		getc(fp_in);
		break;

	case '3':			/* graphics mode - should quit! */
	case '7':
	case 'G':
	case 'V':
	case 'Y':
	case 'Z':
		error(FATAL, "graphics mode is not implemented");
		break;

	default:
		error(FATAL, "missing case for escape o%o\n", ch);
		break;
    }	/* End switch */

}   /* End of escape */
Example #13
0
void
drawspline(


    FILE	*fp,			/* input for point list */
    int		flag			/* flag!=1 connect end points */
)


{


    int		x[100], y[100];
    size_t	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 (fscanf(fp, "%d %d", &x[N], &y[N]) != 2)
		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];
    }	/* End for */

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

    for (i = ((flag!=1)?0:1); i < ((flag!=1)?N-1:N-2); i++)
	fprintf(tf, "%d %d %d %d %d %d Ds\n", x[i], y[i], x[i+1], y[i+1], x[i+2], y[i+2]);

    hgoto(x[N]);			/* where troff expects to be */
    vgoto(y[N]);

    resetpos();				/* not sure where the printer is */

}   /* End of drawspline */
Example #14
0
void movehv(double h, double v)	/* go to internal position h, v */
{
	hgoto(h);
	vgoto(v);
}
Example #15
0
void move(double x, double y)	/* go to position x, y in external coords */
{
	hgoto(xconv(x));
	vgoto(yconv(y));
}
Example #16
0
File: draw.c Project: aksr/heirloom
void
drawline(int dx, int dy, char *s) /* draw line from here to dx, dy using s */
{
	int xd, yd;
	float val, slope;
	int i, numdots;
	int dirmot, perp;
	int motincr, perpincr;
	int ohpos, ovpos, osize;
	float incrway;

	int itemp; /*temp. storage for value returned byint function sgn*/
	osize = size;
	setsize(t_size(pstab[osize-1] / drawsize));
	ohpos = hpos;
	ovpos = vpos;
	xd = dx / DX;
	yd = dy / DX;
	if (xd == 0) {
		numdots = abs (yd);
		numdots = min(numdots, maxdots);
		motincr = DX * sgn (yd);
		for (i = 0; i < numdots; i++) {
			vmot(motincr);
			put1(drawdot);
		}
		vgoto(ovpos + dy);
		setsize(osize);
		return;
	}
	if (yd == 0) {
		numdots = abs (xd);
		motincr = DX * sgn (xd);
		for (i = 0; i < numdots; i++) {
			hmot(motincr);
			put1(drawdot);
		}
		hgoto(ohpos + dx);
		setsize(osize);
		return;
	}
	if (abs (xd) > abs (yd)) {
		val = slope = (float) xd/yd;
		numdots = abs (xd);
		numdots = min(numdots, maxdots);
		dirmot = 'h';
		perp = 'v';
		motincr = DX * sgn (xd);
		perpincr = DX * sgn (yd);
	}
	else {
		val = slope = (float) yd/xd;
		numdots = abs (yd);
		numdots = min(numdots, maxdots);
		dirmot = 'v';
		perp = 'h';
		motincr = DX * sgn (yd);
		perpincr = DX * sgn (xd);
	}
	incrway = itemp = sgn ((int) slope);
	for (i = 0; i < numdots; i++) {
		val -= incrway;
		if (dirmot == 'h')
			hmot(motincr);
		else
			vmot(motincr);
		if (val * slope < 0) {
			if (perp == 'h')
				hmot(perpincr);
			else
				vmot(perpincr);
			val += slope;
		}
		put1(drawdot);
	}
	hgoto(ohpos + dx);
	vgoto(ovpos + dy);
	setsize(osize);
}
Example #17
0
void
conv(register FILE *fp)
{
	register int c, k;
	int m, n, n1, m1;
	char str[4096], buf[4096];

	while ((c = getc(fp)) != EOF) {
		switch (c) {
		case '\n':	/* when input is text */
		case ' ':
		case 0:		/* occasional noise creeps in */
			break;
		case '{':	/* push down current environment */
			t_push();
			break;
		case '}':
			t_pop();
			break;
		case '0': case '1': case '2': case '3': case '4':
		case '5': case '6': case '7': case '8': case '9':
			/* two motion digits plus a character */
			hmot((c-'0')*10 + getc(fp)-'0');
			put1(getc(fp));
			break;
		case 'c':	/* single ascii character */
			put1(getc(fp));
			break;
		case 'C':
			sget(str, sizeof str, fp);
			put1s(str);
			break;
		case 't':	/* straight text */
			fgets(buf, sizeof(buf), fp);
			t_text(buf);
			break;
		case 'D':	/* draw function */
			fgets(buf, sizeof(buf), fp);
			switch (buf[0]) {
			case 'l':	/* draw a line */
				sscanf(buf+1, "%d %d", &n, &m);
				drawline(n, m, ".");
				break;
			case 'c':	/* circle */
				sscanf(buf+1, "%d", &n);
				drawcirc(n);
				break;
			case 'e':	/* ellipse */
				sscanf(buf+1, "%d %d", &m, &n);
				drawellip(m, n);
				break;
			case 'a':	/* arc */
				sscanf(buf+1, "%d %d %d %d", &n, &m, &n1, &m1);
				drawarc(n, m, n1, m1);
				break;
			case '~':	/* wiggly line */
				drawwig(buf+1);
				break;
			default:
				error(FATAL, "unknown drawing function %s\n", buf);
				break;
			}
			break;
		case 's':
			fscanf(fp, "%d", &n);
			if (n == -23) {
				float	f;
				fscanf(fp, "%f", &f);
				setsize(f);
			} else
				setsize(t_size(n));/* ignore fractional sizes */
			break;
		case 'f':
			sget(str, sizeof str, fp);
			setfont(t_font(str));
			break;
		case 'H':	/* absolute horizontal motion */
			/* fscanf(fp, "%d", &n); */
			while ((c = getc(fp)) == ' ')
				;
			k = 0;
			do {
				k = 10 * k + c - '0';
			} while (isdigit(c = getc(fp)));
			ungetc(c, fp);
			hgoto(k);
			break;
		case 'h':	/* relative horizontal motion */
			/* fscanf(fp, "%d", &n); */
			while ((c = getc(fp)) == ' ')
				;
			k = 0;
			do {
				k = 10 * k + c - '0';
			} while (isdigit(c = getc(fp)));
			ungetc(c, fp);
			hmot(k);
			break;
		case 'w':	/* word space */
			putc(' ', stdout);
			break;
		case 'V':
			fscanf(fp, "%d", &n);
			vgoto(n);
			break;
		case 'v':
			fscanf(fp, "%d", &n);
			vmot(n);
			break;
		case 'p':	/* new page */
			fscanf(fp, "%d", &n);
			t_page(n);
			break;
		case 'n':	/* end of line */
			while (getc(fp) != '\n')
				;
			t_newline();
			break;
		case '#':	/* comment */
			while (getc(fp) != '\n')
				;
			break;
		case 'x':	/* device control */
			devcntrl(fp);
			break;
		default:
			error(!FATAL, "unknown input character %o %c\n", c, c);
			done();
		}
	}
}
Example #18
0
void
conv(Biobuf *Bp) {
	long n;
	int r;
	char special[10];
	int save;

	inputlineno = 1;
	if (debug) Bprint(Bstderr, "conv(Biobufhdr *Bp=0x%x)\n", Bp);
	while ((r = Bgetrune(Bp)) >= 0) {
/* Bprint(Bstderr, "r=<%c>,0x%x\n", r, r); */
/*		Bflush(Bstderr); */
		switch (r) {
		case 's':	/* set point size */
			Bgetfield(Bp, 'd', &fontsize, 0);
			break;
		case 'f':	/* set font to postion */
			Bgetfield(Bp, 'd', &fontpos, 0);
			save = inputlineno;
			settrfont();
			inputlineno = save;	/* ugh */
			break;
		case 'c':	/* print rune */
			r = Bgetrune(Bp);
			runeout(r);
			break;
		case 'C':	/* print special character */
			Bgetfield(Bp, 's', special, 10);
			specialout(special);
			break;
		case 'N':	/* print character with numeric value from current font */
			Bgetfield(Bp, 'd', &n, 0);
			break;
		case 'H':	/* go to absolute horizontal position */
			Bgetfield(Bp, 'd', &n, 0);
			hgoto(n);
			break;
		case 'V':	/* go to absolute vertical position */
			Bgetfield(Bp, 'd', &n, 0);
			vgoto(n);
			break;
		case 'h':	/* go to relative horizontal position */
			Bgetfield(Bp, 'd', &n, 0);
			hmot(n);
			break;
		case 'v':	/* go to relative vertical position */
			Bgetfield(Bp, 'd', &n, 0);
			vmot(n);
			break;
		case '0': case '1': case '2': case '3': case '4':
		case '5': case '6': case '7': case '8': case '9':
				/* move right nn units, then print character c */
			n = (r - '0') * 10;
			r = Bgetrune(Bp);
			if (r < 0)
				error(FATAL, "EOF or error reading input\n");
			else if (r < '0' || r > '9')
				error(FATAL, "integer expected\n");
			n += r - '0';
			r = Bgetrune(Bp);
			hmot(n);
			runeout(r);
			break;
		case 'p':	/* begin page */
			Bgetfield(Bp, 'd', &n, 0);
			endpage();
			startpage();
			break;
		case 'n':	/* end of line (information only 'b a' follows) */
			Brdline(Bp, '\n');	/* toss rest of line */
			inputlineno++;
			break;
		case 'w':	/* paddable word space (information only) */
			break;
		case 'D':	/* graphics function */
			draw(Bp);
			break;
		case 'x':	/* device control functions */
			devcntl(Bp);
			break;
		case '#':	/* comment */
			Brdline(Bp, '\n');	/* toss rest of line */
		case '\n':
			inputlineno++;
			break;
		default:
			error(WARNING, "unknown troff function <%c>\n", r);
			break;
		}
	}
	endpage();
	if (debug) Bprint(Bstderr, "r=0x%x\n", r);
	if (debug) Bprint(Bstderr, "leaving conv\n");
}
Example #19
0
void
main(void)
{
	int c, n;
	char str[100], *args[10];
	int jfont, curfont;

	if(initdraw(0, fontfile, 0) < 0){
		fprint(2, "mnihongo: can't initialize display: %r\n");
		exits("open");
	}
	Binit(&bin, 0, OREAD);
	Binit(&bout, 1, OWRITE);

	jfont = -1;
	curfont = 1;
	while ((c = Bgetc(&bin)) >= 0) {
		switch (c) {
		case '\n':	/* when input is text */
		case ' ':
		case '\0':		/* occasional noise creeps in */
			putchar(c);
			break;
		case '0': case '1': case '2': case '3': case '4':
		case '5': case '6': case '7': case '8': case '9':
			/* two motion digits plus a character */
			putchar(c);	/* digit 1 */
			n = (c-'0')*10;
			c = Bgetc(&bin);
			putchar(c);	/* digit 2 */
			n += c - '0';
			hmot(n);
			putchar(Bgetc(&bin));	/* char itself */
			break;
		case 'c':	/* single character */
			c = Bgetrune(&bin);
			if(c==' ')	/* why does this happen? it's troff - bwk */
				break;
			else if(jfont == curfont){
				Bungetrune(&bin);
				Bgetstr(&bin, str);
				kanji(str);
			}else{
				putchar('c');
				putchar(c);
			}
			break;
		case 'C':
			Bgetstr(&bin, str);
			Bprint(&bout, "C%s", str);
			break;
		case 'f':
			Bgetstr(&bin, str);
			curfont = atoi(str);
			if(curfont < 0 || curfont > 20)
				curfont = 1;	/* sanity */
			Bprint(&bout, "%c%s", c, str);
			break;
		case 'N':	/* absolute character number */
		case 's':
		case 'p':	/* new page */
			Bgetint(&bin, &n);
			Bprint(&bout, "%c%d", c, n);
			break;
		case 'H':	/* absolute horizontal motion */
			Bgetint(&bin, &n);
			Bprint(&bout, "%c%d", c, n);
			hgoto(n);
			break;
		case 'h':	/* relative horizontal motion */
			Bgetint(&bin, &n);
			Bprint(&bout, "%c%d", c, n);
			hmot(n);
			break;
		case 'V':
			Bgetint(&bin, &n);
			Bprint(&bout, "%c%d", c, n);
			vgoto(n);
			break;
		case 'v':
			Bgetint(&bin, &n);
			Bprint(&bout, "%c%d", c, n);
			vmot(n);
			break;

		case 'w':	/* word space */
			putchar(c);
			break;

		case 'x':	/* device control */
			Bgetline(&bin, str);
			Bprint(&bout, "%c%s", c, str);
			if(tokenize(str, args, 10)>2 && args[0][0]=='f' && ('0'<=args[1][0] && args[1][0]<='9')){
				if(strncmp(args[2], "Jp", 2) == 0)
					jfont = atoi(args[1]);
				else if(atoi(args[1]) == jfont)
					jfont = -1;
			}
			break;

		case 'D':	/* draw function */
		case 'n':	/* end of line */
		case '#':	/* comment */
			Bgetline(&bin, str);
			Bprint(&bout, "%c%s", c, str);
			break;
		default:
			fprint(2, "mnihongo: unknown input character %o %c\n", c, c);
			exits("error");
		}
	}
}