forsyth20121205-174063a80cc13 years agoHistory
1007 lines · 19.4 KB · Brainfuck
RawDownload
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.