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

📄 init.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include <u.h>#include <libc.h>#include <draw.h>Display	*display;Font	*font;Image	*screen;int	_drawdebug = 0;static char deffontname[] = "*default*";Screen	*_screen;int		debuglockdisplay = 0;static voiddrawshutdown(void){	Display *d;	d = display;	if(d){		display = nil;		closedisplay(d);	}}intgeninitdraw(char *devdir, void(*error)(Display*, char*), char *fontname, char *label, char *windir, int ref){	int fd, n;	Subfont *df;	char buf[128];	display = initdisplay(devdir, windir, error);	if(display == nil)		return -1;	/*	 * Set up default font	 */	df = getdefont(display);	display->defaultsubfont = df;	if(df == nil){		fprint(2, "imageinit: can't open default subfont: %r\n");    Error:		closedisplay(display);		display = nil;		return -1;	}	if(fontname == nil){		fd = open("/env/font", OREAD);		if(fd >= 0){			n = read(fd, buf, sizeof(buf));			if(n>0 && n<sizeof buf-1){				buf[n] = 0;				fontname = buf;			}			close(fd);		}	}	/*	 * Build fonts with caches==depth of screen, for speed.	 * If conversion were faster, we'd use 0 and save memory.	 */	if(fontname == nil){		snprint(buf, sizeof buf, "%d %d\n0 %d\t%s\n", df->height, df->ascent,			df->n-1, deffontname);//BUG: Need something better for this	installsubfont("*default*", df);		font = buildfont(display, buf, deffontname);		if(font == nil){			fprint(2, "imageinit: can't open default font: %r\n");			goto Error;		}	}else{		font = openfont(display, fontname);	/* BUG: grey fonts */		if(font == nil){			fprint(2, "imageinit: can't open font %s: %r\n", fontname);			goto Error;		}	}	display->defaultfont = font;	/*	 * Write label; ignore errors (we might not be running under rio)	 */	if(label){		snprint(buf, sizeof buf, "%s/label", display->windir);		fd = open(buf, OREAD);		if(fd >= 0){			read(fd, display->oldlabel, (sizeof display->oldlabel)-1);			close(fd);			fd = create(buf, OWRITE, 0666);			if(fd >= 0){				write(fd, label, strlen(label));				close(fd);			}		}	}	snprint(buf, sizeof buf, "%s/winname", display->windir);	if(gengetwindow(display, buf, &screen, &_screen, ref) < 0)		goto Error;	atexit(drawshutdown);	return 1;}intinitdraw(void(*error)(Display*, char*), char *fontname , char *label){	char *dev = "/dev";	if(access("/dev/draw/new", AEXIST)<0 && bind("#i", "/dev", MAFTER)<0){		fprint(2, "imageinit: can't bind /dev/draw: %r");		return -1;	}	return geninitdraw(dev, error, fontname, label, dev, Refnone);}/* * Attach, or possibly reattach, to window. * If reattaching, maintain value of screen pointer. */intgengetwindow(Display *d, char *winname, Image **winp, Screen **scrp, int ref){	int n, fd;	char buf[64+1];	Image *image;	Rectangle r;	fd = open(winname, OREAD);	if(fd<0 || (n=read(fd, buf, sizeof buf-1))<=0){		if((image=d->image) == nil){			fprint(2, "gengetwindow: %r\n");			*winp = nil;			d->screenimage = nil;			return -1;		}		strcpy(buf, "noborder");	}else{		close(fd);		buf[n] = '\0';		if(*winp != nil){			_freeimage1(*winp);			freeimage((*scrp)->image);			freescreen(*scrp);			*scrp = nil;		}		image = namedimage(d, buf);		if(image == 0){			fprint(2, "namedimage %s failed: %r\n", buf);			*winp = nil;			d->screenimage = nil;			return -1;		}		assert(image->chan != 0);	}	d->screenimage = image;	*scrp = allocscreen(image, d->white, 0);	if(*scrp == nil){		freeimage(d->screenimage);		*winp = nil;		d->screenimage = nil;		return -1;	}	r = image->r;	if(strncmp(buf, "noborder", 8) != 0)		r = insetrect(image->r, Borderwidth);	*winp = _allocwindow(*winp, *scrp, r, ref, DWhite);	if(*winp == nil){		freescreen(*scrp);		*scrp = nil;		freeimage(image);		d->screenimage = nil;		return -1;	}	d->screenimage = *winp;	assert((*winp)->chan != 0);	return 1;}intgetwindow(Display *d, int ref){	char winname[128];	snprint(winname, sizeof winname, "%s/winname", d->windir);	return gengetwindow(d, winname, &screen, &_screen, ref);}#define	NINFO	12*12Display*initdisplay(char *dev, char *win, void(*error)(Display*, char*)){	char buf[128], info[NINFO+1], *t, isnew;	int n, datafd, ctlfd, reffd;	Display *disp;	Dir *dir;	Image *image;	fmtinstall('P', Pfmt);	fmtinstall('R', Rfmt);	if(dev == 0)		dev = "/dev";	if(win == 0)		win = "/dev";	if(strlen(dev)>sizeof buf-25 || strlen(win)>sizeof buf-25){		werrstr("initdisplay: directory name too long");		return nil;	}	t = strdup(win);	if(t == nil)		return nil;	sprint(buf, "%s/draw/new", dev);	ctlfd = open(buf, ORDWR|OCEXEC);	if(ctlfd < 0){		if(bind("#i", dev, MAFTER) < 0){    Error1:			free(t);			werrstr("initdisplay: %s: %r", buf);			return 0;		}		ctlfd = open(buf, ORDWR|OCEXEC);	}	if(ctlfd < 0)		goto Error1;	if((n=read(ctlfd, info, sizeof info)) < 12){    Error2:		close(ctlfd);		goto Error1;	}	if(n==NINFO+1)		n = NINFO;	buf[n] = '\0';	isnew = 0;	if(n < NINFO)	/* this will do for now, we need something better here */		isnew = 1;	sprint(buf, "%s/draw/%d/data", dev, atoi(info+0*12));	datafd = open(buf, ORDWR|OCEXEC);	if(datafd < 0)		goto Error2;	sprint(buf, "%s/draw/%d/refresh", dev, atoi(info+0*12));	reffd = open(buf, OREAD|OCEXEC);	if(reffd < 0){    Error3:		close(datafd);		goto Error2;	}	disp = mallocz(sizeof(Display), 1);	if(disp == 0){    Error4:		close(reffd);		goto Error3;	}	image = nil;	if(0){    Error5:		free(image);		free(disp);		goto Error4;	}	if(n >= NINFO){		image = mallocz(sizeof(Image), 1);		if(image == nil)			goto Error5;		image->display = disp;		image->id = 0;		image->chan = strtochan(info+2*12);		image->depth = chantodepth(image->chan);		image->repl = atoi(info+3*12);		image->r.min.x = atoi(info+4*12);		image->r.min.y = atoi(info+5*12);		image->r.max.x = atoi(info+6*12);		image->r.max.y = atoi(info+7*12);		image->clipr.min.x = atoi(info+8*12);		image->clipr.min.y = atoi(info+9*12);		image->clipr.max.x = atoi(info+10*12);		image->clipr.max.y = atoi(info+11*12);	}	disp->_isnewdisplay = isnew;	disp->bufsize = iounit(datafd);	if(disp->bufsize <= 0)		disp->bufsize = 8000;	if(disp->bufsize < 512){		werrstr("iounit %d too small", disp->bufsize);		goto Error5;	}	disp->buf = malloc(disp->bufsize+5);	/* +5 for flush message */	if(disp->buf == nil)		goto Error5;	disp->image = image;	disp->dirno = atoi(info+0*12);	disp->fd = datafd;	disp->ctlfd = ctlfd;	disp->reffd = reffd;	disp->bufp = disp->buf;	disp->error = error;	disp->windir = t;	disp->devdir = strdup(dev);	qlock(&disp->qlock);	disp->white = allocimage(disp, Rect(0, 0, 1, 1), GREY1, 1, DWhite);	disp->black = allocimage(disp, Rect(0, 0, 1, 1), GREY1, 1, DBlack);	if(disp->white == nil || disp->black == nil){		free(disp->devdir);		free(disp->white);		free(disp->black);		goto Error5;	}	disp->opaque = disp->white;	disp->transparent = disp->black;	dir = dirfstat(ctlfd);	if(dir!=nil && dir->type=='i'){		disp->local = 1;		disp->dataqid = dir->qid.path;	}	if(dir!=nil && dir->qid.vers==1)	/* other way to tell */		disp->_isnewdisplay = 1;	free(dir);	return disp;}/* * Call with d unlocked. * Note that disp->defaultfont and defaultsubfont are not freed here. */voidclosedisplay(Display *disp){	int fd;	char buf[128];	if(disp == nil)		return;	if(disp == display)		display = nil;	if(disp->oldlabel[0]){		snprint(buf, sizeof buf, "%s/label", disp->windir);		fd = open(buf, OWRITE);		if(fd >= 0){			write(fd, disp->oldlabel, strlen(disp->oldlabel));			close(fd);		}	}	free(disp->devdir);	free(disp->windir);	freeimage(disp->white);	freeimage(disp->black);	close(disp->fd);	close(disp->ctlfd);	/* should cause refresh slave to shut down */	close(disp->reffd);	qunlock(&disp->qlock);	free(disp);}voidlockdisplay(Display *disp){	if(debuglockdisplay){		/* avoid busy looping; it's rare we collide anyway */		while(!canqlock(&disp->qlock)){			fprint(1, "proc %d waiting for display lock...\n", getpid());			sleep(1000);		}	}else		qlock(&disp->qlock);}voidunlockdisplay(Display *disp){	qunlock(&disp->qlock);}voiddrawerror(Display *d, char *s){	char err[ERRMAX];	if(d && d->error)		d->error(d, s);	else{		errstr(err, sizeof err);		fprint(2, "draw: %s: %s\n", s, err);		exits(s);	}}staticintdoflush(Display *d){	int n, nn;	n = d->bufp-d->buf;	if(n <= 0)		return 1;	if((nn=write(d->fd, d->buf, n)) != n){		if(_drawdebug)			fprint(2, "flushimage fail: d=%p: n=%d nn=%d %r\n", d, n, nn); /**/		d->bufp = d->buf;	/* might as well; chance of continuing */		return -1;	}	d->bufp = d->buf;	return 1;}intflushimage(Display *d, int visible){	if(d == nil)		return 0;	if(visible){		*d->bufp++ = 'v';	/* five bytes always reserved for this */		if(d->_isnewdisplay){			BPLONG(d->bufp, d->screenimage->id);			d->bufp += 4;		}	}	return doflush(d);}uchar*bufimage(Display *d, int n){	uchar *p;	if(n<0 || n>d->bufsize){		werrstr("bad count in bufimage");		return 0;	}	if(d->bufp+n > d->buf+d->bufsize)		if(doflush(d) < 0)			return 0;	p = d->bufp;	d->bufp += n;	return p;}

⌨️ 快捷键说明

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