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

📄 util.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#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"static	Point		prevmouse;static	Window	*mousew;voidcvttorunes(char *p, int n, Rune *r, int *nb, int *nr, int *nulls){	uchar *q;	Rune *s;	int j, w;	/*	 * Always guaranteed that n bytes may be interpreted	 * without worrying about partial runes.  This may mean	 * reading up to UTFmax-1 more bytes than n; the caller	 * knows this.  If n is a firm limit, the caller should	 * set p[n] = 0.	 */	q = (uchar*)p;	s = r;	for(j=0; j<n; j+=w){		if(*q < Runeself){			w = 1;			*s = *q++;		}else{			w = chartorune(s, (char*)q);			q += w;		}		if(*s)			s++;		else if(nulls)			*nulls = TRUE;	}	*nb = (char*)q-p;	*nr = s-r;}voiderror(char *s){	fprint(2, "acme: %s: %r\n", s);	remove(acmeerrorfile);	abort();}Window*errorwin1(Rune *dir, int ndir, Rune **incl, int nincl){	Window *w;	Rune *r;	int i, n;	r = runemalloc(ndir+8);	if(n = ndir){	/* assign = */		runemove(r, dir, ndir);		r[n++] = L'/';	}	runemove(r+n, L"+Errors", 7);	n += 7;	w = lookfile(r, n);	if(w == nil){		if(row.ncol == 0)			if(rowadd(&row, nil, -1) == nil)				error("can't create column to make error window");		w = coladd(row.col[row.ncol-1], nil, nil, -1);		w->filemenu = FALSE;		winsetname(w, r, n);	}	free(r);	for(i=nincl; --i>=0; ){		n = runestrlen(incl[i]);		r = runemalloc(n);		runemove(r, incl[i], n);		winaddincl(w, r, n);	}	w->autoindent = globalautoindent;	return w;}/* make new window, if necessary; return with it locked */Window*errorwin(Mntdir *md, int owner){	Window *w;	for(;;){		if(md == nil)			w = errorwin1(nil, 0, nil, 0);		else			w = errorwin1(md->dir, md->ndir, md->incl, md->nincl);		winlock(w, owner);		if(w->col != nil)			break;		/* window was deleted too fast */		winunlock(w);	}	return w;}/* * Incoming window should be locked.  * It will be unlocked and returned window * will be locked in its place. */Window*errorwinforwin(Window *w){	int i, n, nincl, owner;	Rune **incl;	Runestr dir;	Text *t;	t = &w->body;	dir = dirname(t, nil, 0);	if(dir.nr==1 && dir.r[0]=='.'){	/* sigh */		free(dir.r);		dir.r = nil;		dir.nr = 0;	}	incl = nil;	nincl = w->nincl;	if(nincl > 0){		incl = emalloc(nincl*sizeof(Rune*));		for(i=0; i<nincl; i++){			n = runestrlen(w->incl[i]);			incl[i] = runemalloc(n+1);			runemove(incl[i], w->incl[i], n);		}	}	owner = w->owner;	winunlock(w);	for(;;){		w = errorwin1(dir.r, dir.nr, incl, nincl);		winlock(w, owner);		if(w->col != nil)			break;		/* window deleted too fast */		winunlock(w);	}	return w;}typedef struct Warning Warning;struct Warning{	Mntdir *md;	Buffer buf;	Warning *next;};static Warning *warnings;staticvoidaddwarningtext(Mntdir *md, Rune *r, int nr){	Warning *warn;		for(warn = warnings; warn; warn=warn->next){		if(warn->md == md){			bufinsert(&warn->buf, warn->buf.nc, r, nr);			return;		}	}	warn = emalloc(sizeof(Warning));	warn->next = warnings;	warn->md = md;	if(md)		fsysincid(md);	warnings = warn;	bufinsert(&warn->buf, 0, r, nr);	nbsendp(cwarn, 0);}/* called while row is locked */voidflushwarnings(void){	Warning *warn, *next;	Window *w;	Text *t;	int owner, nr, q0, n;	Rune *r;	for(warn=warnings; warn; warn=next) {		w = errorwin(warn->md, 'E');		t = &w->body;		owner = w->owner;		if(owner == 0)			w->owner = 'E';		wincommit(w, t);		/*		 * Most commands don't generate much output. For instance,		 * Edit ,>cat goes through /dev/cons and is already in blocks		 * because of the i/o system, but a few can.  Edit ,p will		 * put the entire result into a single hunk.  So it's worth doing		 * this in blocks (and putting the text in a buffer in the first		 * place), to avoid a big memory footprint.		 */		r = fbufalloc();		q0 = t->file->nc;		for(n = 0; n < warn->buf.nc; n += nr){			nr = warn->buf.nc - n;			if(nr > RBUFSIZE)				nr = RBUFSIZE;			bufread(&warn->buf, n, r, nr);			textbsinsert(t, t->file->nc, r, nr, TRUE, &nr);		}		textshow(t, q0, t->file->nc, 1);		free(r);		winsettag(t->w);		textscrdraw(t);		w->owner = owner;		w->dirty = FALSE;		winunlock(w);		bufclose(&warn->buf);		next = warn->next;		if(warn->md)			fsysdelid(warn->md);		free(warn);	}	warnings = nil;}voidwarning(Mntdir *md, char *s, ...){	Rune *r;	va_list arg;	va_start(arg, s);	r = runevsmprint(s, arg);	va_end(arg);	if(r == nil)		error("runevsmprint failed");	addwarningtext(md, r, runestrlen(r));}intruneeq(Rune *s1, uint n1, Rune *s2, uint n2){	if(n1 != n2)		return FALSE;	return memcmp(s1, s2, n1*sizeof(Rune)) == 0;}uintmin(uint a, uint b){	if(a < b)		return a;	return b;}uintmax(uint a, uint b){	if(a > b)		return a;	return b;}char*runetobyte(Rune *r, int n){	char *s;	if(r == nil)		return nil;	s = emalloc(n*UTFmax+1);	setmalloctag(s, getcallerpc(&r));	snprint(s, n*UTFmax+1, "%.*S", n, r);	return s;}Rune*bytetorune(char *s, int *ip){	Rune *r;	int nb, nr;	nb = strlen(s);	r = runemalloc(nb+1);	cvttorunes(s, nb, r, &nb, &nr, nil);	r[nr] = '\0';	*ip = nr;	return r;}intisalnum(Rune c){	/*	 * Hard to get absolutely right.  Use what we know about ASCII	 * and assume anything above the Latin control characters is	 * potentially an alphanumeric.	 */	if(c <= ' ')		return FALSE;	if(0x7F<=c && c<=0xA0)		return FALSE;	if(utfrune("!\"#$%&'()*+,-./:;<=>?@[\\]^`{|}~", c))		return FALSE;	return TRUE;}intrgetc(void *v, uint n){	return ((Rune*)v)[n];}inttgetc(void *a, uint n){	Text *t;	t = a;	if(n >= t->file->nc)		return 0;	return textreadc(t, n);}Rune*skipbl(Rune *r, int n, int *np){	while(n>0 && (*r==' ' || *r=='\t' || *r=='\n')){		--n;		r++;	}	*np = n;	return r;}Rune*findbl(Rune *r, int n, int *np){	while(n>0 && *r!=' ' && *r!='\t' && *r!='\n'){		--n;		r++;	}	*np = n;	return r;}voidsavemouse(Window *w){	prevmouse = mouse->xy;	mousew = w;}voidrestoremouse(Window *w){	if(mousew!=nil && mousew==w)		moveto(mousectl, prevmouse);	mousew = nil;}voidclearmouse(){	mousew = nil;}char*estrdup(char *s){	char *t;	t = strdup(s);	if(t == nil)		error("strdup failed");	setmalloctag(t, getcallerpc(&s));	return t;}void*emalloc(uint n){	void *p;	p = malloc(n);	if(p == nil)		error("malloc failed");	setmalloctag(p, getcallerpc(&n));	memset(p, 0, n);	return p;}void*erealloc(void *p, uint n){	p = realloc(p, n);	if(p == nil)		error("realloc failed");	setmalloctag(p, getcallerpc(&n));	return p;}/* * Heuristic city. */Window*makenewwindow(Text *t){	Column *c;	Window *w, *bigw, *emptyw;	Text *emptyb;	int i, y, el;	if(activecol)		c = activecol;	else if(seltext && seltext->col)		c = seltext->col;	else if(t && t->col)		c = t->col;	else{		if(row.ncol==0 && rowadd(&row, nil, -1)==nil)			error("can't make column");		c = row.col[row.ncol-1];	}	activecol = c;	if(t==nil || t->w==nil || c->nw==0)		return coladd(c, nil, nil, -1);	/* find biggest window and biggest blank spot */	emptyw = c->w[0];	bigw = emptyw;	for(i=1; i<c->nw; i++){		w = c->w[i];		/* use >= to choose one near bottom of screen */		if(w->body.maxlines >= bigw->body.maxlines)			bigw = w;		if(w->body.maxlines-w->body.nlines >= emptyw->body.maxlines-emptyw->body.nlines)			emptyw = w;	}	emptyb = &emptyw->body;	el = emptyb->maxlines-emptyb->nlines;	/* if empty space is big, use it */	if(el>15 || (el>3 && el>(bigw->body.maxlines-1)/2))		y = emptyb->r.min.y+emptyb->nlines*font->height;	else{		/* if this window is in column and isn't much smaller, split it */		if(t->col==c && Dy(t->w->r)>2*Dy(bigw->r)/3)			bigw = t->w;		y = (bigw->r.min.y + bigw->r.max.y)/2;	}	w = coladd(c, nil, nil, y);	if(w->body.maxlines < 2)		colgrow(w->col, w, 1);	return w;}

⌨️ 快捷键说明

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