1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087 |
- implement Xfidm;
- include "common.m";
- sys : Sys;
- dat : Dat;
- graph : Graph;
- utils : Utils;
- regx : Regx;
- bufferm : Bufferm;
- diskm : Diskm;
- filem : Filem;
- textm : Textm;
- columnm : Columnm;
- scrl : Scroll;
- look : Look;
- exec : Exec;
- windowm : Windowm;
- fsys : Fsys;
- editm: Edit;
- ecmd: Editcmd;
- styxaux: Styxaux;
- UTFmax : import Sys;
- sprint : import sys;
- Smsg0 : import Dat;
- TRUE, FALSE, XXX, BUFSIZE, MAXRPC : import Dat;
- EM_NORMAL, EM_RAW, EM_MASK : import Dat;
- Qdir, Qcons, Qlabel, Qindex, Qeditout : import Dat;
- QWaddr, QWdata, QWevent, QWconsctl, QWctl, QWbody, QWeditout, QWtag, QWrdsel, QWwrsel : import Dat;
- seq, cxfidfree, Lock, Ref, Range, Mntdir, Astring : import dat;
- error, warning, max, min, stralloc, strfree, strncmp : import utils;
- address : import regx;
- Buffer : import bufferm;
- File : import filem;
- Text : import textm;
- scrdraw : import scrl;
- Window : import windowm;
- bflush : import graph;
- Column : import columnm;
- row : import dat;
- FILE, QID, respond : import fsys;
- oldtag, name, offset, count, data, setcount, setdata : import styxaux;
- init(mods : ref Dat->Mods)
- {
- sys = mods.sys;
- dat = mods.dat;
- graph = mods.graph;
- utils = mods.utils;
- regx = mods.regx;
- filem = mods.filem;
- bufferm = mods.bufferm;
- diskm = mods.diskm;
- textm = mods.textm;
- columnm = mods.columnm;
- scrl = mods.scroll;
- look = mods.look;
- exec = mods.exec;
- windowm = mods.windowm;
- fsys = mods.fsys;
- editm = mods.edit;
- ecmd = mods.editcmd;
- styxaux = mods.styxaux;
- }
- nullxfid : Xfid;
- newxfid() : ref Xfid
- {
- x := ref Xfid;
- *x = nullxfid;
- x.buf = array[fsys->messagesize+UTFmax] of byte;
- return x;
- }
- Ctlsize : con 5*12;
- Edel := "deleted window";
- Ebadctl := "ill-formed control message";
- Ebadaddr := "bad address syntax";
- Eaddr := "address out of range";
- Einuse := "already in use";
- Ebadevent:= "bad event syntax";
- clampaddr(w : ref Window)
- {
- 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.buf.nc)
- w.addr.q0 = w.body.file.buf.nc;
- if(w.addr.q1 > w.body.file.buf.nc)
- w.addr.q1 = w.body.file.buf.nc;
- }
- xfidtid : array of int;
- nxfidtid := 0;
- xfidkill()
- {
- if (sys == nil)
- return;
- thispid := sys->pctl(0, nil);
- for (i := 0; i < nxfidtid; i++)
- utils->postnote(Utils->PNPROC, thispid, xfidtid[i], "kill");
- }
- Xfid.ctl(x : self ref Xfid)
- {
- x.tid = sys->pctl(0, nil);
- ox := xfidtid;
- xfidtid = array[nxfidtid+1] of int;
- xfidtid[0:] = ox[0:nxfidtid];
- xfidtid[nxfidtid++] = x.tid;
- ox = nil;
- for (;;) {
- f := <- x.c;
- case (f) {
- Xnil => ;
- Xflush => x.flush();
- Xwalk => x.walk(nil);
- Xopen => x.open();
- Xclose => x.close();
- Xread => x.read();
- Xwrite => x.write();
- * => error("bad case in Xfid.ctl()");
- }
- bflush();
- cxfidfree <-= x;
- }
- }
-
- Xfid.flush(x : self ref Xfid)
- {
- fc : Smsg0;
- i, j : int;
- w : ref Window;
- c : ref Column;
- wx : ref Xfid;
- # search windows for matching tag
- row.qlock.lock();
- loop:
- for(j=0; j<row.ncol; j++){
- c = row.col[j];
- for(i=0; i<c.nw; i++){
- w = c.w[i];
- w.lock('E');
- wx = w.eventx;
- if(wx!=nil && wx.fcall.tag==oldtag(x.fcall)){
- w.eventx = nil;
- wx.flushed = TRUE;
- wx.c <-= Xnil;
- w.unlock();
- break loop;
- }
- w.unlock();
- }
- }
- row.qlock.unlock();
- respond(x, fc, nil);
- }
-
- Xfid.walk(nil : self ref Xfid, cw: chan of ref Window)
- {
- # fc : Smsg0;
- w : ref Window;
- # if(name(x.fcall) != "new")
- # error("unknown path in walk\n");
- row.qlock.lock(); # tasks->procs now
- w = utils->newwindow(nil);
- w.settag();
- # w.refx.inc();
- # x.f.w = w;
- # x.f.qid.path = big QID(w.id, Qdir);
- # x.f.qid.qtype = Sys->QTDIR;
- # fc.qid = x.f.qid;
- row.qlock.unlock();
- # respond(x, fc, nil);
- cw <-= w;
- }
-
- Xfid.open(x : self ref Xfid)
- {
- fc : Smsg0;
- w : ref Window;
- q : int;
- fc.iounit = 0;
- w = x.f.w;
- if(w != nil){
- t := w.body;
- row.qlock.lock(); # tasks->procs now
- w.lock('E');
- q = FILE(x.f.qid);
- case(q){
- QWaddr or QWdata or QWevent =>
- if(w.nopen[q]++ == byte 0){
- if(q == QWaddr){
- w.addr = (Range)(0,0);
- w.limit = (Range)(-1,-1);
- }
- if(q==QWevent && !w.isdir && w.col!=nil){
- w.filemenu = FALSE;
- w.settag();
- }
- }
- 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 != nil){
- w.unlock();
- respond(x, fc, Einuse);
- return;
- }
- w.rdselfd = diskm->tempfile();
- if(w.rdselfd == nil){
- w.unlock();
- respond(x, fc, "can't create temp file");
- return;
- }
- w.nopen[q]++;
- q0 := t.q0;
- q1 := t.q1;
- r := utils->stralloc(BUFSIZE);
- while(q0 < q1){
- n := q1 - q0;
- if(n > BUFSIZE)
- n = BUFSIZE;
- t.file.buf.read(q0, r, 0, n);
- s := array of byte r.s[0:n];
- m := len s;
- if(sys->write(w.rdselfd, s, m) != m){
- warning(nil, "can't write temp file for pipe command %r\n");
- break;
- }
- s = nil;
- q0 += n;
- }
- utils->strfree(r);
- QWwrsel =>
- w.nopen[q]++;
- seq++;
- t.file.mark();
- exec->cut(t, t, FALSE, TRUE);
- w.wrselrange = (Range)(t.q1, t.q1);
- w.nomark = TRUE;
- QWeditout =>
- if(editm->editing == FALSE){
- w.unlock();
- respond(x, fc, "permission denied");
- return;
- }
- w.wrselrange = (Range)(t.q1, t.q1);
- break;
- }
- w.unlock();
- row.qlock.unlock();
- }
- fc.qid = x.f.qid;
- fc.iounit = fsys->messagesize-Styx->IOHDRSZ;
- x.f.open = TRUE;
- respond(x, fc, nil);
- }
-
- Xfid.close(x : self ref Xfid)
- {
- fc : Smsg0;
- w : ref Window;
- q : int;
- w = x.f.w;
- # BUG in C version ? fsysclunk() has just set busy, open to FALSE
- # x.f.busy = FALSE;
- # if(!x.f.open){
- # if(w != nil)
- # w.close();
- # respond(x, fc, nil);
- # return;
- # }
- # x.f.open = FALSE;
- if(w != nil){
- row.qlock.lock(); # tasks->procs now
- w.lock('E');
- q = FILE(x.f.qid);
- case(q){
- QWctl =>
- if(w.ctlfid!=~0 && w.ctlfid==x.f.fid){
- w.ctlfid = ~0;
- w.ctllock.unlock();
- }
- QWdata or QWaddr or QWevent =>
- # BUG: do we need to shut down Xfid?
- if (q == QWdata)
- w.nomark = FALSE;
- if(--w.nopen[q] == byte 0){
- if(q == QWdata)
- w.nomark = FALSE;
- if(q==QWevent && !w.isdir && w.col!=nil){
- w.filemenu = TRUE;
- w.settag();
- }
- if(q == QWevent){
- w.dumpstr = nil;
- w.dumpdir = nil;
- }
- }
- QWrdsel =>
- w.rdselfd = nil;
- QWwrsel =>
- w.nomark = FALSE;
- t :=w.body;
- # before: only did this if !w->noscroll, but that didn't seem right in practice
- t.show(min(w.wrselrange.q0, t.file.buf.nc),
- min(w.wrselrange.q1, t.file.buf.nc), TRUE);
- scrdraw(t);
- QWconsctl=>
- w.echomode = EM_NORMAL;
- }
- w.close();
- w.unlock();
- row.qlock.unlock();
- }
- respond(x, fc, nil);
- }
-
- Xfid.read(x : self ref Xfid)
- {
- fc : Smsg0;
- n, q : int;
- off : int;
- sbuf : string;
- buf : array of byte;
- w : ref Window;
- sbuf = nil;
- q = FILE(x.f.qid);
- w = x.f.w;
- if(w == nil){
- fc.count = 0;
- case(q){
- Qcons or Qlabel =>
- ;
- Qindex =>
- x.indexread();
- return;
- * =>
- warning(nil, sprint("unknown qid %d\n", q));
- }
- respond(x, fc, nil);
- return;
- }
- w.lock('F');
- if(w.col == nil){
- w.unlock();
- respond(x, fc, Edel);
- return;
- }
- off = int offset(x.fcall);
- case(q){
- QWaddr =>
- w.body.commit(TRUE);
- clampaddr(w);
- sbuf = sprint("%11d %11d ", w.addr.q0, w.addr.q1);
- QWbody =>
- x.utfread(w.body, 0, w.body.file.buf.nc, QWbody);
- QWctl =>
- sbuf = w.ctlprint(1);
- QWevent =>
- x.eventread(w);
- QWdata =>
- # BUG: what should happen if q1 > q0?
- if(w.addr.q0 > w.body.file.buf.nc){
- respond(x, fc, Eaddr);
- break;
- }
- w.addr.q0 += x.runeread(w.body, w.addr.q0, w.body.file.buf.nc);
- w.addr.q1 = w.addr.q0;
- QWtag =>
- x.utfread(w.tag, 0, w.tag.file.buf.nc, QWtag);
- QWrdsel =>
- sys->seek(w.rdselfd, big off, 0);
- n = count(x.fcall);
- if(n > BUFSIZE)
- n = BUFSIZE;
- b := array[n] of byte;
- n = sys->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);
- b = nil;
- * =>
- sbuf = sprint("unknown qid %d in read", q);
- respond(x, fc, sbuf);
- sbuf = nil;
- }
- if (sbuf != nil) {
- buf = array of byte sbuf;
- sbuf = nil;
- n = len buf;
- if(off > n)
- off = n;
- if(off+count(x.fcall) > n)
- setcount(x.fcall, n-off);
- fc.count = count(x.fcall);
- fc.data = buf[off:];
- respond(x, fc, nil);
- buf = nil;
- }
- w.unlock();
- }
-
- Xfid.write(x : self ref Xfid)
- {
- fc : Smsg0;
- c, cnt, qid, q, nb, nr, eval : int;
- w : ref Window;
- r : string;
- a : Range;
- t : ref Text;
- q0, tq0, tq1 : int;
- md : ref Mntdir;
- qid = FILE(x.f.qid);
- w = x.f.w;
- row.qlock.lock(); # tasks->procs now
- if(w != nil){
- c = 'F';
- if(qid==QWtag || qid==QWbody)
- c = 'E';
- w.lock(c);
- if(w.col == nil){
- w.unlock();
- row.qlock.unlock();
- respond(x, fc, Edel);
- return;
- }
- }
- bodytag := 0;
- case(qid){
- Qcons =>
- md = x.f.mntdir;
- warning(md, string data(x.fcall));
- fc.count = count(x.fcall);
- respond(x, fc, nil);
- QWconsctl =>
- if (w != nil) {
- r = string data(x.fcall);
- if (strncmp(r, "rawon", 5) == 0)
- w.echomode = EM_RAW;
- else if (strncmp(r, "rawoff", 6) == 0)
- w.echomode = EM_NORMAL;
- }
- fc.count = count(x.fcall);
- respond(x, fc, nil);
- Qlabel =>
- fc.count = count(x.fcall);
- respond(x, fc, nil);
- QWaddr =>
- r = string data(x.fcall);
- nr = len r;
- t = w.body;
- w.commit(t);
- (eval, nb, a) = address(x.f.mntdir, t, w.limit, w.addr, nil, r, 0, nr, TRUE);
- r = nil;
- if(nb < nr){
- respond(x, fc, Ebadaddr);
- break;
- }
- if(!eval){
- respond(x, fc, Eaddr);
- break;
- }
- w.addr = a;
- fc.count = count(x.fcall);
- respond(x, fc, nil);
- Qeditout or
- QWeditout =>
- r = string data(x.fcall);
- nr = len r;
- if(w!=nil)
- err := ecmd->edittext(w.body.file, w.wrselrange.q1, r, nr);
- else
- err = ecmd->edittext(nil, 0, r, nr);
- r = nil;
- if(err != nil){
- respond(x, fc, err);
- break;
- }
- fc.count = count(x.fcall);
- respond(x, fc, nil);
- break;
- QWbody or QWwrsel =>
- t = w.body;
- bodytag = 1;
- QWctl =>
- x.ctlwrite(w);
- QWdata =>
- t = w.body;
- w.commit(t);
- if(w.addr.q0>t.file.buf.nc || w.addr.q1>t.file.buf.nc){
- respond(x, fc, Eaddr);
- break;
- }
- nb = sys->utfbytes(data(x.fcall), count(x.fcall));
- r = string data(x.fcall)[0:nb];
- nr = len r;
- if(w.nomark == FALSE){
- seq++;
- t.file.mark();
- }
- q0 = w.addr.q0;
- if(w.addr.q1 > q0){
- t.delete(q0, w.addr.q1, TRUE);
- w.addr.q1 = q0;
- }
- tq0 = t.q0;
- tq1 = t.q1;
- t.insert(q0, r, nr, TRUE, 0);
- if(tq0 >= q0)
- tq0 += nr;
- if(tq1 >= q0)
- tq1 += nr;
- if(!t.w.noscroll)
- t.show(tq0, tq1, TRUE);
- scrdraw(t);
- w.settag();
- r = nil;
- w.addr.q0 += nr;
- w.addr.q1 = w.addr.q0;
- fc.count = count(x.fcall);
- respond(x, fc, nil);
- QWevent =>
- x.eventwrite(w);
- QWtag =>
- t = w.tag;
- bodytag = 1;
- * =>
- r = sprint("unknown qid %d in write", qid);
- respond(x, fc, r);
- r = nil;
- }
- if (bodytag) {
- q = x.f.nrpart;
- cnt = count(x.fcall);
- if(q > 0){
- nd := array[cnt+q] of byte;
- nd[q:] = data(x.fcall)[0:cnt];
- nd[0:] = x.f.rpart[0:q];
- setdata(x.fcall, nd);
- cnt += q;
- x.f.nrpart = 0;
- }
- nb = sys->utfbytes(data(x.fcall), cnt);
- r = string data(x.fcall)[0:nb];
- nr = len r;
- if(nb < cnt){
- x.f.rpart = data(x.fcall)[nb:cnt];
- x.f.nrpart = cnt-nb;
- }
- if(nr > 0){
- t.w.commit(t);
- if(qid == QWwrsel){
- q0 = w.wrselrange.q1;
- if(q0 > t.file.buf.nc)
- q0 = t.file.buf.nc;
- }else
- q0 = t.file.buf.nc;
- if(qid == QWbody || qid == QWwrsel){
- if(!w.nomark){
- seq++;
- t.file.mark();
- }
- (q0, nr) = t.bsinsert(q0, r, nr, TRUE);
- if(qid!=QWwrsel && !t.w.noscroll)
- t.show(q0+nr, q0+nr, TRUE);
- scrdraw(t);
- }else
- t.insert(q0, r, nr, TRUE, 0);
- w.settag();
- if(qid == QWwrsel)
- w.wrselrange.q1 += nr;
- r = nil;
- }
- fc.count = count(x.fcall);
- respond(x, fc, nil);
- }
- if(w != nil)
- w.unlock();
- row.qlock.unlock();
- }
- Xfid.ctlwrite(x : self ref Xfid, w : ref Window)
- {
- fc : Smsg0;
- i, m, n, nb : int;
- r, err, p, pp : string;
- q : int;
- scrdrw, settag : int;
- t : ref Text;
- err = nil;
- scrdrw = FALSE;
- settag = FALSE;
- w.tag.commit(TRUE);
- nb = sys->utfbytes(data(x.fcall), count(x.fcall));
- r = string data(x.fcall)[0:nb];
- loop :
- for(n=0; n<len r; n+=m){
- p = r[n:];
- if(strncmp(p, "lock", 4) == 0){ # make window exclusive use
- w.ctllock.lock();
- w.ctlfid = x.f.fid;
- m = 4;
- }else
- if(strncmp(p, "unlock", 6) == 0){ # release exclusive use
- w.ctlfid = ~0;
- w.ctllock.unlock();
- m = 6;
- }else
- if(strncmp(p, "clean", 5) == 0){ # mark window 'clean', seq=0
- t = w.body;
- t.eq0 = ~0;
- t.file.reset();
- t.file.mod = FALSE;
- w.dirty = FALSE;
- settag = TRUE;
- m = 5;
- }else
- if(strncmp(p, "show", 4) == 0){ # show dot
- t = w.body;
- t.show(t.q0, t.q1, TRUE);
- m = 4;
- }else
- if(strncmp(p, "name ", 5) == 0){ # set file name
- pp = p[5:];
- m = 5;
- q = utils->strchr(pp, '\n');
- if(q<=0){
- err = Ebadctl;
- break;
- }
- nm := pp[0:q];
- for(i=0; i<len nm; i++)
- if(nm[i] <= ' '){
- err = "bad character in file name";
- break loop;
- }
- seq++;
- w.body.file.mark();
- w.setname(nm, len nm);
- m += (q+1);
- }else
- if(strncmp(p, "dump ", 5) == 0){ # set dump string
- pp = p[5:];
- m = 5;
- q = utils->strchr(pp, '\n');
- if(q<=0){
- err = Ebadctl;
- break;
- }
- nm := pp[0:q];
- w.dumpstr = nm;
- m += (q+1);
- }else
- if(strncmp(p, "dumpdir ", 8) == 0){ # set dump directory
- pp = p[8:];
- m = 8;
- q = utils->strchr(pp, '\n');
- if(q<=0){
- err = Ebadctl;
- break;
- }
- nm := pp[0:q];
- w.dumpdir = nm;
- m += (q+1);
- }else
- if(strncmp(p, "delete", 6) == 0){ # delete for sure
- w.col.close(w, TRUE);
- m = 6;
- }else
- if(strncmp(p, "del", 3) == 0){ # delete, but check dirty
- if(!w.clean(TRUE, FALSE)){
- err = "file dirty";
- break;
- }
- w.col.close(w, TRUE);
- m = 3;
- }else
- if(strncmp(p, "get", 3) == 0){ # get file
- exec->get(w.body, nil, nil, FALSE, nil, 0);
- m = 3;
- }else
- if(strncmp(p, "put", 3) == 0){ # put file
- exec->put(w.body, nil, nil, 0);
- m = 3;
- }else
- if(strncmp(p, "dot=addr", 8) == 0){ # set dot
- w.body.commit(TRUE);
- clampaddr(w);
- w.body.q0 = w.addr.q0;
- w.body.q1 = w.addr.q1;
- w.body.setselect(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
- w.body.commit(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++;
- w.body.file.mark();
- settag = 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
- w.cleartag();
- 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
- if(strncmp(p, "noecho", 6) == 0){ # don't echo chars - mask them
- w.echomode = EM_MASK;
- m = 6;
- }else
- if (strncmp(p, "echo", 4) == 0){ # echo chars (normal state)
- w.echomode = EM_NORMAL;
- m = 4;
- }else{
- err = Ebadctl;
- break;
- }
- while(m < len p && p[m] == '\n')
- m++;
- }
-
- ab := array of byte r[0:n];
- n = len ab;
- ab = nil;
- r = nil;
- if(err != nil)
- n = 0;
- fc.count = n;
- respond(x, fc, err);
- if(settag)
- w.settag();
- if(scrdrw)
- scrdraw(w.body);
- }
- Xfid.eventwrite(x : self ref Xfid, w : ref Window)
- {
- fc : Smsg0;
- m, n, nb : int;
- r, err : string;
- p, q : int;
- t : ref Text;
- c : int;
- q0, q1 : int;
- err = nil;
- nb = sys->utfbytes(data(x.fcall), count(x.fcall));
- r = string data(x.fcall)[0:nb];
- loop :
- for(n=0; n<len r; n+=m){
- p = n;
- w.owner = r[p++]; # disgusting
- c = r[p++];
- while(r[p] == ' ')
- p++;
- q0 = int r[p:];
- q = p;
- if (r[q] == '+' || r[q] == '-')
- q++;
- while (r[q] >= '0' && r[q] <= '9')
- q++;
- if(q == p) {
- err = Ebadevent;
- break;
- }
- p = q;
- while(r[p] == ' ')
- p++;
- q1 = int r[p:];
- q = p;
- if (r[q] == '+' || r[q] == '-')
- q++;
- while (r[q] >= '0' && r[q] <= '9')
- q++;
- if(q == p) {
- err = Ebadevent;
- break;
- }
- p = q;
- while(r[p] == ' ')
- p++;
- if(r[p++] != '\n') {
- err = Ebadevent;
- break;
- }
- m = p-n;
- if('a'<=c && c<='z')
- t = w.tag;
- else if('A'<=c && c<='Z')
- t = w.body;
- else {
- err = Ebadevent;
- break;
- }
- if(q0>t.file.buf.nc || q1>t.file.buf.nc || q0>q1) {
- err = Ebadevent;
- break;
- }
- # row.qlock.lock();
- case(c){
- 'x' or 'X' =>
- exec->execute(t, q0, q1, TRUE, nil);
- 'l' or 'L' =>
- look->look3(t, q0, q1, TRUE);
- * =>
- err = Ebadevent;
- break loop;
- }
- # row.qlock.unlock();
- }
- ab := array of byte r[0:n];
- n = len ab;
- ab = nil;
- r = nil;
- if(err != nil)
- n = 0;
- fc.count = n;
- respond(x, fc, err);
- }
- Xfid.utfread(x : self ref Xfid, t : ref Text, q0, q1 : int, qid : int)
- {
- fc : Smsg0;
- w : ref Window;
- r : ref Astring;
- b, b1 : array of byte;
- q, off, boff : int;
- m, n, nr, nb : int;
- w = t.w;
- w.commit(t);
- off = int offset(x.fcall);
- r = stralloc(BUFSIZE);
- b1 = array[MAXRPC] of byte;
- 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 = q0;
- }
- w.utflastqid = qid;
- while(q<q1 && n<count(x.fcall)){
- w.utflastboff = boff;
- w.utflastq = q;
- nr = q1-q;
- if(nr > BUFSIZE)
- nr = BUFSIZE;
- t.file.buf.read(q, r, 0, nr);
- b = array of byte r.s[0:nr];
- nb = len b;
- if(boff >= off){
- m = nb;
- if(boff+m > off+count(x.fcall))
- m = off+count(x.fcall) - boff;
- b1[n:] = b[0:m];
- n += m;
- }else if(boff+nb > off){
- if(n != 0)
- error("bad count in utfrune");
- m = nb - (off-boff);
- if(m > count(x.fcall))
- m = count(x.fcall);
- b1[0:] = b[off-boff:off-boff+m];
- n += m;
- }
- b = nil;
- boff += nb;
- q += nr;
- }
- strfree(r);
- r = nil;
- fc.count = n;
- fc.data = b1;
- respond(x, fc, nil);
- b1 = nil;
- }
- Xfid.runeread(x : self ref Xfid, t : ref Text, q0, q1 : int) : int
- {
- fc : Smsg0;
- w : ref Window;
- r : ref Astring;
- junk, ok : int;
- b, b1 : array of byte;
- q, boff : int;
- i, rw, m, n, nr, nb : int;
- w = t.w;
- w.commit(t);
- r = stralloc(BUFSIZE);
- b1 = array[MAXRPC] of byte;
- n = 0;
- q = q0;
- boff = 0;
- while(q<q1 && n<count(x.fcall)){
- nr = q1-q;
- if(nr > BUFSIZE)
- nr = BUFSIZE;
- t.file.buf.read(q, r, 0, nr);
- b = array of byte r.s[0:nr];
- nb = len b;
- m = nb;
- if(boff+m > count(x.fcall)){
- i = count(x.fcall) - boff;
- # copy whole runes only
- m = 0;
- nr = 0;
- while(m < i){
- (junk, rw, ok) = sys->byte2char(b, m);
- if(m+rw > i)
- break;
- m += rw;
- nr++;
- }
- if(m == 0)
- break;
- }
- b1[n:] = b[0:m];
- b = nil;
- n += m;
- boff += nb;
- q += nr;
- }
- strfree(r);
- r = nil;
- fc.count = n;
- fc.data = b1;
- respond(x, fc, nil);
- b1 = nil;
- return q-q0;
- }
- Xfid.eventread(x : self ref Xfid, w : ref Window)
- {
- fc : Smsg0;
- b : string;
- i, n : int;
- i = 0;
- x.flushed = FALSE;
- while(w.nevents == 0){
- if(i){
- if(!x.flushed)
- respond(x, fc, "window shut down");
- return;
- }
- w.eventx = x;
- w.unlock();
- <- x.c;
- w.lock('F');
- i++;
- }
- eveb := array of byte w.events;
- ne := len eveb;
- n = w.nevents;
- if(ne > count(x.fcall)) {
- ne = count(x.fcall);
- while (sys->utfbytes(eveb, ne) != ne)
- --ne;
- s := string eveb[0:ne];
- n = len s;
- s = nil;
- }
- fc.count = ne;
- fc.data = eveb;
- respond(x, fc, nil);
- b = w.events;
- w.events = w.events[n:];
- b = nil;
- w.nevents -= n;
- eveb = nil;
- }
- Xfid.indexread(x : self ref Xfid)
- {
- fc : Smsg0;
- i, j, m, n, nmax, cnt, off : int;
- w : ref Window;
- b : array of byte;
- r : ref Astring;
- c : ref Column;
- row.qlock.lock();
- 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.buf.nc*UTFmax + 1;
- }
- }
- nmax++;
- b = array[nmax] of byte;
- r = stralloc(BUFSIZE);
- 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;
- ctls := w.ctlprint(0);
- ctlb := array of byte ctls;
- if (len ctls != Ctlsize || len ctlb != Ctlsize)
- error("bad length in indexread");
- b[n:] = ctlb[0:];
- n += Ctlsize;
- ctls = nil;
- ctlb = nil;
- m = min(BUFSIZE, w.tag.file.buf.nc);
- w.tag.file.buf.read(0, r, 0, m);
- rb := array of byte r.s[0:m];
- b[n:] = rb[0:len rb];
- m = n+len rb;
- rb = nil;
- while(n<m && b[n]!=byte '\n')
- n++;
- b[n++] = byte '\n';
- }
- }
- row.qlock.unlock();
- off = int offset(x.fcall);
- cnt = count(x.fcall);
- if(off > n)
- off = n;
- if(off+cnt > n)
- cnt = n-off;
- fc.count = cnt;
- fc.data = b[off:off+cnt];
- respond(x, fc, nil);
- b = nil;
- strfree(r);
- r = nil;
- }
|