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

📄 view.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
							break;						/* use the smaller side to expand */						if(Dx(r) < Dy(r))							delta = (double)Dx(im->r)/(double)Dx(r);						else							delta = (double)Dy(im->r)/(double)Dy(r);						esetcursor(&reading);						tmp = xallocimage(display, 								Rect(0, 0, (int)((double)Dx(im->r)*delta), (int)((double)Dy(im->r)*delta)), 								im->chan, 0, DBlack);						if(tmp == nil) {							fprint(2, "out of memory during zoom: %r\n");							wexits("memory");						}						resample(im, tmp);						freeimage(im);						im = tmp;						esetcursor(nil);						ul = screen->r.min;						redraw(screen);						flushimage(display, 1);						break;					}				case Fit:	/* fit */					{						double delta;						Rectangle r;												delta = (double)Dx(screen->r)/(double)Dx(im->r);						if((double)Dy(im->r)*delta > Dy(screen->r))							delta = (double)Dy(screen->r)/(double)Dy(im->r);						r = Rect(0, 0, (int)((double)Dx(im->r)*delta), (int)((double)Dy(im->r)*delta));						esetcursor(&reading);						tmp = xallocimage(display, r, im->chan, 0, DBlack);						if(tmp == nil) {							fprint(2, "out of memory during fit: %r\n");							wexits("memory");						}						resample(im, tmp);						freeimage(im);						im = tmp;						esetcursor(nil);						ul = screen->r.min;						redraw(screen);						flushimage(display, 1);						break;					}				case Rot:	/* rotate 90 */					esetcursor(&reading);					im = rot90(im);					esetcursor(nil);					angle = (angle+90) % 360;					redraw(screen);					flushimage(display, 1);					break;				case Upside: 	/* upside-down */					if(im==nil)						break;					esetcursor(&reading);					rot180(im);					esetcursor(nil);					angle = (angle+180) % 360;					redraw(screen);					flushimage(display, 1);					break;				case Restore:	/* restore */					showpage(page, &menu);					break;				case Reverse:	/* reverse */					if(doc->fwdonly)						break;					reverse = !reverse;					menu.lasthit = doc->npage-1-menu.lasthit;						if(page == 0 || page == doc->npage-1) {						page = doc->npage-1-page;						showpage(page, &menu);					}					break;				case Write: /* write */					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 Del: /* delete */					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 Exit:	/* exit */					return;				case Empty1:				case Empty2:				case Empty3:					break;				}; 					case Right:				if(doc->npage == 0)					break;				oldpage = page;				n = emenuhit(RMenu, &m, &menu);				if(n == -1)					break;					if(doc->fwdonly) {					switch(n){					case 0:	/* this page */						break;					case 1:	/* next page */						showpage(++page, &menu);						break;					case 2:	/* exit */						return;					}					break;				}					if(n == doc->npage)					return;				else					page = reverse ? doc->npage-1-n : n;					if(oldpage != page)					showpage(page, &menu);				nxt = 0;				break;			}			break;		case Eplumb:			pm = e.v;			if(pm->ndata <= 0){				plumbfree(pm);				break;			}			if(showdata(pm)) {				s = estrdup("/tmp/pageplumbXXXXXXX");				fd = opentemp(s);				write(fd, pm->data, pm->ndata);				/* lose fd reference on purpose; the file is open ORCLOSE */			} else if(pm->data[0] == '/') {				s = estrdup(pm->data);			} else {				s = emalloc(strlen(pm->wdir)+1+pm->ndata+1);				sprint(s, "%s/%s", pm->wdir, pm->data);				cleanname(s);			}			if((i = doc->addpage(doc, s)) >= 0) {				page = i;				unhide();				showpage(page, &menu);			}			free(s);			plumbfree(pm);			break;		}	}}Image *gray;/* * A draw operation that touches only the area contained in bot but not in top. * mp and sp get aligned with bot.min. */static voidgendrawdiff(Image *dst, Rectangle bot, Rectangle top, 	Image *src, Point sp, Image *mask, Point mp, int op){	Rectangle r;	Point origin;	Point delta;	USED(op);	if(Dx(bot)*Dy(bot) == 0)		return;	/* no points in bot - top */	if(rectinrect(bot, top))		return;	/* bot - top ≡ bot */	if(Dx(top)*Dy(top)==0 || rectXrect(bot, top)==0){		gendrawop(dst, bot, src, sp, mask, mp, op);		return;	}	origin = bot.min;	/* split bot into rectangles that don't intersect top */	/* left side */	if(bot.min.x < top.min.x){		r = Rect(bot.min.x, bot.min.y, top.min.x, bot.max.y);		delta = subpt(r.min, origin);		gendrawop(dst, r, src, addpt(sp, delta), mask, addpt(mp, delta), op);		bot.min.x = top.min.x;	}	/* right side */	if(bot.max.x > top.max.x){		r = Rect(top.max.x, bot.min.y, bot.max.x, bot.max.y);		delta = subpt(r.min, origin);		gendrawop(dst, r, src, addpt(sp, delta), mask, addpt(mp, delta), op);		bot.max.x = top.max.x;	}	/* top */	if(bot.min.y < top.min.y){		r = Rect(bot.min.x, bot.min.y, bot.max.x, top.min.y);		delta = subpt(r.min, origin);		gendrawop(dst, r, src, addpt(sp, delta), mask, addpt(mp, delta), op);		bot.min.y = top.min.y;	}	/* bottom */	if(bot.max.y > top.max.y){		r = Rect(bot.min.x, top.max.y, bot.max.x, bot.max.y);		delta = subpt(r.min, origin);		gendrawop(dst, r, src, addpt(sp, delta), mask, addpt(mp, delta), op);		bot.max.y = top.max.y;	}}static voiddrawdiff(Image *dst, Rectangle bot, Rectangle top, Image *src, Image *mask, Point p, int op){	gendrawdiff(dst, bot, top, src, p, mask, p, op);}/* * Translate the image in the window by delta. */static voidtranslate(Point delta){	Point u;	Rectangle r, or;	if(im == nil)		return;	u = pclip(addpt(ul, delta), ulrange);	delta = subpt(u, ul);	if(delta.x == 0 && delta.y == 0)		return;	/*	 * The upper left corner of the image is currently at ul.	 * We want to move it to u.	 */	or = rectaddpt(Rpt(ZP, Pt(Dx(im->r), Dy(im->r))), ul);	r = rectaddpt(or, delta);	drawop(screen, r, screen, nil, ul, S);	ul = u;	/* fill in gray where image used to be but isn't. */	drawdiff(screen, insetrect(or, -2), insetrect(r, -2), gray, nil, ZP, S);	/* fill in black border */	drawdiff(screen, insetrect(r, -2), r, display->black, nil, ZP, S);	/* fill in image where it used to be off the screen. */	if(rectclip(&or, screen->r))		drawdiff(screen, r, rectaddpt(or, delta), im, nil, im->r.min, S);	else		drawop(screen, r, im, nil, im->r.min, S);	flushimage(display, 1);}voidredraw(Image *screen){	Rectangle r;	if(im == nil)		return;	ulrange.max = screen->r.max;	ulrange.min = subpt(screen->r.min, Pt(Dx(im->r), Dy(im->r)));	ul = pclip(ul, ulrange);	drawop(screen, screen->r, im, nil, subpt(im->r.min, subpt(ul, screen->r.min)), S);	if(im->repl)		return;	/* fill in any outer edges */	/* black border */	r = rectaddpt(im->r, subpt(ul, im->r.min));	border(screen, r, -2, display->black, ZP);	r.min = subpt(r.min, Pt(2,2));	r.max = addpt(r.max, Pt(2,2));	/* gray for the rest */	if(gray == nil) {		gray = xallocimage(display, Rect(0,0,1,1), RGB24, 1, 0x888888FF);		if(gray == nil) {			fprint(2, "g out of memory: %r\n");			wexits("mem");		}	}	border(screen, r, -4000, gray, ZP);//	flushimage(display, 0);	}voideresized(int new){	Rectangle r;	r = screen->r;	if(new && getwindow(display, Refnone) < 0)		fprint(2,"can't reattach to window");	ul = addpt(ul, subpt(screen->r.min, r.min));	redraw(screen);}/* clip p to be in r */Pointpclip(Point p, Rectangle r){	if(p.x < r.min.x)		p.x = r.min.x;	else if(p.x >= r.max.x)		p.x = r.max.x-1;	if(p.y < r.min.y)		p.y = r.min.y;	else if(p.y >= r.max.y)		p.y = r.max.y-1;	return p;}/* * resize is perhaps a misnomer.  * this really just grows the window to be at least dx across * and dy high.  if the window hits the bottom or right edge, * it is backed up until it hits the top or left edge. */voidresize(int dx, int dy){	static Rectangle sr;	Rectangle r, or;	dx += 2*Borderwidth;	dy += 2*Borderwidth;	if(wctlfd < 0){		wctlfd = open("/dev/wctl", OWRITE);		if(wctlfd < 0)			return;	}	r = insetrect(screen->r, -Borderwidth);	if(Dx(r) >= dx && Dy(r) >= dy)		return;	if(Dx(sr)*Dy(sr) == 0)		sr = screenrect();	or = r;	r.max.x = max(r.min.x+dx, r.max.x);	r.max.y = max(r.min.y+dy, r.max.y);	if(r.max.x > sr.max.x){		if(Dx(r) > Dx(sr)){			r.min.x = 0;			r.max.x = sr.max.x;		}else			r = rectaddpt(r, Pt(sr.max.x-r.max.x, 0));	}	if(r.max.y > sr.max.y){		if(Dy(r) > Dy(sr)){			r.min.y = 0;			r.max.y = sr.max.y;		}else			r = rectaddpt(r, Pt(0, sr.max.y-r.max.y));	}	/*	 * Sometimes we can't actually grow the window big enough,	 * and resizing it to the same shape makes it flash.	 */	if(Dx(r) == Dx(or) && Dy(r) == Dy(or))		return;	fprint(wctlfd, "resize -minx %d -miny %d -maxx %d -maxy %d\n",		r.min.x, r.min.y, r.max.x, r.max.y);}/* * If we allocimage after a resize but before flushing the draw buffer, * we won't have seen the reshape event, and we won't have called * getwindow, and allocimage will fail.  So we flushimage before every alloc. */Image*xallocimage(Display *d, Rectangle r, ulong chan, int repl, ulong val){	flushimage(display, 0);	return allocimage(d, r, chan, repl, val);}/* all code below this line should be in the library, but is stolen from colors instead */static char*rdenv(char *name){	char *v;	int fd, size;	fd = open(name, OREAD);	if(fd < 0)		return 0;	size = seek(fd, 0, 2);	v = malloc(size+1);	if(v == 0){		fprint(2, "page: can't malloc: %r\n");		wexits("no mem");	}	seek(fd, 0, 0);	read(fd, v, size);	v[size] = 0;	close(fd);	return v;}voidnewwin(void){	char *srv, *mntsrv;	char spec[100];	int srvfd, cons, pid;	switch(rfork(RFFDG|RFPROC|RFNAMEG|RFENVG|RFNOTEG|RFNOWAIT)){	case -1:		fprint(2, "page: can't fork: %r\n");		wexits("no fork");	case 0:		break;	default:		wexits(0);	}	srv = rdenv("/env/wsys");	if(srv == 0){		mntsrv = rdenv("/mnt/term/env/wsys");		if(mntsrv == 0){			fprint(2, "page: can't find $wsys\n");			wexits("srv");		}		srv = malloc(strlen(mntsrv)+10);		sprint(srv, "/mnt/term%s", mntsrv);		free(mntsrv);		pid  = 0;			/* can't send notes to remote processes! */	}else		pid = getpid();	srvfd = open(srv, ORDWR);	free(srv);	if(srvfd == -1){		fprint(2, "page: can't open %s: %r\n", srv);		wexits("no srv");	}	sprint(spec, "new -pid %d", pid);	if(mount(srvfd, -1, "/mnt/wsys", 0, spec) == -1){		fprint(2, "page: can't mount /mnt/wsys: %r (spec=%s)\n", spec);		wexits("no mount");	}	close(srvfd);	unmount("/mnt/acme", "/dev");	bind("/mnt/wsys", "/dev", MBEFORE);	cons = open("/dev/cons", OREAD);	if(cons==-1){	NoCons:		fprint(2, "page: can't open /dev/cons: %r");		wexits("no cons");	}	dup(cons, 0);	close(cons);	cons = open("/dev/cons", OWRITE);	if(cons==-1)		goto NoCons;	dup(cons, 1);	dup(cons, 2);	close(cons);//	wctlfd = open("/dev/wctl", OWRITE);}Rectanglescreenrect(void){	int fd;	char buf[12*5];	fd = open("/dev/screen", OREAD);	if(fd == -1)		fd=open("/mnt/term/dev/screen", OREAD);	if(fd == -1){		fprint(2, "page: can't open /dev/screen: %r\n");		wexits("window read");	}	if(read(fd, buf, sizeof buf) != sizeof buf){		fprint(2, "page: can't read /dev/screen: %r\n");		wexits("screen read");	}	close(fd);	return Rect(atoi(buf+12), atoi(buf+24), atoi(buf+36), atoi(buf+48));}voidzerox(void){	int pfd[2];	pipe(pfd);	switch(rfork(RFFDG|RFREND|RFPROC)) {		case -1:			wexits("cannot fork in zerox: %r");		case 0: 			dup(pfd[1], 0);			close(pfd[0]);			execl("/bin/page", "page", "-w", nil);			wexits("cannot exec in zerox: %r\n");		default:			close(pfd[1]);			writeimage(pfd[0], im, 0);			close(pfd[0]);			break;	}}

⌨️ 快捷键说明

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