implement WmVt; # note: this code was hacked together in a hurry from some decade-old C code# of mine, so don't expect it to be pretty...# Also, don't expect it to be finished... I had to rush to check this# in... it's just been worked on as a side-project from time to time# But it's good enough to be useful most of the time include "sys.m"; sys: Sys; sprint: import sys;include "draw.m"; draw: Draw; Display, Font, Black, Rect, Image, Point, Endsquare, Enddisc: import draw;include "tk.m"; tk: Tk; Toplevel: import tk;include "tkclient.m"; tkclient: Tkclient;include "sh.m"; CON_Maxnpts: con 1000;Maxnhits: con 5; WmVt: module { init: fn(ctxt: ref Draw->Context, argv: list of string);}; VT_MAXPARAM: con 8; Vt: adt { y1, y2: int; mode: int; # misc mode parameters qmode: int; # extended mode parameters attr: int; # display attributes fg: int; # foreground color bg: int; # background color # saved values: save_x, save_y: int; save_attr: int; save_fg, save_bg: int; save_mode: int; save_qmode: int; # escape code parsing: esc: int; # escape mode pcount: int; # parameter count etype: int; # escape code type ptype: int; # current parameter type value: int; # current value param: array of int; # display info: wid, hgt: int; x, y: int; dx, dy: int; nlcr: int; ccc: int; scr: array of string; cc: array of string;}; display: ref Display;t: ref Toplevel;canvas: ref Image;canvrect: Rect;org: Point;font: ref Font;stderr: ref Sys->FD;vt: ref Vt;pad: string;vtc := array[16] of ref Image;raw := 0;echo := 1;reverse := 0;sq := ""; inpchan: chan of string; shwin_cfg := array[] of { "frame .f", "pack .c .f -side top -fill x", "pack propagate . 0", "focus .f", "bind .f <Key> {send keys {%A}}", "bind . <Configure> {send cmd resize}", "update"}; titlebar(){ tk->cmd(t, "destroy .Wm_t.S"); tk->cmd(t, "button .Wm_t.S -bg #aaaaaa -fg white -text {" + sprint("%d x %d", vt.wid, vt.hgt) + "}; " + "pack .Wm_t.S -side right"); c := "green"; if(raw) c = "red"; tk->cmd(t, "destroy .Wm_t.k"); tk->cmd(t, "button .Wm_t.k -bitmap keyboard.bit"+ " -background "+c+" -command {send wm_title raw}; " + "pack .Wm_t.k -side right"); c = "red"; if(echo) c = "green"; tk->cmd(t, "destroy .Wm_t.d"); tk->cmd(t, "button .Wm_t.d -bitmap display.bit"+ " -background "+c+" -command {send wm_title echo}; " + "pack .Wm_t.d -side right"); c = "white"; if(reverse) c = "black"; tk->cmd(t, "destroy .Wm_t.r"); tk->cmd(t, "button .Wm_t.r -width 24 -height 24 "+ " -background "+c+" -command {send wm_title reverse}; " + "pack .Wm_t.r -side right"); tk->cmd(t, "update");} init(ctxt: ref Draw->Context, nil: list of string){ sys = load Sys Sys->PATH; if (ctxt == nil) { sys->fprint(sys->fildes(2), "vt: no window context\n"); raise "fail:bad context"; } draw = load Draw Draw->PATH; tk = load Tk Tk->PATH; tkclient = load Tkclient Tkclient->PATH; stderr = sys->fildes(2); sys->pctl(Sys->FORKNS, nil); sys->pctl(Sys->NEWPGRP, nil); menubut: chan of string; tkclient->init(); (t, menubut) = tkclient->toplevel(ctxt, "", "WmVt", Tkclient->Appl); display = ctxt.display; font = Font.open(display, "*default*"); vt = ref Vt; vt.hgt = 24; vt.wid = 80; vt.scr = array[vt.hgt] of string; vt.cc = array[vt.hgt] of string; vt_init(vt); pad = ""; for(i:=0; i<vt.wid; i++) pad[i] = ' '; cmd := chan of string; tk->namechan(t, cmd, "cmd"); tk->cmd(t, "canvas .c -height " + string (vt.hgt*font.height) + + " -width " + string (vt.wid*font.width("0")) + " -background red"); tkcmds(t, shwin_cfg); tkclient->onscreen(t, nil); tkclient->startinput(t, "kbd"::"ptr"::nil); titlebar(); keys := chan of string; tk->namechan(t, keys, "keys"); canvas = t.image; canvrect = canvposn(t); org = canvrect.min; npts := 0; WasUp := 1; for(i=0; i<16; i++) { r := 0; g := 0; b := 0; v := 192; if(i&8) v = 255; if(i&1) r = v; if(i&2) g = v; if(i&4) b = v; vtc[i] = display.newimage(((0,0),(1,1)), t.image.chans, 1, display.rgb2cmap(r, g, b)); if (vtc[i] == nil) { sys->fprint(sys->fildes(2), "Failed to allocate image\n"); exit; } } vt_write(vt, "\u001b[2J"); ioc := chan of (int, ref Sys->FileIO, ref Sys->FileIO); spawn newsh(ctxt, ioc); (pid, file, filectl) := <- ioc; if((file == nil) || (filectl == nil)) { sys->print("newsh: %r\n"); return; } # XXX - need to kill this later ic := chan of string; spawn consinp(ic, file.read); inpchan = ic; # hack for(;;) alt { s := <-t.ctxt.kbd => tk->keyboard(t, s); s := <-t.ctxt.ptr => tk->pointer(t, *s); s := <-t.ctxt.ctl or s = <-t.wreq => tkclient->wmctl(t, s); menu := <- menubut => if(menu == "exit") { kill(pid); return; } else if(menu == "raw") { raw = !raw; titlebar(); redraw(); } else if(menu == "echo") { echo = !echo; titlebar(); redraw(); } else if(menu == "reverse") { reverse = !reverse; tmp := vtc[0]; vtc[0] = vtc[7]; vtc[7] = tmp; titlebar(); redraw(); } else tkclient->wmctl(t, menu); tk->cmd(t, "focus .f"); s := <- cmd => (n, cmdstr) := sys->tokenize(s, " \t\n"); case hd cmdstr { "quit" => exit; "resize" => # sys->print("resize\n"); canvas = t.image; canvrect = canvposn(t); org = canvrect.min; # sys->print("%d,%d %d,%d\n", canvrect.max.x, canvrect.min.x, # canvas.r.max.x, canvas.r.min.x); resize((canvrect.max.x-canvrect.min.x)/font.width("0"), (canvrect.max.y-canvrect.min.y)/font.height); titlebar(); redraw(); } c := <- keys => ic <-= c[1:2]; if(echo) scwrite(c[1:2]); (off, data, fid, wc) := <- file.write => if(wc == nil) return; if(echo && !raw && sq != "") { s := ""; for(i=0; i<len sq; i++) s += "\b \b"; scwrite(s); } scwrite(string data); if(echo && !raw && sq != "") scwrite(sq); wc <-= (len data, nil); (off, data, fid, wc) := <- filectl.write => if(string data == "rawon") { raw = 1; echo = 0; titlebar(); redraw(); } if(string data == "rawoff") { raw = 0; echo = 1; titlebar(); redraw(); } wc <-= (len data, nil); }} resize(wid,hgt: int){ scr := array[hgt] of string; cc := array[hgt] of string; for(y :=0; y<hgt; y++) { oy := y + hgt - vt.hgt; if(oy < vt.hgt && oy >= 0) { scr[y] = vt.scr[oy]; cc[y] = vt.cc[oy]; } else { scr[y] = ""; cc[y] = ""; } } vt.x += wid - vt.wid; vt.y += hgt - vt.hgt; if(vt.x < 0) vt.x = 0; if(vt.x >= wid) vt.x = wid; if(vt.y < 0) vt.y = 0; if(vt.y >= hgt) vt.y = hgt; vt.wid = wid; vt.hgt = hgt; vt.scr = scr; vt.cc = cc;} fixdx := 0;fixdy := 0; canvposn(t: ref Toplevel): Rect{ r: Rect; r.min.x = int tk->cmd(t, ".c cget -actx") + int tk->cmd(t, ".dx get"); r.min.y = int tk->cmd(t, ".c cget -acty") + int tk->cmd(t, ".dy get"); r.max.x = r.min.x + int tk->cmd(t, ".c cget -width") + int tk->cmd(t, ".dw get"); r.max.y = r.min.y + int tk->cmd(t, ".c cget -height") + int tk->cmd(t, ".dh get"); # correction for Tk bug (width/height not correct): dx := (t.image.r.max.x - t.image.r.min.x) - (r.max.x - r.min.x); dy := (t.image.r.max.y - t.image.r.min.y) - (r.max.y - r.min.y); if(fixdx == 0) { fixdx = dx; fixdy = dy; } else { r.max.x += dx-fixdx; r.max.y += dy-fixdy; } return r;} redraw(){ # sys->print("redraw\n"); for(y:=0; y<vt.hgt; y++) { xp := canvrect.min.x; yp := canvrect.max.y-(vt.hgt-y)*font.height; f := 0; for(x:=0; x<=len vt.cc[y]; x++) { if(x == len vt.cc[y] || (vt.cc[y][x]>>4) != (vt.cc[y][f]>>4)) { if(x == len vt.cc[y]) w := canvrect.max.x-xp; else w = font.width(vt.scr[y][f:x]); if(len vt.cc[y] == 0) ccc := 7; else ccc = vt.cc[y][f]; canvas.draw(((xp,yp),(xp+w,yp+font.height)), vtc[ccc>>4], nil, (0, 0)); xp += w; f = x; } } xp = canvrect.min.x; f = 0; for(x=1; x<=len vt.scr[y]; x++) { if(x == len vt.scr[y] || (vt.cc[y][x]&15) != (vt.cc[y][f]&15)) { canvas.text((xp,yp), vtc[vt.cc[y][f]&15], (0, 0), font, vt.scr[y][f:x]); xp += font.width(vt.scr[y][f:x]); f = x; } } }} scwrite(s: string){ putchar(vt.x, vt.y, vtscr(vt.y, vt.x), vtcc(vt.y, vt.x)); vt_write(vt, s); putchar(vt.x, vt.y, vtscr(vt.y, vt.x), vtcc(vt.y, vt.x) ^ 16rff);} putchar(x,y: int, ch: int, ccc: int){ if(len vt.scr[y] < x) { vt.scr[y] += pad[0:x-len vt.scr[y]]; vt.cc[y] += pad[0:x-len vt.cc[y]]; } xp := canvrect.min.x+font.width(vt.scr[y][0:x]); yp := canvrect.max.y-(vt.hgt-y)*font.height; s: string; s[0] = ch; canvas.draw(((xp,yp),(xp+font.width(s),yp+font.height)), vtc[ccc>>4], nil, (0, 0)); canvas.text((xp,yp), vtc[ccc&15], (0, 0), font, s);} VT_PUTCHAR(vt: ref Vt, x,y: int, ch: int){ if(len vt.scr[y] < x) { vt.scr[y] += pad[0:x-len vt.scr[y]]; vt.cc[y] += pad[0:x-len vt.cc[y]]; } vt.scr[y][x] = ch; vt.cc[y][x] = vt.ccc; putchar(x, y, ch, int vt.ccc);} VT_SCROLL_UP(vt: ref Vt, x1,y1,x2,y2,n: int){ # XXX - needs to handle vertical slices for(i:=y1; i<=y2-n; i++) { vt.scr[i] = vt.scr[i+n]; vt.cc[i] = vt.cc[i+n]; } r: Rect; r.min.x = canvrect.min.x; r.max.x = r.min.x+(x2-x1+1)*font.width(" "); r.min.y = canvrect.max.y-(vt.hgt-y1)*font.height; r.max.y = r.min.y+(y2-y1-n+1)*font.height; canvas.draw(r, canvas, nil, (r.min.x, r.min.y+font.height*n)); VT_CLEAR(vt, x1,y2-n+1,x2,y2);} VT_SCROLL_DOWN(vt: ref Vt, x1,y1,x2,y2,n: int){ # XXX - needs to handle vertical slices for(i:=y2; i>=y1+n; i--) { vt.scr[i] = vt.scr[i-n]; vt.cc[i] = vt.cc[i-n]; } VT_CLEAR(vt, x1,y1,x2,y1+n-1); redraw();} VT_SCROLL_LEFT(vt: ref Vt, x1,y1,x2,y2,n: int){ # XXX - shouldn't always scroll whole line for(y:=y1; y<=y2; y++) { if(len vt.scr[y] > n) { vt.scr[y] = vt.scr[y][n:]; vt.cc[y] = vt.cc[y][n:]; } else { vt.scr[y] = ""; vt.cc[y] = ""; } } redraw();} VT_SCROLL_RIGHT(vt: ref Vt, x1,y1,x2,y2,n: int){ # XXX - shouldn't always scroll whole line for(y:=y1; y<=y2; y++) { vt.scr[y] = pad[0:n] + vt.scr[y]; vt.cc[y] = pad[0:n] + vt.cc[y]; } redraw();} VT_CLEAR(vt: ref Vt, x1,y1,x2,y2: int){ # XXX - needs to handle vertical slices for(y:=y1; y<=y2; y++) { vt.scr[y] = ""; vt.cc[y] = ""; } r: Rect; r.min.x = canvrect.min.x; r.max.x = r.min.x + (x2-x1+1)*font.width(" "); r.min.y = canvrect.max.y-(vt.hgt-y1)*font.height; r.max.y = r.min.y + (y2-y1+1)*font.height; canvas.draw(r, vtc[vt.ccc>>4], nil, (0, 0));Lines 1–500 of 1007. Load more
implement WmVt; # note: this code was hacked together in a hurry from some decade-old C code # of mine, so don't expect it to be pretty... # Also, don't expect it to be finished... I had to rush to check this # in... it's just been worked on as a side-project from time to time # But it's good enough to be useful most of the time include "sys.m"; sys: Sys; sprint: import sys; include "draw.m"; draw: Draw; Display, Font, Black, Rect, Image, Point, Endsquare, Enddisc: import draw; include "tk.m"; tk: Tk; Toplevel: import tk; include "tkclient.m"; tkclient: Tkclient; include "sh.m"; CON_Maxnpts: con 1000; Maxnhits: con 5; WmVt: module { init: fn(ctxt: ref Draw->Context, argv: list of string); }; VT_MAXPARAM: con 8; Vt: adt { y1, y2: int; mode: int; # misc mode parameters qmode: int; # extended mode parameters attr: int; # display attributes fg: int; # foreground color bg: int; # background color # saved values: save_x, save_y: int; save_attr: int; save_fg, save_bg: int; save_mode: int; save_qmode: int; # escape code parsing: esc: int; # escape mode pcount: int; # parameter count etype: int; # escape code type ptype: int; # current parameter type value: int; # current value param: array of int; # display info: wid, hgt: int; x, y: int; dx, dy: int; nlcr: int; ccc: int; scr: array of string; cc: array of string; }; display: ref Display; t: ref Toplevel; canvas: ref Image; canvrect: Rect; org: Point; font: ref Font; stderr: ref Sys->FD; vt: ref Vt; pad: string; vtc := array[16] of ref Image; raw := 0; echo := 1; reverse := 0; sq := ""; inpchan: chan of string; shwin_cfg := array[] of { "frame .f", "pack .c .f -side top -fill x", "pack propagate . 0", "focus .f", "bind .f <Key> {send keys {%A}}", "bind . <Configure> {send cmd resize}", "update" }; titlebar() { tk->cmd(t, "destroy .Wm_t.S"); tk->cmd(t, "button .Wm_t.S -bg #aaaaaa -fg white -text {" + sprint("%d x %d", vt.wid, vt.hgt) + "}; " + "pack .Wm_t.S -side right"); c := "green"; if(raw) c = "red"; tk->cmd(t, "destroy .Wm_t.k"); tk->cmd(t, "button .Wm_t.k -bitmap keyboard.bit"+ " -background "+c+" -command {send wm_title raw}; " + "pack .Wm_t.k -side right"); c = "red"; if(echo) c = "green"; tk->cmd(t, "destroy .Wm_t.d"); tk->cmd(t, "button .Wm_t.d -bitmap display.bit"+ " -background "+c+" -command {send wm_title echo}; " + "pack .Wm_t.d -side right"); c = "white"; if(reverse) c = "black"; tk->cmd(t, "destroy .Wm_t.r"); tk->cmd(t, "button .Wm_t.r -width 24 -height 24 "+ " -background "+c+" -command {send wm_title reverse}; " + "pack .Wm_t.r -side right"); tk->cmd(t, "update"); } init(ctxt: ref Draw->Context, nil: list of string) { sys = load Sys Sys->PATH; if (ctxt == nil) { sys->fprint(sys->fildes(2), "vt: no window context\n"); raise "fail:bad context"; } draw = load Draw Draw->PATH; tk = load Tk Tk->PATH; tkclient = load Tkclient Tkclient->PATH; stderr = sys->fildes(2); sys->pctl(Sys->FORKNS, nil); sys->pctl(Sys->NEWPGRP, nil); menubut: chan of string; tkclient->init(); (t, menubut) = tkclient->toplevel(ctxt, "", "WmVt", Tkclient->Appl); display = ctxt.display; font = Font.open(display, "*default*"); vt = ref Vt; vt.hgt = 24; vt.wid = 80; vt.scr = array[vt.hgt] of string; vt.cc = array[vt.hgt] of string; vt_init(vt); pad = ""; for(i:=0; i<vt.wid; i++) pad[i] = ' '; cmd := chan of string; tk->namechan(t, cmd, "cmd"); tk->cmd(t, "canvas .c -height " + string (vt.hgt*font.height) + + " -width " + string (vt.wid*font.width("0")) + " -background red"); tkcmds(t, shwin_cfg); tkclient->onscreen(t, nil); tkclient->startinput(t, "kbd"::"ptr"::nil); titlebar(); keys := chan of string; tk->namechan(t, keys, "keys"); canvas = t.image; canvrect = canvposn(t); org = canvrect.min; npts := 0; WasUp := 1; for(i=0; i<16; i++) { r := 0; g := 0; b := 0; v := 192; if(i&8) v = 255; if(i&1) r = v; if(i&2) g = v; if(i&4) b = v; vtc[i] = display.newimage(((0,0),(1,1)), t.image.chans, 1, display.rgb2cmap(r, g, b)); if (vtc[i] == nil) { sys->fprint(sys->fildes(2), "Failed to allocate image\n"); exit; } } vt_write(vt, "\u001b[2J"); ioc := chan of (int, ref Sys->FileIO, ref Sys->FileIO); spawn newsh(ctxt, ioc); (pid, file, filectl) := <- ioc; if((file == nil) || (filectl == nil)) { sys->print("newsh: %r\n"); return; } # XXX - need to kill this later ic := chan of string; spawn consinp(ic, file.read); inpchan = ic; # hack for(;;) alt { s := <-t.ctxt.kbd => tk->keyboard(t, s); s := <-t.ctxt.ptr => tk->pointer(t, *s); s := <-t.ctxt.ctl or s = <-t.wreq => tkclient->wmctl(t, s); menu := <- menubut => if(menu == "exit") { kill(pid); return; } else if(menu == "raw") { raw = !raw; titlebar(); redraw(); } else if(menu == "echo") { echo = !echo; titlebar(); redraw(); } else if(menu == "reverse") { reverse = !reverse; tmp := vtc[0]; vtc[0] = vtc[7]; vtc[7] = tmp; titlebar(); redraw(); } else tkclient->wmctl(t, menu); tk->cmd(t, "focus .f"); s := <- cmd => (n, cmdstr) := sys->tokenize(s, " \t\n"); case hd cmdstr { "quit" => exit; "resize" => # sys->print("resize\n"); canvas = t.image; canvrect = canvposn(t); org = canvrect.min; # sys->print("%d,%d %d,%d\n", canvrect.max.x, canvrect.min.x, # canvas.r.max.x, canvas.r.min.x); resize((canvrect.max.x-canvrect.min.x)/font.width("0"), (canvrect.max.y-canvrect.min.y)/font.height); titlebar(); redraw(); } c := <- keys => ic <-= c[1:2]; if(echo) scwrite(c[1:2]); (off, data, fid, wc) := <- file.write => if(wc == nil) return; if(echo && !raw && sq != "") { s := ""; for(i=0; i<len sq; i++) s += "\b \b"; scwrite(s); } scwrite(string data); if(echo && !raw && sq != "") scwrite(sq); wc <-= (len data, nil); (off, data, fid, wc) := <- filectl.write => if(string data == "rawon") { raw = 1; echo = 0; titlebar(); redraw(); } if(string data == "rawoff") { raw = 0; echo = 1; titlebar(); redraw(); } wc <-= (len data, nil); } } resize(wid,hgt: int) { scr := array[hgt] of string; cc := array[hgt] of string; for(y :=0; y<hgt; y++) { oy := y + hgt - vt.hgt; if(oy < vt.hgt && oy >= 0) { scr[y] = vt.scr[oy]; cc[y] = vt.cc[oy]; } else { scr[y] = ""; cc[y] = ""; } } vt.x += wid - vt.wid; vt.y += hgt - vt.hgt; if(vt.x < 0) vt.x = 0; if(vt.x >= wid) vt.x = wid; if(vt.y < 0) vt.y = 0; if(vt.y >= hgt) vt.y = hgt; vt.wid = wid; vt.hgt = hgt; vt.scr = scr; vt.cc = cc; } fixdx := 0; fixdy := 0; canvposn(t: ref Toplevel): Rect { r: Rect; r.min.x = int tk->cmd(t, ".c cget -actx") + int tk->cmd(t, ".dx get"); r.min.y = int tk->cmd(t, ".c cget -acty") + int tk->cmd(t, ".dy get"); r.max.x = r.min.x + int tk->cmd(t, ".c cget -width") + int tk->cmd(t, ".dw get"); r.max.y = r.min.y + int tk->cmd(t, ".c cget -height") + int tk->cmd(t, ".dh get"); # correction for Tk bug (width/height not correct): dx := (t.image.r.max.x - t.image.r.min.x) - (r.max.x - r.min.x); dy := (t.image.r.max.y - t.image.r.min.y) - (r.max.y - r.min.y); if(fixdx == 0) { fixdx = dx; fixdy = dy; } else { r.max.x += dx-fixdx; r.max.y += dy-fixdy; } return r; } redraw() { # sys->print("redraw\n"); for(y:=0; y<vt.hgt; y++) { xp := canvrect.min.x; yp := canvrect.max.y-(vt.hgt-y)*font.height; f := 0; for(x:=0; x<=len vt.cc[y]; x++) { if(x == len vt.cc[y] || (vt.cc[y][x]>>4) != (vt.cc[y][f]>>4)) { if(x == len vt.cc[y]) w := canvrect.max.x-xp; else w = font.width(vt.scr[y][f:x]); if(len vt.cc[y] == 0) ccc := 7; else ccc = vt.cc[y][f]; canvas.draw(((xp,yp),(xp+w,yp+font.height)), vtc[ccc>>4], nil, (0, 0)); xp += w; f = x; } } xp = canvrect.min.x; f = 0; for(x=1; x<=len vt.scr[y]; x++) { if(x == len vt.scr[y] || (vt.cc[y][x]&15) != (vt.cc[y][f]&15)) { canvas.text((xp,yp), vtc[vt.cc[y][f]&15], (0, 0), font, vt.scr[y][f:x]); xp += font.width(vt.scr[y][f:x]); f = x; } } } } scwrite(s: string) { putchar(vt.x, vt.y, vtscr(vt.y, vt.x), vtcc(vt.y, vt.x)); vt_write(vt, s); putchar(vt.x, vt.y, vtscr(vt.y, vt.x), vtcc(vt.y, vt.x) ^ 16rff); } putchar(x,y: int, ch: int, ccc: int) { if(len vt.scr[y] < x) { vt.scr[y] += pad[0:x-len vt.scr[y]]; vt.cc[y] += pad[0:x-len vt.cc[y]]; } xp := canvrect.min.x+font.width(vt.scr[y][0:x]); yp := canvrect.max.y-(vt.hgt-y)*font.height; s: string; s[0] = ch; canvas.draw(((xp,yp),(xp+font.width(s),yp+font.height)), vtc[ccc>>4], nil, (0, 0)); canvas.text((xp,yp), vtc[ccc&15], (0, 0), font, s); } VT_PUTCHAR(vt: ref Vt, x,y: int, ch: int) { if(len vt.scr[y] < x) { vt.scr[y] += pad[0:x-len vt.scr[y]]; vt.cc[y] += pad[0:x-len vt.cc[y]]; } vt.scr[y][x] = ch; vt.cc[y][x] = vt.ccc; putchar(x, y, ch, int vt.ccc); } VT_SCROLL_UP(vt: ref Vt, x1,y1,x2,y2,n: int) { # XXX - needs to handle vertical slices for(i:=y1; i<=y2-n; i++) { vt.scr[i] = vt.scr[i+n]; vt.cc[i] = vt.cc[i+n]; } r: Rect; r.min.x = canvrect.min.x; r.max.x = r.min.x+(x2-x1+1)*font.width(" "); r.min.y = canvrect.max.y-(vt.hgt-y1)*font.height; r.max.y = r.min.y+(y2-y1-n+1)*font.height; canvas.draw(r, canvas, nil, (r.min.x, r.min.y+font.height*n)); VT_CLEAR(vt, x1,y2-n+1,x2,y2); } VT_SCROLL_DOWN(vt: ref Vt, x1,y1,x2,y2,n: int) { # XXX - needs to handle vertical slices for(i:=y2; i>=y1+n; i--) { vt.scr[i] = vt.scr[i-n]; vt.cc[i] = vt.cc[i-n]; } VT_CLEAR(vt, x1,y1,x2,y1+n-1); redraw(); } VT_SCROLL_LEFT(vt: ref Vt, x1,y1,x2,y2,n: int) { # XXX - shouldn't always scroll whole line for(y:=y1; y<=y2; y++) { if(len vt.scr[y] > n) { vt.scr[y] = vt.scr[y][n:]; vt.cc[y] = vt.cc[y][n:]; } else { vt.scr[y] = ""; vt.cc[y] = ""; } } redraw(); } VT_SCROLL_RIGHT(vt: ref Vt, x1,y1,x2,y2,n: int) { # XXX - shouldn't always scroll whole line for(y:=y1; y<=y2; y++) { vt.scr[y] = pad[0:n] + vt.scr[y]; vt.cc[y] = pad[0:n] + vt.cc[y]; } redraw(); } VT_CLEAR(vt: ref Vt, x1,y1,x2,y2: int) { # XXX - needs to handle vertical slices for(y:=y1; y<=y2; y++) { vt.scr[y] = ""; vt.cc[y] = ""; } r: Rect; r.min.x = canvrect.min.x; r.max.x = r.min.x + (x2-x1+1)*font.width(" "); r.min.y = canvrect.max.y-(vt.hgt-y1)*font.height; r.max.y = r.min.y + (y2-y1+1)*font.height; canvas.draw(r, vtc[vt.ccc>>4], nil, (0, 0));