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

📄 rio.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"/* *  WASHINGTON (AP) - The Food and Drug Administration warned * consumers Wednesday not to use ``Rio'' hair relaxer products * because they may cause severe hair loss or turn hair green.... *    The FDA urged consumers who have experienced problems with Rio * to notify their local FDA office, local health department or the * company at 1‑800‑543‑3002. */void		resize(void);void		move(void);void		delete(void);void		hide(void);void		unhide(int);void		newtile(int);Image	*sweep(void);Image	*bandsize(Window*);Image*	drag(Window*, Rectangle*);void		refresh(Rectangle);void		resized(void);Channel	*exitchan;	/* chan(int) */Channel	*winclosechan; /* chan(Window*); */Rectangle	viewr;int		threadrforkflag = 0;	/* should be RFENVG but that hides rio from plumber */void	mousethread(void*);void	keyboardthread(void*);void winclosethread(void*);void deletethread(void*);void	initcmd(void*);char		*fontname;int		mainpid;enum{	New,	Reshape,	Move,	Delete,	Hide,	Exit,};enum{	Cut,	Paste,	Snarf,	Plumb,	Send,	Scroll,};char		*menu2str[] = { [Cut]		"cut", [Paste]		"paste", [Snarf]		"snarf", [Plumb]		"plumb", [Send]		"send", [Scroll]		"scroll",			nil};Menu menu2 ={	menu2str};int	Hidden = Exit+1;char		*menu3str[100] = { [New]		"New", [Reshape]	"Resize", [Move]		"Move", [Delete]		"Delete", [Hide]		"Hide", [Exit]		"Exit",			nil};Menu menu3 ={	menu3str};char *rcargv[] = { "rc", "-i", nil };char *kbdargv[] = { "rc", "-c", nil, nil };int errorshouldabort = 0;voidderror(Display*, char *errorstr){	error(errorstr);}voidusage(void){	fprint(2, "usage: rio [-f font] [-i initcmd] [-k kbdcmd] [-s]\n");	exits("usage");}voidthreadmain(int argc, char *argv[]){	char *initstr, *kbdin, *s;	static void *arg[1];	char buf[256];	Image *i;	Rectangle r;	if(strstr(argv[0], ".out") == nil){		menu3str[Exit] = nil;		Hidden--;	}	initstr = nil;	kbdin = nil;	maxtab = 0;	ARGBEGIN{	case 'f':		fontname = ARGF();		if(fontname == nil)			usage();		break;	case 'i':		initstr = ARGF();		if(initstr == nil)			usage();		break;	case 'k':		if(kbdin != nil)			usage();		kbdin = ARGF();		if(kbdin == nil)			usage();		break;	case 's':		scrolling = TRUE;		break;	}ARGEND	mainpid = getpid();	if(getwd(buf, sizeof buf) == nil)		startdir = estrdup(".");	else		startdir = estrdup(buf);	if(fontname == nil)		fontname = getenv("font");	if(fontname == nil)		fontname = "/lib/font/bit/lucm/unicode.9.font";	s = getenv("tabstop");	if(s != nil)		maxtab = strtol(s, nil, 0);	if(maxtab == 0)		maxtab = 4;	free(s);	/* check font before barging ahead */	if(access(fontname, 0) < 0){		fprint(2, "rio: can't access %s: %r\n", fontname);		exits("font open");	}	putenv("font", fontname);	snarffd = open("/dev/snarf", OREAD|OCEXEC);	if(geninitdraw(nil, derror, nil, "rio", nil, Refnone) < 0){		fprint(2, "rio: can't open display: %r\n");		exits("display open");	}	iconinit();	view = screen;	viewr = view->r;	mousectl = initmouse(nil, screen);	if(mousectl == nil)		error("can't find mouse");	mouse = mousectl;	keyboardctl = initkeyboard(nil);	if(keyboardctl == nil)		error("can't find keyboard");	wscreen = allocscreen(screen, background, 0);	if(wscreen == nil)		error("can't allocate screen");	draw(view, viewr, background, nil, ZP);	flushimage(display, 1);	exitchan = chancreate(sizeof(int), 0);	winclosechan = chancreate(sizeof(Window*), 0);	deletechan = chancreate(sizeof(char*), 0);	timerinit();	threadcreate(keyboardthread, nil, STACK);	threadcreate(mousethread, nil, STACK);	threadcreate(winclosethread, nil, STACK);	threadcreate(deletethread, nil, STACK);	filsys = filsysinit(xfidinit());	if(filsys == nil)		fprint(2, "rio: can't create file system server: %r\n");	else{		errorshouldabort = 1;	/* suicide if there's trouble after this */		if(initstr)			proccreate(initcmd, initstr, STACK);		if(kbdin){			kbdargv[2] = kbdin;			r = screen->r;			r.max.x = r.min.x+300;			r.max.y = r.min.y+80;			i = allocwindow(wscreen, r, Refbackup, DWhite);			wkeyboard = new(i, FALSE, scrolling, 0, nil, "/bin/rc", kbdargv);			if(wkeyboard == nil)				error("can't create keyboard window");		}		threadnotify(shutdown, 1);		recv(exitchan, nil);	}	killprocs();	threadexitsall(nil);}/* * /dev/snarf updates when the file is closed, so we must open our own * fd here rather than use snarffd */voidputsnarf(void){	int fd, i, n;	if(snarffd<0 || nsnarf==0)		return;	fd = open("/dev/snarf", OWRITE);	if(fd < 0)		return;	/* snarf buffer could be huge, so fprint will truncate; do it in blocks */	for(i=0; i<nsnarf; i+=n){		n = nsnarf-i;		if(n >= 256)			n = 256;		if(fprint(fd, "%.*S", n, snarf+i) < 0)			break;	}	close(fd);}voidgetsnarf(void){	int i, n, nb, nulls;	char *sn, buf[1024];	if(snarffd < 0)		return;	sn = nil;	i = 0;	seek(snarffd, 0, 0);	while((n = read(snarffd, buf, sizeof buf)) > 0){		sn = erealloc(sn, i+n+1);		memmove(sn+i, buf, n);		i += n;		sn[i] = 0;	}	if(i > 0){		snarf = runerealloc(snarf, i+1);		cvttorunes(sn, i, snarf, &nb, &nsnarf, &nulls);		free(sn);	}}voidinitcmd(void *arg){	char *cmd;	cmd = arg;	rfork(RFENVG|RFFDG|RFNOTEG|RFNAMEG);	procexecl(nil, "/bin/rc", "rc", "-c", cmd, nil);	fprint(2, "rio: exec failed: %r\n");	exits("exec");}char *oknotes[] ={	"delete",	"hangup",	"kill",	"exit",	nil};intshutdown(void *, char *msg){	int i;	killprocs();	for(i=0; oknotes[i]; i++)		if(strncmp(oknotes[i], msg, strlen(oknotes[i])) == 0)			threadexitsall(msg);	fprint(2, "rio %d: abort: %s\n", getpid(), msg);	abort();	exits(msg);	return 0;}voidkillprocs(void){	int i;	for(i=0; i<nwindow; i++)		postnote(PNGROUP, window[i]->pid, "hangup");}voidkeyboardthread(void*){	Rune buf[2][20], *rp;	int n, i;	threadsetname("keyboardthread");	n = 0;	for(;;){		rp = buf[n];		n = 1-n;		recv(keyboardctl->c, rp);		for(i=1; i<nelem(buf[0])-1; i++)			if(nbrecv(keyboardctl->c, rp+i) <= 0)				break;		rp[i] = L'\0';		if(input != nil)			sendp(input->ck, rp);	}}/* * Used by /dev/kbdin */voidkeyboardsend(char *s, int cnt){	Rune *r;	int i, nb, nr;	r = runemalloc(cnt);	/* BUGlet: partial runes will be converted to error runes */	cvttorunes(s, cnt, r, &nb, &nr, nil);	for(i=0; i<nr; i++)		send(keyboardctl->c, &r[i]);	free(r);}intportion(int x, int lo, int hi){	x -= lo;	hi -= lo;	if(x < 20)		return 0;	if(x > hi-20)		return 2;	return 1;}intwhichcorner(Window *w, Point p){	int i, j;		i = portion(p.x, w->screenr.min.x, w->screenr.max.x);	j = portion(p.y, w->screenr.min.y, w->screenr.max.y);	return 3*j+i;}voidcornercursor(Window *w, Point p, int force){	if(w!=nil && winborder(w, p))		riosetcursor(corners[whichcorner(w, p)], force);	else		wsetcursor(w, force);}/* thread to allow fsysproc to synchronize window closing with main proc */voidwinclosethread(void*){	Window *w;	threadsetname("winclosethread");	for(;;){		w = recvp(winclosechan);		wclose(w);	}}/* thread to make Deleted windows that the client still holds disappear offscreen after an interval */voiddeletethread(void*){	char *s;	Image *i;	threadsetname("deletethread");	for(;;){		s = recvp(deletechan);		i = namedimage(display, s);		if(i != nil){			/* move it off-screen to hide it, since client is slow in letting it go */			originwindow(i, i->r.min, view->r.max);		}		freeimage(i);		free(s);	}}voiddeletetimeoutproc(void *v){	char *s;	s = v;	sleep(750);	/* remove window from screen after 3/4 of a second */	sendp(deletechan, s);}/* * Button 6 - keyboard toggle - has been pressed. * Send event to keyboard, wait for button up, send that. * Note: there is no coordinate translation done here; this * is just about getting button 6 to the keyboard simulator. */voidkeyboardhide(void){	send(wkeyboard->mc.c, mouse);	do		readmouse(mousectl);	while(mouse->buttons & (1<<5));	send(wkeyboard->mc.c, mouse);}voidmousethread(void*){	int sending, inside, scrolling, moving, band;	Window *oin, *w, *winput;	Image *i;	Rectangle r;	Point xy;	Mouse tmp;	enum {		MReshape,		MMouse,		NALT	};	static Alt alts[NALT+1];	threadsetname("mousethread");	sending = FALSE;	scrolling = FALSE;	moving = FALSE;	alts[MReshape].c = mousectl->resizec;	alts[MReshape].v = nil;	alts[MReshape].op = CHANRCV;	alts[MMouse].c = mousectl->c;	alts[MMouse].v = &mousectl->Mouse;	alts[MMouse].op = CHANRCV;	alts[NALT].op = CHANEND;	for(;;)	    switch(alt(alts)){		case MReshape:			resized();			break;		case MMouse:			if(wkeyboard!=nil && (mouse->buttons & (1<<5))){				keyboardhide();				break;			}		Again:			winput = input;			/* override everything for the keyboard window */			if(wkeyboard!=nil && ptinrect(mouse->xy, wkeyboard->screenr)){				/* make sure it's on top; this call is free if it is */				wtopme(wkeyboard);				winput = wkeyboard;			}			if(winput!=nil && winput->i!=nil){				/* convert to logical coordinates */				xy.x = mouse->xy.x + (winput->i->r.min.x-winput->screenr.min.x);				xy.y = mouse->xy.y + (winput->i->r.min.y-winput->screenr.min.y);				/* the up and down scroll buttons are not subject to the usual rules */				if((mouse->buttons&(8|16)) && !winput->mouseopen)					goto Sending;				inside = ptinrect(mouse->xy, insetrect(winput->screenr, Selborder));				if(winput->mouseopen)					scrolling = FALSE;				else if(scrolling)					scrolling = mouse->buttons;				else					scrolling = mouse->buttons && ptinrect(xy, winput->scrollr);				/* topped will be zero or less if window has been bottomed */				if(sending == FALSE && !scrolling && winborder(winput, mouse->xy) && winput->topped>0){					moving = TRUE;				}else if(inside && (scrolling || winput->mouseopen || (mouse->buttons&1)))					sending = TRUE;			}else				sending = FALSE;			if(sending){			Sending:				if(mouse->buttons == 0){					cornercursor(winput, mouse->xy, 0);					sending = FALSE;				}else					wsetcursor(winput, 0);				tmp = mousectl->Mouse;				tmp.xy = xy;				send(winput->mc.c, &tmp);				continue;			}			w = wpointto(mouse->xy);			/* change cursor if over anyone's border */			if(w != nil)				cornercursor(w, mouse->xy, 0);			else				riosetcursor(nil, 0);			if(moving && (mouse->buttons&7)){				oin = winput;				band = mouse->buttons & 3;				sweeping = 1;				if(band)					i = bandsize(winput);				else					i = drag(winput, &r);				sweeping = 0;				if(i != nil){					if(winput == oin){						if(band)							wsendctlmesg(winput, Reshaped, i->r, i);						else							wsendctlmesg(winput, Moved, r, i);						cornercursor(winput, mouse->xy, 1);					}else						freeimage(i);				}			}			if(w != nil)				cornercursor(w, mouse->xy, 0);			/* we're not sending the event, but if button is down maybe we should */			if(mouse->buttons){				/* w->topped will be zero or less if window has been bottomed */				if(w==nil || (w==winput && w->topped>0)){					if(mouse->buttons & 1){						;					}else if(mouse->buttons & 2){						if(winput && !winput->mouseopen)							button2menu(winput);					}else if(mouse->buttons & 4)						button3menu();				}else{					/* if button 1 event in the window, top the window and wait for button up. */					/* otherwise, top the window and pass the event on */					if(wtop(mouse->xy) && (mouse->buttons!=1 || winborder(w, mouse->xy)))						goto Again;					goto Drain;				}			}			moving = FALSE;			break;		Drain:			do				readmouse(mousectl);			while(mousectl->buttons);			moving = FALSE;			goto Again;	/* recalculate mouse position, cursor */

⌨️ 快捷键说明

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