code: purgatorio

Download patch

ref: df03eca7e7cbfadf1cf8c8c5a94390eaa5013a8b
parent: c02306479fb810515b4905e6df7ad2f74b8e7173
author: henesy <devnull@localhost>
date: Thu Nov 19 19:32:52 EST 2020

wm/tetris: fix New Game button breaking keyboard input

--- a/appl/wm/tetris.b
+++ b/appl/wm/tetris.b
@@ -124,7 +124,9 @@
 		badmod(Arg->PATH);
 	if (ctxt == nil)
 		ctxt = tkclient->makedrawcontext();
+
 	blocksize := 17;			# preferred block size
+
 	arg->init(argv);
 	while ((opt := arg->opt()) != 0) {
 		case opt {
@@ -140,13 +142,21 @@
 		usage();
 	
 	sys->pctl(Sys->NEWPGRP|Sys->FORKNS, nil);
+
 	scoretab = load Scoretable Scoretable->PATH;
+
 	scorech := chan of int;
+
 	spawn scoresrvwait(scorech);
+
 	(win, winctl) := tkclient->toplevel(ctxt, "", "Tetris",Tkclient->Hide);
+
 	seedrand();
+
 	fromuser := chan of string;
+
 	tk->namechan(win, fromuser, "user");
+
 	cmd(win, "bind . <Key> {send user k %s}");
 	cmd(win, "bind . <ButtonRelease-1> {focus .}");
 	cmd(win, "bind .Wm_t <ButtonRelease-1> +{focus .}");
@@ -162,6 +172,7 @@
 		
 	tkclient->onscreen(win, nil);
 	tkclient->startinput(win, "kbd"::"ptr"::nil);
+
 	for (;;) {
 		bd := Board.new(win, ".f", blocksize, maxsize);
 		if (bd == nil) {
@@ -168,18 +179,31 @@
 			sys->fprint(stderr, "tetris: couldn't make board\n");
 			return;
 		}
+
 		cmd(win, "bind .f.c <ButtonRelease-1> {send user m %x %y}");
 		cmd(win, "pack .f -side top");
 		cmd(win, "update");
+
 		g := Game.new(bd);
+
 		(finished, rank) := rungame(g, win, fromuser, winctl, scorech);
 		if (finished)
 			break;
+
 		cmd(win, "pack propagate . 0");
+
 		if (scoretab != nil) {
 			cmd(win, "destroy .f");
+
 			if (showhighscores(win, fromuser, winctl, rank) == 0)
 				break;
+			
+			# Needs kicked after new game
+			# Some may be erroneous
+			cmd(win, "bind . <Key> {send user k %s}");
+			cmd(win, "bind . <ButtonRelease-1> {focus .}");
+			cmd(win, "bind .Wm_t <ButtonRelease-1> +{focus .}");
+			cmd(win, "focus .");
 		} else
 			cmd(win, "destroy .f");
 	}
@@ -188,6 +212,7 @@
 wsize(win: ref Tk->Toplevel, w: string): Point
 {
 	bd := int cmd(win, w + " cget -bd");
+
 	return (int cmd(win, w + " cget -width") + bd * 2,
 		int cmd(win, w + " cget -height") + bd * 2);
 }
@@ -196,30 +221,38 @@
 {	
 	tickchan := chan of int;
 	spawn ticker(g, tickchan);
+
 	paused := 0;
 	tch := chan of int;
 
 	gameover := 0;
 	rank := -1;
+
 	bdsize := wsize(win, ".f.c");
 	boundy := bdsize.y * 2 / 3;
-	id := cmd(win, ".f.c create line " + p2s((0, boundy)) + " " + p2s((bdsize.x, boundy)) +
-			" -fill white");
+
+	id := cmd(win, ".f.c create line " + p2s((0, boundy)) + " " + p2s((bdsize.x, boundy)) + " -fill white");
 	cmd(win, ".f.c lower " + id);
+
 	for (;;) alt {
-	s := <-win.ctxt.kbd =>
-		tk->keyboard(win, s);
-	s := <-win.ctxt.ptr =>
-		tk->pointer(win, *s);
+	key := <-win.ctxt.kbd =>
+		tk->keyboard(win, key);
+
+	ptr := <-win.ctxt.ptr =>
+		tk->pointer(win, *ptr);
+
 	s := <-fromuser =>
 		key: int;
 		if (s[0] == 'm') {
+			# Mouse
 			(nil, toks) := sys->tokenize(s, " ");
+
 			p := Point(int hd tl toks, int hd tl tl toks);
 			if (p.y > boundy)
 				key = ' ';
 			else {
 				x := p.x / (bdsize.x / 3);
+
 				case x {
 				0 =>
 					key = '7';
@@ -235,26 +268,35 @@
 			key = int s[1:];
 		else
 			sys->print("oops (%s)\n", s);
+
 		if (gameover)
 			return (key == 'q', rank);
+
 		if (paused) {
 			paused = 0;
+
 			(tickchan, tch) = (tch, tickchan);
 			if (key != 'q')
 				continue;
 		}
+
 		case key {
 		'9'  or 'c' or Right =>
 			g.move(1);
+
 		'7' or 'z' or Left =>
 			g.move(-1);
+
 		'8' or 'x' or Up =>
 			g.rotate(0);
+
 		' ' or Down =>
 			g.drop();
+
 		'p' =>
 			paused = 1;
 			(tickchan, tch) = (tch, tickchan);
+
 		'q' =>
 			g.delay = -1;
 			while (<-tickchan)
@@ -261,23 +303,27 @@
 				;
 			return (1, rank);
 		}
+
 	s := <-win.ctxt.ctl or
 	s = <-win.wreq or
 	s = <-winctl =>
 		tkclient->wmctl(win, s);
+
 	n := <-tickchan =>
 		if (g.tick() == -1) {
 			while (n)
 				n = <-tickchan;
+
 			if (awaitingscore && !<-scorech) {
 				awaitingscore = 0;
 				scoretab = nil;
 			}
+
 			if (scoretab != nil)
-				rank = scoretab->setscore(g.score, sys->sprint("%d %d %bd", g.nrows, g.level,
-						big readfile("/dev/time") / big 1000000));
+				rank = scoretab->setscore(g.score, sys->sprint("%d %d %bd", g.nrows, g.level, big readfile("/dev/time") / big 1000000));
 			gameover = 1;
 		}
+
 	ok := <-scorech =>
 		awaitingscore = 0;
 		if (!ok)
@@ -292,6 +338,7 @@
 		cw := cmd(win, "label " + w + "." + string i + " -text " + tk->quote(vals[i]) + " -width " + widths[i] + bg);
 		cmd(win, "pack " + cw + " -side left -anchor w");
 	}
+
 	cmd(win, "pack " + w + " -side top");
 }
 
@@ -304,6 +351,7 @@
 	tablerow(win, ".f.h", nil, "raised", array[] of {"User", "Score", "Level", "Rows"}, widths);
 	sl := scoretab->scores();
 	n := 0;
+
 	while (sl != nil) {
 		s := hd sl;
 		bg := "";
@@ -319,23 +367,37 @@
 		tablerow(win, f, bg, "sunken", array[] of {s.user, string s.score, level, nrows}, widths);
 		sl = tl sl;
 	}
+
+	# New game button - breaks keyboard
 	cmd(win, "button .f.b -text {New game} -command {send user s}");
 	cmd(win, "pack .f.b -side top");
+
+	# Renders final scores
 	cmd(win, "pack .f -side top");
 	cmd(win, "update");
+
+	# Events for scoreboard
 	for (;;) alt {
-	s := <-win.ctxt.kbd =>
-		tk->keyboard(win, s);
-	s := <-win.ctxt.ptr =>
-		tk->pointer(win, *s);
+	key := <-win.ctxt.kbd =>
+		tk->keyboard(win, key);
+
+	ptr := <-win.ctxt.ptr =>
+		tk->pointer(win, *ptr);
+
 	s := <-fromuser =>
 		if (s[0] == 'k') {
 			cmd(win, "destroy .f");
+
+			# Don't quit unless 'q' is pressed
 			return int s[1:] != 'q';
+
 		} else if (s[0] == 's') {
 			cmd(win, "destroy .f");
+
+			# Don't quit
 			return 1;
 		}
+
 	s := <-win.ctxt.ctl or
 	s = <-win.wreq or
 	s = <-winctl =>
@@ -719,7 +781,6 @@
 cmd(top: ref Tk->Toplevel, s: string): string
 {
 	e := tk->cmd(top, s);
-#	sys->print("%s\n", s);
 	if (e != nil && e[0] == '!')
 		sys->fprint(stderr, "tetris: tk error on '%s': %s\n", s, e);
 	return e;