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/grid/lib/fbrowse.b | |
| parent | 54bc8ff236ac10b3eaa928fd6bcfc0cdb2ba46ae (diff) | |
20060303a
Diffstat (limited to 'appl/grid/lib/fbrowse.b')
| -rw-r--r-- | appl/grid/lib/fbrowse.b | 390 |
1 files changed, 390 insertions, 0 deletions
diff --git a/appl/grid/lib/fbrowse.b b/appl/grid/lib/fbrowse.b new file mode 100644 index 00000000..bde88e62 --- /dev/null +++ b/appl/grid/lib/fbrowse.b @@ -0,0 +1,390 @@ +implement FBrowse; + +# +# Copyright © 2003 Vita Nuova Holdings Limited. All rights reserved. +# + + +include "sys.m"; + sys : Sys; +include "draw.m"; + draw: Draw; + Rect: import draw; +include "tk.m"; + tk: Tk; +include "tkclient.m"; + tkclient: Tkclient; +include "readdir.m"; + readdir: Readdir; +include "workdir.m"; +include "sh.m"; + sh: Sh; +include "grid/pathreader.m"; + reader: PathReader; +include "grid/browser.m"; + browser: Browser; + Browse, Select, File, Parameter, + DESELECT, SELECT, TOGGLE: import browser; +include "grid/fbrowse.m"; + +br: ref Browse; + +init(ctxt : ref Draw->Context, title, root, currdir: string): string +{ + sys = load Sys Sys->PATH; + if (sys == nil) + badmod(Sys->PATH); + draw = load Draw Draw->PATH; + if (draw == nil) + badmod(Draw->PATH); + readdir = load Readdir Readdir->PATH; + if (readdir == nil) + badmod(Readdir->PATH); + tk = load Tk Tk->PATH; + if (tk == nil) + badmod(Tk->PATH); + tkclient = load Tkclient Tkclient->PATH; + if (tkclient == nil) + badmod(Tkclient->PATH); + tkclient->init(); + workdir := load Workdir Workdir->PATH; + if (workdir == nil) + badmod(Workdir->PATH); + sh = load Sh Sh->PATH; + if (sh == nil) + badmod(Sh->PATH); + browser = load Browser Browser->PATH; + if (browser == nil) + badmod(Browser->PATH); + browser->init(); + reader = load PathReader "$self"; + if (reader == nil) + sys->print("cannot load reader!\n"); + sys->pctl(sys->NEWPGRP, nil); + if (root == nil) + root = "/"; + sys->chdir(root); + if (currdir == nil) + currdir = workdir->init(); + if (root[len root - 1] != '/') + root[len root] = '/'; + if (currdir[len currdir - 1] != '/') + currdir[len currdir] = '/'; + + (top, titlebar) := tkclient->toplevel(ctxt,"", title , tkclient->OK | tkclient->Appl); + browsechan := chan of string; + tk->namechan(top, browsechan, "browsechan"); + br = Browse.new(top, "browsechan", root, root, 2, reader); + br.addopened(File (root, nil), 1); + br.gotoselectfile(File (currdir, nil)); + for (ik := 0; ik < len mainscreen; ik++) + tkcmd(top,mainscreen[ik]); + butchan := chan of string; + tk->namechan(top, butchan, "butchan"); + + tkcmd(top, "pack .f -fill both -expand 1; pack propagate . 0"); + tkcmd(top, ". configure -height 300 -width 300"); + + tkcmd(top, "update"); + released := 1; + title = ""; + + menudata := ("", ""); + + tkclient->onscreen(top, nil); + resize(top, ctxt.display.image); + tkclient->startinput(top, "kbd"::"ptr"::nil); + + path: string; + + main: for (;;) { + alt { + s := <-top.ctxt.kbd => + tk->keyboard(top, s); + s := <-top.ctxt.ptr => + tk->pointer(top, *s); + inp := <-browsechan => + (nil, lst) := sys->tokenize(inp, " \n\t"); + selected := br.getselected(1); + case hd lst { + "double1pane1" => + tkpath := hd tl lst; + file := br.getpath(tkpath); + br.defaultaction(lst, file); + (n, dir) := sys->stat(file.path); + if (n == -1 || dir.mode & sys->DMDIR) + break; + if ((len dir.name > 4 && dir.name[len dir.name - 4:] == ".dis") || + dir.mode & 8r111) + spawn send(butchan, "run "+tkpath); + else if (dir.mode & 8r222) + spawn send(butchan, "write "+tkpath); + else if (dir.mode & 8r444) + spawn send(butchan, "open "+tkpath); + * => + br.defaultaction(lst, nil); + } + if (!File.eq(selected, br.getselected(1))) + actionbutton(top, br.selected[1].file.path, br.selected[1].tkpath); + tkcmd(top, "update"); + inp := <-butchan => + (nil, lst) := sys->tokenize(inp, " \n\t"); + case hd lst { + "refresh" => + br.refresh(); + "shell" => + path = br.getselected(1).path; + if (path == nil) + sys->chdir(root); + else + sys->chdir(path); + sh->run(ctxt, "/dis/wm/sh.dis" :: nil); + + "run" => + spawn run(ctxt, br.getselected(1).path); + "read" => + wtitle := tkcmd(top, hd tl lst+" cget text"); + spawn openfile(ctxt, br.getselected(1).path, wtitle,0); + "write" => + wtitle := tkcmd(top, hd tl lst+" cget text"); + spawn openfile(ctxt, br.getselected(1).path, wtitle,1); + } + tkcmd(top, "update"); + + title = <-top.ctxt.ctl or + title = <-top.wreq or + title = <-titlebar => + if (title == "exit" || title == "ok") + break main; + e := tkclient->wmctl(top, title); + if (e != nil && e[0] == '!') + br.resize(); + } + } + if (title == "ok") + return br.getselected(1).path; + return ""; +} + +send(chanout: chan of string, s: string) +{ + chanout <-= s; +} + +resize(top: ref Tk->Toplevel, img: ref Draw->Image) +{ + if (img != nil) { + scw := img.r.dx(); + sch := img.r.dy(); + ww := int tkcmd(top, ". cget -width"); + wh := int tkcmd(top, ". cget -height"); + if (ww > scw) + tkcmd(top, ". configure -x 0 -width "+string scw); + if (wh > sch) + tkcmd(top, ". configure -y 0 -height "+string sch); + } +} + +mainscreen := array[] of { + "frame .f", + "frame .f.ftop", + "button .f.ftop.bs -text {Shell} -command {send butchan shell} -font /fonts/charon/bold.normal.font", + "button .f.ftop.br -text {Refresh} -command {send butchan refresh} -font /fonts/charon/bold.normal.font", + "grid .f.ftop.bs .f.ftop.br -row 0", + "grid columnconfigure .f.ftop 2 -minsize 30", + "grid .f.ftop -row 0 -column 0 -pady 2 -sticky w", + "label .f.l -text { } -height 1 -bg red", + "grid .f.l -row 1 -sticky ew", + "grid .fbrowse -in .f -row 2 -column 0 -sticky nsew", + "grid rowconfigure .f 2 -weight 1", + "grid columnconfigure .f 0 -weight 1", + + "bind .Wm_t <Button-1> +{focus .Wm_t}", + "bind .Wm_t.title <Button-1> +{focus .Wm_t}", + "focus .Wm_t", +}; + +readpath(file: File): (array of ref sys->Dir, int) +{ + (dirs, nil) := readdir->init(file.path, readdir->NAME | readdir->COMPACT); + return (dirs, 0); +} + +run(ctxt: ref Draw->Context, file: string) +{ + sys->pctl(sys->FORKNS | sys->NEWPGRP, nil); + sys->chdir(browser->prevpath(file)); + sh->run(ctxt, file :: nil); +} + +openscr := array[] of { + "frame .f", + "scrollbar .f.sy -command {.f.t yview}", + "text .f.t -yscrollcommand {.f.sy set} -bg white -font /fonts/charon/plain.normal.font", + "pack .f.sy -side left -fill y", + "pack .f.t -fill both -expand 1", + "bind .Wm_t <Button-1> +{focus .Wm_t}", + "bind .Wm_t.title <Button-1> +{focus .Wm_t}", + "focus .f.t", +}; + +fopensize := ("", ""); + +plumbing := array[] of { + ("bit", "wm/view"), + ("jpg", "wm/view"), +}; + +freader(top: ref Tk->Toplevel, fd: ref sys->FD, sync: chan of int) +{ + sync <-= sys->pctl(0,nil); + buf := array[8192] of byte; + for (;;) { + i := sys->read(fd, buf, len buf); + if (i < 1) + return; + s :=""; + for (j := 0; j < i; j++) { + c := int buf[j]; + if (c == '{' || c == '}') + s[len s] = '\\'; + s[len s] = c; + } + tk->cmd(top, ".f.t insert end {"+s+"}; update"); + } +} + +openfile(ctxt: ref draw->Context, file, title: string, writeable: int) +{ + ext := getext(file); + plumb := getplumb(ext); + if (plumb != nil) { + sh->run(ctxt, plumb :: file :: nil); + return; + } + button := tkclient->Appl; + if (writeable) + button = button | tkclient->OK; + (top, titlebar) := tkclient->toplevel(ctxt, "", title, button); + tkcmds(top, openscr); + tkcmd(top,"pack .f -fill both -expand 1"); + tkcmd(top,"pack propagate . 0"); + (w,h) := fopensize; + if (w != "" && h != "") + tkcmd(top, ". configure -width "+w+" -height "+h); + errors := 0; + killpid := -1; + fd := sys->open(file, sys->OREAD); + if (fd != nil) { + sync := chan of int; + spawn freader(top, fd, sync); + killpid = <-sync; + } + tkcmd(top, "update"); + tkclient->onscreen(top, nil); + tkclient->startinput(top, "kbd"::"ptr"::nil); + main: for (;;) { + alt { + s := <-top.ctxt.kbd => + tk->keyboard(top, s); + s := <-top.ctxt.ptr => + tk->pointer(top, *s); + + title = <-top.ctxt.ctl or + title = <-top.wreq or + title = <-titlebar => + if (title == "exit" || title == "ok") + break main; + tkclient->wmctl(top, title); + } + } + if (killpid != -1) + kill(killpid); + fopensize = (tkcmd(top, ". cget -width"), tkcmd(top, ". cget -height")); + if (title == "ok") { + (n, dir) := sys->stat(file); + if (n != -1) { + fd = sys->create(file, sys->OWRITE, dir.mode); + if (fd != nil) { + s := tkcmd(top, ".f.t get 1.0 end"); + sys->fprint(fd,"%s",s); + fd = nil; + } + } + } +} + +badmod(path: string) +{ + sys->print("FBrowse: failed to load: %s\n",path); + exit; +} + +tkcmd(top: ref Tk->Toplevel, cmd: string): string +{ + e := tk->cmd(top, cmd); + if (e != "" && e[0] == '!') + sys->print("Tk error: '%s': %s\n",cmd,e); + return e; +} + +tkcmds(top: ref Tk->Toplevel, a: array of string) +{ + for (j := 0; j < len a; j++) + tkcmd(top, a[j]); +} + +nactionbuttons := 0; +actionbutton(top: ref Tk->Toplevel, path, tkpath: string) +{ + (n, dir) := sys->stat(path); + for (i := 0; i < nactionbuttons; i++) { + tkcmd(top, "grid forget .f.ftop.baction"+string i); + tkcmd(top, "destroy .f.ftop.baction"+string i); + } + if (path == nil || n == -1 || dir.mode & sys->DMDIR) { + nactionbuttons = 0; + return; + } + buttons : list of (string,string) = nil; + + if (dir.mode & 8r222) + buttons = ("Open", "write "+tkpath) :: buttons; + else if (dir.mode & 8r444) + buttons = ("Open", "read "+tkpath) :: buttons; + if (len dir.name > 4 && dir.name[len dir.name - 4:] == ".dis" || dir.mode & 8r111) + buttons = ("Run", "run "+tkpath) :: buttons; + + nactionbuttons = len buttons; + for (i = 0; i < nactionbuttons; i++) { + name := ".f.ftop.baction"+string i+" "; + (text,cmd) := hd buttons; + tkcmd(top, "button "+name+"-text {"+text+"} "+ + "-font /fonts/charon/bold.normal.font "+ + "-command {send butchan "+cmd+"}"); + tkcmd(top, "grid "+name+" -row 0 -column "+string (4+i)); + buttons = tl buttons; + } +} + +getext(file: string): string +{ + (n, lst) := sys->tokenize(file, "."); + for (; tl lst != nil; lst = tl lst) + ; + return hd lst; +} + +getplumb(ext: string): string +{ + for (i := 0; i < len plumbing; i++) + if (ext == plumbing[i].t0) + return plumbing[i].t1; + return nil; +} + +kill(pid: int) +{ + if ((fd := sys->open("/prog/" + string pid + "/ctl", Sys->OWRITE)) != nil) + sys->fprint(fd, "kill"); +} |
