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/wm/logwindow.b | |
| parent | 54bc8ff236ac10b3eaa928fd6bcfc0cdb2ba46ae (diff) | |
20060303a
Diffstat (limited to 'appl/wm/logwindow.b')
| -rw-r--r-- | appl/wm/logwindow.b | 187 |
1 files changed, 187 insertions, 0 deletions
diff --git a/appl/wm/logwindow.b b/appl/wm/logwindow.b new file mode 100644 index 00000000..4d0326b4 --- /dev/null +++ b/appl/wm/logwindow.b @@ -0,0 +1,187 @@ +implement Logwindow; + +# +# Copyright © 1999 Vita Nuova Limited. All rights reserved. +# + +include "sys.m"; + sys: Sys; + stderr: ref Sys->FD; +include "draw.m"; + draw: Draw; +include "tk.m"; + tk: Tk; + cmd: import tk; +include "tkclient.m"; + tkclient: Tkclient; +include "arg.m"; + +Logwindow: module { + init: fn(ctxt: ref Draw->Context, argv: list of string); +}; + +cfg := array[] of { + "frame .bf", + "checkbutton .bf.scroll -text Scroll -variable scroll -command {send cmd scroll}", + ".bf.scroll select", + "checkbutton .bf.popup -text {Pop up} -variable popup -command {send cmd popup}", + ".bf.popup select", + "pack .bf.scroll .bf.popup -side left", + "frame .t", + "scrollbar .t.scroll -command {.t.t yview}", + "text .t.t -height 7c -yscrollcommand {.t.scroll set}", + "pack .t.scroll -side left -fill y", + "pack .t.t -fill both -expand 1", + "pack .Wm_t -fill x", + "pack .bf -anchor w", + "pack .t -fill both -expand 1", + "pack propagate . 0", +}; + +eflag := 0; + +badmodule(p: string) +{ + sys->fprint(stderr, "logwindow: cannot load %s: %r\n", p); + raise "fail:bad module"; +} + +init(ctxt: ref Draw->Context, argv: list of string) +{ + sys = load Sys Sys->PATH; + stderr = sys->fildes(2); + + tkclient = load Tkclient Tkclient->PATH; + if (tkclient == nil) + badmodule(Tkclient->PATH); + tkclient->init(); + + tk = load Tk Tk->PATH; + if (tk == nil) + badmodule(Tk->PATH); + + arg := load Arg Arg->PATH; + if (arg == nil) + badmodule(Arg->PATH); + + if (ctxt == nil) { + sys->fprint(stderr, "logwindow: nil Draw->Context\n"); + raise "fail:no draw context"; + } + gflag := 0; + title := "Log Window"; + arg->init(argv); + while ((opt := arg->opt()) != 0) { + case opt { + 'e' => + eflag = 1; + 'g' => + gflag = 1; + * => + sys->fprint(stderr, "usage: logwindow [-ge] [title]\n"); + raise "fail:usage"; + } + } + argv = arg->argv(); + if (argv != nil) + title = hd argv; + + if (!gflag) + sys->pctl(Sys->NEWPGRP, nil); + + (top, wmchan) := tkclient->toplevel(ctxt, "", title, Tkclient->Hide|Tkclient->Resize); + if (top == nil) { + sys->fprint(stderr, "logwindow: couldn't make window\n"); + raise "fail: no window"; + } + cmd(top, ". unmap"); + + for (c:=0; c<len cfg; c++) + tk->cmd(top, cfg[c]); + if ((err := tk->cmd(top, "variable lasterror")) != nil) { + sys->fprint(stderr, "logwindow: tk error: %s\n", err); + raise "fail: tk error"; + } + + logwin(sys->fildes(0), top, wmchan); +} + +scrolling := 1; +popup := 1; + +logwin(fd: ref Sys->FD, top: ref Tk->Toplevel, wmchan: chan of string) +{ + cmd := chan of string; + tk->namechan(top, cmd, "cmd"); + raised := 0; + ichan := chan of int; + spawn inputmon(fd, top, ichan); + tkclient->onscreen(top, nil); + tkclient->startinput(top, "kbd"::"ptr"::nil); + tkclient->wmctl(top, "task"); + for (;;) alt { + s := <-top.ctxt.kbd => + tk->keyboard(top, s); + s := <-top.ctxt.ptr => + tk->pointer(top, *s); + s := <-top.ctxt.ctl or + s = <-top.wreq or + s = <-wmchan => + case s { + "task" => + raised = 0; + "untask" => + raised = 1; + } + tkclient->wmctl(top, s); + e := <-ichan => + if (e == 0 && eflag) { + tkclient->wmctl(top, "exit"); + exit; + } + if (!raised && popup) + tkclient->wmctl(top, "untask"); + msg := <-cmd => + case msg { + "scroll" => + scrolling = int tk->cmd(top, "variable scroll"); + "popup" => + popup = int tk->cmd(top, "variable popup"); + } + } +} + +inputmon(fd: ref Sys->FD, top: ref Tk->Toplevel, ichan: chan of int) +{ + buf := array[Sys->ATOMICIO] of byte; + t := 0; + while ((n := sys->read(fd, buf[t:], len buf-t)) > 0) { + t += n; + cl := 0; + for (i := t - 1; i >= 0; i--) { + (nil, cl, nil) = sys->byte2char(buf, i); + if (cl > 0) + break; + } + if (cl == 0) + continue; + logmsg(top, ichan, string buf[0:i+cl]); + buf[0:] = buf[i+cl:t]; + t -= i + cl; + } + if (n < 0) + logmsg(top, ichan, sys->sprint("Input error: %r\n")); + else + logmsg(top, ichan, "Got EOF\n"); + if (eflag) + ichan <-= 0; +} + +logmsg(top: ref Tk->Toplevel, ichan: chan of int, m: string) +{ + tk->cmd(top, ".t.t insert end '"+m); + if (scrolling) + tk->cmd(top, ".t.t see end"); + tk->cmd(top, "update"); + ichan <-= 1; +} |
