17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <draw.h>
47dd7cddfSDavid du Colombier #include <thread.h>
59a747e4fSDavid du Colombier #include <cursor.h>
67dd7cddfSDavid du Colombier #include <mouse.h>
77dd7cddfSDavid du Colombier #include <keyboard.h>
87dd7cddfSDavid du Colombier #include <frame.h>
97dd7cddfSDavid du Colombier #include <fcall.h>
107dd7cddfSDavid du Colombier #include <plumb.h>
117dd7cddfSDavid du Colombier #include "dat.h"
127dd7cddfSDavid du Colombier #include "fns.h"
137dd7cddfSDavid du Colombier
147dd7cddfSDavid du Colombier enum
157dd7cddfSDavid du Colombier {
167dd7cddfSDavid du Colombier Ctlsize = 5*12
177dd7cddfSDavid du Colombier };
187dd7cddfSDavid du Colombier
197dd7cddfSDavid du Colombier char Edel[] = "deleted window";
207dd7cddfSDavid du Colombier char Ebadctl[] = "ill-formed control message";
217dd7cddfSDavid du Colombier char Ebadaddr[] = "bad address syntax";
227dd7cddfSDavid du Colombier char Eaddr[] = "address out of range";
237dd7cddfSDavid du Colombier char Einuse[] = "already in use";
247dd7cddfSDavid du Colombier char Ebadevent[] = "bad event syntax";
2559cc4ca5SDavid du Colombier extern char Eperm[];
267dd7cddfSDavid du Colombier
277dd7cddfSDavid du Colombier static
287dd7cddfSDavid du Colombier void
clampaddr(Window * w)297dd7cddfSDavid du Colombier clampaddr(Window *w)
307dd7cddfSDavid du Colombier {
317dd7cddfSDavid du Colombier if(w->addr.q0 < 0)
327dd7cddfSDavid du Colombier w->addr.q0 = 0;
337dd7cddfSDavid du Colombier if(w->addr.q1 < 0)
347dd7cddfSDavid du Colombier w->addr.q1 = 0;
357dd7cddfSDavid du Colombier if(w->addr.q0 > w->body.file->nc)
367dd7cddfSDavid du Colombier w->addr.q0 = w->body.file->nc;
377dd7cddfSDavid du Colombier if(w->addr.q1 > w->body.file->nc)
387dd7cddfSDavid du Colombier w->addr.q1 = w->body.file->nc;
397dd7cddfSDavid du Colombier }
407dd7cddfSDavid du Colombier
417dd7cddfSDavid du Colombier void
xfidctl(void * arg)427dd7cddfSDavid du Colombier xfidctl(void *arg)
437dd7cddfSDavid du Colombier {
447dd7cddfSDavid du Colombier Xfid *x;
457dd7cddfSDavid du Colombier void (*f)(Xfid*);
467dd7cddfSDavid du Colombier
477dd7cddfSDavid du Colombier threadsetname("xfidctlthread");
487dd7cddfSDavid du Colombier x = arg;
497dd7cddfSDavid du Colombier for(;;){
507dd7cddfSDavid du Colombier f = recvp(x->c);
517dd7cddfSDavid du Colombier (*f)(x);
527dd7cddfSDavid du Colombier flushimage(display, 1);
537dd7cddfSDavid du Colombier sendp(cxfidfree, x);
547dd7cddfSDavid du Colombier }
557dd7cddfSDavid du Colombier }
567dd7cddfSDavid du Colombier
577dd7cddfSDavid du Colombier void
xfidflush(Xfid * x)587dd7cddfSDavid du Colombier xfidflush(Xfid *x)
597dd7cddfSDavid du Colombier {
607dd7cddfSDavid du Colombier Fcall fc;
617dd7cddfSDavid du Colombier int i, j;
627dd7cddfSDavid du Colombier Window *w;
637dd7cddfSDavid du Colombier Column *c;
647dd7cddfSDavid du Colombier Xfid *wx;
657dd7cddfSDavid du Colombier
667dd7cddfSDavid du Colombier /* search windows for matching tag */
677dd7cddfSDavid du Colombier qlock(&row);
687dd7cddfSDavid du Colombier for(j=0; j<row.ncol; j++){
697dd7cddfSDavid du Colombier c = row.col[j];
707dd7cddfSDavid du Colombier for(i=0; i<c->nw; i++){
717dd7cddfSDavid du Colombier w = c->w[i];
727dd7cddfSDavid du Colombier winlock(w, 'E');
737dd7cddfSDavid du Colombier wx = w->eventx;
747dd7cddfSDavid du Colombier if(wx!=nil && wx->tag==x->oldtag){
757dd7cddfSDavid du Colombier w->eventx = nil;
767dd7cddfSDavid du Colombier wx->flushed = TRUE;
777dd7cddfSDavid du Colombier sendp(wx->c, nil);
787dd7cddfSDavid du Colombier winunlock(w);
797dd7cddfSDavid du Colombier goto out;
807dd7cddfSDavid du Colombier }
817dd7cddfSDavid du Colombier winunlock(w);
827dd7cddfSDavid du Colombier }
837dd7cddfSDavid du Colombier }
847dd7cddfSDavid du Colombier out:
857dd7cddfSDavid du Colombier qunlock(&row);
867dd7cddfSDavid du Colombier respond(x, &fc, nil);
877dd7cddfSDavid du Colombier }
887dd7cddfSDavid du Colombier
897dd7cddfSDavid du Colombier void
xfidopen(Xfid * x)907dd7cddfSDavid du Colombier xfidopen(Xfid *x)
917dd7cddfSDavid du Colombier {
927dd7cddfSDavid du Colombier Fcall fc;
937dd7cddfSDavid du Colombier Window *w;
947dd7cddfSDavid du Colombier Text *t;
957dd7cddfSDavid du Colombier char *s;
967dd7cddfSDavid du Colombier Rune *r;
977dd7cddfSDavid du Colombier int m, n, q, q0, q1;
987dd7cddfSDavid du Colombier
997dd7cddfSDavid du Colombier w = x->f->w;
1007dd7cddfSDavid du Colombier t = &w->body;
1017dd7cddfSDavid du Colombier if(w){
1027dd7cddfSDavid du Colombier winlock(w, 'E');
1037dd7cddfSDavid du Colombier q = FILE(x->f->qid);
1047dd7cddfSDavid du Colombier switch(q){
1057dd7cddfSDavid du Colombier case QWaddr:
1067dd7cddfSDavid du Colombier if(w->nopen[q]++ == 0){
1077dd7cddfSDavid du Colombier w->addr = (Range){0,0};
1087dd7cddfSDavid du Colombier w->limit = (Range){-1,-1};
1097dd7cddfSDavid du Colombier }
1107dd7cddfSDavid du Colombier break;
1117dd7cddfSDavid du Colombier case QWdata:
112673c3d8aSDavid du Colombier case QWxdata:
1137dd7cddfSDavid du Colombier w->nopen[q]++;
1147dd7cddfSDavid du Colombier break;
1157dd7cddfSDavid du Colombier case QWevent:
1167dd7cddfSDavid du Colombier if(w->nopen[q]++ == 0){
1177dd7cddfSDavid du Colombier if(!w->isdir && w->col!=nil){
1187dd7cddfSDavid du Colombier w->filemenu = FALSE;
1197dd7cddfSDavid du Colombier winsettag(w);
1207dd7cddfSDavid du Colombier }
1217dd7cddfSDavid du Colombier }
1227dd7cddfSDavid du Colombier break;
1237dd7cddfSDavid du Colombier case QWrdsel:
1247dd7cddfSDavid du Colombier /*
1257dd7cddfSDavid du Colombier * Use a temporary file.
1267dd7cddfSDavid du Colombier * A pipe would be the obvious, but we can't afford the
1277dd7cddfSDavid du Colombier * broken pipe notification. Using the code to read QWbody
1287dd7cddfSDavid du Colombier * is n², which should probably also be fixed. Even then,
1297dd7cddfSDavid du Colombier * though, we'd need to squirrel away the data in case it's
1307dd7cddfSDavid du Colombier * modified during the operation, e.g. by |sort
1317dd7cddfSDavid du Colombier */
1327dd7cddfSDavid du Colombier if(w->rdselfd > 0){
1337dd7cddfSDavid du Colombier winunlock(w);
1347dd7cddfSDavid du Colombier respond(x, &fc, Einuse);
1357dd7cddfSDavid du Colombier return;
1367dd7cddfSDavid du Colombier }
1377dd7cddfSDavid du Colombier w->rdselfd = tempfile();
1387dd7cddfSDavid du Colombier if(w->rdselfd < 0){
1397dd7cddfSDavid du Colombier winunlock(w);
1407dd7cddfSDavid du Colombier respond(x, &fc, "can't create temp file");
1417dd7cddfSDavid du Colombier return;
1427dd7cddfSDavid du Colombier }
1437dd7cddfSDavid du Colombier w->nopen[q]++;
1447dd7cddfSDavid du Colombier q0 = t->q0;
1457dd7cddfSDavid du Colombier q1 = t->q1;
1467dd7cddfSDavid du Colombier r = fbufalloc();
1477dd7cddfSDavid du Colombier s = fbufalloc();
1487dd7cddfSDavid du Colombier while(q0 < q1){
1497dd7cddfSDavid du Colombier n = q1 - q0;
1507dd7cddfSDavid du Colombier if(n > BUFSIZE/UTFmax)
1517dd7cddfSDavid du Colombier n = BUFSIZE/UTFmax;
1527dd7cddfSDavid du Colombier bufread(t->file, q0, r, n);
1537dd7cddfSDavid du Colombier m = snprint(s, BUFSIZE+1, "%.*S", n, r);
1547dd7cddfSDavid du Colombier if(write(w->rdselfd, s, m) != m){
1557dd7cddfSDavid du Colombier warning(nil, "can't write temp file for pipe command %r\n");
1567dd7cddfSDavid du Colombier break;
1577dd7cddfSDavid du Colombier }
1587dd7cddfSDavid du Colombier q0 += n;
1597dd7cddfSDavid du Colombier }
1607dd7cddfSDavid du Colombier fbuffree(s);
1617dd7cddfSDavid du Colombier fbuffree(r);
1627dd7cddfSDavid du Colombier break;
1637dd7cddfSDavid du Colombier case QWwrsel:
1647dd7cddfSDavid du Colombier w->nopen[q]++;
1657dd7cddfSDavid du Colombier seq++;
1667dd7cddfSDavid du Colombier filemark(t->file);
1677dd7cddfSDavid du Colombier cut(t, t, nil, FALSE, TRUE, nil, 0);
1687dd7cddfSDavid du Colombier w->wrselrange = (Range){t->q1, t->q1};
1697dd7cddfSDavid du Colombier w->nomark = TRUE;
1707dd7cddfSDavid du Colombier break;
17159cc4ca5SDavid du Colombier case QWeditout:
17259cc4ca5SDavid du Colombier if(editing == FALSE){
17359cc4ca5SDavid du Colombier winunlock(w);
17459cc4ca5SDavid du Colombier respond(x, &fc, Eperm);
17559cc4ca5SDavid du Colombier return;
17659cc4ca5SDavid du Colombier }
17759cc4ca5SDavid du Colombier w->wrselrange = (Range){t->q1, t->q1};
17859cc4ca5SDavid du Colombier break;
1797dd7cddfSDavid du Colombier }
1807dd7cddfSDavid du Colombier winunlock(w);
1817dd7cddfSDavid du Colombier }
1827dd7cddfSDavid du Colombier fc.qid = x->f->qid;
1839a747e4fSDavid du Colombier fc.iounit = messagesize-IOHDRSZ;
1847dd7cddfSDavid du Colombier x->f->open = TRUE;
1857dd7cddfSDavid du Colombier respond(x, &fc, nil);
1867dd7cddfSDavid du Colombier }
1877dd7cddfSDavid du Colombier
1887dd7cddfSDavid du Colombier void
xfidclose(Xfid * x)1897dd7cddfSDavid du Colombier xfidclose(Xfid *x)
1907dd7cddfSDavid du Colombier {
1917dd7cddfSDavid du Colombier Fcall fc;
1927dd7cddfSDavid du Colombier Window *w;
1937dd7cddfSDavid du Colombier int q;
1947dd7cddfSDavid du Colombier Text *t;
1957dd7cddfSDavid du Colombier
1967dd7cddfSDavid du Colombier w = x->f->w;
1977dd7cddfSDavid du Colombier x->f->busy = FALSE;
1987dd7cddfSDavid du Colombier if(x->f->open == FALSE){
1997dd7cddfSDavid du Colombier if(w != nil)
2007dd7cddfSDavid du Colombier winclose(w);
2017dd7cddfSDavid du Colombier respond(x, &fc, nil);
2027dd7cddfSDavid du Colombier return;
2037dd7cddfSDavid du Colombier }
2047dd7cddfSDavid du Colombier
2057dd7cddfSDavid du Colombier x->f->open = FALSE;
2067dd7cddfSDavid du Colombier if(w){
2077dd7cddfSDavid du Colombier winlock(w, 'E');
2087dd7cddfSDavid du Colombier q = FILE(x->f->qid);
2097dd7cddfSDavid du Colombier switch(q){
2107dd7cddfSDavid du Colombier case QWctl:
2117dd7cddfSDavid du Colombier if(w->ctlfid!=~0 && w->ctlfid==x->f->fid){
2127dd7cddfSDavid du Colombier w->ctlfid = ~0;
2137dd7cddfSDavid du Colombier qunlock(&w->ctllock);
2147dd7cddfSDavid du Colombier }
2157dd7cddfSDavid du Colombier break;
2167dd7cddfSDavid du Colombier case QWdata:
217673c3d8aSDavid du Colombier case QWxdata:
2187dd7cddfSDavid du Colombier w->nomark = FALSE;
2197dd7cddfSDavid du Colombier /* fall through */
2207dd7cddfSDavid du Colombier case QWaddr:
2217dd7cddfSDavid du Colombier case QWevent: /* BUG: do we need to shut down Xfid? */
2227dd7cddfSDavid du Colombier if(--w->nopen[q] == 0){
223673c3d8aSDavid du Colombier if(q == QWdata || q == QWxdata)
2247dd7cddfSDavid du Colombier w->nomark = FALSE;
2257dd7cddfSDavid du Colombier if(q==QWevent && !w->isdir && w->col!=nil){
2267dd7cddfSDavid du Colombier w->filemenu = TRUE;
2277dd7cddfSDavid du Colombier winsettag(w);
2287dd7cddfSDavid du Colombier }
2297dd7cddfSDavid du Colombier if(q == QWevent){
2307dd7cddfSDavid du Colombier free(w->dumpstr);
2317dd7cddfSDavid du Colombier free(w->dumpdir);
2327dd7cddfSDavid du Colombier w->dumpstr = nil;
2337dd7cddfSDavid du Colombier w->dumpdir = nil;
2347dd7cddfSDavid du Colombier }
2357dd7cddfSDavid du Colombier }
2367dd7cddfSDavid du Colombier break;
2377dd7cddfSDavid du Colombier case QWrdsel:
2387dd7cddfSDavid du Colombier close(w->rdselfd);
2397dd7cddfSDavid du Colombier w->rdselfd = 0;
2407dd7cddfSDavid du Colombier break;
2417dd7cddfSDavid du Colombier case QWwrsel:
2427dd7cddfSDavid du Colombier w->nomark = FALSE;
2437dd7cddfSDavid du Colombier t = &w->body;
2447dd7cddfSDavid du Colombier /* before: only did this if !w->noscroll, but that didn't seem right in practice */
2457dd7cddfSDavid du Colombier textshow(t, min(w->wrselrange.q0, t->file->nc),
2469a747e4fSDavid du Colombier min(w->wrselrange.q1, t->file->nc), 1);
2477dd7cddfSDavid du Colombier textscrdraw(t);
2487dd7cddfSDavid du Colombier break;
2497dd7cddfSDavid du Colombier }
2507dd7cddfSDavid du Colombier winunlock(w);
2517dd7cddfSDavid du Colombier winclose(w);
2527dd7cddfSDavid du Colombier }
2537dd7cddfSDavid du Colombier respond(x, &fc, nil);
2547dd7cddfSDavid du Colombier }
2557dd7cddfSDavid du Colombier
2567dd7cddfSDavid du Colombier void
xfidread(Xfid * x)2577dd7cddfSDavid du Colombier xfidread(Xfid *x)
2587dd7cddfSDavid du Colombier {
2597dd7cddfSDavid du Colombier Fcall fc;
2607dd7cddfSDavid du Colombier int n, q;
2617dd7cddfSDavid du Colombier uint off;
2627dd7cddfSDavid du Colombier char *b;
263*9b7bf7dfSDavid du Colombier char buf[256];
2647dd7cddfSDavid du Colombier Window *w;
2657dd7cddfSDavid du Colombier
2667dd7cddfSDavid du Colombier q = FILE(x->f->qid);
2677dd7cddfSDavid du Colombier w = x->f->w;
2687dd7cddfSDavid du Colombier if(w == nil){
2697dd7cddfSDavid du Colombier fc.count = 0;
2707dd7cddfSDavid du Colombier switch(q){
2717dd7cddfSDavid du Colombier case Qcons:
2727dd7cddfSDavid du Colombier case Qlabel:
2737dd7cddfSDavid du Colombier break;
2747dd7cddfSDavid du Colombier case Qindex:
2757dd7cddfSDavid du Colombier xfidindexread(x);
2767dd7cddfSDavid du Colombier return;
2777dd7cddfSDavid du Colombier default:
2787dd7cddfSDavid du Colombier warning(nil, "unknown qid %d\n", q);
2797dd7cddfSDavid du Colombier break;
2807dd7cddfSDavid du Colombier }
2817dd7cddfSDavid du Colombier respond(x, &fc, nil);
2827dd7cddfSDavid du Colombier return;
2837dd7cddfSDavid du Colombier }
2847dd7cddfSDavid du Colombier winlock(w, 'F');
2857dd7cddfSDavid du Colombier if(w->col == nil){
2867dd7cddfSDavid du Colombier winunlock(w);
2877dd7cddfSDavid du Colombier respond(x, &fc, Edel);
2887dd7cddfSDavid du Colombier return;
2897dd7cddfSDavid du Colombier }
2907dd7cddfSDavid du Colombier off = x->offset;
2917dd7cddfSDavid du Colombier switch(q){
2927dd7cddfSDavid du Colombier case QWaddr:
2937dd7cddfSDavid du Colombier textcommit(&w->body, TRUE);
2947dd7cddfSDavid du Colombier clampaddr(w);
2957dd7cddfSDavid du Colombier sprint(buf, "%11d %11d ", w->addr.q0, w->addr.q1);
2967dd7cddfSDavid du Colombier goto Readbuf;
2977dd7cddfSDavid du Colombier
2987dd7cddfSDavid du Colombier case QWbody:
2997dd7cddfSDavid du Colombier xfidutfread(x, &w->body, w->body.file->nc, QWbody);
3007dd7cddfSDavid du Colombier break;
3017dd7cddfSDavid du Colombier
3027dd7cddfSDavid du Colombier case QWctl:
3038a2c5ad0SDavid du Colombier b = winctlprint(w, buf, 1);
3048a2c5ad0SDavid du Colombier goto Readb;
3057dd7cddfSDavid du Colombier
3067dd7cddfSDavid du Colombier Readbuf:
3078a2c5ad0SDavid du Colombier b = buf;
3088a2c5ad0SDavid du Colombier Readb:
3098a2c5ad0SDavid du Colombier n = strlen(b);
3107dd7cddfSDavid du Colombier if(off > n)
3117dd7cddfSDavid du Colombier off = n;
3127dd7cddfSDavid du Colombier if(off+x->count > n)
3137dd7cddfSDavid du Colombier x->count = n-off;
3147dd7cddfSDavid du Colombier fc.count = x->count;
3158a2c5ad0SDavid du Colombier fc.data = b+off;
3167dd7cddfSDavid du Colombier respond(x, &fc, nil);
3178a2c5ad0SDavid du Colombier if(b != buf)
3188a2c5ad0SDavid du Colombier free(b);
3197dd7cddfSDavid du Colombier break;
3207dd7cddfSDavid du Colombier
3217dd7cddfSDavid du Colombier case QWevent:
3227dd7cddfSDavid du Colombier xfideventread(x, w);
3237dd7cddfSDavid du Colombier break;
3247dd7cddfSDavid du Colombier
3257dd7cddfSDavid du Colombier case QWdata:
3267dd7cddfSDavid du Colombier /* BUG: what should happen if q1 > q0? */
3277dd7cddfSDavid du Colombier if(w->addr.q0 > w->body.file->nc){
3287dd7cddfSDavid du Colombier respond(x, &fc, Eaddr);
3297dd7cddfSDavid du Colombier break;
3307dd7cddfSDavid du Colombier }
3317dd7cddfSDavid du Colombier w->addr.q0 += xfidruneread(x, &w->body, w->addr.q0, w->body.file->nc);
3327dd7cddfSDavid du Colombier w->addr.q1 = w->addr.q0;
3337dd7cddfSDavid du Colombier break;
3347dd7cddfSDavid du Colombier
335673c3d8aSDavid du Colombier case QWxdata:
336673c3d8aSDavid du Colombier /* BUG: what should happen if q1 > q0? */
337673c3d8aSDavid du Colombier if(w->addr.q0 > w->body.file->nc){
338673c3d8aSDavid du Colombier respond(x, &fc, Eaddr);
339673c3d8aSDavid du Colombier break;
340673c3d8aSDavid du Colombier }
341673c3d8aSDavid du Colombier w->addr.q0 += xfidruneread(x, &w->body, w->addr.q0, w->addr.q1);
342673c3d8aSDavid du Colombier break;
343673c3d8aSDavid du Colombier
3447dd7cddfSDavid du Colombier case QWtag:
3457dd7cddfSDavid du Colombier xfidutfread(x, &w->tag, w->tag.file->nc, QWtag);
3467dd7cddfSDavid du Colombier break;
3477dd7cddfSDavid du Colombier
3487dd7cddfSDavid du Colombier case QWrdsel:
3497dd7cddfSDavid du Colombier seek(w->rdselfd, off, 0);
3507dd7cddfSDavid du Colombier n = x->count;
3517dd7cddfSDavid du Colombier if(n > BUFSIZE)
3527dd7cddfSDavid du Colombier n = BUFSIZE;
3537dd7cddfSDavid du Colombier b = fbufalloc();
3547dd7cddfSDavid du Colombier n = read(w->rdselfd, b, n);
3557dd7cddfSDavid du Colombier if(n < 0){
3567dd7cddfSDavid du Colombier respond(x, &fc, "I/O error in temp file");
3577dd7cddfSDavid du Colombier break;
3587dd7cddfSDavid du Colombier }
3597dd7cddfSDavid du Colombier fc.count = n;
3607dd7cddfSDavid du Colombier fc.data = b;
3617dd7cddfSDavid du Colombier respond(x, &fc, nil);
3627dd7cddfSDavid du Colombier fbuffree(b);
3637dd7cddfSDavid du Colombier break;
3647dd7cddfSDavid du Colombier
3657dd7cddfSDavid du Colombier default:
3667dd7cddfSDavid du Colombier sprint(buf, "unknown qid %d in read", q);
3677dd7cddfSDavid du Colombier respond(x, &fc, nil);
3687dd7cddfSDavid du Colombier }
3697dd7cddfSDavid du Colombier winunlock(w);
3707dd7cddfSDavid du Colombier }
3717dd7cddfSDavid du Colombier
372*9b7bf7dfSDavid du Colombier static Rune*
fullrunewrite(Xfid * x,int * inr)373*9b7bf7dfSDavid du Colombier fullrunewrite(Xfid *x, int *inr)
374*9b7bf7dfSDavid du Colombier {
375*9b7bf7dfSDavid du Colombier int q, cnt, c, nb, nr;
376*9b7bf7dfSDavid du Colombier Rune *r;
377*9b7bf7dfSDavid du Colombier
378*9b7bf7dfSDavid du Colombier q = x->f->nrpart;
379*9b7bf7dfSDavid du Colombier cnt = x->count;
380*9b7bf7dfSDavid du Colombier if(q > 0){
381*9b7bf7dfSDavid du Colombier memmove(x->data+q, x->data, cnt); /* there's room; see fsysproc */
382*9b7bf7dfSDavid du Colombier memmove(x->data, x->f->rpart, q);
383*9b7bf7dfSDavid du Colombier cnt += q;
384*9b7bf7dfSDavid du Colombier x->f->nrpart = 0;
385*9b7bf7dfSDavid du Colombier }
386*9b7bf7dfSDavid du Colombier r = runemalloc(cnt);
387*9b7bf7dfSDavid du Colombier cvttorunes(x->data, cnt-UTFmax, r, &nb, &nr, nil);
388*9b7bf7dfSDavid du Colombier /* approach end of buffer */
389*9b7bf7dfSDavid du Colombier while(fullrune(x->data+nb, cnt-nb)){
390*9b7bf7dfSDavid du Colombier c = nb;
391*9b7bf7dfSDavid du Colombier nb += chartorune(&r[nr], x->data+c);
392*9b7bf7dfSDavid du Colombier if(r[nr])
393*9b7bf7dfSDavid du Colombier nr++;
394*9b7bf7dfSDavid du Colombier }
395*9b7bf7dfSDavid du Colombier if(nb < cnt){
396*9b7bf7dfSDavid du Colombier memmove(x->f->rpart, x->data+nb, cnt-nb);
397*9b7bf7dfSDavid du Colombier x->f->nrpart = cnt-nb;
398*9b7bf7dfSDavid du Colombier }
399*9b7bf7dfSDavid du Colombier *inr = nr;
400*9b7bf7dfSDavid du Colombier return r;
401*9b7bf7dfSDavid du Colombier }
402*9b7bf7dfSDavid du Colombier
4037dd7cddfSDavid du Colombier void
xfidwrite(Xfid * x)4047dd7cddfSDavid du Colombier xfidwrite(Xfid *x)
4057dd7cddfSDavid du Colombier {
4067dd7cddfSDavid du Colombier Fcall fc;
407*9b7bf7dfSDavid du Colombier int c, qid, nb, nr, eval;
4089a747e4fSDavid du Colombier char buf[64], *err;
4097dd7cddfSDavid du Colombier Window *w;
4107dd7cddfSDavid du Colombier Rune *r;
4117dd7cddfSDavid du Colombier Range a;
4127dd7cddfSDavid du Colombier Text *t;
4137dd7cddfSDavid du Colombier uint q0, tq0, tq1;
4147dd7cddfSDavid du Colombier
4157dd7cddfSDavid du Colombier qid = FILE(x->f->qid);
4167dd7cddfSDavid du Colombier w = x->f->w;
4177dd7cddfSDavid du Colombier if(w){
4187dd7cddfSDavid du Colombier c = 'F';
4197dd7cddfSDavid du Colombier if(qid==QWtag || qid==QWbody)
4207dd7cddfSDavid du Colombier c = 'E';
4217dd7cddfSDavid du Colombier winlock(w, c);
4227dd7cddfSDavid du Colombier if(w->col == nil){
4237dd7cddfSDavid du Colombier winunlock(w);
4247dd7cddfSDavid du Colombier respond(x, &fc, Edel);
4257dd7cddfSDavid du Colombier return;
4267dd7cddfSDavid du Colombier }
4277dd7cddfSDavid du Colombier }
4287dd7cddfSDavid du Colombier x->data[x->count] = 0;
4297dd7cddfSDavid du Colombier switch(qid){
4307dd7cddfSDavid du Colombier case Qcons:
4314fec87e5SDavid du Colombier w = errorwin(x->f->mntdir, 'X');
4323ff48bf5SDavid du Colombier t=&w->body;
4333ff48bf5SDavid du Colombier goto BodyTag;
4343ff48bf5SDavid du Colombier
4357dd7cddfSDavid du Colombier case Qlabel:
4367dd7cddfSDavid du Colombier fc.count = x->count;
4377dd7cddfSDavid du Colombier respond(x, &fc, nil);
4387dd7cddfSDavid du Colombier break;
4397dd7cddfSDavid du Colombier
4407dd7cddfSDavid du Colombier case QWaddr:
4417dd7cddfSDavid du Colombier x->data[x->count] = 0;
4427dd7cddfSDavid du Colombier r = bytetorune(x->data, &nr);
4437dd7cddfSDavid du Colombier t = &w->body;
4447dd7cddfSDavid du Colombier wincommit(w, t);
4457dd7cddfSDavid du Colombier eval = TRUE;
44659cc4ca5SDavid du Colombier a = address(x->f->mntdir, t, w->limit, w->addr, r, 0, nr, rgetc, &eval, (uint*)&nb);
4477dd7cddfSDavid du Colombier free(r);
4487dd7cddfSDavid du Colombier if(nb < nr){
4497dd7cddfSDavid du Colombier respond(x, &fc, Ebadaddr);
4507dd7cddfSDavid du Colombier break;
4517dd7cddfSDavid du Colombier }
4527dd7cddfSDavid du Colombier if(!eval){
4537dd7cddfSDavid du Colombier respond(x, &fc, Eaddr);
4547dd7cddfSDavid du Colombier break;
4557dd7cddfSDavid du Colombier }
4567dd7cddfSDavid du Colombier w->addr = a;
4577dd7cddfSDavid du Colombier fc.count = x->count;
4587dd7cddfSDavid du Colombier respond(x, &fc, nil);
4597dd7cddfSDavid du Colombier break;
4607dd7cddfSDavid du Colombier
46159cc4ca5SDavid du Colombier case Qeditout:
46259cc4ca5SDavid du Colombier case QWeditout:
463*9b7bf7dfSDavid du Colombier r = fullrunewrite(x, &nr);
46459cc4ca5SDavid du Colombier if(w)
465e288d156SDavid du Colombier err = edittext(w, w->wrselrange.q1, r, nr);
46659cc4ca5SDavid du Colombier else
46759cc4ca5SDavid du Colombier err = edittext(nil, 0, r, nr);
46859cc4ca5SDavid du Colombier free(r);
46959cc4ca5SDavid du Colombier if(err != nil){
47059cc4ca5SDavid du Colombier respond(x, &fc, err);
47159cc4ca5SDavid du Colombier break;
47259cc4ca5SDavid du Colombier }
47359cc4ca5SDavid du Colombier fc.count = x->count;
47459cc4ca5SDavid du Colombier respond(x, &fc, nil);
47559cc4ca5SDavid du Colombier break;
47659cc4ca5SDavid du Colombier
477673c3d8aSDavid du Colombier case QWerrors:
478673c3d8aSDavid du Colombier w = errorwinforwin(w);
479673c3d8aSDavid du Colombier t = &w->body;
480673c3d8aSDavid du Colombier goto BodyTag;
481673c3d8aSDavid du Colombier
4827dd7cddfSDavid du Colombier case QWbody:
4837dd7cddfSDavid du Colombier case QWwrsel:
4847dd7cddfSDavid du Colombier t = &w->body;
4857dd7cddfSDavid du Colombier goto BodyTag;
4867dd7cddfSDavid du Colombier
4877dd7cddfSDavid du Colombier case QWctl:
4887dd7cddfSDavid du Colombier xfidctlwrite(x, w);
4897dd7cddfSDavid du Colombier break;
4907dd7cddfSDavid du Colombier
4917dd7cddfSDavid du Colombier case QWdata:
4927dd7cddfSDavid du Colombier a = w->addr;
4937dd7cddfSDavid du Colombier t = &w->body;
4947dd7cddfSDavid du Colombier wincommit(w, t);
4957dd7cddfSDavid du Colombier if(a.q0>t->file->nc || a.q1>t->file->nc){
4967dd7cddfSDavid du Colombier respond(x, &fc, Eaddr);
4977dd7cddfSDavid du Colombier break;
4987dd7cddfSDavid du Colombier }
4997dd7cddfSDavid du Colombier r = runemalloc(x->count);
5007dd7cddfSDavid du Colombier cvttorunes(x->data, x->count, r, &nb, &nr, nil);
5017dd7cddfSDavid du Colombier if(w->nomark == FALSE){
5027dd7cddfSDavid du Colombier seq++;
5037dd7cddfSDavid du Colombier filemark(t->file);
5047dd7cddfSDavid du Colombier }
5057dd7cddfSDavid du Colombier q0 = a.q0;
5067dd7cddfSDavid du Colombier if(a.q1 > q0){
5077dd7cddfSDavid du Colombier textdelete(t, q0, a.q1, TRUE);
5087dd7cddfSDavid du Colombier w->addr.q1 = q0;
5097dd7cddfSDavid du Colombier }
5107dd7cddfSDavid du Colombier tq0 = t->q0;
5117dd7cddfSDavid du Colombier tq1 = t->q1;
5127dd7cddfSDavid du Colombier textinsert(t, q0, r, nr, TRUE);
5137dd7cddfSDavid du Colombier if(tq0 >= q0)
5147dd7cddfSDavid du Colombier tq0 += nr;
5157dd7cddfSDavid du Colombier if(tq1 >= q0)
5167dd7cddfSDavid du Colombier tq1 += nr;
5179a747e4fSDavid du Colombier textsetselect(t, tq0, tq1);
5187dd7cddfSDavid du Colombier if(!t->w->noscroll)
5199a747e4fSDavid du Colombier textshow(t, q0, q0+nr, 0);
5207dd7cddfSDavid du Colombier textscrdraw(t);
5217dd7cddfSDavid du Colombier winsettag(w);
5227dd7cddfSDavid du Colombier free(r);
5237dd7cddfSDavid du Colombier w->addr.q0 += nr;
5247dd7cddfSDavid du Colombier w->addr.q1 = w->addr.q0;
5257dd7cddfSDavid du Colombier fc.count = x->count;
5267dd7cddfSDavid du Colombier respond(x, &fc, nil);
5277dd7cddfSDavid du Colombier break;
5287dd7cddfSDavid du Colombier
5297dd7cddfSDavid du Colombier case QWevent:
5307dd7cddfSDavid du Colombier xfideventwrite(x, w);
5317dd7cddfSDavid du Colombier break;
5327dd7cddfSDavid du Colombier
5337dd7cddfSDavid du Colombier case QWtag:
5347dd7cddfSDavid du Colombier t = &w->tag;
5357dd7cddfSDavid du Colombier goto BodyTag;
5367dd7cddfSDavid du Colombier
5377dd7cddfSDavid du Colombier BodyTag:
538*9b7bf7dfSDavid du Colombier r = fullrunewrite(x, &nr);
5397dd7cddfSDavid du Colombier if(nr > 0){
5407dd7cddfSDavid du Colombier wincommit(w, t);
5417dd7cddfSDavid du Colombier if(qid == QWwrsel){
5427dd7cddfSDavid du Colombier q0 = w->wrselrange.q1;
5437dd7cddfSDavid du Colombier if(q0 > t->file->nc)
5447dd7cddfSDavid du Colombier q0 = t->file->nc;
5457dd7cddfSDavid du Colombier }else
5467dd7cddfSDavid du Colombier q0 = t->file->nc;
5477dd7cddfSDavid du Colombier if(qid == QWtag)
5487dd7cddfSDavid du Colombier textinsert(t, q0, r, nr, TRUE);
5497dd7cddfSDavid du Colombier else{
5507dd7cddfSDavid du Colombier if(w->nomark == FALSE){
5517dd7cddfSDavid du Colombier seq++;
5527dd7cddfSDavid du Colombier filemark(t->file);
5537dd7cddfSDavid du Colombier }
5547dd7cddfSDavid du Colombier q0 = textbsinsert(t, q0, r, nr, TRUE, &nr);
55580ee5cbfSDavid du Colombier textsetselect(t, t->q0, t->q1); /* insert could leave it somewhere else */
5567dd7cddfSDavid du Colombier if(qid!=QWwrsel && !t->w->noscroll)
5579a747e4fSDavid du Colombier textshow(t, q0+nr, q0+nr, 1);
5587dd7cddfSDavid du Colombier textscrdraw(t);
5597dd7cddfSDavid du Colombier }
5607dd7cddfSDavid du Colombier winsettag(w);
5617dd7cddfSDavid du Colombier if(qid == QWwrsel)
5627dd7cddfSDavid du Colombier w->wrselrange.q1 += nr;
5637dd7cddfSDavid du Colombier free(r);
5647dd7cddfSDavid du Colombier }
5657dd7cddfSDavid du Colombier fc.count = x->count;
5667dd7cddfSDavid du Colombier respond(x, &fc, nil);
5677dd7cddfSDavid du Colombier break;
5687dd7cddfSDavid du Colombier
5697dd7cddfSDavid du Colombier default:
5707dd7cddfSDavid du Colombier sprint(buf, "unknown qid %d in write", qid);
5717dd7cddfSDavid du Colombier respond(x, &fc, buf);
5727dd7cddfSDavid du Colombier break;
5737dd7cddfSDavid du Colombier }
5747dd7cddfSDavid du Colombier if(w)
5757dd7cddfSDavid du Colombier winunlock(w);
5767dd7cddfSDavid du Colombier }
5777dd7cddfSDavid du Colombier
5787dd7cddfSDavid du Colombier void
xfidctlwrite(Xfid * x,Window * w)5797dd7cddfSDavid du Colombier xfidctlwrite(Xfid *x, Window *w)
5807dd7cddfSDavid du Colombier {
5817dd7cddfSDavid du Colombier Fcall fc;
5827dd7cddfSDavid du Colombier int i, m, n, nb, nr, nulls;
5837dd7cddfSDavid du Colombier Rune *r;
5847dd7cddfSDavid du Colombier char *err, *p, *pp, *q, *e;
5857dd7cddfSDavid du Colombier int isfbuf, scrdraw, settag;
5867dd7cddfSDavid du Colombier Text *t;
5877dd7cddfSDavid du Colombier
5887dd7cddfSDavid du Colombier err = nil;
5897dd7cddfSDavid du Colombier e = x->data+x->count;
5907dd7cddfSDavid du Colombier scrdraw = FALSE;
5917dd7cddfSDavid du Colombier settag = FALSE;
5927dd7cddfSDavid du Colombier isfbuf = TRUE;
5937dd7cddfSDavid du Colombier if(x->count < RBUFSIZE)
5947dd7cddfSDavid du Colombier r = fbufalloc();
5957dd7cddfSDavid du Colombier else{
5967dd7cddfSDavid du Colombier isfbuf = FALSE;
5977dd7cddfSDavid du Colombier r = emalloc(x->count*UTFmax+1);
5987dd7cddfSDavid du Colombier }
5997dd7cddfSDavid du Colombier x->data[x->count] = 0;
6007dd7cddfSDavid du Colombier textcommit(&w->tag, TRUE);
6017dd7cddfSDavid du Colombier for(n=0; n<x->count; n+=m){
6027dd7cddfSDavid du Colombier p = x->data+n;
6037dd7cddfSDavid du Colombier if(strncmp(p, "lock", 4) == 0){ /* make window exclusive use */
6047dd7cddfSDavid du Colombier qlock(&w->ctllock);
6057dd7cddfSDavid du Colombier w->ctlfid = x->f->fid;
6067dd7cddfSDavid du Colombier m = 4;
6077dd7cddfSDavid du Colombier }else
6087dd7cddfSDavid du Colombier if(strncmp(p, "unlock", 6) == 0){ /* release exclusive use */
6097dd7cddfSDavid du Colombier w->ctlfid = ~0;
6107dd7cddfSDavid du Colombier qunlock(&w->ctllock);
6117dd7cddfSDavid du Colombier m = 6;
6127dd7cddfSDavid du Colombier }else
6137dd7cddfSDavid du Colombier if(strncmp(p, "clean", 5) == 0){ /* mark window 'clean', seq=0 */
6147dd7cddfSDavid du Colombier t = &w->body;
6157dd7cddfSDavid du Colombier t->eq0 = ~0;
6167dd7cddfSDavid du Colombier filereset(t->file);
6177dd7cddfSDavid du Colombier t->file->mod = FALSE;
6187dd7cddfSDavid du Colombier w->dirty = FALSE;
6197dd7cddfSDavid du Colombier settag = TRUE;
6207dd7cddfSDavid du Colombier m = 5;
6217dd7cddfSDavid du Colombier }else
62280ee5cbfSDavid du Colombier if(strncmp(p, "dirty", 5) == 0){ /* mark window 'dirty' */
62380ee5cbfSDavid du Colombier t = &w->body;
62480ee5cbfSDavid du Colombier /* doesn't change sequence number, so "Put" won't appear. it shouldn't. */
62580ee5cbfSDavid du Colombier t->file->mod = TRUE;
62680ee5cbfSDavid du Colombier w->dirty = TRUE;
62780ee5cbfSDavid du Colombier settag = TRUE;
62880ee5cbfSDavid du Colombier m = 5;
62980ee5cbfSDavid du Colombier }else
6307dd7cddfSDavid du Colombier if(strncmp(p, "show", 4) == 0){ /* show dot */
6317dd7cddfSDavid du Colombier t = &w->body;
6329a747e4fSDavid du Colombier textshow(t, t->q0, t->q1, 1);
6337dd7cddfSDavid du Colombier m = 4;
6347dd7cddfSDavid du Colombier }else
6357dd7cddfSDavid du Colombier if(strncmp(p, "name ", 5) == 0){ /* set file name */
6367dd7cddfSDavid du Colombier pp = p+5;
6377dd7cddfSDavid du Colombier m = 5;
6387dd7cddfSDavid du Colombier q = memchr(pp, '\n', e-pp);
6397dd7cddfSDavid du Colombier if(q==nil || q==pp){
6407dd7cddfSDavid du Colombier err = Ebadctl;
6417dd7cddfSDavid du Colombier break;
6427dd7cddfSDavid du Colombier }
6437dd7cddfSDavid du Colombier *q = 0;
6447dd7cddfSDavid du Colombier nulls = FALSE;
6457dd7cddfSDavid du Colombier cvttorunes(pp, q-pp, r, &nb, &nr, &nulls);
6467dd7cddfSDavid du Colombier if(nulls){
6477dd7cddfSDavid du Colombier err = "nulls in file name";
6487dd7cddfSDavid du Colombier break;
6497dd7cddfSDavid du Colombier }
6507dd7cddfSDavid du Colombier for(i=0; i<nr; i++)
6517dd7cddfSDavid du Colombier if(r[i] <= ' '){
6527dd7cddfSDavid du Colombier err = "bad character in file name";
6537dd7cddfSDavid du Colombier goto out;
6547dd7cddfSDavid du Colombier }
6557dd7cddfSDavid du Colombier out:
6567dd7cddfSDavid du Colombier seq++;
6577dd7cddfSDavid du Colombier filemark(w->body.file);
6587dd7cddfSDavid du Colombier winsetname(w, r, nr);
6597dd7cddfSDavid du Colombier m += (q+1) - pp;
6607dd7cddfSDavid du Colombier }else
6617dd7cddfSDavid du Colombier if(strncmp(p, "dump ", 5) == 0){ /* set dump string */
6627dd7cddfSDavid du Colombier pp = p+5;
6637dd7cddfSDavid du Colombier m = 5;
6647dd7cddfSDavid du Colombier q = memchr(pp, '\n', e-pp);
6657dd7cddfSDavid du Colombier if(q==nil || q==pp){
6667dd7cddfSDavid du Colombier err = Ebadctl;
6677dd7cddfSDavid du Colombier break;
6687dd7cddfSDavid du Colombier }
6697dd7cddfSDavid du Colombier *q = 0;
6707dd7cddfSDavid du Colombier nulls = FALSE;
6717dd7cddfSDavid du Colombier cvttorunes(pp, q-pp, r, &nb, &nr, &nulls);
6727dd7cddfSDavid du Colombier if(nulls){
6737dd7cddfSDavid du Colombier err = "nulls in dump string";
6747dd7cddfSDavid du Colombier break;
6757dd7cddfSDavid du Colombier }
6767dd7cddfSDavid du Colombier w->dumpstr = runetobyte(r, nr);
6777dd7cddfSDavid du Colombier m += (q+1) - pp;
6787dd7cddfSDavid du Colombier }else
6797dd7cddfSDavid du Colombier if(strncmp(p, "dumpdir ", 8) == 0){ /* set dump directory */
6807dd7cddfSDavid du Colombier pp = p+8;
6817dd7cddfSDavid du Colombier m = 8;
6827dd7cddfSDavid du Colombier q = memchr(pp, '\n', e-pp);
6837dd7cddfSDavid du Colombier if(q==nil || q==pp){
6847dd7cddfSDavid du Colombier err = Ebadctl;
6857dd7cddfSDavid du Colombier break;
6867dd7cddfSDavid du Colombier }
6877dd7cddfSDavid du Colombier *q = 0;
6887dd7cddfSDavid du Colombier nulls = FALSE;
6897dd7cddfSDavid du Colombier cvttorunes(pp, q-pp, r, &nb, &nr, &nulls);
6907dd7cddfSDavid du Colombier if(nulls){
6917dd7cddfSDavid du Colombier err = "nulls in dump directory string";
6927dd7cddfSDavid du Colombier break;
6937dd7cddfSDavid du Colombier }
6947dd7cddfSDavid du Colombier w->dumpdir = runetobyte(r, nr);
6957dd7cddfSDavid du Colombier m += (q+1) - pp;
6967dd7cddfSDavid du Colombier }else
6977dd7cddfSDavid du Colombier if(strncmp(p, "delete", 6) == 0){ /* delete for sure */
6987dd7cddfSDavid du Colombier colclose(w->col, w, TRUE);
6997dd7cddfSDavid du Colombier m = 6;
7007dd7cddfSDavid du Colombier }else
7017dd7cddfSDavid du Colombier if(strncmp(p, "del", 3) == 0){ /* delete, but check dirty */
7027dd7cddfSDavid du Colombier if(!winclean(w, TRUE)){
7037dd7cddfSDavid du Colombier err = "file dirty";
7047dd7cddfSDavid du Colombier break;
7057dd7cddfSDavid du Colombier }
7067dd7cddfSDavid du Colombier colclose(w->col, w, TRUE);
7077dd7cddfSDavid du Colombier m = 3;
7087dd7cddfSDavid du Colombier }else
7097dd7cddfSDavid du Colombier if(strncmp(p, "get", 3) == 0){ /* get file */
7107dd7cddfSDavid du Colombier get(&w->body, nil, nil, FALSE, XXX, nil, 0);
7117dd7cddfSDavid du Colombier m = 3;
7127dd7cddfSDavid du Colombier }else
7137dd7cddfSDavid du Colombier if(strncmp(p, "put", 3) == 0){ /* put file */
7147dd7cddfSDavid du Colombier put(&w->body, nil, nil, XXX, XXX, nil, 0);
7157dd7cddfSDavid du Colombier m = 3;
7167dd7cddfSDavid du Colombier }else
7177dd7cddfSDavid du Colombier if(strncmp(p, "dot=addr", 8) == 0){ /* set dot */
7187dd7cddfSDavid du Colombier textcommit(&w->body, TRUE);
7197dd7cddfSDavid du Colombier clampaddr(w);
7207dd7cddfSDavid du Colombier w->body.q0 = w->addr.q0;
7217dd7cddfSDavid du Colombier w->body.q1 = w->addr.q1;
7227dd7cddfSDavid du Colombier textsetselect(&w->body, w->body.q0, w->body.q1);
7237dd7cddfSDavid du Colombier settag = TRUE;
7247dd7cddfSDavid du Colombier m = 8;
7257dd7cddfSDavid du Colombier }else
7267dd7cddfSDavid du Colombier if(strncmp(p, "addr=dot", 8) == 0){ /* set addr */
7277dd7cddfSDavid du Colombier w->addr.q0 = w->body.q0;
7287dd7cddfSDavid du Colombier w->addr.q1 = w->body.q1;
7297dd7cddfSDavid du Colombier m = 8;
7307dd7cddfSDavid du Colombier }else
7317dd7cddfSDavid du Colombier if(strncmp(p, "limit=addr", 10) == 0){ /* set limit */
7327dd7cddfSDavid du Colombier textcommit(&w->body, TRUE);
7337dd7cddfSDavid du Colombier clampaddr(w);
7347dd7cddfSDavid du Colombier w->limit.q0 = w->addr.q0;
7357dd7cddfSDavid du Colombier w->limit.q1 = w->addr.q1;
7367dd7cddfSDavid du Colombier m = 10;
7377dd7cddfSDavid du Colombier }else
7387dd7cddfSDavid du Colombier if(strncmp(p, "nomark", 6) == 0){ /* turn off automatic marking */
7397dd7cddfSDavid du Colombier w->nomark = TRUE;
7407dd7cddfSDavid du Colombier m = 6;
7417dd7cddfSDavid du Colombier }else
7427dd7cddfSDavid du Colombier if(strncmp(p, "mark", 4) == 0){ /* mark file */
7437dd7cddfSDavid du Colombier seq++;
7447dd7cddfSDavid du Colombier filemark(w->body.file);
7457dd7cddfSDavid du Colombier settag = TRUE;
7467dd7cddfSDavid du Colombier m = 4;
7477dd7cddfSDavid du Colombier }else
74890630c3aSDavid du Colombier if(strncmp(p, "nomenu", 6) == 0){ /* turn off automatic menu */
74990630c3aSDavid du Colombier w->filemenu = FALSE;
75090630c3aSDavid du Colombier m = 6;
75190630c3aSDavid du Colombier }else
75290630c3aSDavid du Colombier if(strncmp(p, "menu", 4) == 0){ /* enable automatic menu */
75390630c3aSDavid du Colombier w->filemenu = TRUE;
75490630c3aSDavid du Colombier m = 4;
75590630c3aSDavid du Colombier }else
7567dd7cddfSDavid du Colombier if(strncmp(p, "noscroll", 8) == 0){ /* turn off automatic scrolling */
7577dd7cddfSDavid du Colombier w->noscroll = TRUE;
7587dd7cddfSDavid du Colombier m = 8;
7597dd7cddfSDavid du Colombier }else
7607dd7cddfSDavid du Colombier if(strncmp(p, "cleartag", 8) == 0){ /* wipe tag right of bar */
7617dd7cddfSDavid du Colombier wincleartag(w);
7627dd7cddfSDavid du Colombier settag = TRUE;
7637dd7cddfSDavid du Colombier m = 8;
7647dd7cddfSDavid du Colombier }else
7657dd7cddfSDavid du Colombier if(strncmp(p, "scroll", 6) == 0){ /* turn on automatic scrolling (writes to body only) */
7667dd7cddfSDavid du Colombier w->noscroll = FALSE;
7677dd7cddfSDavid du Colombier m = 6;
7687dd7cddfSDavid du Colombier }else{
7697dd7cddfSDavid du Colombier err = Ebadctl;
7707dd7cddfSDavid du Colombier break;
7717dd7cddfSDavid du Colombier }
7727dd7cddfSDavid du Colombier while(p[m] == '\n')
7737dd7cddfSDavid du Colombier m++;
7747dd7cddfSDavid du Colombier }
7757dd7cddfSDavid du Colombier
7767dd7cddfSDavid du Colombier if(isfbuf)
7777dd7cddfSDavid du Colombier fbuffree(r);
7787dd7cddfSDavid du Colombier else
7797dd7cddfSDavid du Colombier free(r);
7807dd7cddfSDavid du Colombier if(err)
7817dd7cddfSDavid du Colombier n = 0;
7827dd7cddfSDavid du Colombier fc.count = n;
7837dd7cddfSDavid du Colombier respond(x, &fc, err);
7847dd7cddfSDavid du Colombier if(settag)
7857dd7cddfSDavid du Colombier winsettag(w);
7867dd7cddfSDavid du Colombier if(scrdraw)
7877dd7cddfSDavid du Colombier textscrdraw(&w->body);
7887dd7cddfSDavid du Colombier }
7897dd7cddfSDavid du Colombier
7907dd7cddfSDavid du Colombier void
xfideventwrite(Xfid * x,Window * w)7917dd7cddfSDavid du Colombier xfideventwrite(Xfid *x, Window *w)
7927dd7cddfSDavid du Colombier {
7937dd7cddfSDavid du Colombier Fcall fc;
7947dd7cddfSDavid du Colombier int m, n;
7957dd7cddfSDavid du Colombier Rune *r;
7967dd7cddfSDavid du Colombier char *err, *p, *q;
7977dd7cddfSDavid du Colombier int isfbuf;
7987dd7cddfSDavid du Colombier Text *t;
7997dd7cddfSDavid du Colombier int c;
8007dd7cddfSDavid du Colombier uint q0, q1;
8017dd7cddfSDavid du Colombier
8027dd7cddfSDavid du Colombier err = nil;
8037dd7cddfSDavid du Colombier isfbuf = TRUE;
8047dd7cddfSDavid du Colombier if(x->count < RBUFSIZE)
8057dd7cddfSDavid du Colombier r = fbufalloc();
8067dd7cddfSDavid du Colombier else{
8077dd7cddfSDavid du Colombier isfbuf = FALSE;
8087dd7cddfSDavid du Colombier r = emalloc(x->count*UTFmax+1);
8097dd7cddfSDavid du Colombier }
8107dd7cddfSDavid du Colombier for(n=0; n<x->count; n+=m){
8117dd7cddfSDavid du Colombier p = x->data+n;
8127dd7cddfSDavid du Colombier w->owner = *p++; /* disgusting */
8137dd7cddfSDavid du Colombier c = *p++;
8147dd7cddfSDavid du Colombier while(*p == ' ')
8157dd7cddfSDavid du Colombier p++;
8167dd7cddfSDavid du Colombier q0 = strtoul(p, &q, 10);
8177dd7cddfSDavid du Colombier if(q == p)
8187dd7cddfSDavid du Colombier goto Rescue;
8197dd7cddfSDavid du Colombier p = q;
8207dd7cddfSDavid du Colombier while(*p == ' ')
8217dd7cddfSDavid du Colombier p++;
8227dd7cddfSDavid du Colombier q1 = strtoul(p, &q, 10);
8237dd7cddfSDavid du Colombier if(q == p)
8247dd7cddfSDavid du Colombier goto Rescue;
8257dd7cddfSDavid du Colombier p = q;
8267dd7cddfSDavid du Colombier while(*p == ' ')
8277dd7cddfSDavid du Colombier p++;
8287dd7cddfSDavid du Colombier if(*p++ != '\n')
8297dd7cddfSDavid du Colombier goto Rescue;
8307dd7cddfSDavid du Colombier m = p-(x->data+n);
8317dd7cddfSDavid du Colombier if('a'<=c && c<='z')
8327dd7cddfSDavid du Colombier t = &w->tag;
8337dd7cddfSDavid du Colombier else if('A'<=c && c<='Z')
8347dd7cddfSDavid du Colombier t = &w->body;
8357dd7cddfSDavid du Colombier else
8367dd7cddfSDavid du Colombier goto Rescue;
8377dd7cddfSDavid du Colombier if(q0>t->file->nc || q1>t->file->nc || q0>q1)
8387dd7cddfSDavid du Colombier goto Rescue;
8397dd7cddfSDavid du Colombier
84059cc4ca5SDavid du Colombier qlock(&row); /* just like mousethread */
8417dd7cddfSDavid du Colombier switch(c){
8427dd7cddfSDavid du Colombier case 'x':
8437dd7cddfSDavid du Colombier case 'X':
8447dd7cddfSDavid du Colombier execute(t, q0, q1, TRUE, nil);
8457dd7cddfSDavid du Colombier break;
8467dd7cddfSDavid du Colombier case 'l':
8477dd7cddfSDavid du Colombier case 'L':
8487dd7cddfSDavid du Colombier look3(t, q0, q1, TRUE);
8497dd7cddfSDavid du Colombier break;
8507dd7cddfSDavid du Colombier default:
85159cc4ca5SDavid du Colombier qunlock(&row);
8527dd7cddfSDavid du Colombier goto Rescue;
8537dd7cddfSDavid du Colombier }
85459cc4ca5SDavid du Colombier qunlock(&row);
8557dd7cddfSDavid du Colombier
8567dd7cddfSDavid du Colombier }
8577dd7cddfSDavid du Colombier
8587dd7cddfSDavid du Colombier Out:
8597dd7cddfSDavid du Colombier if(isfbuf)
8607dd7cddfSDavid du Colombier fbuffree(r);
8617dd7cddfSDavid du Colombier else
8627dd7cddfSDavid du Colombier free(r);
8637dd7cddfSDavid du Colombier if(err)
8647dd7cddfSDavid du Colombier n = 0;
8657dd7cddfSDavid du Colombier fc.count = n;
8667dd7cddfSDavid du Colombier respond(x, &fc, err);
8677dd7cddfSDavid du Colombier return;
8687dd7cddfSDavid du Colombier
8697dd7cddfSDavid du Colombier Rescue:
8707dd7cddfSDavid du Colombier err = Ebadevent;
8717dd7cddfSDavid du Colombier goto Out;
8727dd7cddfSDavid du Colombier }
8737dd7cddfSDavid du Colombier
8747dd7cddfSDavid du Colombier void
xfidutfread(Xfid * x,Text * t,uint q1,int qid)8757dd7cddfSDavid du Colombier xfidutfread(Xfid *x, Text *t, uint q1, int qid)
8767dd7cddfSDavid du Colombier {
8777dd7cddfSDavid du Colombier Fcall fc;
8787dd7cddfSDavid du Colombier Window *w;
8797dd7cddfSDavid du Colombier Rune *r;
8807dd7cddfSDavid du Colombier char *b, *b1;
8817dd7cddfSDavid du Colombier uint q, off, boff;
8827dd7cddfSDavid du Colombier int m, n, nr, nb;
8837dd7cddfSDavid du Colombier
8847dd7cddfSDavid du Colombier w = t->w;
8857dd7cddfSDavid du Colombier wincommit(w, t);
8867dd7cddfSDavid du Colombier off = x->offset;
8877dd7cddfSDavid du Colombier r = fbufalloc();
8887dd7cddfSDavid du Colombier b = fbufalloc();
8897dd7cddfSDavid du Colombier b1 = fbufalloc();
8907dd7cddfSDavid du Colombier n = 0;
8917dd7cddfSDavid du Colombier if(qid==w->utflastqid && off>=w->utflastboff && w->utflastq<=q1){
8927dd7cddfSDavid du Colombier boff = w->utflastboff;
8937dd7cddfSDavid du Colombier q = w->utflastq;
8947dd7cddfSDavid du Colombier }else{
8957dd7cddfSDavid du Colombier /* BUG: stupid code: scan from beginning */
8967dd7cddfSDavid du Colombier boff = 0;
8977dd7cddfSDavid du Colombier q = 0;
8987dd7cddfSDavid du Colombier }
8997dd7cddfSDavid du Colombier w->utflastqid = qid;
9007dd7cddfSDavid du Colombier while(q<q1 && n<x->count){
9017dd7cddfSDavid du Colombier /*
9027dd7cddfSDavid du Colombier * Updating here avoids partial rune problem: we're always on a
9037dd7cddfSDavid du Colombier * char boundary. The cost is we will usually do one more read
9047dd7cddfSDavid du Colombier * than we really need, but that's better than being n^2.
9057dd7cddfSDavid du Colombier */
9067dd7cddfSDavid du Colombier w->utflastboff = boff;
9077dd7cddfSDavid du Colombier w->utflastq = q;
9087dd7cddfSDavid du Colombier nr = q1-q;
9097dd7cddfSDavid du Colombier if(nr > BUFSIZE/UTFmax)
9107dd7cddfSDavid du Colombier nr = BUFSIZE/UTFmax;
9117dd7cddfSDavid du Colombier bufread(t->file, q, r, nr);
9127dd7cddfSDavid du Colombier nb = snprint(b, BUFSIZE+1, "%.*S", nr, r);
9137dd7cddfSDavid du Colombier if(boff >= off){
9147dd7cddfSDavid du Colombier m = nb;
9157dd7cddfSDavid du Colombier if(boff+m > off+x->count)
9167dd7cddfSDavid du Colombier m = off+x->count - boff;
9177dd7cddfSDavid du Colombier memmove(b1+n, b, m);
9187dd7cddfSDavid du Colombier n += m;
9197dd7cddfSDavid du Colombier }else if(boff+nb > off){
9207dd7cddfSDavid du Colombier if(n != 0)
9217dd7cddfSDavid du Colombier error("bad count in utfrune");
9227dd7cddfSDavid du Colombier m = nb - (off-boff);
9237dd7cddfSDavid du Colombier if(m > x->count)
9247dd7cddfSDavid du Colombier m = x->count;
9257dd7cddfSDavid du Colombier memmove(b1, b+(off-boff), m);
9267dd7cddfSDavid du Colombier n += m;
9277dd7cddfSDavid du Colombier }
9287dd7cddfSDavid du Colombier boff += nb;
9297dd7cddfSDavid du Colombier q += nr;
9307dd7cddfSDavid du Colombier }
9317dd7cddfSDavid du Colombier fbuffree(r);
9327dd7cddfSDavid du Colombier fbuffree(b);
9337dd7cddfSDavid du Colombier fc.count = n;
9347dd7cddfSDavid du Colombier fc.data = b1;
9357dd7cddfSDavid du Colombier respond(x, &fc, nil);
9367dd7cddfSDavid du Colombier fbuffree(b1);
9377dd7cddfSDavid du Colombier }
9387dd7cddfSDavid du Colombier
9397dd7cddfSDavid du Colombier int
xfidruneread(Xfid * x,Text * t,uint q0,uint q1)9407dd7cddfSDavid du Colombier xfidruneread(Xfid *x, Text *t, uint q0, uint q1)
9417dd7cddfSDavid du Colombier {
9427dd7cddfSDavid du Colombier Fcall fc;
9437dd7cddfSDavid du Colombier Window *w;
9447dd7cddfSDavid du Colombier Rune *r, junk;
9457dd7cddfSDavid du Colombier char *b, *b1;
9467dd7cddfSDavid du Colombier uint q, boff;
9477dd7cddfSDavid du Colombier int i, rw, m, n, nr, nb;
9487dd7cddfSDavid du Colombier
9497dd7cddfSDavid du Colombier w = t->w;
9507dd7cddfSDavid du Colombier wincommit(w, t);
9517dd7cddfSDavid du Colombier r = fbufalloc();
9527dd7cddfSDavid du Colombier b = fbufalloc();
9537dd7cddfSDavid du Colombier b1 = fbufalloc();
9547dd7cddfSDavid du Colombier n = 0;
9557dd7cddfSDavid du Colombier q = q0;
9567dd7cddfSDavid du Colombier boff = 0;
9577dd7cddfSDavid du Colombier while(q<q1 && n<x->count){
9587dd7cddfSDavid du Colombier nr = q1-q;
9597dd7cddfSDavid du Colombier if(nr > BUFSIZE/UTFmax)
9607dd7cddfSDavid du Colombier nr = BUFSIZE/UTFmax;
9617dd7cddfSDavid du Colombier bufread(t->file, q, r, nr);
9627dd7cddfSDavid du Colombier nb = snprint(b, BUFSIZE+1, "%.*S", nr, r);
9637dd7cddfSDavid du Colombier m = nb;
9647dd7cddfSDavid du Colombier if(boff+m > x->count){
9657dd7cddfSDavid du Colombier i = x->count - boff;
9667dd7cddfSDavid du Colombier /* copy whole runes only */
9677dd7cddfSDavid du Colombier m = 0;
9687dd7cddfSDavid du Colombier nr = 0;
9697dd7cddfSDavid du Colombier while(m < i){
9707dd7cddfSDavid du Colombier rw = chartorune(&junk, b+m);
9717dd7cddfSDavid du Colombier if(m+rw > i)
9727dd7cddfSDavid du Colombier break;
9737dd7cddfSDavid du Colombier m += rw;
9747dd7cddfSDavid du Colombier nr++;
9757dd7cddfSDavid du Colombier }
9767dd7cddfSDavid du Colombier if(m == 0)
9777dd7cddfSDavid du Colombier break;
9787dd7cddfSDavid du Colombier }
9797dd7cddfSDavid du Colombier memmove(b1+n, b, m);
9807dd7cddfSDavid du Colombier n += m;
9817dd7cddfSDavid du Colombier boff += nb;
9827dd7cddfSDavid du Colombier q += nr;
9837dd7cddfSDavid du Colombier }
9847dd7cddfSDavid du Colombier fbuffree(r);
9857dd7cddfSDavid du Colombier fbuffree(b);
9867dd7cddfSDavid du Colombier fc.count = n;
9877dd7cddfSDavid du Colombier fc.data = b1;
9887dd7cddfSDavid du Colombier respond(x, &fc, nil);
9897dd7cddfSDavid du Colombier fbuffree(b1);
9907dd7cddfSDavid du Colombier return q-q0;
9917dd7cddfSDavid du Colombier }
9927dd7cddfSDavid du Colombier
9937dd7cddfSDavid du Colombier void
xfideventread(Xfid * x,Window * w)9947dd7cddfSDavid du Colombier xfideventread(Xfid *x, Window *w)
9957dd7cddfSDavid du Colombier {
9967dd7cddfSDavid du Colombier Fcall fc;
9977dd7cddfSDavid du Colombier char *b;
9987dd7cddfSDavid du Colombier int i, n;
9997dd7cddfSDavid du Colombier
10007dd7cddfSDavid du Colombier i = 0;
10017dd7cddfSDavid du Colombier x->flushed = FALSE;
10027dd7cddfSDavid du Colombier while(w->nevents == 0){
10037dd7cddfSDavid du Colombier if(i){
10047dd7cddfSDavid du Colombier if(!x->flushed)
10057dd7cddfSDavid du Colombier respond(x, &fc, "window shut down");
10067dd7cddfSDavid du Colombier return;
10077dd7cddfSDavid du Colombier }
10087dd7cddfSDavid du Colombier w->eventx = x;
10097dd7cddfSDavid du Colombier winunlock(w);
10107dd7cddfSDavid du Colombier recvp(x->c);
10117dd7cddfSDavid du Colombier winlock(w, 'F');
10127dd7cddfSDavid du Colombier i++;
10137dd7cddfSDavid du Colombier }
10147dd7cddfSDavid du Colombier
10157dd7cddfSDavid du Colombier n = w->nevents;
10167dd7cddfSDavid du Colombier if(n > x->count)
10177dd7cddfSDavid du Colombier n = x->count;
10187dd7cddfSDavid du Colombier fc.count = n;
10197dd7cddfSDavid du Colombier fc.data = w->events;
10207dd7cddfSDavid du Colombier respond(x, &fc, nil);
10217dd7cddfSDavid du Colombier b = w->events;
102259cc4ca5SDavid du Colombier w->events = estrdup(w->events+n);
10237dd7cddfSDavid du Colombier free(b);
10247dd7cddfSDavid du Colombier w->nevents -= n;
10257dd7cddfSDavid du Colombier }
10267dd7cddfSDavid du Colombier
10277dd7cddfSDavid du Colombier void
xfidindexread(Xfid * x)10287dd7cddfSDavid du Colombier xfidindexread(Xfid *x)
10297dd7cddfSDavid du Colombier {
10307dd7cddfSDavid du Colombier Fcall fc;
10317dd7cddfSDavid du Colombier int i, j, m, n, nmax, isbuf, cnt, off;
10327dd7cddfSDavid du Colombier Window *w;
10337dd7cddfSDavid du Colombier char *b;
10347dd7cddfSDavid du Colombier Rune *r;
10357dd7cddfSDavid du Colombier Column *c;
10367dd7cddfSDavid du Colombier
10377dd7cddfSDavid du Colombier qlock(&row);
10387dd7cddfSDavid du Colombier nmax = 0;
10397dd7cddfSDavid du Colombier for(j=0; j<row.ncol; j++){
10407dd7cddfSDavid du Colombier c = row.col[j];
10417dd7cddfSDavid du Colombier for(i=0; i<c->nw; i++){
10427dd7cddfSDavid du Colombier w = c->w[i];
10437dd7cddfSDavid du Colombier nmax += Ctlsize + w->tag.file->nc*UTFmax + 1;
10447dd7cddfSDavid du Colombier }
10457dd7cddfSDavid du Colombier }
10467dd7cddfSDavid du Colombier nmax++;
10477dd7cddfSDavid du Colombier isbuf = (nmax<=RBUFSIZE);
10487dd7cddfSDavid du Colombier if(isbuf)
10499a747e4fSDavid du Colombier b = (char*)x->buf;
10507dd7cddfSDavid du Colombier else
10517dd7cddfSDavid du Colombier b = emalloc(nmax);
10527dd7cddfSDavid du Colombier r = fbufalloc();
10537dd7cddfSDavid du Colombier n = 0;
10547dd7cddfSDavid du Colombier for(j=0; j<row.ncol; j++){
10557dd7cddfSDavid du Colombier c = row.col[j];
10567dd7cddfSDavid du Colombier for(i=0; i<c->nw; i++){
10577dd7cddfSDavid du Colombier w = c->w[i];
10587dd7cddfSDavid du Colombier /* only show the currently active window of a set */
10597dd7cddfSDavid du Colombier if(w->body.file->curtext != &w->body)
10607dd7cddfSDavid du Colombier continue;
10619a747e4fSDavid du Colombier winctlprint(w, b+n, 0);
10627dd7cddfSDavid du Colombier n += Ctlsize;
10637dd7cddfSDavid du Colombier m = min(RBUFSIZE, w->tag.file->nc);
10647dd7cddfSDavid du Colombier bufread(w->tag.file, 0, r, m);
10657dd7cddfSDavid du Colombier m = n + snprint(b+n, nmax-n-1, "%.*S", m, r);
10667dd7cddfSDavid du Colombier while(n<m && b[n]!='\n')
10677dd7cddfSDavid du Colombier n++;
10687dd7cddfSDavid du Colombier b[n++] = '\n';
10697dd7cddfSDavid du Colombier }
10707dd7cddfSDavid du Colombier }
10717dd7cddfSDavid du Colombier qunlock(&row);
10727dd7cddfSDavid du Colombier off = x->offset;
10737dd7cddfSDavid du Colombier cnt = x->count;
10747dd7cddfSDavid du Colombier if(off > n)
10757dd7cddfSDavid du Colombier off = n;
10767dd7cddfSDavid du Colombier if(off+cnt > n)
10777dd7cddfSDavid du Colombier cnt = n-off;
10787dd7cddfSDavid du Colombier fc.count = cnt;
10797dd7cddfSDavid du Colombier memmove(r, b+off, cnt);
10807dd7cddfSDavid du Colombier fc.data = (char*)r;
10817dd7cddfSDavid du Colombier if(!isbuf)
10827dd7cddfSDavid du Colombier free(b);
10837dd7cddfSDavid du Colombier respond(x, &fc, nil);
10847dd7cddfSDavid du Colombier fbuffree(r);
10857dd7cddfSDavid du Colombier }
1086