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

📄 event.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include <u.h>#include <libc.h>#include <draw.h>#include <cursor.h>#include <event.h>typedef struct	Slave Slave;typedef struct	Ebuf Ebuf;struct Slave{	int	pid;	Ebuf	*head;		/* ueue of messages for this descriptor */	Ebuf	*tail;	int	(*fn)(int, Event*, uchar*, int);};struct Ebuf{	Ebuf	*next;	int	n;		/* number of bytes in buf */	uchar	buf[EMAXMSG];};static	Slave	eslave[MAXSLAVE];static	int	Skeyboard = -1;static	int	Smouse = -1;static	int	Stimer = -1;static	int	logfid;static	int	nslave;static	int	parentpid;static	int	epipe[2];static	int	eforkslave(ulong);static	void	extract(void);static	void	ekill(void);static	int	enote(void *, char *);static	int	mousefd;static	int	cursorfd;staticEbuf*ebread(Slave *s){	Ebuf *eb;	Dir *d;	ulong l;	for(;;){		d = dirfstat(epipe[0]);		if(d == nil)			drawerror(display, "events: eread stat error");		l = d->length;		free(d);		if(s->head && l==0)			break;		extract();	}	eb = s->head;	s->head = s->head->next;	if(s->head == 0)		s->tail = 0;	return eb;}ulongevent(Event *e){	return eread(~0UL, e);}ulongeread(ulong keys, Event *e){	Ebuf *eb;	int i, id;	if(keys == 0)		return 0;	for(;;){		for(i=0; i<nslave; i++)			if((keys & (1<<i)) && eslave[i].head){				id = 1<<i;				if(i == Smouse)					e->mouse = emouse();				else if(i == Skeyboard)					e->kbdc = ekbd();				else if(i == Stimer)					eslave[i].head = 0;				else{					eb = ebread(&eslave[i]);					e->n = eb->n;					if(eslave[i].fn)						id = (*eslave[i].fn)(id, e, eb->buf, eb->n);					else						memmove(e->data, eb->buf, eb->n);					free(eb);				}				return id;			}		extract();	}}intecanmouse(void){	if(Smouse < 0)		drawerror(display, "events: mouse not initialized");	return ecanread(Emouse);}intecankbd(void){	if(Skeyboard < 0)		drawerror(display, "events: keyboard not initialzed");	return ecanread(Ekeyboard);}intecanread(ulong keys){	Dir *d;	int i;	ulong l;	for(;;){		for(i=0; i<nslave; i++)			if((keys & (1<<i)) && eslave[i].head)				return 1;		d = dirfstat(epipe[0]);		if(d == nil)			drawerror(display, "events: ecanread stat error");		l = d->length;		free(d);		if(l == 0)			return 0;		extract();	}}ulongestartfn(ulong key, int fd, int n, int (*fn)(int, Event*, uchar*, int)){	char buf[EMAXMSG+1];	int i, r;	if(fd < 0)		drawerror(display, "events: bad file descriptor");	if(n <= 0 || n > EMAXMSG)		n = EMAXMSG;	i = eforkslave(key);	if(i < MAXSLAVE){		eslave[i].fn = fn;		return 1<<i;	}	buf[0] = i - MAXSLAVE;	while((r = read(fd, buf+1, n))>0)		if(write(epipe[1], buf, r+1)!=r+1)			break;	buf[0] = MAXSLAVE;	write(epipe[1], buf, 1);	_exits(0);	return 0;}ulongestart(ulong key, int fd, int n){	return estartfn(key, fd, n, nil);}ulongetimer(ulong key, int n){	char t[2];	if(Stimer != -1)		drawerror(display, "events: timer started twice");	Stimer = eforkslave(key);	if(Stimer < MAXSLAVE)		return 1<<Stimer;	if(n <= 0)		n = 1000;	t[0] = t[1] = Stimer - MAXSLAVE;	do		sleep(n);	while(write(epipe[1], t, 2) == 2);	t[0] = MAXSLAVE;	write(epipe[1], t, 1);	_exits(0);	return 0;}static voidekeyslave(int fd){	Rune r;	char t[3], k[10];	int kr, kn, w;	if(eforkslave(Ekeyboard) < MAXSLAVE)		return;	kn = 0;	t[0] = Skeyboard;	for(;;){		while(!fullrune(k, kn)){			kr = read(fd, k+kn, sizeof k - kn);			if(kr <= 0)				goto breakout;			kn += kr;		}		w = chartorune(&r, k);		kn -= w;		memmove(k, &k[w], kn);		t[1] = r;		t[2] = r>>8;		if(write(epipe[1], t, 3) != 3)			break;	}breakout:;	t[0] = MAXSLAVE;	write(epipe[1], t, 1);	_exits(0);}voideinit(ulong keys){	int ctl, fd;	char buf[256];	parentpid = getpid();	if(pipe(epipe) < 0)		drawerror(display, "events: einit pipe");	atexit(ekill);	atnotify(enote, 1);	snprint(buf, sizeof buf, "%s/mouse", display->devdir);	mousefd = open(buf, ORDWR|OCEXEC);	if(mousefd < 0)		drawerror(display, "einit: can't open mouse\n");	snprint(buf, sizeof buf, "%s/cursor", display->devdir);	cursorfd = open(buf, ORDWR|OCEXEC);	if(cursorfd < 0)		drawerror(display, "einit: can't open cursor\n");	if(keys&Ekeyboard){		snprint(buf, sizeof buf, "%s/cons", display->devdir);		fd = open(buf, OREAD);		if(fd < 0)			drawerror(display, "events: can't open console");		snprint(buf, sizeof buf, "%s/consctl", display->devdir);		ctl = open("/dev/consctl", OWRITE|OCEXEC);		if(ctl < 0)			drawerror(display, "events: can't open consctl");		write(ctl, "rawon", 5);		for(Skeyboard=0; Ekeyboard & ~(1<<Skeyboard); Skeyboard++)			;		ekeyslave(fd);	}	if(keys&Emouse){		estart(Emouse, mousefd, 1+4*12);		for(Smouse=0; Emouse & ~(1<<Smouse); Smouse++)			;	}}static voidextract(void){	Slave *s;	Ebuf *eb;	int i, n;	uchar ebuf[EMAXMSG+1];	/* avoid generating a message if there's nothing to show. */	/* this test isn't perfect, though; could do flushimage(display, 0) then call extract */	/* also: make sure we don't interfere if we're multiprocessing the display */	if(display->locking){		/* if locking is being done by program, this means it can't depend on automatic flush in emouse() etc. */		if(canqlock(&display->qlock)){			if(display->bufp > display->buf)				flushimage(display, 1);			unlockdisplay(display);		}	}else		if(display->bufp > display->buf)			flushimage(display, 1);loop:	if((n=read(epipe[0], ebuf, EMAXMSG+1)) < 0	|| ebuf[0] >= MAXSLAVE)		drawerror(display, "eof on event pipe");	if(n == 0)		goto loop;	i = ebuf[0];	if(i >= nslave || n <= 1)		drawerror(display, "events: protocol error: short read");	s = &eslave[i];	if(i == Stimer){		s->head = (Ebuf *)1;		return;	}	if(i == Skeyboard && n != 3)		drawerror(display, "events: protocol error: keyboard");	if(i == Smouse){		if(n < 1+1+2*12)			drawerror(display, "events: protocol error: mouse");		if(ebuf[1] == 'r')			eresized(1);		/* squash extraneous mouse events */		if((eb=s->tail) && memcmp(eb->buf+1+2*12, ebuf+1+1+2*12, 12)==0){			memmove(eb->buf, &ebuf[1], n - 1);			return;		}	}	/* try to save space by only allocating as much buffer as we need */	eb = malloc(sizeof(*eb) - sizeof(eb->buf) + n - 1);	if(eb == 0)		drawerror(display, "events: protocol error 4");	eb->n = n - 1;	memmove(eb->buf, &ebuf[1], n - 1);	eb->next = 0;	if(s->head)		s->tail = s->tail->next = eb;	else		s->head = s->tail = eb;}static inteforkslave(ulong key){	int i, pid;	for(i=0; i<MAXSLAVE; i++)		if((key & ~(1<<i)) == 0 && eslave[i].pid == 0){			if(nslave <= i)				nslave = i + 1;			/*			 * share the file descriptors so the last child			 * out closes all connections to the window server.			 */			switch(pid = rfork(RFPROC)){			case 0:				return MAXSLAVE+i;			case -1:				fprint(2, "events: fork error\n");				exits("fork");			}			eslave[i].pid = pid;			eslave[i].head = eslave[i].tail = 0;			return i;		}	drawerror(display, "events: bad slave assignment");	return 0;}static intenote(void *v, char *s){	char t[1];	int i, pid;	USED(v, s);	pid = getpid();	if(pid != parentpid){		for(i=0; i<nslave; i++){			if(pid == eslave[i].pid){				t[0] = MAXSLAVE;				write(epipe[1], t, 1);				break;			}		}		return 0;	}	close(epipe[0]);	epipe[0] = -1;	close(epipe[1]);	epipe[1] = -1;	for(i=0; i<nslave; i++){		if(pid == eslave[i].pid)			continue;	/* don't kill myself */		postnote(PNPROC, eslave[i].pid, "die");	}	return 0;}static voidekill(void){	enote(0, 0);}Mouseemouse(void){	Mouse m;	Ebuf *eb;	static but[2];	int b;	if(Smouse < 0)		drawerror(display, "events: mouse not initialized");	eb = ebread(&eslave[Smouse]);	m.xy.x = atoi((char*)eb->buf+1+0*12);	m.xy.y = atoi((char*)eb->buf+1+1*12);	b = atoi((char*)eb->buf+1+2*12);	m.buttons = b;	m.msec = atoi((char*)eb->buf+1+3*12);	if (logfid)		fprint(logfid, "b: %d xy: %P\n", m.buttons, m.xy);	free(eb);	return m;}intekbd(void){	Ebuf *eb;	int c;	if(Skeyboard < 0)		drawerror(display, "events: keyboard not initialzed");	eb = ebread(&eslave[Skeyboard]);	c = eb->buf[0] + (eb->buf[1]<<8);	free(eb);	return c;}voidemoveto(Point pt){	char buf[2*12+2];	int n;	n = sprint(buf, "m%d %d", pt.x, pt.y);	write(mousefd, buf, n);}voidesetcursor(Cursor *c){	uchar curs[2*4+2*2*16];	if(c == 0)		write(cursorfd, curs, 0);	else{		BPLONG(curs+0*4, c->offset.x);		BPLONG(curs+1*4, c->offset.y);		memmove(curs+2*4, c->clr, 2*2*16);		write(cursorfd, curs, sizeof curs);	}}intereadmouse(Mouse *m){	int n;	char buf[128];	do{		n = read(mousefd, buf, sizeof(buf));		if(n < 0)	/* probably interrupted */			return -1;		n = eatomouse(m, buf, n);	}while(n == 0);	return n;}inteatomouse(Mouse *m, char *buf, int n){	if(n != 1+4*12){		werrstr("atomouse: bad count");		return -1;	}	if(buf[0] == 'r')		eresized(1);	m->xy.x = atoi(buf+1+0*12);	m->xy.y = atoi(buf+1+1*12);	m->buttons = atoi(buf+1+2*12);	m->msec = atoi(buf+1+3*12);	return n;}

⌨️ 快捷键说明

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