123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350 |
- 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){
- t.file.mod = FALSE;
- dirty = FALSE;
- }else{
- t.file.mod = TRUE;
- dirty = TRUE;
- }
- for(i=0; i<t.file.ntext; i++)
- t.file.text[i].w.dirty = dirty;
- name = nil;
- r = nil;
- w.settag();
- t.file.unread = FALSE;
- for(i=0; i<t.file.ntext; i++){
- u = t.file.text[i];
- u.w.tag.setselect(u.w.tag.file.buf.nc, u.w.tag.file.buf.nc);
- scrl->scrdraw(u);
- }
- }
- putfile(f: ref File, q0: int, q1: int, name: string)
- {
- n : int;
- r, s : ref Astring;
- w : ref Window;
- i, q : int;
- fd : ref Sys->FD;
- d : Dir;
- ok : int;
- w = f.curtext.w;
-
- {
- if(name == f.name){
- (ok, d) = sys->stat(name);
- if(ok >= 0 && (f.dev!=d.dev || f.qidpath!=d.qid.path || f.mtime<d.mtime)){
- f.dev = d.dev;
- f.qidpath = d.qid.path;
- f.mtime = d.mtime;
- if(f.unread)
- warning(nil, sys->sprint("%s not written; file already exists\n", name));
- else
- warning(nil, sys->sprint("%s modified since last read\n", name));
- raise "e";
- }
- }
- fd = sys->create(name, OWRITE, 8r664); # was 666
- if(fd == nil){
- warning(nil, sprint("can't create file %s: %r\n", name));
- raise "e";
- }
- r = stralloc(BUFSIZE);
- s = stralloc(BUFSIZE);
-
- {
- (ok, d) = sys->fstat(fd);
- if(ok>=0 && (d.mode&Sys->DMAPPEND) && d.length>big 0){
- warning(nil, sprint("%s not written; file is append only\n", name));
- raise "e";
- }
- for(q = q0; q < q1; q += n){
- n = q1 - q;
- if(n > BUFSIZE)
- n = BUFSIZE;
- f.buf.read(q, r, 0, n);
- ab := array of byte r.s[0:n];
- if(sys->write(fd, ab, len ab) != len ab){
- ab = nil;
- warning(nil, sprint("can't write file %s: %r\n", name));
- raise "e";
- }
- ab = nil;
- }
- if(name == f.name){
- d0 : Dir;
-
- if(q0 != 0 || q1 != f.buf.nc){
- f.mod = TRUE;
- w.dirty = TRUE;
- f.unread = TRUE;
- }
- else{
- (ok, d0) = sys->fstat(fd); # use old values if we failed
- if (ok >= 0)
- d = d0;
- f.qidpath = d.qid.path;
- f.dev = d.dev;
- f.mtime = d.mtime;
- f.mod = FALSE;
- w.dirty = FALSE;
- f.unread = FALSE;
- }
- for(i=0; i<f.ntext; i++){
- f.text[i].w.putseq = f.seq;
- f.text[i].w.dirty = w.dirty;
- }
- }
- strfree(s);
- strfree(r);
- s = r = nil;
- name = nil;
- fd = nil;
- w.settag();
- }
- exception{
- * =>
- strfree(s);
- strfree(r);
- s = r = nil;
- fd = nil;
- raise "e";
- }
- }
- exception{
- * =>
- name = nil;
- return;
- }
- }
- put(et : ref Text, argt : ref Text, arg : string, narg : int)
- {
- namer : string;
- name : string;
- w : ref Window;
- if(et==nil || et.w==nil || et.w.isdir)
- return;
- w = et.w;
- f := w.body.file;
-
- name = getname(w.body, argt, arg, narg, TRUE);
- if(name == nil){
- warning(nil, "no file name\n");
- return;
- }
- namer = name;
- putfile(f, 0, f.buf.nc, namer);
- name = nil;
- }
- dump(argt : ref Text, isdump : int, arg : string, narg : int)
- {
- name : string;
- if(narg)
- name = arg;
- else
- (nil, name) = getbytearg(argt, FALSE, TRUE);
- if(isdump)
- row.dump(name);
- else {
- if (!row.qlock.locked())
- error("row not locked in dump()");
- row.loadx(name, FALSE);
- }
- name = nil;
- }
- cut(et : ref Text, t : ref Text, dosnarf : int, docut : int)
- {
- q0, q1, n, locked, c : int;
- r : ref Astring;
- # use current window if snarfing and its selection is non-null
- if(et!=t && dosnarf && et.w!=nil){
- if(et.w.body.q1>et.w.body.q0){
- t = et.w.body;
- t.file.mark(); # seq has been incremented by execute
- }
- else if(et.w.tag.q1>et.w.tag.q0)
- t = et.w.tag;
- }
- if(t == nil)
- return;
- locked = FALSE;
- if(t.w!=nil && et.w!=t.w){
- locked = TRUE;
- c = 'M';
- if(et.w != nil)
- c = et.w.owner;
- t.w.lock(c);
- }
- if(t.q0 == t.q1){
- if(locked)
- t.w.unlock();
- return;
- }
- if(dosnarf){
- q0 = t.q0;
- q1 = t.q1;
- snarfbuf.delete(0, snarfbuf.nc);
- r = stralloc(BUFSIZE);
- while(q0 < q1){
- n = q1 - q0;
- if(n > BUFSIZE)
- n = BUFSIZE;
- t.file.buf.read(q0, r, 0, n);
- snarfbuf.insert(snarfbuf.nc, r.s, n);
- q0 += n;
- }
- strfree(r);
- r = nil;
- acme->putsnarf();
- }
- if(docut){
- t.delete(t.q0, t.q1, TRUE);
- t.setselect(t.q0, t.q0);
- if(t.w != nil){
- scrl->scrdraw(t);
- t.w.settag();
- }
- }else if(dosnarf) # Snarf command
- dat->argtext = t;
- if(locked)
- t.w.unlock();
- }
- paste(et : ref Text, t : ref Text, selectall : int, tobody: int)
- {
- c : int;
- q, q0, q1, n : int;
- r : ref Astring;
- # if(tobody), use body of executing window (Paste or Send command)
- if(tobody && et!=nil && et.w!=nil){
- t = et.w.body;
- t.file.mark(); # seq has been incremented by execute
- }
- if(t == nil)
- return;
- acme->getsnarf();
- if(t==nil || snarfbuf.nc==0)
- return;
- if(t.w!=nil && et.w!=t.w){
- c = 'M';
- if(et.w != nil)
- c = et.w.owner;
- t.w.lock(c);
- }
- cut(t, t, FALSE, TRUE);
- q = 0;
- q0 = t.q0;
- q1 = t.q0+snarfbuf.nc;
- r = stralloc(BUFSIZE);
- while(q0 < q1){
- n = q1 - q0;
- if(n > BUFSIZE)
- n = BUFSIZE;
- if(r == nil)
- r = stralloc(n);
- snarfbuf.read(q, r, 0, n);
- t.insert(q0, r.s, n, TRUE, 0);
- q += n;
- q0 += n;
- }
- strfree(r);
- r = nil;
- if(selectall)
- t.setselect(t.q0, q1);
- else
- t.setselect(q1, q1);
- if(t.w != nil){
- scrl->scrdraw(t);
- t.w.settag();
- }
- if(t.w!=nil && et.w!=t.w)
- t.w.unlock();
- }
- look(et : ref Text, t : ref Text, argt : ref Text)
- {
- r : string;
- s : ref Astring;
- n : int;
- if(et != nil && et.w != nil){
- t = et.w.body;
- (nil, r, n) = getarg(argt, FALSE, FALSE);
- if(r == nil){
- n = t.q1-t.q0;
- s = stralloc(n);
- t.file.buf.read(t.q0, s, 0, n);
- r = s.s;
- }
- lookx->search(t, r, n);
- r = nil;
- }
- }
- send(et : ref Text, t : ref Text)
- {
- if(et.w==nil)
- return;
- t = et.w.body;
- if(t.q0 != t.q1)
- cut(t, t, TRUE, FALSE);
- t.setselect(t.file.buf.nc, t.file.buf.nc);
- paste(t, t, TRUE, TRUE);
- if(t.readc(t.file.buf.nc-1) != '\n'){
- t.insert(t.file.buf.nc, "\n", 1, TRUE, 0);
- t.setselect(t.file.buf.nc, t.file.buf.nc);
- }
- }
- edit(et: ref Text, argt: ref Text, arg: string, narg: int)
- {
- r: string;
- leng: int;
- if(et == nil)
- return;
- (nil, r, leng) = getarg(argt, FALSE, TRUE);
- seq++;
- if(r != nil){
- editm->editcmd(et, r, leng);
- r = nil;
- }else
- editm->editcmd(et, arg, narg);
- }
- exitx()
- {
- if(row.clean(TRUE))
- acme->acmeexit(nil);
- }
- putall()
- {
- i, j, e : int;
- w : ref Window;
- c : ref Column;
- a : string;
- for(i=0; i<row.ncol; i++){
- c = row.col[i];
- for(j=0; j<c.nw; j++){
- w = c.w[j];
- if(w.isscratch || w.isdir || len w.body.file.name==0)
- continue;
- if(w.nopen[QWevent] > byte 0)
- continue;
- a = w.body.file.name;
- e = utils->access(a);
- if(w.body.file.mod || w.body.ncache)
- if(e < 0)
- warning(nil, sprint("no auto-Put of %s: %r\n", a));
- else{
- w.commit(w.body);
- put(w.body, nil, nil, 0);
- }
- a = nil;
- }
- }
- }
- id(et : ref Text)
- {
- if(et != nil && et.w != nil)
- warning(nil, sprint("/mnt/acme/%d/\n", et.w.id));
- }
- limbo(et: ref Text)
- {
- s := getname(et.w.body, nil, nil, 0, 0);
- if(s == nil)
- return;
- for(l := len s; l > 0 && s[--l] != '/'; )
- ;
- if(s[l] == '/')
- s = s[l+1: ];
- s = "limbo -gw " + s;
- (dir, n) := dirname(et, nil, 0);
- if(n==1 && dir[0]=='.'){ # sigh
- dir = nil;
- n = 0;
- }
- spawn run(nil, s, dir, n, TRUE, nil, nil, FALSE);
- }
- local(et : ref Text, argt : ref Text, arg : string)
- {
- a, aa : string;
- dir : string;
- n : int;
- (aa, a) = getbytearg(argt, TRUE, TRUE);
- (dir, n) = dirname(et, nil, 0);
- if(n==1 && dir[0]=='.'){ # sigh
- dir = nil;
- n = 0;
- }
- spawn run(nil, arg, dir, n, FALSE, aa, a, FALSE);
- }
- kill(argt : ref Text, arg : string, narg : int)
- {
- a, cmd, r : string;
- na : int;
- (nil, r, na) = getarg(argt, FALSE, FALSE);
- if(r != nil)
- kill(nil, r, na);
- # loop condition: *arg is not a blank
- for(;;){
- (a, na) = findbl(arg, narg);
- if(a == arg)
- break;
- cmd = arg[0:narg-na];
- dat->ckill <-= cmd;
- (arg, narg) = skipbl(a, na);
- }
- }
- lineno(et : ref Text)
- {
- n : int;
- if (et == nil || et.w == nil || (et = et.w.body) == nil)
- return;
- q0 := et.q0;
- q1 := et.q1;
- if (q0 < 0 || q1 < 0 || q0 > q1)
- return;
- ln0 := 1;
- ln1 := 1;
- rp := stralloc(BUFSIZE);
- nc := et.file.buf.nc;
- if (q0 >= nc)
- q0 = nc-1;
- if (q1 >= nc)
- q1 = nc-1;
- for (q := 0; q < q1; ) {
- if (q+BUFSIZE > nc)
- n = nc-q;
- else
- n = BUFSIZE;
- et.file.buf.read(q, rp, 0, n);
- for (i := 0; i < n && q < q1; i++) {
- if (rp.s[i] == '\n') {
- if (q < q0)
- ln0++;
- if (q < q1-1)
- ln1++;
- }
- q++;
- }
- }
- rp = nil;
- if (et.file.name != nil)
- file := et.file.name + ":";
- else
- file = nil;
- if (ln0 == ln1)
- warning(nil, sprint("%s%d\n", file, ln0));
- else
- warning(nil, sprint("%s%d,%d\n", file, ln0, ln1));
- }
- fontx(et : ref Text, t : ref Text, argt : ref Text, arg : string, narg : int)
- {
- a, r, flag, file : string;
- na, nf : int;
- aa : string;
- newfont : ref Reffont;
- dp : ref Dat->Dirlist;
- i, fix : int;
- if(et==nil || et.w==nil)
- return;
- t = et.w.body;
- flag = nil;
- file = nil;
- # loop condition: *arg is not a blank
- nf = 0;
- for(;;){
- (a, na) = findbl(arg, narg);
- if(a == arg)
- break;
- r = arg[0:narg-na];
- if(r == "fix" || r == "var"){
- flag = nil;
- flag = r;
- }else{
- file = r;
- nf = narg-na;
- }
- (arg, narg) = skipbl(a, na);
- }
- (nil, r, na) = getarg(argt, FALSE, TRUE);
- if(r != nil)
- if(r == "fix" || r == "var"){
- flag = nil;
- flag = r;
- }else{
- file = r;
- nf = na;
- }
- fix = 1;
- if(flag != nil)
- fix = flag == "fix";
- else if(file == nil){
- newfont = Reffont.get(FALSE, FALSE, FALSE, nil);
- if(newfont != nil)
- fix = newfont.f.name == t.frame.font.name;
- }
- if(file != nil){
- aa = file[0:nf];
- newfont = Reffont.get(fix, flag!=nil, FALSE, aa);
- aa = nil;
- }else
- newfont = Reffont.get(fix, FALSE, FALSE, nil);
- if(newfont != nil){
- graph->draw(gui->mainwin, t.w.r, acme->textcols[Framem->BACK], nil, (0, 0));
- t.reffont.close();
- t.reffont = newfont;
- t.frame.font = newfont.f;
- if(t.w.isdir){
- t.all.min.x++; # force recolumnation; disgusting!
- for(i=0; i<t.w.ndl; i++){
- dp = t.w.dlp[i];
- aa = dp.r;
- dp.wid = graph->strwidth(newfont.f, aa);
- aa = nil;
- }
- }
- # avoid shrinking of window due to quantization
- t.w.col.grow(t.w, -1, 1);
- }
- file = nil;
- flag = nil;
- }
- incl(et : ref Text, argt : ref Text, arg : string, narg : int)
- {
- a, r : string;
- w : ref Window;
- na, n, leng : int;
- if(et==nil || et.w==nil)
- return;
- w = et.w;
- n = 0;
- (nil, r, leng) = getarg(argt, FALSE, TRUE);
- if(r != nil){
- n++;
- w.addincl(r, leng);
- }
- # loop condition: *arg is not a blank
- for(;;){
- (a, na) = findbl(arg, narg);
- if(a == arg)
- break;
- r = arg[0:narg-na];
- n++;
- w.addincl(r, narg-na);
- (arg, narg) = skipbl(a, na);
- }
- if(n==0 && w.nincl){
- for(n=w.nincl; --n>=0; )
- warning(nil, sprint("%s ", w.incl[n]));
- warning(nil, "\n");
- }
- }
- tab(et : ref Text, argt : ref Text, arg : string, narg : int)
- {
- a, r, p : string;
- w : ref Window;
- na, leng, tab : int;
- if(et==nil || et.w==nil)
- return;
- w = et.w;
- (nil, r, leng) = getarg(argt, FALSE, TRUE);
- tab = 0;
- if(r!=nil && leng>0){
- p = r[0:leng];
- if('0'<=p[0] && p[0]<='9')
- tab = int p;
- p = nil;
- }else{
- (a, na) = findbl(arg, narg);
- if(a != arg){
- p = arg[0:narg-na];
- if('0'<=p[0] && p[0]<='9')
- tab = int p;
- p = nil;
- }
- }
- if(tab > 0){
- if(w.body.tabstop != tab){
- w.body.tabstop = tab;
- w.reshape(w.r, 1);
- }
- }else
- warning(nil, sys->sprint("%s: Tab %d\n", w.body.file.name, w.body.tabstop));
- }
- alphabet(et: ref Text, argt: ref Text, arg: string, narg: int)
- {
- r: string;
- leng: int;
- if(et == nil)
- return;
- (nil, r, leng) = getarg(argt, FALSE, FALSE);
- if(r != nil)
- setalphabet(r[0:leng]);
- else
- setalphabet(arg[0:narg]);
- }
- runfeed(p : array of ref Sys->FD, c : chan of int)
- {
- n : int;
- buf : array of byte;
- s : string;
- sys->pctl(Sys->FORKFD, nil);
- c <-= 1;
- # p[1] = nil;
- buf = array[256] of byte;
- for(;;){
- if((n = sys->read(p[0], buf, 256)) <= 0)
- break;
- s = string buf[0:n];
- dat->cerr <-= s;
- s = nil;
- }
- buf = nil;
- exit;
- }
- run(win : ref Window, s : string, rdir : string, ndir : int, newns : int, argaddr : string, arg : string, iseditcmd: int)
- {
- c : ref Dat->Command;
- name, dir : string;
- e, t : int;
- av : list of string;
- r : int;
- incl : array of string;
- inarg, i, nincl : int;
- tfd : ref Sys->FD;
- p : array of ref Sys->FD;
- pc : chan of int;
- winid : int;
- c = ref Dat->Command;
- t = 0;
- while(t < len s && (s[t]==' ' || s[t]=='\n' || s[t]=='\t'))
- t++;
- for(e=t; e < len s; e++)
- if(s[e]==' ' || s[e]=='\n' || s[e]=='\t' )
- break;
- name = s[t:e];
- e = utils->strrchr(name, '/');
- if(e >= 0)
- name = name[e+1:];
- name += " "; # add blank here for ease in waittask
- c.name = name;
- name = nil;
- pipechar := 0;
- if (t < len s && (s[t] == '<' || s[t] == '|' || s[t] == '>')){
- pipechar = s[t++];
- s = s[t:];
- }
- c.pid = sys->pctl(0, nil);
- c.iseditcmd = iseditcmd;
- c.text = s;
- dat->ccommand <-= c;
- #
- # must pctl() after communication because rendezvous name
- # space is part of RFNAMEG.
- #
-
- if(newns){
- wids : string = "";
- filename: string;
- if(win != nil){
- filename = win.body.file.name;
- wids = string win.id;
- nincl = win.nincl;
- incl = array[nincl] of string;
- for(i=0; i<nincl; i++)
- incl[i] = win.incl[i];
- winid = win.id;
- win.close();
- }else{
- winid = 0;
- nincl = 0;
- incl = nil;
- if(dat->activewin != nil)
- winid = (dat->activewin).id;
- }
- # sys->pctl(Sys->FORKNS|Sys->FORKFD|Sys->NEWPGRP, nil);
- sys->pctl(Sys->FORKNS|Sys->NEWFD|Sys->FORKENV|Sys->NEWPGRP, 0::1::2::fsys->fsyscfd()::nil);
- if(rdir != nil){
- dir = rdir[0:ndir];
- sys->chdir(dir); # ignore error: probably app. window
- dir = nil;
- }
- if(filename != nil)
- utils->setenv("%", filename);
- c.md = fsys->fsysmount(rdir, ndir, incl, nincl);
- if(c.md == nil){
- # error("child: can't mount /mnt/acme");
- warning(nil, "can't mount /mnt/acme");
- exit;
- }
- if(winid > 0 && (pipechar=='|' || pipechar=='>')){
- buf := sys->sprint("/mnt/acme/%d/rdsel", winid);
- tfd = sys->open(buf, OREAD);
- }
- else
- tfd = sys->open("/dev/null", OREAD);
- sys->dup(tfd.fd, 0);
- tfd = nil;
- if((winid > 0 || iseditcmd) && (pipechar=='|' || pipechar=='<')){
- buf: string;
- if(iseditcmd){
- if(winid > 0)
- buf = sprint("/mnt/acme/%d/editout", winid);
- else
- buf = sprint("/mnt/acme/editout");
- }
- else
- buf = sys->sprint("/mnt/acme/%d/wrsel", winid);
- tfd = sys->open(buf, OWRITE);
- }
- else
- tfd = sys->open("/dev/cons", OWRITE);
- sys->dup(tfd.fd, 1);
- tfd = nil;
- if(winid > 0 && (pipechar=='|' || pipechar=='<')){
- tfd = sys->open("/dev/cons", OWRITE);
- sys->dup(tfd.fd, 2);
- }
- else
- sys->dup(1, 2);
- tfd = nil;
- utils->setenv("acmewin", wids);
- }else{
- if(win != nil)
- win.close();
- sys->pctl(Sys->FORKFD|Sys->NEWPGRP, nil);
- if(rdir != nil){
- dir = rdir[0:ndir];
- sys->chdir(dir); # ignore error: probably app. window
- dir = nil;
- }
- p = array[2] of ref Sys->FD;
- if(sys->pipe(p) < 0){
- error("child: can't pipe");
- exit;
- }
- pc = chan of int;
- spawn runfeed(p, pc);
- <-pc;
- pc = nil;
- fsys->fsysclose();
- tfd = sys->open("/dev/null", OREAD);
- sys->dup(tfd.fd, 0);
- tfd = nil;
- sys->dup(p[1].fd, 1);
- sys->dup(1, 2);
- p[0] = p[1] = nil;
- }
- if(argaddr != nil)
- utils->setenv("acmeaddr", argaddr);
- hard := 0;
- if(len s > 512-10) # may need to print into stack
- hard = 1;
- else {
- inarg = FALSE;
- for(e=0; e < len s; e++){
- r = s[e];
- if(r==' ' || r=='\t')
- continue;
- if(r < ' ') {
- hard = 1;
- break;
- }
- if(utils->strchr("#;&|^$=`'{}()<>[]*?^~`", r) >= 0) {
- hard = 1;
- break;
- }
- inarg = TRUE;
- }
- if (!hard) {
- if(!inarg)
- exit;
- av = nil;
- sa := -1;
- for(e=0; e < len s; e++){
- r = s[e];
- if(r==' ' || r=='\t'){
- if (sa >= 0) {
- av = s[sa:e] :: av;
- sa = -1;
- }
- continue;
- }
- if (sa < 0)
- sa = e;
- }
- if (sa >= 0)
- av = s[sa:e] :: av;
- if (arg != nil)
- av = arg :: av;
- av = utils->reverse(av);
- c.av = av;
- exec(hd av, av);
- dat->cwait <-= string c.pid + " \"Exec\":";
- exit;
- }
- }
- if(arg != nil){
- s = sprint("%s '%s'", s, arg); # BUG: what if quote in arg?
- c.text = s;
- }
- av = nil;
- av = s :: av;
- av = "-c" :: av;
- av = "/dis/sh" :: av;
- exec(hd av, av);
- dat->cwait <-= string c.pid + " \"Exec\":";
- exit;
- }
- # Nasty bug causes
- # Edit ,|nonexistentcommand
- # (or ,> or ,<) to lock up acme. Easy fix. Add these two lines
- # to the failure case of runwaittask():
- #
- # /sys/src/cmd/acme/exec.c:1287 a exec.c:1288,1289
- # else{
- # if(c->iseditcmd)
- # sendul(cedit, 0);
- # free(c->name);
- # free(c->text);
- # free(c);
- # }
|