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

📄 view.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * the actual viewer that handles screen stuff */#include <u.h>#include <libc.h>#include <draw.h>#include <cursor.h>#include <event.h>#include <bio.h>#include <plumb.h>#include <ctype.h>#include <keyboard.h>#include "page.h"Document *doc;Image *im;int page;int angle = 0;int showbottom = 0;		/* on the next showpage, move the image so the bottom is visible. */Rectangle ulrange;	/* the upper left corner of the image must be in this rectangle */Point ul;			/* the upper left corner of the image is at this point on the screen */Point pclip(Point, Rectangle);Rectangle mkrange(Rectangle screenr, Rectangle imr);void redraw(Image*);Cursor reading={	{-1, -1},	{0xff, 0x80, 0xff, 0x80, 0xff, 0x00, 0xfe, 0x00, 	 0xff, 0x00, 0xff, 0x80, 0xff, 0xc0, 0xef, 0xe0, 	 0xc7, 0xf0, 0x03, 0xf0, 0x01, 0xe0, 0x00, 0xc0, 	 0x03, 0xff, 0x03, 0xff, 0x03, 0xff, 0x03, 0xff, },	{0x00, 0x00, 0x7f, 0x00, 0x7e, 0x00, 0x7c, 0x00, 	 0x7e, 0x00, 0x7f, 0x00, 0x6f, 0x80, 0x47, 0xc0, 	 0x03, 0xe0, 0x01, 0xf0, 0x00, 0xe0, 0x00, 0x40, 	 0x00, 0x00, 0x01, 0xb6, 0x01, 0xb6, 0x00, 0x00, }};Cursor query = {	{-7,-7},	{0x0f, 0xf0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, 	 0x7c, 0x7e, 0x78, 0x7e, 0x00, 0xfc, 0x01, 0xf8, 	 0x03, 0xf0, 0x07, 0xe0, 0x07, 0xc0, 0x07, 0xc0, 	 0x07, 0xc0, 0x07, 0xc0, 0x07, 0xc0, 0x07, 0xc0, },	{0x00, 0x00, 0x0f, 0xf0, 0x1f, 0xf8, 0x3c, 0x3c, 	 0x38, 0x1c, 0x00, 0x3c, 0x00, 0x78, 0x00, 0xf0, 	 0x01, 0xe0, 0x03, 0xc0, 0x03, 0x80, 0x03, 0x80, 	 0x00, 0x00, 0x03, 0x80, 0x03, 0x80, 0x00, 0x00, }};enum {	Left = 1,	Middle = 2,	Right = 4,	RMenu = 3,};voidunhide(void){	static int wctl = -1;	if(wctl < 0)		wctl = open("/dev/wctl", OWRITE);	if(wctl < 0)		return;	write(wctl, "unhide", 6);}int max(int a, int b){	return a > b ? a : b;}int min(int a, int b){	return a < b ? a : b;}char*menugen(int n){	static char menustr[32];	char *p;	int len;	if(n == doc->npage)		return "exit";	if(n > doc->npage)		return nil;	if(reverse)		n = doc->npage-1-n;	p = doc->pagename(doc, n);	len = (sizeof menustr)-2;	if(strlen(p) > len && strrchr(p, '/'))		p = strrchr(p, '/')+1;	if(strlen(p) > len)		p = p+strlen(p)-len;	strcpy(menustr+1, p);	if(page == n)		menustr[0] = '>';	else		menustr[0] = ' ';	return menustr;}voidshowpage(int page, Menu *m){	Image *tmp;	if(doc->fwdonly)		m->lasthit = 0;	/* this page */	else		m->lasthit = reverse ? doc->npage-1-page : page;		esetcursor(&reading);	freeimage(im);	if((page < 0 || page >= doc->npage) && !doc->fwdonly){		im = nil;		return;	}	im = doc->drawpage(doc, page);	if(im == nil) {		if(doc->fwdonly)	/* this is how we know we're out of pages */			wexits(0);		im = xallocimage(display, Rect(0,0,50,50), GREY1, 1, DBlack);		if(im == nil) {			fprint(2, "out of memory: %r\n");			wexits("memory");		}		string(im, ZP, display->white, ZP, display->defaultfont, "?");	}else if(resizing){		resize(Dx(im->r), Dy(im->r));	}	if(im->r.min.x > 0 || im->r.min.y > 0) {		tmp = xallocimage(display, Rect(0, 0, Dx(im->r), Dy(im->r)), im->chan, 0, DNofill);		if(tmp == nil) {			fprint(2, "out of memory during showpage: %r\n");			wexits("memory");		}		drawop(tmp, tmp->r, im, nil, im->r.min, S);		freeimage(im);		im = tmp;	}	switch(angle){	case 90:		im = rot90(im);		break;	case 180:		rot180(im);		break;	case 270:		im = rot270(im);		break;	}	esetcursor(nil);	if(showbottom){		ul.y = screen->r.max.y - Dy(im->r);		showbottom = 0;	}	redraw(screen);	flushimage(display, 1);}char*writebitmap(void){	char basename[64];	char name[64+30];	static char result[200];	char *p, *q;	int fd;	if(im == nil)		return "no image";	memset(basename, 0, sizeof basename);	if(doc->docname)		strncpy(basename, doc->docname, sizeof(basename)-1);	else if((p = menugen(page)) && p[0] != '\0')		strncpy(basename, p+1, sizeof(basename)-1);	if(basename[0]) {		if(q = strrchr(basename, '/'))			q++;		else			q = basename;		if(p = strchr(q, '.'))			*p = 0;				memset(name, 0, sizeof name);		snprint(name, sizeof(name)-1, "%s.%d.bit", q, page+1);		if(access(name, 0) >= 0) {			strcat(name, "XXXX");			mktemp(name);		}		if(access(name, 0) >= 0)			return "couldn't think of a name for bitmap";	} else {		strcpy(name, "bitXXXX");		mktemp(name);		if(access(name, 0) >= 0) 			return "couldn't think of a name for bitmap";	}	if((fd = create(name, OWRITE, 0666)) < 0) {		snprint(result, sizeof result, "cannot create %s: %r", name);		return result;	}	if(writeimage(fd, im, 0) < 0) {		snprint(result, sizeof result, "cannot writeimage: %r");		close(fd);		return result;	}	close(fd);	snprint(result, sizeof result, "wrote %s", name);	return result;}static void translate(Point);static intshowdata(Plumbmsg *msg){	char *s;	s = plumblookup(msg->attr, "action");	return s && strcmp(s, "showdata")==0;}/* correspond to entries in miditems[] below, * changing one means you need to change */enum{	Restore = 0,	Zin,	Fit,	Rot,	Upside,	Empty1,	Next,	Prev,	Zerox,	Empty2,	Reverse,	Del,	Write,	Empty3,	Exit,}; voidviewer(Document *dd){	int i, fd, n, oldpage;	int nxt;	Menu menu, midmenu;	Mouse m;	Event e;	Point dxy, oxy, xy0;	Rectangle r;	Image *tmp;	static char *fwditems[] = { "this page", "next page", "exit", 0 }; 	static char *miditems[] = { 		"orig size", 		"zoom in", 		"fit window", 		"rotate 90", 		"upside down", 		"", 		"next", 		"prev",		"zerox", 		"",  		"reverse", 		"discard", 		"write", 		"",  		"quit",  		0  	};	char *s;	enum { Eplumb = 4 };	Plumbmsg *pm;	doc = dd;    /* save global for menuhit */	ul = screen->r.min;	einit(Emouse|Ekeyboard);	if(doc->addpage != nil)		eplumb(Eplumb, "image");	esetcursor(&reading);	r.min = ZP;	/*	 * im is a global pointer to the current image.	 * eventually, i think we will have a layer between	 * the display routines and the ps/pdf/whatever routines	 * to perhaps cache and handle images of different	 * sizes, etc.	 */	im = 0;	page = reverse ? doc->npage-1 : 0;	if(doc->fwdonly) {		menu.item = fwditems;		menu.gen = 0;		menu.lasthit = 0;	} else {		menu.item = 0;		menu.gen = menugen;		menu.lasthit = 0;	}	midmenu.item = miditems;	midmenu.gen = 0;	midmenu.lasthit = Next;	showpage(page, &menu);	esetcursor(nil);	nxt = 0;	for(;;) {		/*		 * throughout, if doc->fwdonly is set, we restrict the functionality		 * a fair amount.  we don't care about doc->npage anymore, and		 * all that can be done is select the next page.		 */		switch(eread(Emouse|Ekeyboard|Eplumb, &e)){		case Ekeyboard:			if(e.kbdc <= 0xFF && isdigit(e.kbdc)) {				nxt = nxt*10+e.kbdc-'0';				break;			} else if(e.kbdc != '\n')				nxt = 0;			switch(e.kbdc) {			case 'r':	/* reverse page order */				if(doc->fwdonly)					break;				reverse = !reverse;				menu.lasthit = doc->npage-1-menu.lasthit;				/*				 * the theory is that if we are reversing the				 * document order and are on the first or last				 * page then we're just starting and really want		 	 	 * to view the other end.  maybe the if				 * should be dropped and this should happen always.				 */				if(page == 0 || page == doc->npage-1) {					page = doc->npage-1-page;					showpage(page, &menu);				}				break;			case 'w':	/* write bitmap of current screen */				esetcursor(&reading);				s = writebitmap();				if(s)					string(screen, addpt(screen->r.min, Pt(5,5)), display->black, ZP,						display->defaultfont, s);				esetcursor(nil);				flushimage(display, 1);				break;			case 'd':	/* remove image from working set */				if(doc->rmpage && page < doc->npage) {					if(doc->rmpage(doc, page) >= 0) {						if(doc->npage < 0)							wexits(0);						if(page >= doc->npage)							page = doc->npage-1;						showpage(page, &menu);					}				}				break;			case 'q':			case 0x04: /* ctrl-d */				wexits(0);			case 'u':				if(im==nil)					break;				esetcursor(&reading);				rot180(im);				esetcursor(nil);				angle = (angle+180) % 360;				redraw(screen);				flushimage(display, 1);				break;			case '-':			case '\b':			case Kleft:				if(page > 0 && !doc->fwdonly) {					--page;					showpage(page, &menu);				}				break;			case '\n':				if(nxt) {					nxt--;					if(nxt >= 0 && nxt < doc->npage && !doc->fwdonly)						showpage(page=nxt, &menu);					nxt = 0;					break;				}				goto Gotonext;			case Kright:			case ' ':			Gotonext:				if(doc->npage && ++page >= doc->npage && !doc->fwdonly)					wexits(0);				showpage(page, &menu);				break;			/*			 * The upper y coordinate of the image is at ul.y in screen->r.			 * Panning up means moving the upper left corner down.  If the			 * upper left corner is currently visible, we need to go back a page.			 */			case Kup:				if(screen->r.min.y <= ul.y && ul.y < screen->r.max.y){					if(page > 0 && !doc->fwdonly){						--page;						showbottom = 1;						showpage(page, &menu);					}				} else {					i = Dy(screen->r)/2;					if(i > 10)						i -= 10;					if(i+ul.y > screen->r.min.y)						i = screen->r.min.y - ul.y;					translate(Pt(0, i));				}				break;			/*			 * If the lower y coordinate is on the screen, we go to the next page.			 * The lower y coordinate is at ul.y + Dy(im->r).			 */			case Kdown:				i = ul.y + Dy(im->r);				if(screen->r.min.y <= i && i <= screen->r.max.y){					ul.y = screen->r.min.y;					goto Gotonext;				} else {					i = -Dy(screen->r)/2;					if(i < -10)						i += 10;					if(i+ul.y+Dy(im->r) <= screen->r.max.y)						i = screen->r.max.y - Dy(im->r) - ul.y - 1;					translate(Pt(0, i));				}				break;			default:				esetcursor(&query);				sleep(1000);				esetcursor(nil);				break;				}			break;		case Emouse:			m = e.mouse;			switch(m.buttons){			case Left:				oxy = m.xy;				xy0 = oxy;				do {					dxy = subpt(m.xy, oxy);					oxy = m.xy;						translate(dxy);					m = emouse();				} while(m.buttons == Left);				if(m.buttons) {					dxy = subpt(xy0, oxy);					translate(dxy);				}				break;				case Middle:				if(doc->npage == 0)					break;				n = emenuhit(Middle, &m, &midmenu);				if(n == -1)					break;				switch(n){				case Next: 	/* next */					if(reverse)						page--;					else						page++;					if(page < 0) {						if(reverse) return;						else page = 0;					}					if((page >= doc->npage) && !doc->fwdonly)						return;						showpage(page, &menu);					nxt = 0;					break;				case Prev:	/* prev */					if(reverse)						page++;					else						page--;					if(page < 0) {						if(reverse) return;						else page = 0;					}					if((page >= doc->npage) && !doc->fwdonly && !reverse)						return;						showpage(page, &menu);					nxt = 0;					break;				case Zerox:	/* prev */					zerox();					break;				case Zin:	/* zoom in */					{						double delta;						Rectangle r;						r = egetrect(Middle, &m);						if((rectclip(&r, rectaddpt(im->r, ul)) == 0) ||							Dx(r) == 0 || Dy(r) == 0)

⌨️ 快捷键说明

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