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

📄 wind.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 3 页
字号:
#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 <complete.h>#include "dat.h"#include "fns.h"#define MOVEIT if(0)enum{	HiWater	= 640000,	/* max size of history */	LoWater	= 400000,	/* min size of history after max'ed */	MinWater	= 20000,	/* room to leave available when reallocating */};static	int		topped;static	int		id;static	Image	*cols[NCOL];static	Image	*grey;static	Image	*darkgrey;static	Cursor	*lastcursor;static	Image	*titlecol;static	Image	*lighttitlecol;static	Image	*holdcol;static	Image	*lightholdcol;static	Image	*paleholdcol;Window*wmk(Image *i, Mousectl *mc, Channel *ck, Channel *cctl, int scrolling){	Window *w;	Rectangle r;	if(cols[0] == nil){		/* greys are multiples of 0x11111100+0xFF, 14* being palest */		grey = allocimage(display, Rect(0,0,1,1), CMAP8, 1, 0xEEEEEEFF);		darkgrey = allocimage(display, Rect(0,0,1,1), CMAP8, 1, 0x666666FF);		cols[BACK] = display->white;		cols[HIGH] = allocimage(display, Rect(0,0,1,1), CMAP8, 1, 0xCCCCCCFF);		cols[BORD] = allocimage(display, Rect(0,0,1,1), CMAP8, 1, 0x999999FF);		cols[TEXT] = display->black;		cols[HTEXT] = display->black;		titlecol = allocimage(display, Rect(0,0,1,1), CMAP8, 1, DGreygreen);		lighttitlecol = allocimage(display, Rect(0,0,1,1), CMAP8, 1, DPalegreygreen);		holdcol = allocimage(display, Rect(0,0,1,1), CMAP8, 1, DMedblue);		lightholdcol = allocimage(display, Rect(0,0,1,1), CMAP8, 1, DGreyblue);		paleholdcol = allocimage(display, Rect(0,0,1,1), CMAP8, 1, DPalegreyblue);	}	w = emalloc(sizeof(Window));	w->screenr = i->r;	r = insetrect(i->r, Selborder+1);	w->i = i;	w->mc = *mc;	w->ck = ck;	w->cctl = cctl;	w->cursorp = nil;	w->conswrite = chancreate(sizeof(Conswritemesg), 0);	w->consread =  chancreate(sizeof(Consreadmesg), 0);	w->mouseread =  chancreate(sizeof(Mousereadmesg), 0);	w->wctlread =  chancreate(sizeof(Consreadmesg), 0);	w->scrollr = r;	w->scrollr.max.x = r.min.x+Scrollwid;	w->lastsr = ZR;	r.min.x += Scrollwid+Scrollgap;	frinit(w, r, font, i, cols);	w->maxtab = maxtab*stringwidth(font, "0");	w->topped = ++topped;	w->id = ++id;	w->notefd = -1;	w->scrolling = scrolling;	w->dir = estrdup(startdir);	w->label = estrdup("<unnamed>");	r = insetrect(w->i->r, Selborder);	draw(w->i, r, cols[BACK], nil, w->entire.min);	wborder(w, Selborder);	wscrdraw(w);	incref(w);	/* ref will be removed after mounting; avoids delete before ready to be deleted */	return w;}voidwsetname(Window *w){	int i, n;	char err[ERRMAX];		n = sprint(w->name, "window.%d.%d", w->id, w->namecount++);	for(i='A'; i<='Z'; i++){		if(nameimage(w->i, w->name, 1) > 0)			return;		errstr(err, sizeof err);		if(strcmp(err, "image name in use") != 0)			break;		w->name[n] = i;		w->name[n+1] = 0;	}	w->name[0] = 0;	fprint(2, "rio: setname failed: %s\n", err);}voidwresize(Window *w, Image *i, int move){	Rectangle r, or;	or = w->i->r;	if(move || (Dx(or)==Dx(i->r) && Dy(or)==Dy(i->r)))		draw(i, i->r, w->i, nil, w->i->r.min);	freeimage(w->i);	w->i = i;	wsetname(w);	w->mc.image = i;	r = insetrect(i->r, Selborder+1);	w->scrollr = r;	w->scrollr.max.x = r.min.x+Scrollwid;	w->lastsr = ZR;	r.min.x += Scrollwid+Scrollgap;	if(move)		frsetrects(w, r, w->i);	else{		frclear(w, FALSE);		frinit(w, r, w->font, w->i, cols);		wsetcols(w);		w->maxtab = maxtab*stringwidth(w->font, "0");		r = insetrect(w->i->r, Selborder);		draw(w->i, r, cols[BACK], nil, w->entire.min);		wfill(w);		wsetselect(w, w->q0, w->q1);		wscrdraw(w);	}	wborder(w, Selborder);	w->topped = ++topped;	w->resized = TRUE;	w->mouse.counter++;}voidwrefresh(Window *w, Rectangle){	/* BUG: rectangle is ignored */	if(w == input)		wborder(w, Selborder);	else		wborder(w, Unselborder);	if(w->mouseopen)		return;	draw(w->i, insetrect(w->i->r, Borderwidth), w->cols[BACK], nil, w->i->r.min);	w->ticked = 0;	if(w->p0 > 0)		frdrawsel(w, frptofchar(w, 0), 0, w->p0, 0);	if(w->p1 < w->nchars)		frdrawsel(w, frptofchar(w, w->p1), w->p1, w->nchars, 0);	frdrawsel(w, frptofchar(w, w->p0), w->p0, w->p1, 1);	w->lastsr = ZR;	wscrdraw(w);}intwclose(Window *w){	int i;	i = decref(w);	if(i > 0)		return 0;	if(i < 0)		error("negative ref count");	if(!w->deleted)		wclosewin(w);	wsendctlmesg(w, Exited, ZR, nil);	return 1;}voidwinctl(void *arg){	Rune *rp, *bp, *tp, *up, *kbdr;	uint qh;	int nr, nb, c, wid, i, npart, initial, lastb;	char *s, *t, part[3];	Window *w;	Mousestate *mp, m;	enum { WKey, WMouse, WMouseread, WCtl, WCwrite, WCread, WWread, NWALT };	Alt alts[NWALT+1];	Mousereadmesg mrm;	Conswritemesg cwm;	Consreadmesg crm;	Consreadmesg cwrm;	Stringpair pair;	Wctlmesg wcm;	char buf[4*12+1];	w = arg;	snprint(buf, sizeof buf, "winctl-id%d", w->id);	threadsetname(buf);	mrm.cm = chancreate(sizeof(Mouse), 0);	cwm.cw = chancreate(sizeof(Stringpair), 0);	crm.c1 = chancreate(sizeof(Stringpair), 0);	crm.c2 = chancreate(sizeof(Stringpair), 0);	cwrm.c1 = chancreate(sizeof(Stringpair), 0);	cwrm.c2 = chancreate(sizeof(Stringpair), 0);		alts[WKey].c = w->ck;	alts[WKey].v = &kbdr;	alts[WKey].op = CHANRCV;	alts[WMouse].c = w->mc.c;	alts[WMouse].v = &w->mc.Mouse;	alts[WMouse].op = CHANRCV;	alts[WMouseread].c = w->mouseread;	alts[WMouseread].v = &mrm;	alts[WMouseread].op = CHANSND;	alts[WCtl].c = w->cctl;	alts[WCtl].v = &wcm;	alts[WCtl].op = CHANRCV;	alts[WCwrite].c = w->conswrite;	alts[WCwrite].v = &cwm;	alts[WCwrite].op = CHANSND;	alts[WCread].c = w->consread;	alts[WCread].v = &crm;	alts[WCread].op = CHANSND;	alts[WWread].c = w->wctlread;	alts[WWread].v = &cwrm;	alts[WWread].op = CHANSND;	alts[NWALT].op = CHANEND;	npart = 0;	lastb = -1;	for(;;){		if(w->mouseopen && w->mouse.counter != w->mouse.lastcounter)			alts[WMouseread].op = CHANSND;		else			alts[WMouseread].op = CHANNOP;		if(!w->scrolling && !w->mouseopen && w->qh>w->org+w->nchars)			alts[WCwrite].op = CHANNOP;		else			alts[WCwrite].op = CHANSND;		if(w->deleted || !w->wctlready)			alts[WWread].op = CHANNOP;		else			alts[WWread].op = CHANSND;		/* this code depends on NL and EOT fitting in a single byte */		/* kind of expensive for each loop; worth precomputing? */		if(w->holding)			alts[WCread].op = CHANNOP;		else if(npart || (w->rawing && w->nraw>0))			alts[WCread].op = CHANSND;		else{			alts[WCread].op = CHANNOP;			for(i=w->qh; i<w->nr; i++){				c = w->r[i];				if(c=='\n' || c=='\004'){					alts[WCread].op = CHANSND;					break;				}			}		}		switch(alt(alts)){		case WKey:			for(i=0; kbdr[i]!=L'\0'; i++)				wkeyctl(w, kbdr[i]);//			wkeyctl(w, r);///			while(nbrecv(w->ck, &r))//				wkeyctl(w, r);			break;		case WMouse:			if(w->mouseopen) {				w->mouse.counter++;				/* queue click events */				if(!w->mouse.qfull && lastb != w->mc.buttons) {	/* add to ring */					mp = &w->mouse.queue[w->mouse.wi];					if(++w->mouse.wi == nelem(w->mouse.queue))						w->mouse.wi = 0;					if(w->mouse.wi == w->mouse.ri)						w->mouse.qfull = TRUE;					mp->Mouse = w->mc;					mp->counter = w->mouse.counter;					lastb = w->mc.buttons;				}			} else				wmousectl(w);			break;		case WMouseread:			/* send a queued event or, if the queue is empty, the current state */			/* if the queue has filled, we discard all the events it contained. */			/* the intent is to discard frantic clicking by the user during long latencies. */			w->mouse.qfull = FALSE;			if(w->mouse.wi != w->mouse.ri) {				m = w->mouse.queue[w->mouse.ri];				if(++w->mouse.ri == nelem(w->mouse.queue))					w->mouse.ri = 0;			} else				m = (Mousestate){w->mc.Mouse, w->mouse.counter};			w->mouse.lastcounter = m.counter;			send(mrm.cm, &m.Mouse);			continue;		case WCtl:			if(wctlmesg(w, wcm.type, wcm.r, wcm.image) == Exited){				chanfree(crm.c1);				chanfree(crm.c2);				chanfree(mrm.cm);				chanfree(cwm.cw);				chanfree(cwrm.c1);				chanfree(cwrm.c2);				threadexits(nil);			}			continue;		case WCwrite:			recv(cwm.cw, &pair);			rp = pair.s;			nr = pair.ns;			bp = rp;			for(i=0; i<nr; i++)				if(*bp++ == '\b'){					--bp;					initial = 0;					tp = runemalloc(nr);					runemove(tp, rp, i);					up = tp+i;					for(; i<nr; i++){						*up = *bp++;						if(*up == '\b')							if(up == tp)								initial++;							else								--up;						else							up++;					}					if(initial){						if(initial > w->qh)							initial = w->qh;						qh = w->qh-initial;						wdelete(w, qh, qh+initial);						w->qh = qh;					}					free(rp);					rp = tp;					nr = up-tp;					rp[nr] = 0;					break;				}			w->qh = winsert(w, rp, nr, w->qh)+nr;			if(w->scrolling || w->mouseopen)				wshow(w, w->qh);			wsetselect(w, w->q0, w->q1);			wscrdraw(w);			free(rp);			break;		case WCread:			recv(crm.c1, &pair);			t = pair.s;			nb = pair.ns;			i = npart;			npart = 0;			if(i)				memmove(t, part, i);			while(i<nb && (w->qh<w->nr || w->nraw>0)){				if(w->qh == w->nr){					wid = runetochar(t+i, &w->raw[0]);					w->nraw--;					runemove(w->raw, w->raw+1, w->nraw);				}else					wid = runetochar(t+i, &w->r[w->qh++]);				c = t[i];	/* knows break characters fit in a byte */				i += wid;				if(!w->rawing && (c == '\n' || c=='\004')){					if(c == '\004')						i--;					break;				}			}			if(i==nb && w->qh<w->nr && w->r[w->qh]=='\004')				w->qh++;			if(i > nb){				npart = i-nb;				memmove(part, t+nb, npart);				i = nb;			}			pair.s = t;			pair.ns = i;			send(crm.c2, &pair);			continue;		case WWread:			w->wctlready = 0;			recv(cwrm.c1, &pair);			if(w->deleted || w->i==nil)				pair.ns = sprint(pair.s, "");			else{				s = "visible";				for(i=0; i<nhidden; i++)					if(hidden[i] == w){						s = "hidden";						break;					}				t = "notcurrent";				if(w == input)					t = "current";				pair.ns = snprint(pair.s, pair.ns, "%11d %11d %11d %11d %s %s ",					w->i->r.min.x, w->i->r.min.y, w->i->r.max.x, w->i->r.max.y, t, s);			}			send(cwrm.c2, &pair);			continue;		}		if(!w->deleted)			flushimage(display, 1);	}}voidwaddraw(Window *w, Rune *r, int nr){	w->raw = runerealloc(w->raw, w->nraw+nr);	runemove(w->raw+w->nraw, r, nr);	w->nraw += nr;}/* * Need to do this in a separate proc because if process we're interrupting * is dying and trying to print tombstone, kernel is blocked holding p->debug lock. */voidinterruptproc(void *v){	int *notefd;	notefd = v;	write(*notefd, "interrupt", 9);	free(notefd);}intwindfilewidth(Window *w, uint q0, int oneelement){	uint q;	Rune r;	q = q0;	while(q > 0){		r = w->r[q-1];		if(r<=' ')			break;		if(oneelement && r=='/')			break;		--q;	}	return q0-q;}voidshowcandidates(Window *w, Completion *c){	int i;	Fmt f;	Rune *rp;	uint nr, qline, q0;	char *s;	runefmtstrinit(&f);	if (c->nmatch == 0)		s = "[no matches in ";	else		s = "[";	if(c->nfile > 32)		fmtprint(&f, "%s%d files]\n", s, c->nfile);	else{		fmtprint(&f, "%s", s);		for(i=0; i<c->nfile; i++){			if(i > 0)				fmtprint(&f, " ");			fmtprint(&f, "%s", c->filename[i]);		}		fmtprint(&f, "]\n");	}	/* place text at beginning of line before host point */	qline = w->qh;	while(qline>0 && w->r[qline-1] != '\n')		qline--;	rp = runefmtstrflush(&f);	nr = runestrlen(rp);	q0 = w->q0;	q0 += winsert(w, rp, runestrlen(rp), qline) - qline;	free(rp);	wsetselect(w, q0+nr, q0+nr);}Rune*namecomplete(Window *w){	int nstr, npath;	Rune *rp, *path, *str;	Completion *c;	char *s, *dir, *root;	/* control-f: filename completion; works back to white space or / */	if(w->q0<w->nr && w->r[w->q0]>' ')	/* must be at end of word */		return nil;	nstr = windfilewidth(w, w->q0, TRUE);	str = runemalloc(nstr);	runemove(str, w->r+(w->q0-nstr), nstr);	npath = windfilewidth(w, w->q0-nstr, FALSE);	path = runemalloc(npath);	runemove(path, w->r+(w->q0-nstr-npath), npath);	rp = nil;	/* is path rooted? if not, we need to make it relative to window path */	if(npath>0 && path[0]=='/'){		dir = malloc(UTFmax*npath+1);		sprint(dir, "%.*S", npath, path);	}else{		if(strcmp(w->dir, "") == 0)			root = ".";		else			root = w->dir;		dir = malloc(strlen(root)+1+UTFmax*npath+1);		sprint(dir, "%s/%.*S", root, npath, path);	}	dir = cleanname(dir);	s = smprint("%.*S", nstr, str);	c = complete(dir, s);	free(s);	if(c == nil)		goto Return;	if(!c->advance)		showcandidates(w, c);	if(c->advance)		rp = runesmprint("%s", c->string);  Return:	freecompletion(c);	free(dir);	free(path);	free(str);	return rp;}voidwkeyctl(Window *w, Rune r){	uint q0 ,q1;	int n, nb, nr;	Rune *rp;	int *notefd;	if(r == 0)		return;	if(w->deleted)		return;	/* navigation keys work only when mouse is not open */

⌨️ 快捷键说明

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