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

📄 acme.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <u.h>#include <libc.h>#include <draw.h>#include <thread.h>#include <cursor.h>#include <mouse.h>#include <keyboard.h>#include <frame.h>#include <fcall.h>#include <plumb.h>#include "dat.h"#include "fns.h"	/* for generating syms in mkfile only: */	#include <bio.h>	#include "edit.h"void	mousethread(void*);void	keyboardthread(void*);void	waitthread(void*);void	xfidallocthread(void*);void	newwindowthread(void*);void plumbproc(void*);Reffont	**fontcache;int		nfontcache;char		wdir[512] = ".";Reffont	*reffonts[2];int		snarffd = -1;int		mainpid;int		plumbsendfd;int		plumbeditfd;enum{	NSnarf = 1000	/* less than 1024, I/O buffer size */};Rune	snarfrune[NSnarf+1];char		*fontnames[2] ={	"/lib/font/bit/lucidasans/euro.8.font",	"/lib/font/bit/lucm/unicode.9.font"};Command *command;void	acmeerrorinit(void);void	readfile(Column*, char*);int	shutdown(void*, char*);voidderror(Display*, char *errorstr){	error(errorstr);}voidthreadmain(int argc, char *argv[]){	int i;	char *p, *loadfile;	char buf[256];	Column *c;	int ncol;	Display *d;	static void *arg[1];	rfork(RFENVG|RFNAMEG);	ncol = -1;	loadfile = nil;	ARGBEGIN{	case 'a':		globalautoindent = TRUE;		break;	case 'b':		bartflag = TRUE;		break;	case 'c':		p = ARGF();		if(p == nil)			goto Usage;		ncol = atoi(p);		if(ncol <= 0)			goto Usage;		break;	case 'f':		fontnames[0] = ARGF();		if(fontnames[0] == nil)			goto Usage;		break;	case 'F':		fontnames[1] = ARGF();		if(fontnames[1] == nil)			goto Usage;		break;	case 'l':		loadfile = ARGF();		if(loadfile == nil)			goto Usage;		break;	default:	Usage:		fprint(2, "usage: acme [-ab] [-c ncol] [-f font] [-F fixedfont] [-l loadfile | file...]\n");		exits("usage");	}ARGEND	fontnames[0] = estrdup(fontnames[0]);	fontnames[1] = estrdup(fontnames[1]);	quotefmtinstall();	cputype = getenv("cputype");	objtype = getenv("objtype");	home = getenv("home");	p = getenv("tabstop");	if(p != nil){		maxtab = strtoul(p, nil, 0);		free(p);	}	if(maxtab == 0)		maxtab = 4; 	if(loadfile)		rowloadfonts(loadfile);	putenv("font", fontnames[0]);	snarffd = open("/dev/snarf", OREAD|OCEXEC);	if(cputype){		sprint(buf, "/acme/bin/%s", cputype);		bind(buf, "/bin", MBEFORE);	}	bind("/acme/bin", "/bin", MBEFORE);	getwd(wdir, sizeof wdir);	if(geninitdraw(nil, derror, fontnames[0], "acme", nil, Refnone) < 0){		fprint(2, "acme: can't open display: %r\n");		exits("geninitdraw");	}	d = display;	font = d->defaultfont;	reffont.f = font;	reffonts[0] = &reffont;	incref(&reffont);	/* one to hold up 'font' variable */	incref(&reffont);	/* one to hold up reffonts[0] */	fontcache = emalloc(sizeof(Reffont*));	nfontcache = 1;	fontcache[0] = &reffont;	iconinit();	timerinit();	rxinit();	cwait = threadwaitchan();	ccommand = chancreate(sizeof(Command**), 0);	ckill = chancreate(sizeof(Rune*), 0);	cxfidalloc = chancreate(sizeof(Xfid*), 0);	cxfidfree = chancreate(sizeof(Xfid*), 0);	cnewwindow = chancreate(sizeof(Channel*), 0);	cerr = chancreate(sizeof(char*), 0);	cedit = chancreate(sizeof(int), 0);	cexit = chancreate(sizeof(int), 0);	cwarn = chancreate(sizeof(void*), 1);	if(cwait==nil || ccommand==nil || ckill==nil || cxfidalloc==nil || cxfidfree==nil || cerr==nil || cexit==nil || cwarn==nil){		fprint(2, "acme: can't create initial channels: %r\n");		exits("channels");	}	mousectl = initmouse(nil, screen);	if(mousectl == nil){		fprint(2, "acme: can't initialize mouse: %r\n");		exits("mouse");	}	mouse = mousectl;	keyboardctl = initkeyboard(nil);	if(keyboardctl == nil){		fprint(2, "acme: can't initialize keyboard: %r\n");		exits("keyboard");	}	mainpid = getpid();	plumbeditfd = plumbopen("edit", OREAD|OCEXEC);	if(plumbeditfd >= 0){		cplumb = chancreate(sizeof(Plumbmsg*), 0);		proccreate(plumbproc, nil, STACK);	}	plumbsendfd = plumbopen("send", OWRITE|OCEXEC);	fsysinit();	#define	WPERCOL	8	disk = diskinit();	if(!loadfile || !rowload(&row, loadfile, TRUE)){		rowinit(&row, screen->clipr);		if(ncol < 0){			if(argc == 0)				ncol = 2;			else{				ncol = (argc+(WPERCOL-1))/WPERCOL;				if(ncol < 2)					ncol = 2;			}		}		if(ncol == 0)			ncol = 2;		for(i=0; i<ncol; i++){			c = rowadd(&row, nil, -1);			if(c==nil && i==0)				error("initializing columns");		}		c = row.col[row.ncol-1];		if(argc == 0)			readfile(c, wdir);		else			for(i=0; i<argc; i++){				p = utfrrune(argv[i], '/');				if((p!=nil && strcmp(p, "/guide")==0) || i/WPERCOL>=row.ncol)					readfile(c, argv[i]);				else					readfile(row.col[i/WPERCOL], argv[i]);			}	}	flushimage(display, 1);	acmeerrorinit();	threadcreate(keyboardthread, nil, STACK);	threadcreate(mousethread, nil, STACK);	threadcreate(waitthread, nil, STACK);	threadcreate(xfidallocthread, nil, STACK);	threadcreate(newwindowthread, nil, STACK);	threadnotify(shutdown, 1);	recvul(cexit);	killprocs();	threadexitsall(nil);}voidreadfile(Column *c, char *s){	Window *w;	Rune rb[256];	int nb, nr;	Runestr rs;	w = coladd(c, nil, nil, -1);	cvttorunes(s, strlen(s), rb, &nb, &nr, nil);	rs = cleanrname((Runestr){rb, nr});	winsetname(w, rs.r, rs.nr);	textload(&w->body, 0, s, 1);	w->body.file->mod = FALSE;	w->dirty = FALSE;	winsettag(w);	textscrdraw(&w->body);	textsetselect(&w->tag, w->tag.file->nc, w->tag.file->nc);}char *oknotes[] ={	"delete",	"hangup",	"kill",	"exit",	nil};int	dumping;intshutdown(void*, char *msg){	int i;	killprocs();	if(!dumping && strcmp(msg, "kill")!=0 && strcmp(msg, "exit")!=0 && getpid()==mainpid){		dumping = TRUE;		rowdump(&row, nil);	}	for(i=0; oknotes[i]; i++)		if(strncmp(oknotes[i], msg, strlen(oknotes[i])) == 0)			threadexitsall(msg);	print("acme: %s\n", msg);	abort();	return 0;}voidkillprocs(void){	Command *c;	fsysclose();//	if(display)//		flushimage(display, 1);	for(c=command; c; c=c->next)		postnote(PNGROUP, c->pid, "hangup");	remove(acmeerrorfile);}static int errorfd;voidacmeerrorproc(void *){	char *buf;	int n;	threadsetname("acmeerrorproc");	buf = emalloc(8192+1);	while((n=read(errorfd, buf, 8192)) >= 0){		buf[n] = '\0';		sendp(cerr, estrdup(buf));	}}voidacmeerrorinit(void){	int fd, pfd[2];	char buf[64];	if(pipe(pfd) < 0)		error("can't create pipe");	sprint(acmeerrorfile, "/srv/acme.%s.%d", getuser(), mainpid);	fd = create(acmeerrorfile, OWRITE, 0666);	if(fd < 0){		remove(acmeerrorfile);  		fd = create(acmeerrorfile, OWRITE, 0666);		if(fd < 0)			error("can't create acmeerror file");	}	sprint(buf, "%d", pfd[0]);	write(fd, buf, strlen(buf));	close(fd);	/* reopen pfd[1] close on exec */	sprint(buf, "/fd/%d", pfd[1]);	errorfd = open(buf, OREAD|OCEXEC);	if(errorfd < 0)		error("can't re-open acmeerror file");	close(pfd[1]);	close(pfd[0]);	proccreate(acmeerrorproc, nil, STACK);}voidplumbproc(void *){	Plumbmsg *m;	threadsetname("plumbproc");	for(;;){		m = plumbrecv(plumbeditfd);		if(m == nil)			threadexits(nil);		sendp(cplumb, m);	}}voidkeyboardthread(void *){	Rune r;	Timer *timer;	Text *t;	enum { KTimer, KKey, NKALT };	static Alt alts[NKALT+1];	alts[KTimer].c = nil;	alts[KTimer].v = nil;	alts[KTimer].op = CHANNOP;	alts[KKey].c = keyboardctl->c;	alts[KKey].v = &r;	alts[KKey].op = CHANRCV;	alts[NKALT].op = CHANEND;	timer = nil;	typetext = nil;	threadsetname("keyboardthread");	for(;;){		switch(alt(alts)){		case KTimer:			timerstop(timer);			t = typetext;			if(t!=nil && t->what==Tag){				winlock(t->w, 'K');				wincommit(t->w, t);				winunlock(t->w);				flushimage(display, 1);			}			alts[KTimer].c = nil;			alts[KTimer].op = CHANNOP;			break;		case KKey:		casekeyboard:			typetext = rowtype(&row, r, mouse->xy);			t = typetext;			if(t!=nil && t->col!=nil && !(r==Kdown || r==Kleft || r==Kright))	/* scrolling doesn't change activecol */				activecol = t->col;			if(t!=nil && t->w!=nil)				t->w->body.file->curtext = &t->w->body;			if(timer != nil)				timercancel(timer);			if(t!=nil && t->what==Tag) {				timer = timerstart(500);				alts[KTimer].c = timer->c;				alts[KTimer].op = CHANRCV;			}else{				timer = nil;				alts[KTimer].c = nil;				alts[KTimer].op = CHANNOP;			}			if(nbrecv(keyboardctl->c, &r) > 0)				goto casekeyboard;			flushimage(display, 1);			break;		}	}}voidmousethread(void *){	Text *t, *argt;	int but;	uint q0, q1;	Window *w;	Plumbmsg *pm;	Mouse m;	char *act;	enum { MResize, MMouse, MPlumb, MWarnings, NMALT };	static Alt alts[NMALT+1];	threadsetname("mousethread");	alts[MResize].c = mousectl->resizec;	alts[MResize].v = nil;	alts[MResize].op = CHANRCV;	alts[MMouse].c = mousectl->c;	alts[MMouse].v = &mousectl->Mouse;	alts[MMouse].op = CHANRCV;	alts[MPlumb].c = cplumb;	alts[MPlumb].v = &pm;	alts[MPlumb].op = CHANRCV;	alts[MWarnings].c = cwarn;	alts[MWarnings].v = nil;	alts[MWarnings].op = CHANRCV;	if(cplumb == nil)		alts[MPlumb].op = CHANNOP;	alts[NMALT].op = CHANEND;		for(;;){		qlock(&row);		flushwarnings();		qunlock(&row);		flushimage(display, 1);		switch(alt(alts)){		case MResize:			if(getwindow(display, Refnone) < 0)				error("attach to window");			scrlresize();			rowresize(&row, screen->clipr);			break;		case MPlumb:			if(strcmp(pm->type, "text") == 0){				act = plumblookup(pm->attr, "action");				if(act==nil || strcmp(act, "showfile")==0)					plumblook(pm);				else if(strcmp(act, "showdata")==0)					plumbshow(pm);			}			plumbfree(pm);			break;		case MWarnings:			break;		case MMouse:			/*			 * Make a copy so decisions are consistent; mousectl changes			 * underfoot.  Can't just receive into m because this introduces			 * another race; see /sys/src/libdraw/mouse.c.

⌨️ 快捷键说明

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