diff options
| author | Charles.Forsyth <devnull@localhost> | 2006-12-22 17:07:39 +0000 |
|---|---|---|
| committer | Charles.Forsyth <devnull@localhost> | 2006-12-22 17:07:39 +0000 |
| commit | 37da2899f40661e3e9631e497da8dc59b971cbd0 (patch) | |
| tree | cbc6d4680e347d906f5fa7fca73214418741df72 /appl/acme/wind.b | |
| parent | 54bc8ff236ac10b3eaa928fd6bcfc0cdb2ba46ae (diff) | |
20060303a
Diffstat (limited to 'appl/acme/wind.b')
| -rw-r--r-- | appl/acme/wind.b | 554 |
1 files changed, 554 insertions, 0 deletions
diff --git a/appl/acme/wind.b b/appl/acme/wind.b new file mode 100644 index 00000000..2b97fafa --- /dev/null +++ b/appl/acme/wind.b @@ -0,0 +1,554 @@ +implement Windowm; + +include "common.m"; + +sys : Sys; +utils : Utils; +drawm : Draw; +graph : Graph; +gui : Gui; +dat : Dat; +bufferm : Bufferm; +textm : Textm; +filem : Filem; +look : Look; +scrl : Scroll; +acme : Acme; + +sprint : import sys; +FALSE, TRUE, XXX, Astring : import Dat; +Reffont, reffont, Lock, Ref, button, modbutton : import dat; +Point, Rect, Image : import drawm; +min, max, error, warning, stralloc, strfree : import utils; +font, draw : import graph; +black, white, mainwin : import gui; +Buffer : import bufferm; +Body, Text, Tag : import textm; +File : import filem; +Xfid : import Xfidm; +scrdraw : import scrl; +tagcols, textcols : import acme; +BORD : import Framem; + +init(mods : ref Dat->Mods) +{ + sys = mods.sys; + dat = mods.dat; + utils = mods.utils; + drawm = mods.draw; + graph = mods.graph; + gui = mods.gui; + textm = mods.textm; + filem = mods.filem; + bufferm = mods.bufferm; + look = mods.look; + scrl = mods.scroll; + acme = mods.acme; +} + +winid : int; +nullwin : Window; + +Window.init(w : self ref Window, clone : ref Window, r : Rect) +{ + r1, br : Rect; + f : ref File; + rf : ref Reffont; + rp : ref Astring; + nc : int; + dummy : ref File = nil; + + c := w.col; + *w = nullwin; + w.col = c; + w.nopen = array[Dat->QMAX] of byte; + for (i := 0; i < Dat->QMAX; i++) + w.nopen[i] = byte 0; + w.qlock = Lock.init(); + w.ctllock = Lock.init(); + w.refx = Ref.init(); + w.tag = textm->newtext(); + w.tag.w = w; + w.body = textm->newtext(); + w.body.w = w; + w.id = ++winid; + w.refx.inc(); + w.ctlfid = ~0; + w.utflastqid = -1; + r1 = r; + r1.max.y = r1.min.y + font.height; + reffont.r.inc(); + f = dummy.addtext(w.tag); + w.tag.init(f, r1, reffont, tagcols); + w.tag.what = Tag; + # tag is a copy of the contents, not a tracked image + if(clone != nil){ + w.tag.delete(0, w.tag.file.buf.nc, TRUE); + nc = clone.tag.file.buf.nc; + rp = utils->stralloc(nc); + clone.tag.file.buf.read(0, rp, 0, nc); + w.tag.insert(0, rp.s, nc, TRUE, 0); + utils->strfree(rp); + rp = nil; + w.tag.file.reset(); + w.tag.setselect(nc, nc); + } + r1 = r; + r1.min.y += font.height + 1; + if(r1.max.y < r1.min.y) + r1.max.y = r1.min.y; + f = nil; + if(clone != nil){ + f = clone.body.file; + w.body.org = clone.body.org; + w.isscratch = clone.isscratch; + rf = Reffont.get(FALSE, FALSE, FALSE, clone.body.reffont.f.name); + }else + rf = Reffont.get(FALSE, FALSE, FALSE, nil); + f = f.addtext(w.body); + w.body.what = Body; + w.body.init(f, r1, rf, textcols); + r1.min.y -= 1; + r1.max.y = r1.min.y+1; + draw(mainwin, r1, tagcols[BORD], nil, (0, 0)); + scrdraw(w.body); + w.r = r; + w.r.max.y = w.body.frame.r.max.y; + br.min = w.tag.scrollr.min; + br.max.x = br.min.x + button.r.dx(); + br.max.y = br.min.y + button.r.dy(); + draw(mainwin, br, button, nil, button.r.min); + w.filemenu = TRUE; + w.maxlines = w.body.frame.maxlines; + if(clone != nil){ + w.dirty = clone.dirty; + w.body.setselect(clone.body.q0, clone.body.q1); + w.settag(); + } +} + +Window.reshape(w : self ref Window, r : Rect, safe : int) : int +{ + r1, br : Rect; + y : int; + b : ref Image; + + r1 = r; + r1.max.y = r1.min.y + font.height; + y = r1.max.y; + if(!safe || !w.tag.frame.r.eq(r1)){ + y = w.tag.reshape(r1); + b = button; + if(w.body.file.mod && !w.isdir && !w.isscratch) + b = modbutton; + br.min = w.tag.scrollr.min; + br.max.x = br.min.x + b.r.dx(); + br.max.y = br.min.y + b.r.dy(); + draw(mainwin, br, b, nil, b.r.min); + } + if(!safe || !w.body.frame.r.eq(r1)){ + if(y+1+font.height > r.max.y){ # no body + r1.min.y = y; + r1.max.y = y; + w.body.reshape(r1); + w.r = r; + w.r.max.y = y; + return y; + } + r1 = r; + r1.min.y = y; + r1.max.y = y + 1; + draw(mainwin, r1, tagcols[BORD], nil, (0, 0)); + r1.min.y = y + 1; + r1.max.y = r.max.y; + y = w.body.reshape(r1); + w.r = r; + w.r.max.y = y; + scrdraw(w.body); + } + w.maxlines = min(w.body.frame.nlines, max(w.maxlines, w.body.frame.maxlines)); + return w.r.max.y; +} + +Window.lock1(w : self ref Window, owner : int) +{ + w.refx.inc(); + w.qlock.lock(); + w.owner = owner; +} + +Window.lock(w : self ref Window, owner : int) +{ + i : int; + f : ref File; + + f = w.body.file; + for(i=0; i<f.ntext; i++) + f.text[i].w.lock1(owner); +} + +Window.unlock(w : self ref Window) +{ + f := w.body.file; + # + # subtle: loop runs backwards to avoid tripping over + # winclose indirectly editing f.text and freeing f + # on the last iteration of the loop + # + for(i:=f.ntext-1; i>=0; i--){ + w = f.text[i].w; + w.owner = 0; + w.qlock.unlock(); + w.close(); + } +} + +Window.mousebut(w : self ref Window) +{ + graph->cursorset(w.tag.scrollr.min.add(w.tag.scrollr.max).div(2)); +} + +Window.dirfree(w : self ref Window) +{ + i : int; + dl : ref Dat->Dirlist; + + if(w.isdir){ + for(i=0; i<w.ndl; i++){ + dl = w.dlp[i]; + dl.r = nil; + dl = nil; + } + } + w.dlp = nil; + w.ndl = 0; +} + +Window.close(w : self ref Window) +{ + i : int; + + if(w.refx.dec() == 0){ + w.dirfree(); + w.tag.close(); + w.body.close(); + if(dat->activewin == w) + dat->activewin = nil; + for(i=0; i<w.nincl; i++) + w.incl[i] = nil; + w.incl = nil; + w.events = nil; + w = nil; + } +} + +Window.delete(w : self ref Window) +{ + x : ref Xfid; + + x = w.eventx; + if(x != nil){ + w.nevents = 0; + w.events = nil; + w.eventx = nil; + x.c <-= Xfidm->Xnil; + } +} + +Window.undo(w : self ref Window, isundo : int) +{ + body : ref Text; + i : int; + f : ref File; + v : ref Window; + + if(w==nil) + return; + w.utflastqid = -1; + body = w.body; + (body.q0, body.q1) = body.file.undo(isundo, body.q0, body.q1); + body.show(body.q0, body.q1); + f = body.file; + for(i=0; i<f.ntext; i++){ + v = f.text[i].w; + v.dirty = (f.seq != v.putseq); + if(v != w){ + v.body.q0 = v.body.frame.p0+v.body.org; + v.body.q1 = v.body.frame.p1+v.body.org; + } + } + w.settag(); +} + +Window.setname(w : self ref Window, name : string, n : int) +{ + t : ref Text; + v : ref Window; + i : int; + + t = w.body; + if(t.file.name == name) + return; + w.isscratch = FALSE; + if(n>=6 && name[n-6:n] == "/guide") + w.isscratch = TRUE; + else if(n>=7 && name[n-7:n] == "+Errors") + w.isscratch = TRUE; + t.file.setname(name, n); + for(i=0; i<t.file.ntext; i++){ + v = t.file.text[i].w; + v.settag(); + v.isscratch = w.isscratch; + } +} + +Window.typex(w : self ref Window, t : ref Text, r : int) +{ + i : int; + + t.typex(r, w.echomode); + if(t.what == Body) + for(i=0; i<t.file.ntext; i++) + scrdraw(t.file.text[i]); + w.settag(); +} + +Window.cleartag(w : self ref Window) +{ + i, n : int; + r : ref Astring; + + # w must be committed + n = w.tag.file.buf.nc; + r = utils->stralloc(n); + w.tag.file.buf.read(0, r, 0, n); + for(i=0; i<n; i++) + if(r.s[i]==' ' || r.s[i]=='\t') + break; + for(; i<n; i++) + if(r.s[i] == '|') + break; + if(i == n) + return; + i++; + w.tag.delete(i, n, TRUE); + utils->strfree(r); + r = nil; + w.tag.file.mod = FALSE; + if(w.tag.q0 > i) + w.tag.q0 = i; + if(w.tag.q1 > i) + w.tag.q1 = i; + w.tag.setselect(w.tag.q0, w.tag.q1); +} + +Window.settag(w : self ref Window) +{ + i : int; + f : ref File; + + f = w.body.file; + for(i=0; i<f.ntext; i++){ + v := f.text[i].w; + if(v.col.safe || v.body.frame.maxlines>0) + v.settag1(); + } +} + +Window.settag1(w : self ref Window) +{ + ii, j, k, n, bar, dirty : int; + old : ref Astring; + new : string; + r : int; + b : ref Image; + q0, q1 : int; + br : Rect; + + if(w.tag.ncache!=0 || w.tag.file.mod) + w.commit(w.tag); # check file name; also can now modify tag + old = utils->stralloc(w.tag.file.buf.nc); + w.tag.file.buf.read(0, old, 0, w.tag.file.buf.nc); + for(ii=0; ii<w.tag.file.buf.nc; ii++) + if(old.s[ii]==' ' || old.s[ii]=='\t') + break; + if(old.s[0:ii] != w.body.file.name){ + w.tag.delete(0, ii, TRUE); + w.tag.insert(0, w.body.file.name, len w.body.file.name, TRUE, 0); + strfree(old); + old = nil; + old = utils->stralloc(w.tag.file.buf.nc); + w.tag.file.buf.read(0, old, 0, w.tag.file.buf.nc); + } + new = w.body.file.name + " Del Snarf"; + if(w.filemenu){ + if(w.body.file.delta.nc>0 || w.body.ncache) + new += " Undo"; + if(w.body.file.epsilon.nc > 0) + new += " Redo"; + dirty = w.body.file.name != nil && (w.body.ncache || w.body.file.seq!=w.putseq); + if(!w.isdir && dirty) + new += " Put"; + } + if(w.isdir) + new += " Get"; + l := len w.body.file.name; + if(l >= 2 && w.body.file.name[l-2: ] == ".b") + new += " Limbo"; + new += " |"; + r = utils->strchr(old.s, '|'); + if(r >= 0) + k = r+1; + else{ + k = w.tag.file.buf.nc; + if(w.body.file.seq == 0) + new += " Look "; + } + if(new != old.s[0:k]){ + n = k; + if(n > len new) + n = len new; + for(j=0; j<n; j++) + if(old.s[j] != new[j]) + break; + q0 = w.tag.q0; + q1 = w.tag.q1; + w.tag.delete(j, k, TRUE); + w.tag.insert(j, new[j:], len new - j, TRUE, 0); + # try to preserve user selection + r = utils->strchr(old.s, '|'); + if(r >= 0){ + bar = r; + if(q0 > bar){ + bar = utils->strchr(new, '|')-bar; + w.tag.q0 = q0+bar; + w.tag.q1 = q1+bar; + } + } + } + strfree(old); + old = nil; + new = nil; + w.tag.file.mod = FALSE; + n = w.tag.file.buf.nc+w.tag.ncache; + if(w.tag.q0 > n) + w.tag.q0 = n; + if(w.tag.q1 > n) + w.tag.q1 = n; + w.tag.setselect(w.tag.q0, w.tag.q1); + b = button; + if(!w.isdir && !w.isscratch && (w.body.file.mod || w.body.ncache)) + b = modbutton; + br.min = w.tag.scrollr.min; + br.max.x = br.min.x + b.r.dx(); + br.max.y = br.min.y + b.r.dy(); + draw(mainwin, br, b, nil, b.r.min); +} + +Window.commit(w : self ref Window, t : ref Text) +{ + r : ref Astring; + i : int; + f : ref File; + + t.commit(TRUE); + f = t.file; + if(f.ntext > 1) + for(i=0; i<f.ntext; i++) + f.text[i].commit(FALSE); # no-op for t + if(t.what == Body) + return; + r = utils->stralloc(w.tag.file.buf.nc); + w.tag.file.buf.read(0, r, 0, w.tag.file.buf.nc); + for(i=0; i<w.tag.file.buf.nc; i++) + if(r.s[i]==' ' || r.s[i]=='\t') + break; + if(r.s[0:i] != w.body.file.name){ + dat->seq++; + w.body.file.mark(); + w.body.file.mod = TRUE; + w.dirty = TRUE; + w.setname(r.s, i); + w.settag(); + } + utils->strfree(r); + r = nil; +} + +Window.addincl(w : self ref Window, r : string, n : int) +{ + { + (ok, d) := sys->stat(r); + if(ok < 0){ + if(r[0] == '/') + raise "e"; + (r, n) = look->dirname(w.body, r, n); + (ok, d) = sys->stat(r); + if(ok < 0) + raise "e"; + } + if((d.mode&Sys->DMDIR) == 0){ + warning(nil, sprint("%s: not a directory\n", r)); + r = nil; + return; + } + w.nincl++; + owi := w.incl; + w.incl = array[w.nincl] of string; + w.incl[1:] = owi[0:w.nincl-1]; + owi = nil; + w.incl[0] = r; + r = nil; + } + exception{ + * => + warning(nil, sprint("%s: %r\n", r)); + r = nil; + } +} + +Window.clean(w : self ref Window, conservative : int, exiting : int) : int # as it stands, conservative is always TRUE +{ + if(w.isscratch || w.isdir) # don't whine if it's a guide file, error window, etc. + return TRUE; + if((!conservative||exiting) && w.nopen[Dat->QWevent]>byte 0) + return TRUE; + if(w.dirty){ + if(w.body.file.name != nil) + warning(nil, sprint("%s modified\n", w.body.file.name)); + else{ + if(w.body.file.buf.nc < 100) # don't whine if it's too small + return TRUE; + warning(nil, "unnamed file modified\n"); + } + w.dirty = FALSE; + return FALSE; + } + return TRUE; +} + +Window.ctlprint(w : self ref Window) : string +{ + return sprint("%11d %11d %11d %11d %11d ", w.id, w.tag.file.buf.nc, + w.body.file.buf.nc, w.isdir, w.dirty); +} + +Window.event(w : self ref Window, fmt : string) +{ + n : int; + x : ref Xfid; + + if(w.nopen[Dat->QWevent] == byte 0) + return; + if(w.owner == 0) + error("no window owner"); + n = len fmt; + w.events[len w.events] = w.owner; + w.events += fmt; + w.nevents += n+1; + x = w.eventx; + if(x != nil){ + w.eventx = nil; + x.c <-= Xfidm->Xnil; + } +} |
