📄 xfid.c
字号:
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->count; respond(x, &fc, nil); break; default: sprint(buf, "unknown qid %d in write", qid); respond(x, &fc, buf); break; } if(w) winunlock(w);}voidxfidctlwrite(Xfid *x, Window *w){ Fcall fc; int i, m, n, nb, nr, nulls; Rune *r; char *err, *p, *pp, *q, *e; int isfbuf, scrdraw, settag; Text *t; err = nil; e = x->data+x->count; scrdraw = FALSE; settag = FALSE; isfbuf = TRUE; if(x->count < RBUFSIZE) r = fbufalloc(); else{ isfbuf = FALSE; r = emalloc(x->count*UTFmax+1); } x->data[x->count] = 0; textcommit(&w->tag, TRUE); for(n=0; n<x->count; n+=m){ p = x->data+n; if(strncmp(p, "lock", 4) == 0){ /* make window exclusive use */ qlock(&w->ctllock); w->ctlfid = x->f->fid; m = 4; }else if(strncmp(p, "unlock", 6) == 0){ /* release exclusive use */ w->ctlfid = ~0; qunlock(&w->ctllock); m = 6; }else if(strncmp(p, "clean", 5) == 0){ /* mark window 'clean', seq=0 */ t = &w->body; t->eq0 = ~0; filereset(t->file); t->file->mod = FALSE; w->dirty = FALSE; settag = TRUE; m = 5; }else if(strncmp(p, "dirty", 5) == 0){ /* mark window 'dirty' */ t = &w->body; /* doesn't change sequence number, so "Put" won't appear. it shouldn't. */ t->file->mod = TRUE; w->dirty = TRUE; settag = TRUE; m = 5; }else if(strncmp(p, "show", 4) == 0){ /* show dot */ t = &w->body; textshow(t, t->q0, t->q1, 1); m = 4; }else if(strncmp(p, "name ", 5) == 0){ /* set file name */ pp = p+5; m = 5; q = memchr(pp, '\n', e-pp); if(q==nil || q==pp){ err = Ebadctl; break; } *q = 0; nulls = FALSE; cvttorunes(pp, q-pp, r, &nb, &nr, &nulls); if(nulls){ err = "nulls in file name"; break; } for(i=0; i<nr; i++) if(r[i] <= ' '){ err = "bad character in file name"; goto out; }out: seq++; filemark(w->body.file); winsetname(w, r, nr); m += (q+1) - pp; }else if(strncmp(p, "dump ", 5) == 0){ /* set dump string */ pp = p+5; m = 5; q = memchr(pp, '\n', e-pp); if(q==nil || q==pp){ err = Ebadctl; break; } *q = 0; nulls = FALSE; cvttorunes(pp, q-pp, r, &nb, &nr, &nulls); if(nulls){ err = "nulls in dump string"; break; } w->dumpstr = runetobyte(r, nr); m += (q+1) - pp; }else if(strncmp(p, "dumpdir ", 8) == 0){ /* set dump directory */ pp = p+8; m = 8; q = memchr(pp, '\n', e-pp); if(q==nil || q==pp){ err = Ebadctl; break; } *q = 0; nulls = FALSE; cvttorunes(pp, q-pp, r, &nb, &nr, &nulls); if(nulls){ err = "nulls in dump directory string"; break; } w->dumpdir = runetobyte(r, nr); m += (q+1) - pp; }else if(strncmp(p, "delete", 6) == 0){ /* delete for sure */ colclose(w->col, w, TRUE); m = 6; }else if(strncmp(p, "del", 3) == 0){ /* delete, but check dirty */ if(!winclean(w, TRUE)){ err = "file dirty"; break; } colclose(w->col, w, TRUE); m = 3; }else if(strncmp(p, "get", 3) == 0){ /* get file */ get(&w->body, nil, nil, FALSE, XXX, nil, 0); m = 3; }else if(strncmp(p, "put", 3) == 0){ /* put file */ put(&w->body, nil, nil, XXX, XXX, nil, 0); m = 3; }else if(strncmp(p, "dot=addr", 8) == 0){ /* set dot */ textcommit(&w->body, TRUE); clampaddr(w); w->body.q0 = w->addr.q0; w->body.q1 = w->addr.q1; textsetselect(&w->body, w->body.q0, w->body.q1); settag = TRUE; m = 8; }else if(strncmp(p, "addr=dot", 8) == 0){ /* set addr */ w->addr.q0 = w->body.q0; w->addr.q1 = w->body.q1; m = 8; }else if(strncmp(p, "limit=addr", 10) == 0){ /* set limit */ textcommit(&w->body, TRUE); clampaddr(w); w->limit.q0 = w->addr.q0; w->limit.q1 = w->addr.q1; m = 10; }else if(strncmp(p, "nomark", 6) == 0){ /* turn off automatic marking */ w->nomark = TRUE; m = 6; }else if(strncmp(p, "mark", 4) == 0){ /* mark file */ seq++; filemark(w->body.file); settag = TRUE; m = 4; }else if(strncmp(p, "nomenu", 6) == 0){ /* turn off automatic menu */ w->filemenu = FALSE; m = 6; }else if(strncmp(p, "menu", 4) == 0){ /* enable automatic menu */ w->filemenu = TRUE; m = 4; }else if(strncmp(p, "noscroll", 8) == 0){ /* turn off automatic scrolling */ w->noscroll = TRUE; m = 8; }else if(strncmp(p, "cleartag", 8) == 0){ /* wipe tag right of bar */ wincleartag(w); settag = TRUE; m = 8; }else if(strncmp(p, "scroll", 6) == 0){ /* turn on automatic scrolling (writes to body only) */ w->noscroll = FALSE; m = 6; }else{ err = Ebadctl; break; } while(p[m] == '\n') m++; } if(isfbuf) fbuffree(r); else free(r); if(err) n = 0; fc.count = n; respond(x, &fc, err); if(settag) winsettag(w); if(scrdraw) textscrdraw(&w->body);}voidxfideventwrite(Xfid *x, Window *w){ Fcall fc; int m, n; Rune *r; char *err, *p, *q; int isfbuf; Text *t; int c; uint q0, q1; err = nil; isfbuf = TRUE; if(x->count < RBUFSIZE) r = fbufalloc(); else{ isfbuf = FALSE; r = emalloc(x->count*UTFmax+1); } for(n=0; n<x->count; n+=m){ p = x->data+n; w->owner = *p++; /* disgusting */ c = *p++; while(*p == ' ') p++; q0 = strtoul(p, &q, 10); if(q == p) goto Rescue; p = q; while(*p == ' ') p++; q1 = strtoul(p, &q, 10); if(q == p) goto Rescue; p = q; while(*p == ' ') p++; if(*p++ != '\n') goto Rescue; m = p-(x->data+n); if('a'<=c && c<='z') t = &w->tag; else if('A'<=c && c<='Z') t = &w->body; else goto Rescue; if(q0>t->file->nc || q1>t->file->nc || q0>q1) goto Rescue; qlock(&row); /* just like mousethread */ switch(c){ case 'x': case 'X': execute(t, q0, q1, TRUE, nil); break; case 'l': case 'L': look3(t, q0, q1, TRUE); break; default: qunlock(&row); goto Rescue; } qunlock(&row); } Out: if(isfbuf) fbuffree(r); else free(r); if(err) n = 0; fc.count = n; respond(x, &fc, err); return; Rescue: err = Ebadevent; goto Out;}voidxfidutfread(Xfid *x, Text *t, uint q1, int qid){ Fcall fc; Window *w; Rune *r; char *b, *b1; uint q, off, boff; int m, n, nr, nb; w = t->w; wincommit(w, t); off = x->offset; r = fbufalloc(); b = fbufalloc(); b1 = fbufalloc(); n = 0; if(qid==w->utflastqid && off>=w->utflastboff && w->utflastq<=q1){ boff = w->utflastboff; q = w->utflastq; }else{ /* BUG: stupid code: scan from beginning */ boff = 0; q = 0; } w->utflastqid = qid; while(q<q1 && n<x->count){ /* * Updating here avoids partial rune problem: we're always on a * char boundary. The cost is we will usually do one more read * than we really need, but that's better than being n^2. */ w->utflastboff = boff; w->utflastq = q; nr = q1-q; if(nr > BUFSIZE/UTFmax) nr = BUFSIZE/UTFmax; bufread(t->file, q, r, nr); nb = snprint(b, BUFSIZE+1, "%.*S", nr, r); if(boff >= off){ m = nb; if(boff+m > off+x->count) m = off+x->count - boff; memmove(b1+n, b, m); n += m; }else if(boff+nb > off){ if(n != 0) error("bad count in utfrune"); m = nb - (off-boff); if(m > x->count) m = x->count; memmove(b1, b+(off-boff), m); n += m; } boff += nb; q += nr; } fbuffree(r); fbuffree(b); fc.count = n; fc.data = b1; respond(x, &fc, nil); fbuffree(b1);}intxfidruneread(Xfid *x, Text *t, uint q0, uint q1){ Fcall fc; Window *w; Rune *r, junk; char *b, *b1; uint q, boff; int i, rw, m, n, nr, nb; w = t->w; wincommit(w, t); r = fbufalloc(); b = fbufalloc(); b1 = fbufalloc(); n = 0; q = q0; boff = 0; while(q<q1 && n<x->count){ nr = q1-q; if(nr > BUFSIZE/UTFmax) nr = BUFSIZE/UTFmax; bufread(t->file, q, r, nr); nb = snprint(b, BUFSIZE+1, "%.*S", nr, r); m = nb; if(boff+m > x->count){ i = x->count - boff; /* copy whole runes only */ m = 0; nr = 0; while(m < i){ rw = chartorune(&junk, b+m); if(m+rw > i) break; m += rw; nr++; } if(m == 0) break; } memmove(b1+n, b, m); n += m; boff += nb; q += nr; } fbuffree(r); fbuffree(b); fc.count = n; fc.data = b1; respond(x, &fc, nil); fbuffree(b1); return q-q0;}voidxfideventread(Xfid *x, Window *w){ Fcall fc; char *b; 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->count) n = x->count; fc.count = n; fc.data = w->events; respond(x, &fc, nil); b = w->events; w->events = estrdup(w->events+n); free(b); w->nevents -= n;}voidxfidindexread(Xfid *x){ Fcall fc; int i, j, m, n, nmax, isbuf, cnt, off; Window *w; char *b; Rune *r; Column *c; qlock(&row); nmax = 0; for(j=0; j<row.ncol; j++){ c = row.col[j]; for(i=0; i<c->nw; i++){ w = c->w[i]; nmax += Ctlsize + w->tag.file->nc*UTFmax + 1; } } nmax++; isbuf = (nmax<=RBUFSIZE); if(isbuf) b = (char*)x->buf; else b = emalloc(nmax); r = fbufalloc(); n = 0; for(j=0; j<row.ncol; j++){ c = row.col[j]; for(i=0; i<c->nw; i++){ w = c->w[i]; /* only show the currently active window of a set */ if(w->body.file->curtext != &w->body) continue; winctlprint(w, b+n, 0); n += Ctlsize; m = min(RBUFSIZE, w->tag.file->nc); bufread(w->tag.file, 0, r, m); m = n + snprint(b+n, nmax-n-1, "%.*S", m, r); while(n<m && b[n]!='\n') n++; b[n++] = '\n'; } } qunlock(&row); off = x->offset; cnt = x->count; if(off > n) off = n; if(off+cnt > n) cnt = n-off; fc.count = cnt; memmove(r, b+off, cnt); fc.data = (char*)r; if(!isbuf) free(b); respond(x, &fc, nil); fbuffree(r);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -