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

📄 xfid.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"enum{	Ctlsize	= 5*12};char	Edel[]		= "deleted window";char	Ebadctl[]		= "ill-formed control message";char	Ebadaddr[]	= "bad address syntax";char	Eaddr[]		= "address out of range";char	Einuse[]		= "already in use";char	Ebadevent[]	= "bad event syntax";extern char Eperm[];staticvoidclampaddr(Window *w){	if(w->addr.q0 < 0)		w->addr.q0 = 0;	if(w->addr.q1 < 0)		w->addr.q1 = 0;	if(w->addr.q0 > w->body.file->nc)		w->addr.q0 = w->body.file->nc;	if(w->addr.q1 > w->body.file->nc)		w->addr.q1 = w->body.file->nc;}voidxfidctl(void *arg){	Xfid *x;	void (*f)(Xfid*);	threadsetname("xfidctlthread");	x = arg;	for(;;){		f = recvp(x->c);		(*f)(x);		flushimage(display, 1);		sendp(cxfidfree, x);	}}voidxfidflush(Xfid *x){	Fcall fc;	int i, j;	Window *w;	Column *c;	Xfid *wx;	/* search windows for matching tag */	qlock(&row);	for(j=0; j<row.ncol; j++){		c = row.col[j];		for(i=0; i<c->nw; i++){			w = c->w[i];			winlock(w, 'E');			wx = w->eventx;			if(wx!=nil && wx->tag==x->oldtag){				w->eventx = nil;				wx->flushed = TRUE;				sendp(wx->c, nil);				winunlock(w);				goto out;			}			winunlock(w);		}	}out:	qunlock(&row);	respond(x, &fc, nil);}voidxfidopen(Xfid *x){	Fcall fc;	Window *w;	Text *t;	char *s;	Rune *r;	int m, n, q, q0, q1;	w = x->f->w;	t = &w->body;	if(w){		winlock(w, 'E');		q = FILE(x->f->qid);		switch(q){		case QWaddr:			if(w->nopen[q]++ == 0){				w->addr = (Range){0,0};				w->limit = (Range){-1,-1};			}			break;		case QWdata:		case QWxdata:			w->nopen[q]++;			break;		case QWevent:			if(w->nopen[q]++ == 0){				if(!w->isdir && w->col!=nil){					w->filemenu = FALSE;					winsettag(w);				}			}			break;		case QWrdsel:			/*			 * Use a temporary file.			 * A pipe would be the obvious, but we can't afford the			 * broken pipe notification.  Using the code to read QWbody			 * is n², which should probably also be fixed.  Even then,			 * though, we'd need to squirrel away the data in case it's			 * modified during the operation, e.g. by |sort			 */			if(w->rdselfd > 0){				winunlock(w);				respond(x, &fc, Einuse);				return;			}			w->rdselfd = tempfile();			if(w->rdselfd < 0){				winunlock(w);				respond(x, &fc, "can't create temp file");				return;			}			w->nopen[q]++;			q0 = t->q0;			q1 = t->q1;			r = fbufalloc();			s = fbufalloc();			while(q0 < q1){				n = q1 - q0;				if(n > BUFSIZE/UTFmax)					n = BUFSIZE/UTFmax;				bufread(t->file, q0, r, n);				m = snprint(s, BUFSIZE+1, "%.*S", n, r);				if(write(w->rdselfd, s, m) != m){					warning(nil, "can't write temp file for pipe command %r\n");					break;				}				q0 += n;			}			fbuffree(s);			fbuffree(r);			break;		case QWwrsel:			w->nopen[q]++;			seq++;			filemark(t->file);			cut(t, t, nil, FALSE, TRUE, nil, 0);			w->wrselrange = (Range){t->q1, t->q1};			w->nomark = TRUE;			break;		case QWeditout:			if(editing == FALSE){				winunlock(w);				respond(x, &fc, Eperm);				return;			}			w->wrselrange = (Range){t->q1, t->q1};			break;		}		winunlock(w);	}	fc.qid = x->f->qid;	fc.iounit = messagesize-IOHDRSZ;	x->f->open = TRUE;	respond(x, &fc, nil);}voidxfidclose(Xfid *x){	Fcall fc;	Window *w;	int q;	Text *t;	w = x->f->w;	x->f->busy = FALSE;	if(x->f->open == FALSE){		if(w != nil)			winclose(w);		respond(x, &fc, nil);		return;	}	x->f->open = FALSE;	if(w){		winlock(w, 'E');		q = FILE(x->f->qid);		switch(q){		case QWctl:			if(w->ctlfid!=~0 && w->ctlfid==x->f->fid){				w->ctlfid = ~0;				qunlock(&w->ctllock);			}			break;		case QWdata:		case QWxdata:			w->nomark = FALSE;			/* fall through */		case QWaddr:		case QWevent:	/* BUG: do we need to shut down Xfid? */			if(--w->nopen[q] == 0){				if(q == QWdata || q == QWxdata)					w->nomark = FALSE;				if(q==QWevent && !w->isdir && w->col!=nil){					w->filemenu = TRUE;					winsettag(w);				}				if(q == QWevent){					free(w->dumpstr);					free(w->dumpdir);					w->dumpstr = nil;					w->dumpdir = nil;				}			}			break;		case QWrdsel:			close(w->rdselfd);			w->rdselfd = 0;			break;		case QWwrsel:			w->nomark = FALSE;			t = &w->body;			/* before: only did this if !w->noscroll, but that didn't seem right in practice */			textshow(t, min(w->wrselrange.q0, t->file->nc),				min(w->wrselrange.q1, t->file->nc), 1);			textscrdraw(t);			break;		}		winunlock(w);		winclose(w);	}	respond(x, &fc, nil);}voidxfidread(Xfid *x){	Fcall fc;	int n, q;	uint off;	char *b;	char buf[128];	Window *w;	q = FILE(x->f->qid);	w = x->f->w;	if(w == nil){		fc.count = 0;		switch(q){		case Qcons:		case Qlabel:			break;		case Qindex:			xfidindexread(x);			return;		default:			warning(nil, "unknown qid %d\n", q);			break;		}		respond(x, &fc, nil);		return;	}	winlock(w, 'F');	if(w->col == nil){		winunlock(w);		respond(x, &fc, Edel);		return;	}	off = x->offset;	switch(q){	case QWaddr:		textcommit(&w->body, TRUE);		clampaddr(w);		sprint(buf, "%11d %11d ", w->addr.q0, w->addr.q1);		goto Readbuf;	case QWbody:		xfidutfread(x, &w->body, w->body.file->nc, QWbody);		break;	case QWctl:		b = winctlprint(w, buf, 1);		goto Readb;	Readbuf:		b = buf;	Readb:		n = strlen(b);		if(off > n)			off = n;		if(off+x->count > n)			x->count = n-off;		fc.count = x->count;		fc.data = b+off;		respond(x, &fc, nil);		if(b != buf)			free(b);		break;	case QWevent:		xfideventread(x, w);		break;	case QWdata:		/* BUG: what should happen if q1 > q0? */		if(w->addr.q0 > w->body.file->nc){			respond(x, &fc, Eaddr);			break;		}		w->addr.q0 += xfidruneread(x, &w->body, w->addr.q0, w->body.file->nc);		w->addr.q1 = w->addr.q0;		break;	case QWxdata:		/* BUG: what should happen if q1 > q0? */		if(w->addr.q0 > w->body.file->nc){			respond(x, &fc, Eaddr);			break;		}		w->addr.q0 += xfidruneread(x, &w->body, w->addr.q0, w->addr.q1);		break;	case QWtag:		xfidutfread(x, &w->tag, w->tag.file->nc, QWtag);		break;	case QWrdsel:		seek(w->rdselfd, off, 0);		n = x->count;		if(n > BUFSIZE)			n = BUFSIZE;		b = fbufalloc();		n = read(w->rdselfd, b, n);		if(n < 0){			respond(x, &fc, "I/O error in temp file");			break;		}		fc.count = n;		fc.data = b;		respond(x, &fc, nil);		fbuffree(b);		break;	default:		sprint(buf, "unknown qid %d in read", q);		respond(x, &fc, nil);	}	winunlock(w);}voidxfidwrite(Xfid *x){	Fcall fc;	int c, cnt, qid, q, nb, nr, eval;	char buf[64], *err;	Window *w;	Rune *r;	Range a;	Text *t;	uint q0, tq0, tq1;	qid = FILE(x->f->qid);	w = x->f->w;	if(w){		c = 'F';		if(qid==QWtag || qid==QWbody)			c = 'E';		winlock(w, c);		if(w->col == nil){			winunlock(w);			respond(x, &fc, Edel);			return;		}	}	x->data[x->count] = 0;	switch(qid){	case Qcons:		w = errorwin(x->f->mntdir, 'X');		t=&w->body;		goto BodyTag;	case Qlabel:		fc.count = x->count;		respond(x, &fc, nil);		break;	case QWaddr:		x->data[x->count] = 0;		r = bytetorune(x->data, &nr);		t = &w->body;		wincommit(w, t);		eval = TRUE;		a = address(x->f->mntdir, t, w->limit, w->addr, r, 0, nr, rgetc, &eval, (uint*)&nb);		free(r);		if(nb < nr){			respond(x, &fc, Ebadaddr);			break;		}		if(!eval){			respond(x, &fc, Eaddr);			break;		}		w->addr = a;		fc.count = x->count;		respond(x, &fc, nil);		break;	case Qeditout:	case QWeditout:		r = bytetorune(x->data, &nr);		if(w)			err = edittext(w, w->wrselrange.q1, r, nr);		else			err = edittext(nil, 0, r, nr);		free(r);		if(err != nil){			respond(x, &fc, err);			break;		}		fc.count = x->count;		respond(x, &fc, nil);		break;	case QWerrors:		w = errorwinforwin(w);		t = &w->body;		goto BodyTag;	case QWbody:	case QWwrsel:		t = &w->body;		goto BodyTag;	case QWctl:		xfidctlwrite(x, w);		break;	case QWdata:		a = w->addr;		t = &w->body;		wincommit(w, t);		if(a.q0>t->file->nc || a.q1>t->file->nc){			respond(x, &fc, Eaddr);			break;		}		r = runemalloc(x->count);		cvttorunes(x->data, x->count, r, &nb, &nr, nil);		if(w->nomark == FALSE){			seq++;			filemark(t->file);		}		q0 = a.q0;		if(a.q1 > q0){			textdelete(t, q0, a.q1, TRUE);			w->addr.q1 = q0;		}		tq0 = t->q0;		tq1 = t->q1;		textinsert(t, q0, r, nr, TRUE);		if(tq0 >= q0)			tq0 += nr;		if(tq1 >= q0)			tq1 += nr;		textsetselect(t, tq0, tq1);		if(!t->w->noscroll)			textshow(t, q0, q0+nr, 0);		textscrdraw(t);		winsettag(w);		free(r);		w->addr.q0 += nr;		w->addr.q1 = w->addr.q0;		fc.count = x->count;		respond(x, &fc, nil);		break;	case QWevent:		xfideventwrite(x, w);		break;	case QWtag:		t = &w->tag;		goto BodyTag;	BodyTag:		q = x->f->nrpart;		cnt = x->count;		if(q > 0){			memmove(x->data+q, x->data, cnt);	/* there's room; see fsysproc */			memmove(x->data, x->f->rpart, q);			cnt += q;			x->f->nrpart = 0;		}		r = runemalloc(cnt);		cvttorunes(x->data, cnt-UTFmax, r, &nb, &nr, nil);		/* approach end of buffer */		while(fullrune(x->data+nb, cnt-nb)){			c = nb;			nb += chartorune(&r[nr], x->data+c);			if(r[nr])				nr++;		}		if(nb < cnt){			memmove(x->f->rpart, x->data+nb, cnt-nb);			x->f->nrpart = cnt-nb;		}		if(nr > 0){			wincommit(w, t);			if(qid == QWwrsel){				q0 = w->wrselrange.q1;				if(q0 > t->file->nc)					q0 = t->file->nc;			}else				q0 = t->file->nc;			if(qid == QWtag)				textinsert(t, q0, r, nr, TRUE);			else{

⌨️ 快捷键说明

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