implement Exec; include "common.m"; sys : Sys;dat : Dat;acme : Acme;utils : Utils;graph : Graph;gui : Gui;lookx : Look;bufferm : Bufferm;textm : Textm;scrl : Scroll;filem : Filem;windowm : Windowm;rowm : Rowm;columnm : Columnm;fsys : Fsys;editm: Edit; Dir, OREAD, OWRITE : import Sys;EVENTSIZE, QWaddr, QWdata, QWevent, Astring : import dat;Lock, Reffont, Ref, seltext, seq, row : import dat;warning, error, skipbl, findbl, stralloc, strfree, exec : import utils;dirname : import lookx;Body, Text : import textm;File : import filem;sprint : import sys;TRUE, FALSE, XXX, BUFSIZE : import Dat;Buffer : import bufferm;Row : import rowm;Column : import columnm;Window : import windowm;setalphabet: import textm; # snarfbuf : ref Buffer; init(mods : ref Dat->Mods){ sys = mods.sys; dat = mods.dat; acme = mods.acme; utils = mods.utils; graph = mods.graph; gui = mods.gui; lookx = mods.look; bufferm = mods.bufferm; textm = mods.textm; scrl = mods.scroll; filem = mods.filem; rowm = mods.rowm; windowm = mods.windowm; columnm = mods.columnm; fsys = mods.fsys; editm = mods.edit; snarfbuf = bufferm->newbuffer();} Exectab : adt { name : string; fun : int; mark : int; flag1 : int; flag2 : int;}; F_ALPHABET, F_CUT, F_DEL, F_DELCOL, F_DUMP, F_EDIT, F_EXITX, F_FONTX, F_GET, F_ID, F_INCL, F_KILL, F_LIMBO, F_LINENO, F_LOCAL, F_LOOK, F_NEW, F_NEWCOL, F_PASTE, F_PUT, F_PUTALL, F_UNDO, F_SEND, F_SORT, F_TAB, F_ZEROX : con iota; exectab := array[] of { Exectab ( "Alphabet", F_ALPHABET, FALSE, XXX, XXX ), Exectab ( "Cut", F_CUT, TRUE, TRUE, TRUE ), Exectab ( "Del", F_DEL, FALSE, FALSE, XXX ), Exectab ( "Delcol", F_DELCOL, FALSE, XXX, XXX ), Exectab ( "Delete", F_DEL, FALSE, TRUE, XXX ), Exectab ( "Dump", F_DUMP, FALSE, TRUE, XXX ), Exectab ( "Edit", F_EDIT, FALSE, XXX, XXX ), Exectab ( "Exit", F_EXITX, FALSE, XXX, XXX ), Exectab ( "Font", F_FONTX, FALSE, XXX, XXX ), Exectab ( "Get", F_GET, FALSE, TRUE, XXX ), Exectab ( "ID", F_ID, FALSE, XXX, XXX ), Exectab ( "Incl", F_INCL, FALSE, XXX, XXX ), Exectab ( "Kill", F_KILL, FALSE, XXX, XXX ), Exectab ( "Limbo", F_LIMBO, FALSE, XXX, XXX ), Exectab ( "Lineno", F_LINENO, FALSE, XXX, XXX ), Exectab ( "Load", F_DUMP, FALSE, FALSE, XXX ), Exectab ( "Local", F_LOCAL, FALSE, XXX, XXX ), Exectab ( "Look", F_LOOK, FALSE, XXX, XXX ), Exectab ( "New", F_NEW, FALSE, XXX, XXX ), Exectab ( "Newcol", F_NEWCOL, FALSE, XXX, XXX ), Exectab ( "Paste", F_PASTE, TRUE, TRUE, XXX ), Exectab ( "Put", F_PUT, FALSE, XXX, XXX ), Exectab ( "Putall", F_PUTALL, FALSE, XXX, XXX ), Exectab ( "Redo", F_UNDO, FALSE, FALSE, XXX ), Exectab ( "Send", F_SEND, TRUE, XXX, XXX ), Exectab ( "Snarf", F_CUT, FALSE, TRUE, FALSE ), Exectab ( "Sort", F_SORT, FALSE, XXX, XXX ), Exectab ( "Tab", F_TAB, FALSE, XXX, XXX ), Exectab ( "Undo", F_UNDO, FALSE, TRUE, XXX ), Exectab ( "Zerox", F_ZEROX, FALSE, XXX, XXX ), Exectab ( nil, 0, 0, 0, 0 ),}; runfun(fun : int, et, t, argt : ref Text, flag1, flag2 : int, arg : string, narg : int){ case (fun) { F_ALPHABET => alphabet(et, argt, arg, narg); F_CUT => cut(et, t, flag1, flag2); F_DEL => del(et, flag1); F_DELCOL => delcol(et); F_DUMP => dump(argt, flag1, arg, narg); F_EDIT => edit(et, argt, arg, narg); F_EXITX => exitx(); F_FONTX => fontx(et, t, argt, arg, narg); F_GET => get(et, t, argt, flag1, arg, narg); F_ID => id(et); F_INCL => incl(et, argt, arg, narg); F_KILL => kill(argt, arg, narg); F_LIMBO => limbo(et); F_LINENO => lineno(et); F_LOCAL => local(et, argt, arg); F_LOOK => look(et, t, argt); F_NEW => lookx->new(et, t, argt, flag1, flag2, arg, narg); F_NEWCOL => newcol(et); F_PASTE => paste(et, t, flag1, flag2); F_PUT => put(et, argt, arg, narg); F_PUTALL => putall(); F_UNDO => undo(et, flag1); F_SEND => send(et, t); F_SORT => sort(et); F_TAB => tab(et, argt, arg, narg); F_ZEROX => zerox(et, t); * => error("bad case in runfun()"); }} lookup(r : string, n : int) : int{ nr : int; (r, n) = skipbl(r, n); if(n == 0) return -1; (nil, nr) = findbl(r, n); nr = n-nr; for(i := 0; exectab[i].name != nil; i++) if (r[0:nr] == exectab[i].name) return i; return -1;} isexecc(c : int) : int{ if(lookx->isfilec(c)) return 1; return c=='<' || c=='|' || c=='>';} execute(t : ref Text, aq0 : int, aq1 : int, external : int, argt : ref Text){ q0, q1 : int; r : ref Astring; s, dir, aa, a : string; e : int; c, n, f : int; q0 = aq0; q1 = aq1; if(q1 == q0){ # expand to find word (actually file name) # if in selection, choose selection if(t.q1>t.q0 && t.q0<=q0 && q0<=t.q1){ q0 = t.q0; q1 = t.q1; }else{ while(q1<t.file.buf.nc && isexecc(c=t.readc(q1)) && c!=':') q1++; while(q0>0 && isexecc(c=t.readc(q0-1)) && c!=':') q0--; if(q1 == q0) return; } } r = stralloc(q1-q0); t.file.buf.read(q0, r, 0, q1-q0); e = lookup(r.s, q1-q0); if(!external && t.w!=nil && t.w.nopen[QWevent]>byte 0){ f = 0; if(e >= 0) f |= 1; if(q0!=aq0 || q1!=aq1){ t.file.buf.read(aq0, r, 0, aq1-aq0); f |= 2; } (aa, a) = getbytearg(argt, TRUE, TRUE); if(a != nil){ if(len a > EVENTSIZE){ # too big; too bad aa = a = nil; warning(nil, "`argument string too long\n"); return; } f |= 8; } c = 'x'; if(t.what == Body) c = 'X'; n = aq1-aq0; if(n <= EVENTSIZE) t.w.event(sprint("%c%d %d %d %d %s\n", c, aq0, aq1, f, n, r.s[0:n])); else t.w.event(sprint("%c%d %d %d 0 \n", c, aq0, aq1, f)); if(q0!=aq0 || q1!=aq1){ n = q1-q0; t.file.buf.read(q0, r, 0, n); if(n <= EVENTSIZE) t.w.event(sprint("%c%d %d 0 %d %s\n", c, q0, q1, n, r.s[0:n])); else t.w.event(sprint("%c%d %d 0 0 \n", c, q0, q1)); } if(a != nil){ t.w.event(sprint("%c0 0 0 %d %s\n", c, len a, a)); if(aa != nil) t.w.event(sprint("%c0 0 0 %d %s\n", c, len aa, aa)); else t.w.event(sprint("%c0 0 0 0 \n", c)); } strfree(r); r = nil; a = aa = nil; return; } if(e >= 0){ if(exectab[e].mark && seltext!=nil) if(seltext.what == Body){ seq++; seltext.w.body.file.mark(); } (s, n) = skipbl(r.s, q1-q0); (s, n) = findbl(s, n); (s, n) = skipbl(s, n); runfun(exectab[e].fun, t, seltext, argt, exectab[e].flag1, exectab[e].flag2, s, n); strfree(r); r = nil; return; } (dir, n) = dirname(t, nil, 0); if(n==1 && dir[0]=='.'){ # sigh dir = nil; n = 0; } (aa, a) = getbytearg(argt, TRUE, TRUE); if(t.w != nil) t.w.refx.inc(); spawn run(t.w, r.s, dir, n, TRUE, aa, a, FALSE);} printarg(argt : ref Text, q0 : int, q1 : int) : string{ buf : string; if(argt.what!=Body || argt.file.name==nil) return nil; if(q0 == q1) buf = sprint("%s:#%d", argt.file.name, q0); else buf = sprint("%s:#%d,#%d", argt.file.name, q0, q1); return buf;} getarg(argt : ref Text, doaddr : int, dofile : int) : (string, string, int){ r : ref Astring; n : int; e : Dat->Expand; a : string; ok : int; if(argt == nil) return (nil, nil, 0); a = nil; argt.commit(TRUE); (ok, e) = lookx->expand(argt, argt.q0, argt.q1); if (ok) { e.bname = nil; if(len e.name && dofile){ if(doaddr) a = printarg(argt, e.q0, e.q1); return (a, e.name, len e.name); } e.name = nil; }else{ e.q0 = argt.q0; e.q1 = argt.q1; } n = e.q1 - e.q0; r = stralloc(n); argt.file.buf.read(e.q0, r, 0, n); if(doaddr) a = printarg(argt, e.q0, e.q1); return(a, r.s, n);} getbytearg(argt : ref Text, doaddr : int, dofile : int) : (string, string){ r : string; n : int; aa : string; (aa, r, n) = getarg(argt, doaddr, dofile); if(r == nil) return (nil, nil); return (aa, r);} newcol(et : ref Text){ c : ref Column; c = et.row.add(nil, -1); if(c != nil) c.add(nil, nil, -1).settag();} delcol(et : ref Text){ c := et.col; if(c==nil || !c.clean(FALSE)) return; for(i:=0; i<c.nw; i++){ w := c.w[i]; if(int w.nopen[QWevent]+int w.nopen[QWaddr]+int w.nopen[QWdata] > 0){ warning(nil, sys->sprint("can't delete column; %s is running an external command\n", w.body.file.name)); return; } } c.row.close(c, TRUE);} del(et : ref Text, flag1 : int){ if(et.col==nil || et.w == nil) return; if(flag1 || et.w.body.file.ntext>1 || et.w.clean(FALSE, FALSE)) et.col.close(et.w, TRUE);} sort(et : ref Text){ if(et.col != nil) et.col.sort();} seqof(w: ref Window, isundo: int): int{ # if it's undo, see who changed with us if(isundo) return w.body.file.seq; # if it's redo, see who we'll be sync'ed up with return w.body.file.redoseq();} undo(et : ref Text, flag1 : int){ i, j: int; c: ref Column; w: ref Window; seq: int; if(et==nil || et.w== nil) return; seq = seqof(et.w, flag1); for(i=0; i<row.ncol; i++){ c = row.col[i]; for(j=0; j<c.nw; j++){ w = c.w[j]; if(seqof(w, flag1) == seq) w.undo(flag1); } } # et.w.undo(flag1);} getname(t : ref Text, argt : ref Text, arg : string, narg : int, isput : int) : string{ r, dir : string; i, n, ndir, promote : int; (nil, r, n) = getarg(argt, FALSE, TRUE); promote = FALSE; if(r == nil) promote = TRUE; else if(isput){ # if are doing a Put, want to synthesize name even for non-existent file # best guess is that file name doesn't contain a slash promote = TRUE; for(i=0; i<n; i++) if(r[i] == '/'){ promote = FALSE; break; } if(promote){ t = argt; arg = r; narg = n; } } if(promote){ n = narg; if(n <= 0) return t.file.name; # prefix with directory name if necessary dir = nil; ndir = 0; if(n>0 && arg[0]!='/'){ (dir, ndir) = dirname(t, nil, 0); if(n==1 && dir[0]=='.'){ # sigh dir = nil; ndir = 0; } } if(dir != nil){ r = dir[0:ndir] + arg[0:n]; dir = nil; n += ndir; }else r = arg[0:n]; } return r;} zerox(et : ref Text, t : ref Text){ nw : ref Window; c, locked : int; locked = FALSE; if(t!=nil && t.w!=nil && t.w!=et.w){ locked = TRUE; c = 'M'; if(et.w != nil) c = et.w.owner; t.w.lock(c); } if(t == nil) t = et; if(t==nil || t.w==nil) return; t = t.w.body; if(t.w.isdir) warning(nil, sprint("%s is a directory; Zerox illegal\n", t.file.name)); else{ nw = t.w.col.add(nil, t.w, -1); # ugly: fix locks so w.unlock works nw.lock1(t.w.owner); } if(locked) t.w.unlock();} get(et : ref Text, t : ref Text, argt : ref Text, flag1 : int, arg : string, narg : int){ name : string; r : string; i, n, dirty : int; w : ref Window; u : ref Text; d : Dir; ok : int; if(flag1) if(et==nil || et.w==nil) return; if(!et.w.isdir && (et.w.body.file.buf.nc>0 && !et.w.clean(TRUE, FALSE))) return; w = et.w; t = w.body; name = getname(t, argt, arg, narg, FALSE); if(name == nil){ warning(nil, "no file name\n"); return; } if(t.file.ntext>1){ (ok, d) = sys->stat(name); if (ok == 0 && d.qid.qtype & Sys->QTDIR) { warning(nil, sprint("%s is a directory; can't read with multiple windows on it\n", name)); return; } } r = name; n = len name; for(i=0; i<t.file.ntext; i++){ u = t.file.text[i]; # second and subsequent calls with zero an already empty buffer, but OK u.reset(); u.w.dirfree(); } samename := r[0:n] == t.file.name; t.loadx(0, name, samename); if(samename){Lines 1–500 of 1350. Load more
implement Exec; include "common.m"; sys : Sys; dat : Dat; acme : Acme; utils : Utils; graph : Graph; gui : Gui; lookx : Look; bufferm : Bufferm; textm : Textm; scrl : Scroll; filem : Filem; windowm : Windowm; rowm : Rowm; columnm : Columnm; fsys : Fsys; editm: Edit; Dir, OREAD, OWRITE : import Sys; EVENTSIZE, QWaddr, QWdata, QWevent, Astring : import dat; Lock, Reffont, Ref, seltext, seq, row : import dat; warning, error, skipbl, findbl, stralloc, strfree, exec : import utils; dirname : import lookx; Body, Text : import textm; File : import filem; sprint : import sys; TRUE, FALSE, XXX, BUFSIZE : import Dat; Buffer : import bufferm; Row : import rowm; Column : import columnm; Window : import windowm; setalphabet: import textm; # snarfbuf : ref Buffer; init(mods : ref Dat->Mods) { sys = mods.sys; dat = mods.dat; acme = mods.acme; utils = mods.utils; graph = mods.graph; gui = mods.gui; lookx = mods.look; bufferm = mods.bufferm; textm = mods.textm; scrl = mods.scroll; filem = mods.filem; rowm = mods.rowm; windowm = mods.windowm; columnm = mods.columnm; fsys = mods.fsys; editm = mods.edit; snarfbuf = bufferm->newbuffer(); } Exectab : adt { name : string; fun : int; mark : int; flag1 : int; flag2 : int; }; F_ALPHABET, F_CUT, F_DEL, F_DELCOL, F_DUMP, F_EDIT, F_EXITX, F_FONTX, F_GET, F_ID, F_INCL, F_KILL, F_LIMBO, F_LINENO, F_LOCAL, F_LOOK, F_NEW, F_NEWCOL, F_PASTE, F_PUT, F_PUTALL, F_UNDO, F_SEND, F_SORT, F_TAB, F_ZEROX : con iota; exectab := array[] of { Exectab ( "Alphabet", F_ALPHABET, FALSE, XXX, XXX ), Exectab ( "Cut", F_CUT, TRUE, TRUE, TRUE ), Exectab ( "Del", F_DEL, FALSE, FALSE, XXX ), Exectab ( "Delcol", F_DELCOL, FALSE, XXX, XXX ), Exectab ( "Delete", F_DEL, FALSE, TRUE, XXX ), Exectab ( "Dump", F_DUMP, FALSE, TRUE, XXX ), Exectab ( "Edit", F_EDIT, FALSE, XXX, XXX ), Exectab ( "Exit", F_EXITX, FALSE, XXX, XXX ), Exectab ( "Font", F_FONTX, FALSE, XXX, XXX ), Exectab ( "Get", F_GET, FALSE, TRUE, XXX ), Exectab ( "ID", F_ID, FALSE, XXX, XXX ), Exectab ( "Incl", F_INCL, FALSE, XXX, XXX ), Exectab ( "Kill", F_KILL, FALSE, XXX, XXX ), Exectab ( "Limbo", F_LIMBO, FALSE, XXX, XXX ), Exectab ( "Lineno", F_LINENO, FALSE, XXX, XXX ), Exectab ( "Load", F_DUMP, FALSE, FALSE, XXX ), Exectab ( "Local", F_LOCAL, FALSE, XXX, XXX ), Exectab ( "Look", F_LOOK, FALSE, XXX, XXX ), Exectab ( "New", F_NEW, FALSE, XXX, XXX ), Exectab ( "Newcol", F_NEWCOL, FALSE, XXX, XXX ), Exectab ( "Paste", F_PASTE, TRUE, TRUE, XXX ), Exectab ( "Put", F_PUT, FALSE, XXX, XXX ), Exectab ( "Putall", F_PUTALL, FALSE, XXX, XXX ), Exectab ( "Redo", F_UNDO, FALSE, FALSE, XXX ), Exectab ( "Send", F_SEND, TRUE, XXX, XXX ), Exectab ( "Snarf", F_CUT, FALSE, TRUE, FALSE ), Exectab ( "Sort", F_SORT, FALSE, XXX, XXX ), Exectab ( "Tab", F_TAB, FALSE, XXX, XXX ), Exectab ( "Undo", F_UNDO, FALSE, TRUE, XXX ), Exectab ( "Zerox", F_ZEROX, FALSE, XXX, XXX ), Exectab ( nil, 0, 0, 0, 0 ), }; runfun(fun : int, et, t, argt : ref Text, flag1, flag2 : int, arg : string, narg : int) { case (fun) { F_ALPHABET => alphabet(et, argt, arg, narg); F_CUT => cut(et, t, flag1, flag2); F_DEL => del(et, flag1); F_DELCOL => delcol(et); F_DUMP => dump(argt, flag1, arg, narg); F_EDIT => edit(et, argt, arg, narg); F_EXITX => exitx(); F_FONTX => fontx(et, t, argt, arg, narg); F_GET => get(et, t, argt, flag1, arg, narg); F_ID => id(et); F_INCL => incl(et, argt, arg, narg); F_KILL => kill(argt, arg, narg); F_LIMBO => limbo(et); F_LINENO => lineno(et); F_LOCAL => local(et, argt, arg); F_LOOK => look(et, t, argt); F_NEW => lookx->new(et, t, argt, flag1, flag2, arg, narg); F_NEWCOL => newcol(et); F_PASTE => paste(et, t, flag1, flag2); F_PUT => put(et, argt, arg, narg); F_PUTALL => putall(); F_UNDO => undo(et, flag1); F_SEND => send(et, t); F_SORT => sort(et); F_TAB => tab(et, argt, arg, narg); F_ZEROX => zerox(et, t); * => error("bad case in runfun()"); } } lookup(r : string, n : int) : int { nr : int; (r, n) = skipbl(r, n); if(n == 0) return -1; (nil, nr) = findbl(r, n); nr = n-nr; for(i := 0; exectab[i].name != nil; i++) if (r[0:nr] == exectab[i].name) return i; return -1; } isexecc(c : int) : int { if(lookx->isfilec(c)) return 1; return c=='<' || c=='|' || c=='>'; } execute(t : ref Text, aq0 : int, aq1 : int, external : int, argt : ref Text) { q0, q1 : int; r : ref Astring; s, dir, aa, a : string; e : int; c, n, f : int; q0 = aq0; q1 = aq1; if(q1 == q0){ # expand to find word (actually file name) # if in selection, choose selection if(t.q1>t.q0 && t.q0<=q0 && q0<=t.q1){ q0 = t.q0; q1 = t.q1; }else{ while(q1<t.file.buf.nc && isexecc(c=t.readc(q1)) && c!=':') q1++; while(q0>0 && isexecc(c=t.readc(q0-1)) && c!=':') q0--; if(q1 == q0) return; } } r = stralloc(q1-q0); t.file.buf.read(q0, r, 0, q1-q0); e = lookup(r.s, q1-q0); if(!external && t.w!=nil && t.w.nopen[QWevent]>byte 0){ f = 0; if(e >= 0) f |= 1; if(q0!=aq0 || q1!=aq1){ t.file.buf.read(aq0, r, 0, aq1-aq0); f |= 2; } (aa, a) = getbytearg(argt, TRUE, TRUE); if(a != nil){ if(len a > EVENTSIZE){ # too big; too bad aa = a = nil; warning(nil, "`argument string too long\n"); return; } f |= 8; } c = 'x'; if(t.what == Body) c = 'X'; n = aq1-aq0; if(n <= EVENTSIZE) t.w.event(sprint("%c%d %d %d %d %s\n", c, aq0, aq1, f, n, r.s[0:n])); else t.w.event(sprint("%c%d %d %d 0 \n", c, aq0, aq1, f)); if(q0!=aq0 || q1!=aq1){ n = q1-q0; t.file.buf.read(q0, r, 0, n); if(n <= EVENTSIZE) t.w.event(sprint("%c%d %d 0 %d %s\n", c, q0, q1, n, r.s[0:n])); else t.w.event(sprint("%c%d %d 0 0 \n", c, q0, q1)); } if(a != nil){ t.w.event(sprint("%c0 0 0 %d %s\n", c, len a, a)); if(aa != nil) t.w.event(sprint("%c0 0 0 %d %s\n", c, len aa, aa)); else t.w.event(sprint("%c0 0 0 0 \n", c)); } strfree(r); r = nil; a = aa = nil; return; } if(e >= 0){ if(exectab[e].mark && seltext!=nil) if(seltext.what == Body){ seq++; seltext.w.body.file.mark(); } (s, n) = skipbl(r.s, q1-q0); (s, n) = findbl(s, n); (s, n) = skipbl(s, n); runfun(exectab[e].fun, t, seltext, argt, exectab[e].flag1, exectab[e].flag2, s, n); strfree(r); r = nil; return; } (dir, n) = dirname(t, nil, 0); if(n==1 && dir[0]=='.'){ # sigh dir = nil; n = 0; } (aa, a) = getbytearg(argt, TRUE, TRUE); if(t.w != nil) t.w.refx.inc(); spawn run(t.w, r.s, dir, n, TRUE, aa, a, FALSE); } printarg(argt : ref Text, q0 : int, q1 : int) : string { buf : string; if(argt.what!=Body || argt.file.name==nil) return nil; if(q0 == q1) buf = sprint("%s:#%d", argt.file.name, q0); else buf = sprint("%s:#%d,#%d", argt.file.name, q0, q1); return buf; } getarg(argt : ref Text, doaddr : int, dofile : int) : (string, string, int) { r : ref Astring; n : int; e : Dat->Expand; a : string; ok : int; if(argt == nil) return (nil, nil, 0); a = nil; argt.commit(TRUE); (ok, e) = lookx->expand(argt, argt.q0, argt.q1); if (ok) { e.bname = nil; if(len e.name && dofile){ if(doaddr) a = printarg(argt, e.q0, e.q1); return (a, e.name, len e.name); } e.name = nil; }else{ e.q0 = argt.q0; e.q1 = argt.q1; } n = e.q1 - e.q0; r = stralloc(n); argt.file.buf.read(e.q0, r, 0, n); if(doaddr) a = printarg(argt, e.q0, e.q1); return(a, r.s, n); } getbytearg(argt : ref Text, doaddr : int, dofile : int) : (string, string) { r : string; n : int; aa : string; (aa, r, n) = getarg(argt, doaddr, dofile); if(r == nil) return (nil, nil); return (aa, r); } newcol(et : ref Text) { c : ref Column; c = et.row.add(nil, -1); if(c != nil) c.add(nil, nil, -1).settag(); } delcol(et : ref Text) { c := et.col; if(c==nil || !c.clean(FALSE)) return; for(i:=0; i<c.nw; i++){ w := c.w[i]; if(int w.nopen[QWevent]+int w.nopen[QWaddr]+int w.nopen[QWdata] > 0){ warning(nil, sys->sprint("can't delete column; %s is running an external command\n", w.body.file.name)); return; } } c.row.close(c, TRUE); } del(et : ref Text, flag1 : int) { if(et.col==nil || et.w == nil) return; if(flag1 || et.w.body.file.ntext>1 || et.w.clean(FALSE, FALSE)) et.col.close(et.w, TRUE); } sort(et : ref Text) { if(et.col != nil) et.col.sort(); } seqof(w: ref Window, isundo: int): int { # if it's undo, see who changed with us if(isundo) return w.body.file.seq; # if it's redo, see who we'll be sync'ed up with return w.body.file.redoseq(); } undo(et : ref Text, flag1 : int) { i, j: int; c: ref Column; w: ref Window; seq: int; if(et==nil || et.w== nil) return; seq = seqof(et.w, flag1); for(i=0; i<row.ncol; i++){ c = row.col[i]; for(j=0; j<c.nw; j++){ w = c.w[j]; if(seqof(w, flag1) == seq) w.undo(flag1); } } # et.w.undo(flag1); } getname(t : ref Text, argt : ref Text, arg : string, narg : int, isput : int) : string { r, dir : string; i, n, ndir, promote : int; (nil, r, n) = getarg(argt, FALSE, TRUE); promote = FALSE; if(r == nil) promote = TRUE; else if(isput){ # if are doing a Put, want to synthesize name even for non-existent file # best guess is that file name doesn't contain a slash promote = TRUE; for(i=0; i<n; i++) if(r[i] == '/'){ promote = FALSE; break; } if(promote){ t = argt; arg = r; narg = n; } } if(promote){ n = narg; if(n <= 0) return t.file.name; # prefix with directory name if necessary dir = nil; ndir = 0; if(n>0 && arg[0]!='/'){ (dir, ndir) = dirname(t, nil, 0); if(n==1 && dir[0]=='.'){ # sigh dir = nil; ndir = 0; } } if(dir != nil){ r = dir[0:ndir] + arg[0:n]; dir = nil; n += ndir; }else r = arg[0:n]; } return r; } zerox(et : ref Text, t : ref Text) { nw : ref Window; c, locked : int; locked = FALSE; if(t!=nil && t.w!=nil && t.w!=et.w){ locked = TRUE; c = 'M'; if(et.w != nil) c = et.w.owner; t.w.lock(c); } if(t == nil) t = et; if(t==nil || t.w==nil) return; t = t.w.body; if(t.w.isdir) warning(nil, sprint("%s is a directory; Zerox illegal\n", t.file.name)); else{ nw = t.w.col.add(nil, t.w, -1); # ugly: fix locks so w.unlock works nw.lock1(t.w.owner); } if(locked) t.w.unlock(); } get(et : ref Text, t : ref Text, argt : ref Text, flag1 : int, arg : string, narg : int) { name : string; r : string; i, n, dirty : int; w : ref Window; u : ref Text; d : Dir; ok : int; if(flag1) if(et==nil || et.w==nil) return; if(!et.w.isdir && (et.w.body.file.buf.nc>0 && !et.w.clean(TRUE, FALSE))) return; w = et.w; t = w.body; name = getname(t, argt, arg, narg, FALSE); if(name == nil){ warning(nil, "no file name\n"); return; } if(t.file.ntext>1){ (ok, d) = sys->stat(name); if (ok == 0 && d.qid.qtype & Sys->QTDIR) { warning(nil, sprint("%s is a directory; can't read with multiple windows on it\n", name)); return; } } r = name; n = len name; for(i=0; i<t.file.ntext; i++){ u = t.file.text[i]; # second and subsequent calls with zero an already empty buffer, but OK u.reset(); u.w.dirfree(); } samename := r[0:n] == t.file.name; t.loadx(0, name, samename); if(samename){