⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 htroff.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include	<u.h>#include	<libc.h>#include	<draw.h>#include	<cursor.h>#include	<event.h>#include	<bio.h>#include	"proof.h"int	res;int	hpos;int	vpos;int	DIV = 11;Point offset;Point xyoffset = { 0,0 };Rectangle	view[MAXVIEW];Rectangle	bound[MAXVIEW];		/* extreme points */int	nview = 1;int	lastp;	/* last page number we were on */#define	NPAGENUMS	200struct pagenum {	int	num;	long	adr;} pagenums[NPAGENUMS];int	npagenums;int	curfont, cursize;char	*getcmdstr(void);static void	initpage(void);static void	view_setup(int);static Point	scale(Point);static void	clearview(Rectangle);static int	addpage(int);static void	spline(Image *, int, Point *);static int	skipto(int, int);static void	wiggly(int);static void	devcntrl(void);static void	eatline(void);static int	getn(void);static int	botpage(int);static void	getstr(char *);static void	getutf(char *);#define Do screen->r.min#define Dc screen->r.max/* declarations and definitions of font stuff are in font.c and main.c */static voidinitpage(void){	int i;	view_setup(nview);	for (i = 0; i < nview-1; i++)		draw(screen, view[i], screen, nil, view[i+1].min);	clearview(view[nview-1]);	offset = view[nview-1].min;	vpos = 0;}static voidview_setup(int n){	int i, j, v, dx, dy, r, c;	switch (n) {	case 1: r = 1; c = 1; break;	case 2: r = 1; c = 2; break;	case 3: r = 1; c = 3; break;	case 4: r = 2; c = 2; break;	case 5: case 6: r = 2; c = 3; break;	case 7: case 8: case 9: r = 3; c = 3; break;	default: r = (n+2)/3; c = 3; break; /* finking out */	}	dx = (Dc.x - Do.x) / c;	dy = (Dc.y - Do.y) / r;	v = 0;	for (i = 0; i < r && v < n; i++)		for (j = 0; j < c && v < n; j++) {			view[v] = screen->r;			view[v].min.x = Do.x + j * dx;			view[v].max.x = Do.x + (j+1) * dx;			view[v].min.y = Do.y + i * dy;			view[v].max.y = Do.y + (i+1) * dy;			v++;		}}static voidclearview(Rectangle r){	draw(screen, r, display->white, nil, r.min);}int resized;void eresized(int new){	/* this is called if we are resized */	if(new && getwindow(display, Refnone) < 0)		drawerror(display, "can't reattach to window");	initpage();	resized = 1;}static Pointscale(Point p){	p.x /= DIV;	p.y /= DIV;	return addpt(xyoffset, addpt(offset,p));}static intaddpage(int n){	int i;	for (i = 0; i < npagenums; i++)		if (n == pagenums[i].num)			return i;	if (npagenums < NPAGENUMS-1) {		pagenums[npagenums].num = n;		pagenums[npagenums].adr = offsetc();		npagenums++;	}	return npagenums;}voidreadpage(void){	int c, i, a, alpha, phi;	static int first = 0;	int m, n, gonow = 1;	Rune r[32], t;	Point p,q,qq;	offset = screen->clipr.min;	esetcursor(&deadmouse);	while (gonow)	{		c = getc();		switch (c)		{		case -1:			esetcursor(0);			if (botpage(lastp+1)) {				initpage();				break;			}			exits(0);		case 'p':	/* new page */			lastp = getn();			addpage(lastp);			if (first++ > 0) {				esetcursor(0);				botpage(lastp);				esetcursor(&deadmouse);			}			initpage();			break;		case '\n':	/* when input is text */		case ' ':		case 0:		/* occasional noise creeps in */			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 */			hpos += (c-'0')*10 + getc()-'0';		/* FALLS THROUGH */		case 'c':	/* single ascii character */			r[0] = getrune();			r[1] = 0;			dochar(r);			break;		case 'C':			for(i=0; ; i++){				t = getrune();				if(isspace(t))					break;				r[i] = t;			}			r[i] = 0;			dochar(r);			break;		case 'N':			r[0] = getn();			r[1] = 0;			dochar(r);			break;		case 'D':	/* draw function */			switch (getc())			{			case 'l':	/* draw a line */				n = getn();				m = getn();				p = Pt(hpos,vpos);				q = addpt(p, Pt(n,m));				hpos += n;				vpos += m;				line(screen, scale(p), scale(q), 0, 0, 0, display->black, ZP);				break;			case 'c':	/* circle */				/*nop*/				m = getn()/2;				p = Pt(hpos+m,vpos);				hpos += 2*m;				ellipse(screen, scale(p), m/DIV, m/DIV, 0, display->black, ZP);				/* p=currentpt; p.x+=dmap(m/2);circle bp,p,a,ONES,Mode*/				break;			case 'e':	/* ellipse */				/*nop*/				m = getn()/2;				n = getn()/2;				p = Pt(hpos+m,vpos);				hpos += 2*m;				ellipse(screen, scale(p), m/DIV, n/DIV, 0, display->black, ZP);				break;			case 'a':	/* arc */				p = scale(Pt(hpos,vpos));				n = getn();				m = getn();				hpos += n;				vpos += m;				q = scale(Pt(hpos,vpos));				n = getn();				m = getn();				hpos += n;				vpos += m;				qq = scale(Pt(hpos,vpos));				/*				  * tricky: convert from 3-point clockwise to				  * center, angle1, delta-angle counterclockwise.				 */				a = hypot(qq.x-q.x, qq.y-q.y);				phi = atan2(q.y-p.y, p.x-q.x)*180./PI;				alpha = atan2(q.y-qq.y, qq.x-q.x)*180./PI - phi;				if(alpha < 0)					alpha += 360;				arc(screen, q, a, a, 0, display->black, ZP, phi, alpha);				break;			case '~':	/* wiggly line */				wiggly(0);				break;			default:				break;			}			eatline();			break;		case 's':			n = getn();	/* ignore fractional sizes */			if (cursize == n)				break;			cursize = n;			if (cursize >= NFONT)				cursize = NFONT-1;			break;		case 'f':			curfont = getn();			break;		case 'H':	/* absolute horizontal motion */			hpos = getn();			break;		case 'h':	/* relative horizontal motion */			hpos += getn();			break;		case 'w':	/* word space */			break;		case 'V':			vpos = getn();			break;		case 'v':			vpos += getn();			break;		case '#':	/* comment */		case 'n':	/* end of line */			eatline();			break;		case 'x':	/* device control */			devcntrl();			break;		default:			fprint(2, "unknown input character %o %c at offset %lud\n", c, c, offsetc());			exits("bad char");		}	}	esetcursor(0);}static voidspline(Image *b, int n, Point *pp){	long w, t1, t2, t3, fac=1000; 	int i, j, steps=10; 	Point p, q;	for (i = n; i > 0; i--)		pp[i] = pp[i-1];	pp[n+1] = pp[n];	n += 2;	p = pp[0];	for(i = 0; i < n-2; i++)	{		for(j = 0; j < steps; j++)		{			w = fac * j / steps;			t1 = w * w / (2 * fac);			w = w - fac/2;			t2 = 3*fac/4 - w * w / fac;			w = w - fac/2;			t3 = w * w / (2*fac);			q.x = (t1*pp[i+2].x + t2*pp[i+1].x + 				t3*pp[i].x + fac/2) / fac;			q.y = (t1*pp[i+2].y + t2*pp[i+1].y + 				t3*pp[i].y + fac/2) / fac;			line(b, p, q, 0, 0, 0, display->black, ZP);			p = q;		}	}}/* Have to parse skipped pages, to find out what fonts are loaded. */static intskipto(int gotop, int curp){	char *p;	int i;	if (gotop == curp)		return 1;	for (i = 0; i < npagenums; i++)		if (pagenums[i].num == gotop) {			if (seekc(pagenums[i].adr) == Beof) {				fprint(2, "can't rewind input\n");				return 0;			}			return 1;		}	if (gotop <= curp) {	    restart:		if (seekc(0) == Beof) {			fprint(2, "can't rewind input\n");			return 0;		}	}	for(;;){		p = rdlinec();		if (p == 0) {			if(gotop>curp){				gotop = curp;				goto restart;			}			return 0;		} else if (*p == 'p') {			lastp = curp = atoi(p+1);			addpage(lastp);	/* maybe 1 too high */			if (curp>=gotop)				return 1;		}	}}static voidwiggly(int skip){	Point p[300];	int c,i,n;	for (n = 1; (c = getc()) != '\n' && c>=0; n++) {		ungetc();		p[n].x = getn();		p[n].y = getn();	}	p[0] = Pt(hpos, vpos);	for (i = 1; i < n; i++)		p[i] = addpt(p[i],p[i-1]);	hpos = p[n-1].x;	vpos = p[n-1].y;	for (i = 0; i < n; i++)		p[i] = scale(p[i]);	if (!skip)		spline(screen,n,p);}static voiddevcntrl(void)	/* interpret device control functions */{        char str[80];	int n;	getstr(str);	switch (str[0]) {	/* crude for now */	case 'i':	/* initialize */		break;	case 'T':	/* device name */		getstr(devname);		break;	case 't':	/* trailer */		break;	case 'p':	/* pause -- can restart */		break;	case 's':	/* stop */		break;	case 'r':	/* resolution assumed when prepared */		res=getn();		DIV = floor(.5 + res/(100.0*mag));		if (DIV < 1)			DIV = 1;		mag = res/(100.0*DIV); /* adjust mag according to DIV coarseness */		break;	case 'f':	/* font used */		n = getn();		getstr(str);		loadfontname(n, str);		break;	/* these don't belong here... */	case 'H':	/* char height */		break;	case 'S':	/* slant */		break;	case 'X':		break;	}	eatline();}intisspace(int c){	return c==' ' || c=='\t' || c=='\n';}static voidgetstr(char *is){	uchar *s = (uchar *) is;	for (*s = getc(); isspace(*s); *s = getc())		;	for (; !isspace(*s); *++s = getc())		;	ungetc();	*s = 0;}static voidgetutf(char *s)		/* get next utf char, as bytes */{	int c, i;	for (i=0;;) {		c = getc();		if (c < 0)			return;		s[i++] = c;		if (fullrune(s, i)) {			s[i] = 0;			return;		}	}}static voideatline(void){	int c;	while ((c=getc()) != '\n' && c >= 0)		;}static intgetn(void){	int n, c, sign;	while (c = getc())		if (!isspace(c))			break;	if(c == '-'){		sign = -1;		c = getc();	}else		sign = 1;	for (n = 0; '0'<=c && c<='9'; c = getc())		n = n*10 + c - '0';	while (c == ' ')		c = getc();	ungetc();	return(n*sign);}static intbotpage(int np)	/* called at bottom of page np-1 == top of page np */{	char *p;	int n;	while (p = getcmdstr()) {		if (*p == '\0')			return 0;		if (*p == 'q')			exits(p);		if (*p == 'c')		/* nop */			continue;		if (*p == 'm') {			mag = atof(p+1);			if (mag <= .1 || mag >= 10)				mag = DEFMAG;			allfree();	/* zap fonts */			DIV = floor(.5 + res/(100.0*mag));			if (DIV < 1)				DIV = 1;			mag = res/(100.0*DIV);			return skipto(np-1, np);	/* reprint the page */		}		if (*p == 'x') {			xyoffset.x += atoi(p+1)*100;			skipto(np-1, np);			return 1;		}		if (*p == 'y') {			xyoffset.y += atoi(p+1)*100;			skipto(np-1, np);			return 1;		}		if (*p == '/') {	/* divide into n pieces */			nview = atoi(p+1);			if (nview < 1)				nview = 1;			else if (nview > MAXVIEW)				nview = MAXVIEW;			return skipto(np-1, np);		}		if (*p == 'p') {			if (p[1] == '\0'){	/* bare 'p' */				if(skipto(np-1, np))					return 1;				continue;			}			p++;		}		if ('0'<=*p && *p<='9') {			n = atoi(p);			if(skipto(n, np))				return 1;			continue;		}		if (*p == '-' || *p == '+') {			n = atoi(p);			if (n == 0)				n = *p == '-' ? -1 : 1;			if(skipto(np - 1 + n, np))				return 1;			continue;		}		if (*p == 'd') {			dbg = 1 - dbg;			continue;		}		fprint(2, "illegal;  try q, 17, +2, -1, p, m.7, /2, x1, y-.5 or return\n");	}	return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -