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

📄 ps.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
/* * ps.c *  * provide postscript file reading support for page */#include <u.h>#include <libc.h>#include <draw.h>#include <event.h>#include <bio.h>#include <ctype.h>#include "page.h"typedef struct PSInfo	PSInfo;typedef struct Page	Page;	struct Page {	char *name;	int offset;			/* offset of page beginning within file */};struct PSInfo {	GSInfo;	Rectangle bbox;	/* default bounding box */	Page *page;	int npage;	int clueless;	/* don't know where page boundaries are */	long psoff;	/* location of %! in file */	char ctm[256];};static int	pswritepage(Document *d, int fd, int page);static Image*	psdrawpage(Document *d, int page);static char*	pspagename(Document*, int);#define R(r) (r).min.x, (r).min.y, (r).max.x, (r).max.yRectanglerdbbox(char *p){	Rectangle r;	int a;	char *f[4];	while(*p == ':' || *p == ' ' || *p == '\t')		p++;	if(tokenize(p, f, 4) != 4)		return Rect(0,0,0,0);	r = Rect(atoi(f[0]), atoi(f[1]), atoi(f[2]), atoi(f[3]));	r = canonrect(r);	if(Dx(r) <= 0 || Dy(r) <= 0)		return Rect(0,0,0,0);	if(truetoboundingbox)		return r;	/* initdraw not called yet, can't use %R */	if(chatty) fprint(2, "[%d %d %d %d] -> ", R(r));	/*	 * attempt to sniff out A4, 8½×11, others	 * A4 is 596×842	 * 8½×11 is 612×792	 */	a = Dx(r)*Dy(r);	if(a < 300*300){	/* really small, probably supposed to be */		/* empty */	} else if(Dx(r) <= 596 && r.max.x <= 596 && Dy(r) > 792 && Dy(r) <= 842 && r.max.y <= 842)	/* A4 */		r = Rect(0, 0, 596, 842);	else {	/* cast up to 8½×11 */		if(Dx(r) <= 612 && r.max.x <= 612){			r.min.x = 0;			r.max.x = 612;		}		if(Dy(r) <= 792 && r.max.y <= 792){			r.min.y = 0;			r.max.y = 792;		}	}	if(chatty) fprint(2, "[%d %d %d %d]\n", R(r));	return r;}#define RECT(X) X.min.x, X.min.y, X.max.x, X.max.yintprefix(char *x, char *y){	return strncmp(x, y, strlen(y)) == 0;}/* * document ps is really being printed as n-up pages. * we need to treat every n pages as 1. */voidrepaginate(PSInfo *ps, int n){	int i, np, onp;	Page *page;	page = ps->page;	onp = ps->npage;	np = (ps->npage+n-1)/n;	if(chatty) {		for(i=0; i<=onp+1; i++)			print("page %d: %d\n", i, page[i].offset);	}	for(i=0; i<np; i++)		page[i] = page[n*i];	/* trailer */	page[np] = page[onp];	/* EOF */	page[np+1] = page[onp+1];	ps->npage = np;	if(chatty) {		for(i=0; i<=np+1; i++)			print("page %d: %d\n", i, page[i].offset);	}}Document*initps(Biobuf *b, int argc, char **argv, uchar *buf, int nbuf){	Document *d;	PSInfo *ps;	char *p;	char *q, *r;	char eol;	char *nargv[1];	char fdbuf[20];	char tmp[32];	int fd;	int i;	int incomments;	int cantranslate;	int trailer=0;	int nesting=0;	int dumb=0;	int landscape=0;	long psoff;	long npage, mpage;	Page *page;	Rectangle bbox = Rect(0,0,0,0);	if(argc > 1) {		fprint(2, "can only view one ps file at a time\n");		return nil;	}	fprint(2, "reading through postscript...\n");	if(b == nil){	/* standard input; spool to disk (ouch) */		fd = spooltodisk(buf, nbuf, nil);		sprint(fdbuf, "/fd/%d", fd);		b = Bopen(fdbuf, OREAD);		if(b == nil){			fprint(2, "cannot open disk spool file\n");			wexits("Bopen temp");		}		nargv[0] = fdbuf;		argv = nargv;	}	/* find %!, perhaps after PCL nonsense */	Bseek(b, 0, 0);	psoff = 0;	eol = 0;	for(i=0; i<16; i++){		psoff = Boffset(b);		if(!(p = Brdline(b, eol='\n')) && !(p = Brdline(b, eol='\r'))) {			fprint(2, "cannot find end of first line\n");			wexits("initps");		}		if(p[0]=='\x1B')			p++, psoff++;		if(p[0] == '%' && p[1] == '!')			break;	}	if(i == 16){		werrstr("not ps");		return nil;	}	/* page counting */	npage = 0;	mpage = 16;	page = emalloc(mpage*sizeof(*page));	memset(page, 0, mpage*sizeof(*page));	cantranslate = goodps;	incomments = 1;Keepreading:	while(p = Brdline(b, eol)) {		if(p[0] == '%')			if(chatty) fprint(2, "ps %.*s\n", utfnlen(p, Blinelen(b)-1), p);		if(npage == mpage) {			mpage *= 2;			page = erealloc(page, mpage*sizeof(*page));			memset(&page[npage], 0, npage*sizeof(*page));		}		if(p[0] != '%' || p[1] != '%')			continue;		if(prefix(p, "%%BeginDocument")) {			nesting++;			continue;		}		if(nesting > 0 && prefix(p, "%%EndDocument")) {			nesting--;			continue;		}		if(nesting)			continue;		if(prefix(p, "%%EndComment")) {			incomments = 0;			continue;		}		if(reverse == -1 && prefix(p, "%%PageOrder")) {			/* glean whether we should reverse the viewing order */			p[Blinelen(b)-1] = 0;			if(strstr(p, "Ascend"))				reverse = 0;			else if(strstr(p, "Descend"))				reverse = 1;			else if(strstr(p, "Special"))				dumb = 1;			p[Blinelen(b)-1] = '\n';			continue;		} else if(prefix(p, "%%Trailer")) {			incomments = 1;			page[npage].offset = Boffset(b)-Blinelen(b);			trailer = 1;			continue;		} else if(incomments && prefix(p, "%%Orientation")) {			if(strstr(p, "Landscape"))				landscape = 1;		} else if(incomments && Dx(bbox)==0 && prefix(p, q="%%BoundingBox")) {			bbox = rdbbox(p+strlen(q)+1);			if(chatty)				/* can't use %R because haven't initdraw() */				fprint(2, "document bbox [%d %d %d %d]\n",					RECT(bbox));			continue;		}		/*		 * If they use the initgraphics command, we can't play our translation tricks.		 */		p[Blinelen(b)-1] = 0;		if((q=strstr(p, "initgraphics")) && ((r=strchr(p, '%'))==nil || r > q))			cantranslate = 0;		p[Blinelen(b)-1] = eol;		if(!prefix(p, "%%Page:"))			continue;		/* 		 * figure out of the %%Page: line contains a page number		 * or some other page description to use in the menu bar.		 * 		 * lines look like %%Page: x y or %%Page: x		 * we prefer just x, and will generate our		 * own if necessary.		 */		p[Blinelen(b)-1] = 0;		if(chatty) fprint(2, "page %s\n", p);		r = p+7;		while(*r == ' ' || *r == '\t')			r++;		q = r;		while(*q && *q != ' ' && *q != '\t')			q++;		free(page[npage].name);		if(*r) {			if(*r == '"' && *q == '"')				r++, q--;			if(*q)				*q = 0;			page[npage].name = estrdup(r);			*q = 'x';		} else {			snprint(tmp, sizeof tmp, "p %ld", npage+1);			page[npage].name = estrdup(tmp);		}		/*		 * store the offset info for later viewing		 */		trailer = 0;		p[Blinelen(b)-1] = eol;		page[npage++].offset = Boffset(b)-Blinelen(b);	}	if(Blinelen(b) > 0){		fprint(2, "page: linelen %d\n", Blinelen(b));		Bseek(b, Blinelen(b), 1);		goto Keepreading;	}	if(Dx(bbox) == 0 || Dy(bbox) == 0)		bbox = Rect(0,0,612,792);	/* 8½×11 */	/*	 * if we didn't find any pages, assume the document	 * is one big page	 */	if(npage == 0) {		dumb = 1;		if(chatty) fprint(2, "don't know where pages are\n");		reverse = 0;		goodps = 0;		trailer = 0;		page[npage].name = "p 1";		page[npage++].offset = 0;	}	if(npage+2 > mpage) {		mpage += 2;		page = erealloc(page, mpage*sizeof(*page));		memset(&page[mpage-2], 0, 2*sizeof(*page));	}	if(!trailer)		page[npage].offset = Boffset(b);	Bseek(b, 0, 2); /* EOF */	page[npage+1].offset = Boffset(b);	d = emalloc(sizeof(*d));	ps = emalloc(sizeof(*ps));	ps->page = page;	ps->npage = npage;	ps->bbox = bbox;	ps->psoff = psoff;	d->extra = ps;	d->npage = ps->npage;	d->b = b;	d->drawpage = psdrawpage;	d->pagename = pspagename;	d->fwdonly = ps->clueless = dumb;	d->docname = argv[0];	if(spawngs(ps, "-dSAFER") < 0)		return nil;	if(!cantranslate)		bbox.min = ZP;	setdim(ps, bbox, ppi, landscape);	if(goodps){		/*		 * We want to only send the page (i.e. not header and trailer) information	 	 * for each page, so initialize the device by sending the header now.		 */		pswritepage(d, ps->gsfd, -1);		waitgs(ps);	}	if(dumb) {		fprint(ps->gsfd, "(%s) run\n", argv[0]);		fprint(ps->gsfd, "(/fd/3) (w) file dup (THIS IS NOT A PLAN9 BITMAP 01234567890123456789012345678901234567890123456789\\n) writestring flushfile\n");	}	ps->bbox = bbox;	return d;}static intpswritepage(Document *d, int fd, int page){	Biobuf *b = d->b;	PSInfo *ps = d->extra;	int t, n, i;	long begin, end;	char buf[8192];	if(page == -1)		begin = ps->psoff;	else		begin = ps->page[page].offset;	end = ps->page[page+1].offset;	if(chatty) {		fprint(2, "writepage(%d)... from #%ld to #%ld...\n",			page, begin, end);	}	Bseek(b, begin, 0);	t = end-begin;	n = sizeof(buf);	if(n > t) n = t;	while(t > 0 && (i=Bread(b, buf, n)) > 0) {		if(write(fd, buf, i) != i)			return -1;		t -= i;		if(n > t)			n = t;	}	return end-begin;}static Image*psdrawpage(Document *d, int page){	PSInfo *ps = d->extra;	Image *im;	if(ps->clueless)		return readimage(display, ps->gsdfd, 0);	waitgs(ps);	if(goodps)		pswritepage(d, ps->gsfd, page);	else {		pswritepage(d, ps->gsfd, -1);		pswritepage(d, ps->gsfd, page);		pswritepage(d, ps->gsfd, d->npage);	}	/*	 * If last line terminator is \r, gs will read ahead to check for \n	 * so send one to avoid deadlock.	 */	write(ps->gsfd, "\n", 1);	im = readimage(display, ps->gsdfd, 0);	if(im == nil) {		fprint(2, "fatal: readimage error %r\n");		wexits("readimage");	}	waitgs(ps);	return im;}static char*pspagename(Document *d, int page){	PSInfo *ps = (PSInfo *) d->extra;	return ps->page[page].name;}

⌨️ 快捷键说明

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