Esempio n. 1
0
File: xfid.c Progetto: fr1tz/nadir
void
xfidflush(Xfid *x)
{
	Fcall fc;
	int i, j;
	Window *w;
	Column *c;
	Xfid *wx;

	/* search windows for matching tag */
	qlock(&row.lk);
	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->fcall.tag==x->fcall.oldtag){
				w->eventx = nil;
				wx->flushed = TRUE;
				sendp(wx->c, nil);
				winunlock(w);
				goto out;
			}
			winunlock(w);
		}
	}
out:
	qunlock(&row.lk);
	respond(x, &fc, nil);
}
Esempio n. 2
0
Text*
rowtype(Row *row, Rune r, Point p)
{
	Window *w;
	Text *t;

	clearmouse();
	qlock(row);
	if(bartflag)
		t = barttext;
	else
		t = rowwhich(row, p);
	if(t!=nil && !(t->what==Tag && ptinrect(p, t->scrollr))){
		w = t->w;
		if(w == nil)
			texttype(t, r);
		else{
			winlock(w, 'K');
			wintype(w, t, r);
			winunlock(w);
		}
	}
	qunlock(row);
	return t;
}
Esempio n. 3
0
void
keyboardthread(void *)
{
	Rune r;
	Timer *timer;
	Text *t;
	enum { KTimer, KKey, NKALT };
	static Alt alts[NKALT+1];

	alts[KTimer].c = nil;
	alts[KTimer].v = nil;
	alts[KTimer].op = CHANNOP;
	alts[KKey].c = keyboardctl->c;
	alts[KKey].v = &r;
	alts[KKey].op = CHANRCV;
	alts[NKALT].op = CHANEND;

	timer = nil;
	typetext = nil;
	threadsetname("keyboardthread");
	for(;;){
		switch(alt(alts)){
		case KTimer:
			timerstop(timer);
			t = typetext;
			if(t!=nil && t->what==Tag){
				winlock(t->w, 'K');
				wincommit(t->w, t);
				winunlock(t->w);
				flushimage(display, 1);
			}
			alts[KTimer].c = nil;
			alts[KTimer].op = CHANNOP;
			break;
		case KKey:
		casekeyboard:
			typetext = rowtype(&row, r, mouse->xy);
			t = typetext;
			if(t!=nil && t->col!=nil && !(r==Kdown || r==Kleft || r==Kright))	/* scrolling doesn't change activecol */
				activecol = t->col;
			if(t!=nil && t->w!=nil)
				t->w->body.file->curtext = &t->w->body;
			if(timer != nil)
				timercancel(timer);
			if(t!=nil && t->what==Tag) {
				timer = timerstart(500);
				alts[KTimer].c = timer->c;
				alts[KTimer].op = CHANRCV;
			}else{
				timer = nil;
				alts[KTimer].c = nil;
				alts[KTimer].op = CHANNOP;
			}
			if(nbrecv(keyboardctl->c, &r) > 0)
				goto casekeyboard;
			flushimage(display, 1);
			break;
		}
	}
}
Esempio n. 4
0
/*
 * 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;
}
Esempio n. 5
0
/* called while row is locked */
void
flushwarnings(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;
}
Esempio n. 6
0
/* 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;
}
Esempio n. 7
0
File: xfid.c Progetto: fr1tz/nadir
void
xfideventread(Xfid *x, Window *w)
{
	Fcall fc;
	int i, n;

	i = 0;
	x->flushed = FALSE;
	while(w->nevents == 0){
		if(i){
			if(!x->flushed)
				respond(x, &fc, "window shut down");
			return;
		}
		w->eventx = x;
		winunlock(w);
		recvp(x->c);
		winlock(w, 'F');
		i++;
	}

	n = w->nevents;
	if(n > x->fcall.count)
		n = x->fcall.count;
	fc.count = n;
	fc.data = w->events;
	respond(x, &fc, nil);
	w->nevents -= n;
	if(w->nevents){
		memmove(w->events, w->events+n, w->nevents);
		w->events = erealloc(w->events, w->nevents);
	}else{
		free(w->events);
		w->events = nil;
	}
}
Esempio n. 8
0
void
mousethread(void *v)
{
	Text *t, *argt;
	int but;
	uint q0, q1;
	Window *w;
	Plumbmsg *pm;
	Mouse m;
	char *act;
	enum { MResize, MMouse, MPlumb, MWarnings, NMALT };
	static Alt alts[NMALT+1];

	USED(v);
	threadsetname("mousethread");
	alts[MResize].c = mousectl->resizec;
	alts[MResize].v = nil;
	alts[MResize].op = CHANRCV;
	alts[MMouse].c = mousectl->c;
	alts[MMouse].v = &mousectl->m;
	alts[MMouse].op = CHANRCV;
	alts[MPlumb].c = cplumb;
	alts[MPlumb].v = &pm;
	alts[MPlumb].op = CHANRCV;
	alts[MWarnings].c = cwarn;
	alts[MWarnings].v = nil;
	alts[MWarnings].op = CHANRCV;
	if(cplumb == nil)
		alts[MPlumb].op = CHANNOP;
	alts[NMALT].op = CHANEND;

	for(;;){
		qlock(&row.lk);
		flushwarnings();
		qunlock(&row.lk);
		flushimage(display, 1);
		switch(alt(alts)){
		case MResize:
			if(getwindow(display, Refnone) < 0)
				error("attach to window");
			draw(screen, screen->r, display->white, nil, ZP);
			iconinit();
			scrlresize();
			rowresize(&row, screen->clipr);
			break;
		case MPlumb:
			if(strcmp(pm->type, "text") == 0){
				act = plumblookup(pm->attr, "action");
				if(act==nil || strcmp(act, "showfile")==0)
					plumblook(pm);
				else if(strcmp(act, "showdata")==0)
					plumbshow(pm);
			}
			plumbfree(pm);
			break;
		case MWarnings:
			break;
		case MMouse:
			/*
			 * Make a copy so decisions are consistent; mousectl changes
			 * underfoot.  Can't just receive into m because this introduces
			 * another race; see /sys/src/libdraw/mouse.c.
			 */
			m = mousectl->m;
			qlock(&row.lk);
			t = rowwhich(&row, m.xy);
			if(t!=mousetext && mousetext!=nil && mousetext->w!=nil){
				winlock(mousetext->w, 'M');
				mousetext->eq0 = ~0;
				wincommit(mousetext->w, mousetext);
				winunlock(mousetext->w);
			}
			mousetext = t;
			if(t == nil)
				goto Continue;
			w = t->w;
			if(t==nil || m.buttons==0)
				goto Continue;
			but = 0;
			if(m.buttons == 1)
				but = 1;
			else if(m.buttons == 2)
				but = 2;
			else if(m.buttons == 4)
				but = 3;
			barttext = t;
			if(t->what==Body && ptinrect(m.xy, t->scrollr)){
				if(but){
					if(swapscrollbuttons){
						if(but == 1)
							but = 3;
						else if(but == 3)
							but = 1;
					}
					winlock(w, 'M');
					t->eq0 = ~0;
					textscroll(t, but);
					winunlock(w);
				}
				goto Continue;
			}
			/* scroll buttons, wheels, etc. */
			if(w != nil && (m.buttons & (8|16))){
				if(m.buttons & 8)
					but = Kscrolloneup;
				else
					but = Kscrollonedown;
				winlock(w, 'M');
				t->eq0 = ~0;
				texttype(t, but);
				winunlock(w);
				goto Continue;
			}
			if(ptinrect(m.xy, t->scrollr)){
				if(but){
					if(t->what == Columntag)
						rowdragcol(&row, t->col, but);
					else if(t->what == Tag){
						coldragwin(t->col, t->w, but);
						if(t->w)
							barttext = &t->w->body;
					}
					if(t->col)
						activecol = t->col;
				}
				goto Continue;
			}
			if(m.buttons){
				if(w)
					winlock(w, 'M');
				t->eq0 = ~0;
				if(w)
					wincommit(w, t);
				else
					textcommit(t, TRUE);
				if(m.buttons & 1){
					textselect(t);
					if(w)
						winsettag(w);
					argtext = t;
					seltext = t;
					if(t->col)
						activecol = t->col;	/* button 1 only */
					if(t->w!=nil && t==&t->w->body)
						activewin = t->w;
				}else if(m.buttons & 2){
					if(textselect2(t, &q0, &q1, &argt))
						execute(t, q0, q1, FALSE, argt);
				}else if(m.buttons & 4){
					if(textselect3(t, &q0, &q1))
						look3(t, q0, q1, FALSE);
				}
				if(w)
					winunlock(w);
				goto Continue;
			}
    Continue:
			qunlock(&row.lk);
			break;
		}
	}
}
Esempio n. 9
0
File: xfid.c Progetto: fr1tz/nadir
void
xfidopen(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;
	q = FILE(x->f->qid);
	if(w){
		winlock(w, 'E');
		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->b, 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;
			}
			if(!canqlock(&w->editoutlk)){
				winunlock(w);
				respond(x, &fc, Einuse);
				return;
			}
			w->wrselrange = range(t->q1, t->q1);
			break;
		}
		winunlock(w);
	}
	else{
		switch(q){
		case Qeditout:
			if(!canqlock(&editoutlk)){
				respond(x, &fc, Einuse);
				return;
			}
			break;
		}
	}
	fc.qid = x->f->qid;
	fc.iounit = messagesize-IOHDRSZ;
	x->f->open = TRUE;
	respond(x, &fc, nil);
}
Esempio n. 10
0
File: xfid.c Progetto: fr1tz/nadir
void
xfidwrite(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->fcall.data[x->fcall.count] = 0;
	switch(qid){
	case Qcons:
		w = errorwin(x->f->mntdir, 'X');
		t=&w->body;
		goto BodyTag;

	case Qlabel:
		fc.count = x->fcall.count;
		respond(x, &fc, nil);
		break;

	case QWaddr:
		x->fcall.data[x->fcall.count] = 0;
		r = bytetorune(x->fcall.data, &nr);
		t = &w->body;
		wincommit(w, t);
		eval = TRUE;
		a = address(FALSE, 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->fcall.count;
		respond(x, &fc, nil);
		break;

	case Qeditout:
	case QWeditout:
		r = bytetorune(x->fcall.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->fcall.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->b.nc || a.q1>t->file->b.nc){
			respond(x, &fc, Eaddr);
			break;
		}
		r = runemalloc(x->fcall.count);
		cvttorunes(x->fcall.data, x->fcall.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->fcall.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->fcall.count;
		if(q > 0){
			memmove(x->fcall.data+q, x->fcall.data, cnt);	/* there's room; see fsysproc */
			memmove(x->fcall.data, x->f->rpart, q);
			cnt += q;
			x->f->nrpart = 0;
		}
		r = runemalloc(cnt);
		cvttorunes(x->fcall.data, cnt-UTFmax, r, &nb, &nr, nil);
		/* approach end of buffer */
		while(fullrune(x->fcall.data+nb, cnt-nb)){
			c = nb;
			nb += chartorune(&r[nr], x->fcall.data+c);
			if(r[nr])
				nr++;
		}
		if(nb < cnt){
			memmove(x->f->rpart, x->fcall.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->b.nc)
					q0 = t->file->b.nc;
			}else
				q0 = t->file->b.nc;
			if(qid == QWtag)
				textinsert(t, q0, r, nr, TRUE);
			else{
				if(w->nomark == FALSE){
					seq++;
					filemark(t->file);
				}
				q0 = textbsinsert(t, q0, r, nr, TRUE, &nr);
				textsetselect(t, t->q0, t->q1);	/* insert could leave it somewhere else */
				if(qid!=QWwrsel && !t->w->noscroll)
					textshow(t, q0+nr, q0+nr, 1);
				textscrdraw(t);
			}
			winsettag(w);
			if(qid == QWwrsel)
				w->wrselrange.q1 += nr;
			free(r);
		}
		fc.count = x->fcall.count;
		respond(x, &fc, nil);
		break;

	default:
		sprint(buf, "unknown qid %d in write", qid);
		respond(x, &fc, buf);
		break;
	}
	if(w)
		winunlock(w);
}
Esempio n. 11
0
File: xfid.c Progetto: fr1tz/nadir
void
xfidread(Xfid *x)
{
	Fcall fc;
	int n, q;
	uint off;
	char *b;
	char buf[256];
	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->fcall.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->b.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->fcall.count > n)
			x->fcall.count = n-off;
		fc.count = x->fcall.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->b.nc){
			respond(x, &fc, Eaddr);
			break;
		}
		w->addr.q0 += xfidruneread(x, &w->body, w->addr.q0, w->body.file->b.nc);
		w->addr.q1 = w->addr.q0;
		break;

	case QWxdata:
		/* BUG: what should happen if q1 > q0? */
		if(w->addr.q0 > w->body.file->b.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->b.nc, QWtag);
		break;

	case QWrdsel:
		seek(w->rdselfd, off, 0);
		n = x->fcall.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);
}
Esempio n. 12
0
File: xfid.c Progetto: fr1tz/nadir
void
xfidclose(Xfid *x)
{
	Fcall fc;
	Window *w;
	int q;
	Text *t;

	w = x->f->w;
	x->f->busy = FALSE;
	x->f->w = nil;
	if(x->f->open == FALSE){
		if(w != nil)
			winclose(w);
		respond(x, &fc, nil);
		return;
	}

	q = FILE(x->f->qid);
	x->f->open = FALSE;
	if(w){
		winlock(w, 'E');
		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->b.nc),
				min(w->wrselrange.q1, t->file->b.nc), 1);
			textscrdraw(t);
			break;
		case QWeditout:
			qunlock(&w->editoutlk);
			break;
		}
		winunlock(w);
		winclose(w);
	}
	else{
		switch(q){
		case Qeditout:
			qunlock(&editoutlk);
			break;
		}
	}
	respond(x, &fc, nil);
}
Esempio n. 13
0
void
look3(Text *t, uint q0, uint q1, int external)
{
	int n, c, f, expanded;
	Text *ct;
	Expand e;
	Rune *r;
	uint p;
	Plumbmsg *m;
	Runestr dir;
	char buf[32];

	ct = seltext;
	if(ct == nil)
		seltext = t;
	expanded = expand(t, q0, q1, &e);
	if(!external && t->w!=nil && t->w->nopen[QWevent]>0){
		/* send alphanumeric expansion to external client */
		if(expanded == FALSE)
			return;
		f = 0;
		if((e.u.at!=nil && t->w!=nil) || (e.nname>0 && lookfile(e.name, e.nname)!=nil))
			f = 1;		/* acme can do it without loading a file */
		if(q0!=e.q0 || q1!=e.q1)
			f |= 2;	/* second (post-expand) message follows */
		if(e.nname)
			f |= 4;	/* it's a file name */
		c = 'l';
		if(t->what == Body)
			c = 'L';
		n = q1-q0;
		if(n <= EVENTSIZE){
			r = runemalloc(n);
			bufread(&t->file->b, q0, r, n);
			winevent(t->w, "%c%d %d %d %d %.*S\n", c, q0, q1, f, n, n, r);
			free(r);
		}else
			winevent(t->w, "%c%d %d %d 0 \n", c, q0, q1, f, n);
		if(q0==e.q0 && q1==e.q1)
			return;
		if(e.nname){
			n = e.nname;
			if(e.a1 > e.a0)
				n += 1+(e.a1-e.a0);
			r = runemalloc(n);
			runemove(r, e.name, e.nname);
			if(e.a1 > e.a0){
				r[e.nname] = ':';
				bufread(&e.u.at->file->b, e.a0, r+e.nname+1, e.a1-e.a0);
			}
		}else{
			n = e.q1 - e.q0;
			r = runemalloc(n);
			bufread(&t->file->b, e.q0, r, n);
		}
		f &= ~2;
		if(n <= EVENTSIZE)
			winevent(t->w, "%c%d %d %d %d %.*S\n", c, e.q0, e.q1, f, n, n, r);
		else
			winevent(t->w, "%c%d %d %d 0 \n", c, e.q0, e.q1, f, n);
		free(r);
		goto Return;
	}
	if(plumbsendfid != nil){
		/* send whitespace-delimited word to plumber */
		m = emalloc(sizeof(Plumbmsg));
		m->src = estrdup("acme");
		m->dst = nil;
		dir = dirname(t, nil, 0);
		if(dir.nr==1 && dir.r[0]=='.'){	/* sigh */
			free(dir.r);
			dir.r = nil;
			dir.nr = 0;
		}
		if(dir.nr == 0)
			m->wdir = estrdup(wdir);
		else
			m->wdir = runetobyte(dir.r, dir.nr);
		free(dir.r);
		m->type = estrdup("text");
		m->attr = nil;
		buf[0] = '\0';
		if(q1 == q0){
			if(t->q1>t->q0 && t->q0<=q0 && q0<=t->q1){
				q0 = t->q0;
				q1 = t->q1;
			}else{
				p = q0;
				while(q0>0 && (c=tgetc(t, q0-1))!=' ' && c!='\t' && c!='\n')
					q0--;
				while(q1<t->file->b.nc && (c=tgetc(t, q1))!=' ' && c!='\t' && c!='\n')
					q1++;
				if(q1 == q0){
					plumbfree(m);
					goto Return;
				}
				sprint(buf, "click=%d", p-q0);
				m->attr = plumbunpackattr(buf);
			}
		}
		r = runemalloc(q1-q0);
		bufread(&t->file->b, q0, r, q1-q0);
		m->data = runetobyte(r, q1-q0);
		m->ndata = strlen(m->data);
		free(r);
		if(m->ndata<messagesize-1024 && plumbsendtofid(plumbsendfid, m) >= 0){
			plumbfree(m);
			goto Return;
		}
		plumbfree(m);
		/* plumber failed to match; fall through */
	}

	/* interpret alphanumeric string ourselves */
	if(expanded == FALSE)
		return;
	if(e.name || e.u.at)
		openfile(t, &e);
	else{
		if(t->w == nil)
			return;
		ct = &t->w->body;
		if(t->w != ct->w)
			winlock(ct->w, 'M');
		if(t == ct)
			textsetselect(ct, e.q1, e.q1);
		n = e.q1 - e.q0;
		r = runemalloc(n);
		bufread(&t->file->b, e.q0, r, n);
		if(search(ct, r, n) && e.jump)
			moveto(mousectl, addpt(frptofchar(&ct->fr, ct->fr.p0), Pt(4, ct->fr.font->height-4)));
		if(t->w != ct->w)
			winunlock(ct->w);
		free(r);
	}

   Return:
	free(e.name);
	free(e.bname);
}