diff options
Diffstat (limited to 'appl/acme/acme.b')
| -rw-r--r-- | appl/acme/acme.b | 1125 |
1 files changed, 1125 insertions, 0 deletions
diff --git a/appl/acme/acme.b b/appl/acme/acme.b new file mode 100644 index 00000000..5d880f8b --- /dev/null +++ b/appl/acme/acme.b @@ -0,0 +1,1125 @@ +implement Acme; + +include "common.m"; + +sys : Sys; +bufio : Bufio; +workdir : Workdir; +drawm : Draw; +styx : Styx; +acme : Acme; +gui : Gui; +graph : Graph; +dat : Dat; +framem : Framem; +utils : Utils; +regx : Regx; +scrl : Scroll; +textm : Textm; +filem : Filem; +windowm : Windowm; +rowm : Rowm; +columnm : Columnm; +bufferm : Bufferm; +diskm : Diskm; +exec : Exec; +look : Look; +timerm : Timerm; +fsys : Fsys; +xfidm : Xfidm; +plumbmsg : Plumbmsg; +editm: Edit; +editlog: Editlog; +editcmd: Editcmd; +styxaux: Styxaux; + +sprint : import sys; +BACK, HIGH, BORD, TEXT, HTEXT, NCOL : import Framem; +Point, Rect, Font, Image, Display, Pointer: import drawm; +TRUE, FALSE, maxtab : import dat; +Ref, Reffont, Command, Timer, Lock, Cursor : import dat; +row, reffont, activecol, mouse, typetext, mousetext, barttext, argtext, seltext, button, modbutton, colbutton, arrowcursor, boxcursor, plumbed : import dat; +Xfid : import xfidm; +cmouse, ckeyboard, cwait, ccommand, ckill, cxfidalloc, cxfidfree, cerr, cplumb, cedit : import dat; +font, bflush, balloc, draw : import graph; +Arg, PNPROC, PNGROUP : import utils; +arginit, argopt, argf, error, warning, postnote : import utils; +yellow, green, red, blue, black, white, mainwin, display : import gui; +Disk : import diskm; +Row : import rowm; +Column : import columnm; +Window : import windowm; +Text, Tag, Body, Columntag : import textm; +Buffer : import bufferm; +snarfbuf : import exec; +Msg : import plumbmsg; + +tfd : ref Sys->FD; +lasttime : int; + +init(ctxt : ref Draw->Context, argl : list of string) +{ + acmectxt = ctxt; + + sys = load Sys Sys->PATH; + sys->pctl(Sys->NEWPGRP, nil); + + { + # tfd = sys->create("./time", Sys->OWRITE, 8r600); + # lasttime = sys->millisec(); + bufio = load Bufio Bufio->PATH; + workdir = load Workdir Workdir->PATH; + drawm = load Draw Draw->PATH; + + styx = load Styx Styx->PATH; + + acme = load Acme SELF; + + gui = load Gui path(Gui->PATH); + graph = load Graph path(Graph->PATH); + dat = load Dat path(Dat->PATH); + framem = load Framem path(Framem->PATH); + utils = load Utils path(Utils->PATH); + regx = load Regx path(Regx->PATH); + scrl = load Scroll path(Scroll->PATH); + textm = load Textm path(Textm->PATH); + filem = load Filem path(Filem->PATH); + windowm = load Windowm path(Windowm->PATH); + rowm = load Rowm path(Rowm->PATH); + columnm = load Columnm path(Columnm->PATH); + bufferm = load Bufferm path(Bufferm->PATH); + diskm = load Diskm path(Diskm->PATH); + exec = load Exec path(Exec->PATH); + look = load Look path(Look->PATH); + timerm = load Timerm path(Timerm->PATH); + fsys = load Fsys path(Fsys->PATH); + xfidm = load Xfidm path(Xfidm->PATH); + plumbmsg = load Plumbmsg Plumbmsg->PATH; + editm = load Edit path(Edit->PATH); + editlog = load Editlog path(Editlog->PATH); + editcmd = load Editcmd path(Editcmd->PATH); + styxaux = load Styxaux path(Styxaux->PATH); + + mods := ref Dat->Mods(sys, bufio, drawm, styx, styxaux, + acme, gui, graph, dat, framem, + utils, regx, scrl, + textm, filem, windowm, rowm, columnm, + bufferm, diskm, exec, look, timerm, + fsys, xfidm, plumbmsg, editm, editlog, editcmd); + + styx->init(); + styxaux->init(); + + utils->init(mods); + gui->init(mods); + graph->init(mods); + dat->init(mods); + framem->init(mods); + regx->init(mods); + scrl->init(mods); + textm->init(mods); + filem->init(mods); + windowm->init(mods); + rowm->init(mods); + columnm->init(mods); + bufferm->init(mods); + diskm->init(mods); + exec->init(mods); + look->init(mods); + timerm->init(mods); + fsys->init(mods); + xfidm->init(mods); + editm->init(mods); + editlog->init(mods); + editcmd->init(mods); + + utils->debuginit(); + + if (plumbmsg->init(1, "edit", Dat->PLUMBSIZE) >= 0) + plumbed = 1; + + main(argl); + + } +# exception{ +# * => +# sys->fprint(sys->fildes(2), "acme: fatal: %s\n", utils->getexc()); +# sys->print("acme: fatal: %s\n", utils->getexc()); +# shutdown("error"); +# } +} + +timing(s : string) +{ + thistime := sys->millisec(); + sys->fprint(tfd, "%s %d\n", s, thistime-lasttime); + lasttime = thistime; +} + +path(p : string) : string +{ + if (RELEASECOPY) + return p; + else { + # inlined strrchr since not loaded yet + for (n := len p - 1; n >= 0; n--) + if (p[n] == '/') + break; + if (n >= 0) + p = p[n+1:]; + return "/usr/jrf/acme/" + p; + } +} + +waitpid0, waitpid1 : int; +mainpid : int; + +fontcache : array of ref Reffont; +nfontcache : int; +reffonts : array of ref Reffont; +deffontnames := array[2] of { + "/fonts/lucidasans/euro.8.font", + "/fonts/lucm/unicode.9.font", +}; + +command : ref Command; + +WPERCOL : con 8; + +NSnarf : con 32; +snarfrune : ref Dat->Astring; + +main(argl : list of string) +{ + i, ac : int; + loadfile : string; + p : int; + c : ref Column; + arg : ref Arg; + ncol : int; + + ncol = -1; + + mainpid = sys->pctl(0, nil); + loadfile = nil; + fontnames = array[2] of string; + fontnames[0:] = deffontnames[0:2]; + f := utils->getenv("acme-font"); + if (f != nil) + fontnames[0] = f; + f = utils->getenv("acme-Font"); + if (f != nil) + fontnames[1] = f; + arg = arginit(argl); + while(ac = argopt(arg)) case(ac){ + 'b' => + dat->bartflag = TRUE; + 'c' => + ncol = int argf(arg); + 'f' => + fontnames[0] = argf(arg); + 'F' => + fontnames[1] = argf(arg); + 'l' => + loadfile = argf(arg); + } + + dat->home = utils->getenv("home"); + if (dat->home == nil) + dat->home = utils->gethome(utils->getuser()); + ts := utils->getenv("tabstop"); + if (ts != nil) + maxtab = int ts; + if (maxtab <= 0) + maxtab = 4; + snarfrune = utils->stralloc(NSnarf); + sys->pctl(Sys->FORKNS|Sys->FORKENV, nil); + utils->setenv("font", fontnames[0]); + sys->bind("/acme/dis", "/dis", Sys->MBEFORE); + wdir = workdir->init(); + if (wdir == nil) + wdir = "."; + workdir = nil; + + graph->binit(); + font = Font.open(display, fontnames[0]); + if(font == nil){ + fontnames[0] = deffontnames[0]; + font = Font.open(display, fontnames[0]); + if (font == nil) { + warning(nil, sprint("can't open font file %s: %r\n", fontnames[0])); + return; + } + } + reffont = ref Reffont; + reffont.r = Ref.init(); + reffont.f = font; + reffonts = array[2] of ref Reffont; + reffonts[0] = reffont; + reffont.r.inc(); # one to hold up 'font' variable + reffont.r.inc(); # one to hold up reffonts[0] + fontcache = array[1] of ref Reffont; + nfontcache = 1; + fontcache[0] = reffont; + + iconinit(); + usercolinit(); + timerm->timerinit(); + regx->rxinit(); + + cwait = chan of string; + ccommand = chan of ref Command; + ckill = chan of string; + cxfidalloc = chan of ref Xfid; + cxfidfree = chan of ref Xfid; + cerr = chan of string; + cplumb = chan of ref Msg; + cedit = chan of int; + + gui->spawnprocs(); + # spawn keyboardproc(); + # spawn mouseproc(); + sync := chan of int; + spawn waitproc(sys->pctl(0, nil), sync); + <- sync; + spawn plumbproc(); + + fsys->fsysinit(); + dat->disk = (dat->disk).init(); + row = rowm->newrow(); + if(loadfile != nil) { + row.qlock.lock(); # tasks->procs now + row.loadx(loadfile, TRUE); + row.qlock.unlock(); + } + else{ + row.init(mainwin.clipr); + if(ncol < 0){ + if(arg.av == nil) + ncol = 2; + else{ + ncol = (len arg.av+(WPERCOL-1))/WPERCOL; + if(ncol < 2) + ncol = 2; + } + } + if(ncol == 0) + ncol = 2; + for(i=0; i<ncol; i++){ + c = row.add(nil, -1); + if(c==nil && i==0) + error("initializing columns"); + } + c = row.col[row.ncol-1]; + if(arg.av == nil) + readfile(c, wdir); + else + i = 0; + for( ; arg.av != nil; arg.av = tl arg.av){ + filen := hd arg.av; + p = utils->strrchr(filen, '/'); + if((p>=0 && filen[p:] == "/guide") || i/WPERCOL>=row.ncol) + readfile(c, filen); + else + readfile(row.col[i/WPERCOL], filen); + i++; + } + } + bflush(); + + spawn keyboardtask(); + spawn mousetask(); + spawn waittask(); + spawn xfidalloctask(); + + # notify(shutdown); + # waitc := chan of int; + # <-waitc; + # killprocs(); + exit; +} + +readfile(c : ref Column, s : string) +{ + w : ref Window; + r : string; + nr : int; + + w = c.add(nil, nil, -1); + (r, nr) = look->cleanname(s, len s); + w.setname(r, nr); + w.body.loadx(0, s, 1); + w.body.file.mod = FALSE; + w.dirty = FALSE; + w.settag(); + scrl->scrdraw(w.body); + w.tag.setselect(w.tag.file.buf.nc, w.tag.file.buf.nc); +} + +oknotes := array[6] of { + "delete", + "hangup", + "kill", + "exit", + "error", + nil +}; + +dumping : int; + +shutdown(msg : string) +{ + i : int; + + # notify(nil); + if(!dumping && msg != "kill" && msg != "exit" && (1 || sys->pctl(0, nil)==mainpid) && row != nil){ + dumping = TRUE; + row.dump(nil); + } + for(i=0; oknotes[i] != nil; i++) + if(utils->strncmp(oknotes[i], msg, len oknotes[i]) == 0) { + killprocs(); + exit; + } + # killprocs(); + sys->fprint(sys->fildes(2), "acme: %s\n", msg); + sys->print("acme: %s\n", msg); + # exit; +} + +acmeexit(err: string) +{ + if(err != nil) + shutdown(err); + graph->cursorswitch(nil); + if (plumbed) + plumbmsg->shutdown(); + killprocs(); + gui->killwins(); + exit; +} + +killprocs() +{ + c : ref Command; + kill := "kill"; + thispid := sys->pctl(0, nil); + fsys->fsysclose(); + + postnote(PNPROC, thispid, mousepid, kill); + postnote(PNPROC, thispid, keyboardpid, kill); + postnote(PNPROC, thispid, timerpid, kill); + postnote(PNPROC, thispid, waitpid0, kill); + postnote(PNPROC, thispid, waitpid1, kill); + postnote(PNPROC, thispid, fsyspid, kill); + postnote(PNPROC, thispid, mainpid, kill); + postnote(PNPROC, thispid, keytid, kill); + postnote(PNPROC, thispid, mousetid, kill); + postnote(PNPROC, thispid, waittid, kill); + postnote(PNPROC, thispid, xfidalloctid, kill); + # postnote(PNPROC, thispid, lockpid, kill); + postnote(PNPROC, thispid, plumbpid, kill); + + # draw(mainwin, mainwin.r, white, nil, mainwin.r.min); + + for(c=command; c != nil; c=c.next) + postnote(PNGROUP, thispid, c.pid, "kill"); + + xfidm->xfidkill(); +} + +keytid : int; +mousetid : int; +waittid : int; +xfidalloctid : int; + +keyboardtask() +{ + r : int; + timer : ref Timer; + null : ref Timer; + t : ref Text; + + { + keytid = sys->pctl(0, nil); + null = ref Timer; + null.c = chan of int; + timer = null; + typetext = nil; + for(;;){ + alt{ + <-(timer.c) => + timerm->timerstop(timer); + t = typetext; + if(t!=nil && t.what==Tag && !t.w.qlock.locked()){ + t.w.lock('K'); + t.w.commit(t); + t.w.unlock(); + bflush(); + } + timer = null; + r = <-ckeyboard => + gotkey := 1; + while (gotkey) { + typetext = row.typex(r, mouse.xy); + t = typetext; + if(t!=nil && t.col!=nil) + activecol = t.col; + if(t!=nil && t.w!=nil) + t.w.body.file.curtext = t.w.body; + if(timer != null) + spawn timerm->timerwaittask(timer); + if(t!=nil && t.what==Tag) + timer = timerm->timerstart(500); + else + timer = null; + alt { + r = <- ckeyboard => + gotkey = 1; # do this case again + * => + gotkey = 0; + } + bflush(); + } + } + } + } + exception{ + * => + shutdown(utils->getexc()); + raise; + # acmeexit(nil); + } +} + +mousetask() +{ + t, argt : ref Text; + but, ok : int; + q0, q1 : int; + w : ref Window; + m : ref Msg; + + { + mousetid = sys->pctl(0, nil); + sync := chan of int; + spawn waitproc(mousetid, sync); + <- sync; + for(;;){ + alt{ + *mouse = *<-cmouse => + row.qlock.lock(); + if (mouse.buttons & M_QUIT) { + if (row.clean(TRUE)) + acmeexit(nil); + # shutdown("kill"); + row.qlock.unlock(); + break; + } + if (mouse.buttons & M_HELP) { + warning(nil, "no help provided (yet)"); + bflush(); + row.qlock.unlock(); + break; + } + if(mouse.buttons & M_RESIZE){ + draw(mainwin, mainwin.r, white, nil, mainwin.r.min); + scrl->scrresize(); + row.reshape(mainwin.clipr); + bflush(); + row.qlock.unlock(); + break; + } + t = row.which(mouse.xy); + if(t!=mousetext && mousetext!=nil && mousetext.w!=nil){ + mousetext.w.lock('M'); + mousetext.eq0 = ~0; + mousetext.w.commit(mousetext); + mousetext.w.unlock(); + } + mousetext = t; + if(t == nil) { + bflush(); + row.qlock.unlock(); + break; + } + w = t.w; + if(t==nil || mouse.buttons==0) { + bflush(); + row.qlock.unlock(); + break; + } + if(w != nil) + w.body.file.curtext = w.body; + but = 0; + if(mouse.buttons == 1) + but = 1; + else if(mouse.buttons == 2) + but = 2; + else if(mouse.buttons == 4) + but = 3; + barttext = t; + if(t.what==Body && mouse.xy.in(t.scrollr)){ + if(but){ + w.lock('M'); + t.eq0 = ~0; + scrl->scroll(t, but); + t.w.unlock(); + } + bflush(); + row.qlock.unlock(); + break; + } + if(mouse.xy.in(t.scrollr)){ + if(but){ + if(t.what == Columntag) + row.dragcol(t.col); + else if(t.what == Tag){ + t.col.dragwin(t.w, but); + if(t.w != nil) + barttext = t.w.body; + } + if(t.col != nil) + activecol = t.col; + } + bflush(); + row.qlock.unlock(); + break; + } + if(mouse.buttons){ + if(w != nil) + w.lock('M'); + t.eq0 = ~0; + if(w != nil) + w.commit(t); + else + t.commit(TRUE); + if(mouse.buttons & 1){ + t.select(0); + if(w != nil) + w.settag(); + argtext = t; + seltext = t; + if(t.col != nil) + activecol = t.col; # button 1 only + if(t.w != nil && t == t.w.body) + dat->activewin = t.w; + }else if(mouse.buttons & 2){ + (ok, argt, q0, q1) = t.select2(q0, q1); + if(ok) + exec->execute(t, q0, q1, FALSE, argt); + }else if(mouse.buttons & 4){ + (ok, q0, q1) = t.select3(q0, q1); + if(ok) + look->look3(t, q0, q1, FALSE); + } + if(w != nil) + w.unlock(); + bflush(); + row.qlock.unlock(); + break; + } + m = <- cplumb => + if (m.kind == "text") { + attrs := plumbmsg->string2attrs(m.attr); + (found, act) := plumbmsg->lookup(attrs, "action"); + if (!found || act == nil || act == "showfile") + look->plumblook(m); + else if (act == "showdata") + look->plumbshow(m); + } + bflush(); + } + } + } + exception{ + * => + shutdown(utils->getexc()); + raise; + # acmeexit(nil); + } +} + +# list of processes that have exited but we have not heard of yet +Pid : adt { + pid : int; + msg : string; + next : cyclic ref Pid; +}; + +waittask() +{ + status : string; + c, lc : ref Command; + pid : int; + found : int; + cmd : string; + err : string; + t : ref Text; + pids : ref Pid; + + waittid = sys->pctl(0, nil); + command = nil; + for(;;){ + alt{ + err = <-cerr => + row.qlock.lock(); + warning(nil, err); + err = nil; + bflush(); + row.qlock.unlock(); + break; + cmd = <-ckill => + found = FALSE; + for(c=command; c != nil; c=c.next){ + # -1 for blank + if(c.name[0:len c.name - 1] == cmd){ + if(postnote(PNGROUP, waittid, c.pid, "kill") < 0) + warning(nil, sprint("kill %s: %r\n", cmd)); + found = TRUE; + } + } + if(!found) + warning(nil, sprint("Kill: no process %s\n", cmd)); + cmd = nil; + break; + status = <-cwait => + pid = int status; + lc = nil; + for(c=command; c != nil; c=c.next){ + if(c.pid == pid){ + if(lc != nil) + lc.next = c.next; + else + command = c.next; + break; + } + lc = c; + } + row.qlock.lock(); + t = row.tag; + t.commit(TRUE); + if(c == nil){ + # warning(nil, sprint("unknown child pid %d\n", pid)); + p := ref Pid; + p.pid = pid; + p.msg = status; + p.next = pids; + pids = p; + } + else{ + if(look->search(t, c.name, len c.name)){ + t.delete(t.q0, t.q1, TRUE); + t.setselect(0, 0); + } + if(status[len status - 1] != ':') + warning(c.md, sprint("%s\n", status)); + bflush(); + } + row.qlock.unlock(); + if(c != nil){ + if(c.iseditcmd) + cedit <- = 0; + fsys->fsysdelid(c.md); + c = nil; + } + break; + c = <-ccommand => + lastp : ref Pid = nil; + for(p := pids; p != nil; p = p.next){ + if(p.pid == c.pid){ + status = p.msg; + if(status[len status - 1] != ':') + warning(c.md, sprint("%s\n", status)); + if(lastp == nil) + pids = p.next; + else + lastp.next = p.next; + if(c.iseditcmd) + cedit <- = 0; + fsys->fsysdelid(c.md); + c = nil; + break; + } + lastp = p; + } + c.next = command; + command = c; + row.qlock.lock(); + t = row.tag; + t.commit(TRUE); + t.insert(0, c.name, len c.name, TRUE, 0); + t.setselect(0, 0); + bflush(); + row.qlock.unlock(); + break; + } + } +} + +xfidalloctask() +{ + xfree, x : ref Xfid; + + xfidalloctid = sys->pctl(0, nil); + xfree = nil; + for(;;){ + alt{ + <-cxfidalloc => + x = xfree; + if(x != nil) + xfree = x.next; + else{ + x = xfidm->newxfid(); + x.c = chan of int; + spawn x.ctl(); + } + cxfidalloc <-= x; + break; + x = <-cxfidfree => + x.next = xfree; + xfree = x; + break; + } + } +} + +frgetmouse() +{ + bflush(); + *mouse = *<-cmouse; +} + +waitproc(pid : int, sync: chan of int) +{ + fd : ref Sys->FD; + n : int; + + if (waitpid0 == 0) + waitpid0 = sys->pctl(0, nil); + else + waitpid1 = sys->pctl(0, nil); + sys->pctl(Sys->FORKFD, nil); + # w := sprint("/prog/%d/wait", pid); + w := sprint("#p/%d/wait", pid); + fd = sys->open(w, Sys->OREAD); + if (fd == nil) + error("fd == nil in waitproc"); + sync <-= 0; + buf := array[Sys->WAITLEN] of byte; + status := ""; + for(;;){ + if ((n = sys->read(fd, buf, len buf))<0) + error("bad read in waitproc"); + status = string buf[0:n]; + cwait <-= status; + } +} + +get(fix : int, save : int, setfont : int, name : string) : ref Reffont +{ + r : ref Reffont; + f : ref Font; + i : int; + + r = nil; + if(name == nil){ + name = fontnames[fix]; + r = reffonts[fix]; + } + if(r == nil){ + for(i=0; i<nfontcache; i++) + if(name == fontcache[i].f.name){ + r = fontcache[i]; + break; + } + if (i >= nfontcache) { + f = Font.open(display, name); + if(f == nil){ + warning(nil, sprint("can't open font file %s: %r\n", name)); + return nil; + } + r = ref Reffont; + r.r = Ref.init(); + r.f = f; + ofc := fontcache; + fontcache = array[nfontcache+1] of ref Reffont; + fontcache[0:] = ofc[0:nfontcache]; + ofc = nil; + fontcache[nfontcache++] = r; + } + } + if(save){ + r.r.inc(); + if(reffonts[fix] != nil) + reffonts[fix].close(); + reffonts[fix] = r; + fontnames[fix] = name; + } + if(setfont){ + reffont.f = r.f; + r.r.inc(); + reffonts[0].close(); + font = r.f; + reffonts[0] = r; + r.r.inc(); + iconinit(); + } + r.r.inc(); + return r; +} + +close(r : ref Reffont) +{ + i : int; + + if(r.r.dec() == 0){ + for(i=0; i<nfontcache; i++) + if(r == fontcache[i]) + break; + if(i >= nfontcache) + warning(nil, "internal error: can't find font in cache\n"); + else{ + fontcache[i:] = fontcache[i+1:nfontcache]; + nfontcache--; + } + r.f = nil; + r = nil; + } +} + +arrowbits := array[64] of { + byte 16rFF, byte 16rE0, byte 16rFF, byte 16rE0, + byte 16rFF, byte 16rC0, byte 16rFF, byte 16r00, + byte 16rFF, byte 16r00, byte 16rFF, byte 16r80, + byte 16rFF, byte 16rC0, byte 16rFF, byte 16rE0, + byte 16rE7, byte 16rF0, byte 16rE3, byte 16rF8, + byte 16rC1, byte 16rFC, byte 16r00, byte 16rFE, + byte 16r00, byte 16r7F, byte 16r00, byte 16r3E, + byte 16r00, byte 16r1C, byte 16r00, byte 16r08, + + byte 16r00, byte 16r00, byte 16r7F, byte 16rC0, + byte 16r7F, byte 16r00, byte 16r7C, byte 16r00, + byte 16r7E, byte 16r00, byte 16r7F, byte 16r00, + byte 16r6F, byte 16r80, byte 16r67, byte 16rC0, + byte 16r43, byte 16rE0, byte 16r41, byte 16rF0, + byte 16r00, byte 16rF8, byte 16r00, byte 16r7C, + byte 16r00, byte 16r3E, byte 16r00, byte 16r1C, + byte 16r00, byte 16r08, byte 16r00, byte 16r00, +}; + +# outer boundary of width 1 is white +# next boundary of width 3 is black +# next boundary of width 1 is white +# inner boundary of width 4 is transparent +boxbits := array[64] of { + byte 16rFF, byte 16rFF, byte 16rFF, byte 16rFF, + byte 16rFF, byte 16rFF, byte 16rFF, byte 16rFF, + byte 16rFF, byte 16rFF, byte 16rF8, byte 16r1F, + byte 16rF8, byte 16r1F, byte 16rF8, byte 16r1F, + byte 16rF8, byte 16r1F, byte 16rF8, byte 16r1F, + byte 16rF8, byte 16r1F, byte 16rFF, byte 16rFF, + byte 16rFF, byte 16rFF, byte 16rFF, byte 16rFF, + byte 16rFF, byte 16rFF, byte 16rFF, byte 16rFF, + + + byte 16r00, byte 16r00, byte 16r7F, byte 16rFE, + byte 16r7F, byte 16rFE, byte 16r7F, byte 16rFE, + byte 16r70, byte 16r0E, byte 16r70, byte 16r0E, + byte 16r70, byte 16r0E, byte 16r70, byte 16r0E, + byte 16r70, byte 16r0E, byte 16r70, byte 16r0E, + byte 16r70, byte 16r0E, byte 16r70, byte 16r0E, + byte 16r7F, byte 16rFE, byte 16r7F, byte 16rFE, + byte 16r7F, byte 16rFE, byte 16r00, byte 16r00, +}; + +iconinit() +{ + r : Rect; + + tagcols = array[NCOL] of ref Draw->Image; + tagcols[BACK] = imagemix(display.rgb(16raa, 16rff, 16rff), white, 1, 3); # mix DPalebluegreenwith DWhite + tagcols[HIGH] = display.rgb(16r9e, 16ree, 16ree); # was DPalegreygreen + tagcols[BORD] = display.rgb(16r88, 16r88, 16rcc); # was DPurpleblue + tagcols[TEXT] = black; + tagcols[HTEXT] = black; + + textcols = array[NCOL] of ref Draw->Image; + textcols[BACK] = imagemix(display.rgb(16rff, 16rff, 16raa), white, 1, 3); # mix DPaleyellow with DWhite + textcols[HIGH] = display.rgb(16ree, 16ree, 16r9e); # was DDarkyellow + textcols[BORD] = display.rgb(16r99, 16r99, 16r4c); # was Dyellowgreen + textcols[TEXT] = black; + textcols[HTEXT] = black; + + if(button != nil) + button = modbutton = colbutton = nil; + + r = ((0, 0), (Dat->Scrollwid+2, font.height+1)); + button = balloc(r, mainwin.chans, Draw->White); + draw(button, r, tagcols[BACK], nil, r.min); + r.max.x -= 2; + draw(button, r, tagcols[BORD], nil, (0, 0)); + r = r.inset(2); + draw(button, r, tagcols[BACK], nil, (0, 0)); + + r = button.r; + modbutton = balloc(r, mainwin.chans, Draw->White); + draw(modbutton, r, tagcols[BACK], nil, r.min); + r.max.x -= 2; + draw(modbutton, r, tagcols[BORD], nil, (0, 0)); + r = r.inset(2); + draw(modbutton, r, display.rgb(16r00, 16r00, 16r99), nil, (0, 0)); # was DMedblue + + r = button.r; + colbutton = balloc(r, mainwin.chans, Draw->White); + draw(colbutton, r, tagcols[BACK], nil, r.min); + r.max.x -= 2; + draw(colbutton, r, tagcols[BORD], nil, (0, 0)); + +# arrowcursor = ref Cursor((-1, -1), (16, 32), arrowbits); + boxcursor = ref Cursor((-7, -7), (16, 32), boxbits); + + but2col = display.rgb(16raa, 16r00, 16r00); + but3col = display.rgb(16r00, 16r66, 16r00); + but2colt = white; + but3colt = white; + + graph->cursorswitch(arrowcursor); +} + +colrec : adt { + name : string; + image : ref Image; +}; + +coltab : array of colrec; + +cinit() +{ + coltab = array[6] of colrec; + coltab[0].name = "yellow"; coltab[0].image = yellow; + coltab[1].name = "green"; coltab[1].image = green; + coltab[2].name = "red"; coltab[2].image = red; + coltab[3].name = "blue"; coltab[3].image = blue; + coltab[4].name = "black"; coltab[4].image = black; + coltab[5].name = "white"; coltab[5].image = white; +} + +col(s : string, n : int) : int +{ + return ((s[n]-'0') << 4) | (s[n+1]-'0'); +} + +rgb(s : string, n : int) : (int, int, int) +{ + return (col(s, n), col(s, n+2), col(s, n+4)); +} + +imagemix(i1 : ref Image, i2 : ref Image, n1 : int, n2 : int) : ref Image +{ + # 2,2 1,3 only : generalize later + i3 := balloc(((0, 0), (2, 2)), mainwin.chans, Draw->White); + draw(i3, i3.r, i2, nil, (0, 0)); + draw(i3, ((0, 0), (1, 1)), i1, nil, (0, 0)); + if (n1 == n2) + draw(i3, ((1, 1), (2, 2)), i1, nil, (0, 0)); + i3.repl = 1; + i3.clipr = ((-1729, -1729), (1729, 1729)); + return i3; +} + +cenv(s : string, t : string, but : int, i : ref Image) : ref Image +{ + c := utils->getenv("acme-" + s + "-" + t + "-" + string but); + if (c == nil) + c = utils->getenv("acme-" + s + "-" + string but); + if (c == nil && but != 0) + c = utils->getenv("acme-" + s); + if (c != nil) { + if (c[0] == '#' && len c >= 7) { + (r, g, b) := rgb(c, 1); + i1 := display.rgb(r, g, b); + if (len c >= 15 && c[7] == '/' && c[8] == '#') { + (r, g, b) = rgb(c, 9); + i2 := display.rgb(r, g, b); + return imagemix(i1, i2, 2, 2); + } + return i1; + } + for (j := 0; j < len c; j++) + if (c[j] >= 'A' && c[j] <= 'Z') + c[j] += 'a'-'A'; + for (j = 0; j < len coltab; j++) + if (c == coltab[j].name) + return coltab[j].image; + } + return i; +} + +usercolinit() +{ + cinit(); + textcols[TEXT] = cenv("fg", "text", 0, textcols[TEXT]); + textcols[BACK] = cenv("bg", "text", 0, textcols[BACK]); + textcols[HTEXT] = cenv("fg", "text", 1, textcols[HTEXT]); + textcols[HIGH] = cenv("bg", "text", 1, textcols[HIGH]); + but2colt= cenv("fg", "text", 2, but2colt); + but2col = cenv("bg", "text", 2, but2col); + but3colt = cenv("fg", "text", 3, but3colt); + but3col = cenv("bg", "text", 3, but3col); + tagcols[TEXT] = cenv("fg", "tag", 0, tagcols[TEXT]); + tagcols[BACK] = cenv("bg", "tag", 0, tagcols[BACK]); + tagcols[HTEXT] = cenv("fg", "tag", 1, tagcols[HTEXT]); + tagcols[HIGH] = cenv("bg", "tag", 1, tagcols[HIGH]); +} + +getsnarf() +{ + # return; + fd := sys->open("/chan/snarf", sys->OREAD); + if(fd == nil) + return; + snarfbuf.reset(); + snarfbuf.loadx(0, fd); +} + +putsnarf() +{ + n : int; + + # return; + if(snarfbuf.nc == 0) + return; + fd := sys->open("/chan/snarf", sys->OWRITE); + if(fd == nil) + return; + for(i:=0; i<snarfbuf.nc; i+=n){ + n = snarfbuf.nc-i; + if(n >= NSnarf) + n = NSnarf; + snarfbuf.read(i, snarfrune, 0, n); + sys->fprint(fd, "%s", snarfrune.s[0:n]); + } +} + +plumbpid : int; + +plumbproc() +{ + plumbpid = sys->pctl(0, nil); + for(;;){ + msg := Msg.recv(); + if(msg == nil){ + sys->print("Acme: can't read /chan/plumb.edit: %r\n"); + plumbpid = 0; + plumbed = 0; + return; + } + if(msg.kind != "text"){ + sys->print("Acme: can't interpret '%s' kind of message\n", msg.kind); + continue; + } +# sys->print("msg %s\n", string msg.data); + cplumb <-= msg; + } +} |
