shithub: puzzles

Download patch

ref: 6d347772d007e854bfcbdaecbb38abd7ef56ac6f
parent: 9c7d5576c074bd7b9d0fe8a249df31da2df31c9e
author: sirjofri <sirjofri@sirjofri.de>
date: Mon May 13 16:16:09 EDT 2024

first working ui, still with issues

--- a/mkfile
+++ b/mkfile
@@ -98,5 +98,7 @@
 
 </sys/src/cmd/mkmany
 
+# LDFLAGS=$LDFLAGS -p
+
 auxiliary/hatgen.$O: auxiliary/hatgen.c
 	$CC $CFLAGS -o $target auxiliary/hatgen.c
--- a/plan9.c
+++ b/plan9.c
@@ -12,6 +12,8 @@
 #error Plan 9 should not be COMBINED
 #endif
 
+//#define DIRECTDRAW
+
 struct frontend {
 	Image *image;
 	midend *me;
@@ -19,14 +21,13 @@
 	Image **colors;
 	int ncolors;
 	Point ZP;
-	int topbarh;
 	Controlset *cs;
 	Channel *c;
 	int showframe;
-	Rectangle rect;
+	int timeractive;
 };
 
-frontend *fe;
+frontend *fe = nil;
 
 void
 frontend_default_colour(frontend *fe, float *output)
@@ -49,10 +50,12 @@
 void
 deactivate_timer(frontend *fe)
 {
+	fe->timeractive = 0;
 }
 
 void activate_timer(frontend *fe)
 {
+	fe->timeractive = 1;
 }
 
 void fatal(const char *fmt, ...)
@@ -86,10 +89,18 @@
 	exits(nil);
 }
 
+char *showcmd = "c_game show";
+#define ugf chanprint(fe->cs->ctl, showcmd);
+
 static void p9_draw_text(void *handle, int x, int y, int fonttype, int fontsize, int align, int color, const char *text)
 {
 	frontend *fe = (frontend*)handle;
+#ifdef DIRECTDRAW
+	string(screen, addpt(Pt(x, y), fe->ZP), fe->colors[color], ZP, font, text);
+#else
 	string(fe->image, Pt(x, y), fe->colors[color], ZP, font, text);
+	ugf;
+#endif
 }
 
 static void
@@ -96,7 +107,12 @@
 p9_draw_rect(void *handle, int x, int y, int w, int h, int color)
 {
 	frontend *fe = (frontend*)handle;
+#ifdef DIRECTDRAW
+	draw(screen, rectaddpt(Rect(x, y, x+w, y+h), fe->ZP), fe->colors[color], nil, ZP);
+#else
 	draw(fe->image, Rect(x, y, x+w, y+h), fe->colors[color], nil, ZP);
+	ugf;
+#endif
 }
 
 static void
@@ -103,7 +119,12 @@
 p9_draw_line(void *handle, int x1, int y1, int x2, int y2, int color)
 {
 	frontend *fe = (frontend*)handle;
+#ifdef DIRECTDRAW
+	line(screen, addpt(Pt(x1, y1), fe->ZP), addpt(Pt(x2, y2), fe->ZP), Endsquare, Endsquare, 1, fe->colors[color], ZP);
+#else
 	line(fe->image, Pt(x1, y1), Pt(x2, y2), Endsquare, Endsquare, 1, fe->colors[color], ZP);
+	ugf;
+#endif
 }
 
 static void
@@ -110,7 +131,12 @@
 p9_draw_thick_line(void *handle, float thickness, float x1, float y1, float x2, float y2, int color)
 {
 	frontend *fe = (frontend*)handle;
+#ifdef DIRECTDRAW
+	line(screen, addpt(Pt(x1, y1), fe->ZP), addpt(Pt(x2, y2), fe->ZP), Endsquare, Endsquare, thickness, fe->colors[color], ZP);
+#else
 	line(fe->image, Pt(x1, y1), Pt(x2, y2), Endsquare, Endsquare, thickness, fe->colors[color], ZP);
+	ugf;
+#endif
 }
 
 static void
@@ -121,14 +147,27 @@
 	
 	points = malloc(npoints * sizeof(Point));
 	for (int i = 0; i < npoints; i++) {
+#ifdef DIRECTDRAW
+		points[i].x = coords[i*2+0] + fe->ZP.x;
+		points[i].y = coords[i*2+1] + fe->ZP.y;
+#else
 		points[i].x = coords[i*2+0];
 		points[i].y = coords[i*2+1];
+#endif
 	}
 	
+#ifdef DIRECTDRAW
 	if (fillcolor > 0)
+		fillpoly(screen, points, npoints, 0, fe->colors[fillcolor], ZP);
+	if (outlinecolor > 0)
+		poly(screen, points, npoints, Endsquare, Endsquare, 1, fe->colors[outlinecolor], ZP);
+#else
+	if (fillcolor > 0)
 		fillpoly(fe->image, points, npoints, 0, fe->colors[fillcolor], ZP);
 	if (outlinecolor > 0)
 		poly(fe->image, points, npoints, Endsquare, Endsquare, 1, fe->colors[outlinecolor], ZP);
+	ugf;
+#endif
 	
 	free(points);
 }
@@ -137,14 +176,23 @@
 p9_draw_circle(void *handle, int cx, int cy, int radius, int fillcolor, int outlinecolor)
 {
 	frontend *fe = (frontend*)handle;
+#ifdef DIRECTDRAW
+	Point c = addpt(Pt(cx, cy), fe->ZP);
+	fillellipse(screen, c, radius, radius, fe->colors[fillcolor], ZP);
+	ellipse(screen, c, radius, radius, 0, fe->colors[outlinecolor], ZP);
+#else
 	Point c = Pt(cx, cy);
 	fillellipse(fe->image, c, radius, radius, fe->colors[fillcolor], ZP);
 	ellipse(fe->image, c, radius, radius, 0, fe->colors[outlinecolor], ZP);
+	ugf;
+#endif
 }
 
 static void
 p9_draw_update(void *handle, int x, int y, int w, int h)
 {
+	frontend *fe = (frontend*)handle;
+	chanprint(fe->cs->ctl, showcmd);
 }
 
 static void
@@ -165,8 +213,6 @@
 static void
 p9_end_draw(void *handle)
 {
-	frontend* fe = (frontend*)handle;
-	chanprint(fe->cs->ctl, "c_game image frame");
 }
 
 static void
@@ -175,10 +221,6 @@
 	frontend *fe = (frontend*)handle;
 	
 	chanprint(fe->cs->ctl, "l_status value %q", text);
-	
-	return;
-	draw(fe->image, Rect(fe->ZP.x+10, fe->image->r.max.y-20, fe->image->r.max.x, fe->image->r.max.y), fe->background, nil, ZP);
-	string(fe->image, Pt(fe->ZP.x+10, fe->image->r.max.y-20), display->black, ZP, font, text);
 }
 
 static blitter*
@@ -254,7 +296,6 @@
 	Point p;
 	
 	menu = createrow(cs, "rowmain");
-	chanprint(cs->ctl, "rowmain border 1");
 	
 	stackmain = createstack(cs, "stackmain");
 	chanprint(cs->ctl, "stackmain border 1");
@@ -265,12 +306,14 @@
 	chanprint(cs->ctl, "b_game border 1");
 	chanprint(cs->ctl, "b_game align center");
 	chanprint(cs->ctl, "b_game text game");
-	chanprint(cs->ctl, "b_game image i_white");
-	chanprint(cs->ctl, "b_game light i_black");
-	chanprint(cs->ctl, "b_game size %d %d 100 %d", p.x, p.y, p.y);
+	chanprint(cs->ctl, "b_game size %d %d 500 %d", p.x, p.y, p.y);
 	c_game = createbox(cs, "c_game");
-	chanprint(cs->ctl, "c_game image frame");
 	chanprint(cs->ctl, "c_game border 1");
+#ifdef DIRECTDRAW
+	chanprint(cs->ctl, "c_game image background");
+#else
+	chanprint(cs->ctl, "c_game image frame");
+#endif
 	controlwire(c_game, "event", c);
 	controlwire(b_game, "event", c);
 	
@@ -277,8 +320,8 @@
 	b_settings = createtextbutton(cs, "b_settings");
 	p = stringsize(font, "settings");
 	chanprint(cs->ctl, "b_settings text settings");
-	chanprint(cs->ctl, "b_settings border 1");
-	chanprint(cs->ctl, "b_settings size %d %d 100 %d", p.x, p.y, p.y);
+	chanprint(cs->ctl, "b_settings align center");
+	chanprint(cs->ctl, "b_settings size %d %d 500 %d", p.x, p.y, p.y);
 	c_settings = createcolumn(cs, "c_settings");
 	controlwire(c_settings, "event", c);
 	controlwire(b_settings, "event", c);
@@ -294,8 +337,26 @@
 }
 
 void
-initfe(frontend *fe, Channel *c)
+timerthread(void *v)
 {
+	Channel *c;
+	long totaltime;
+	long newtime;
+	
+	c = v;
+	totaltime = times(nil);
+	
+	for (;;) {
+		sleep(100); /* minimum tick time */
+		newtime = times(nil);
+		chanprint(c, "tick: %ld\n", newtime - totaltime);
+		totaltime = newtime;
+	}
+}
+
+void
+initfe(frontend *fe)
+{
 	float *colors;
 	int ncolors;
 	int r, g, b;
@@ -302,10 +363,7 @@
 	int col;
 	float bgcol[3];
 	
-	fe->topbarh = 20;
 	fe->image = allocimage(display, screen->r, screen->chan, 0, 0);
-	fe->ZP = screen->r.min;
-	fe->ZP.y += fe->topbarh;
 	
 	frontend_default_colour(fe, bgcol);
 	fe->background = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, rgb2col(bgcol[0]*255., bgcol[1]*255., bgcol[2]*255.));
@@ -320,24 +378,44 @@
 	}
 	free(colors);
 	
-	fe->cs = newcontrolset(fe->image, nil, nil, nil);
-	fe->cs->clicktotype = 1;
-	fe->c = c;
+	fe->cs = newcontrolset(screen, nil, nil, nil);
+	fe->c = chancreate(sizeof(char*), 0);
 	ctldeletequits = 1;
 	namectlimage(fe->image, "frame");
 	namectlimage(display->black, "i_black");
 	namectlimage(display->white, "i_white");
+	namectlimage(fe->background, "background");
 	initui(fe->cs, fe->c);
+	
+	// needs different timer option - atnotify(2) / alarm(2) ?
+	//threadcreate(timerthread, fe->c, 4096);
 }
 
-void
-resize(void)
+int windowset = 0;
+
+Point
+resize(int *resizenop)
 {
-	int x, y;
-	x = screen->r.max.x - screen->r.min.x;
-	y = screen->r.max.y - screen->r.min.y;
+	int x, y, fd;
+	x = Dx(screen->r);
+	y = Dy(screen->r) - 2*font->height;
 	
 	midend_size(fe->me, &x, &y, 1, 1.);
+	
+	// to test
+	if (0 && !windowset) {
+		fd = open("/dev/wctl", OWRITE);
+		if (fd >= 0) {
+			fprint(fd, "resize -dx %d -dy %d\n", x+2, y + 2*font->height);
+			close(fd);
+			windowset = 1;
+		}
+	} else
+		windowset = 0;
+	
+	/* do not resize if we're waiting for the window resize */
+	*resizenop = windowset;
+	return Pt(x, y);
 }
 
 void
@@ -344,7 +422,9 @@
 resizecontrolset(Controlset *cs)
 {
 	Rectangle rmenu, rarea, sarea;
+	int resizenop;
 	Control *ctl;
+	Point newsize;
 	
 	if (getwindow(display, Refnone) < 0) {
 		sysfatal("resize failed: %r");
@@ -351,23 +431,27 @@
 	}
 	
 	rmenu = screen->r;
-	rmenu.max.y = rmenu.min.y + 16;
+	rmenu.max.y = rmenu.min.y + font->height;
 	rarea = screen->r;
-	rarea.min.y = rmenu.min.y + 16;
-	rarea.max.y = rarea.max.y - 16;
+	rarea.min.y = rmenu.min.y + font->height;
+	rarea.max.y = rarea.max.y - font->height;
 	sarea = screen->r;
-	sarea.min.y = sarea.max.y - 16;
+	sarea.min.y = sarea.max.y - font->height;
 	
 	if (fe->image) {
 		freeimage(fe->image);
 		fe->image = nil;
 	}
-	fe->image = allocimage(display, screen->r, screen->chan, 0, 0);
-	fe->rect = rarea;
+	newsize = resize(&resizenop);
+	fe->image = allocimage(display, Rect(0, 0, newsize.x, newsize.y), screen->chan, 0, 0);
+	if (0 && resizenop)
+		return;
 	draw(screen, screen->r, fe->background, nil, ZP);
-	resize();
-	midend_redraw(fe->me);
 	
+#ifndef DIRECTDRAW
+	midend_force_redraw(fe->me);
+#endif
+	
 	chanprint(cs->ctl, "rowmain rect %R\nrowmain show", rmenu);
 	chanprint(cs->ctl, "c_game rect %R\nc_settings rect %R", rarea, rarea);
 	chanprint(cs->ctl, "stackmain rect %R\nstackmain show", rarea);
@@ -374,6 +458,11 @@
 	chanprint(cs->ctl, "stackmain reveal %d", fe->showframe);
 	chanprint(cs->ctl, "l_status rect %R\nl_status show", sarea);
 	
+#ifdef DIRECTDRAW
+	if (fe->showframe == 0)
+		midend_force_redraw(fe->me);
+#endif
+	
 	ctl = controlcalled("c_game");
 	fe->ZP = ctl->rect.min;
 }
@@ -461,6 +550,8 @@
 void
 showframe(int frame)
 {
+	if (frame == 0)
+		midend_force_redraw(fe->me);
 	fe->showframe = frame;
 	chanprint(fe->cs->ctl, "stackmain reveal %d", frame);
 }
@@ -480,9 +571,18 @@
 }
 
 void
+tick(float delta)
+{
+	if (fe->timeractive) {
+		midend_timer(fe->me, delta);
+	}
+}
+
+void
 threadmain(int argc, char **argv)
 {
-	int x, y, n;
+	int x, y, n, r;
+	int lastmouse;
 	long l;
 	char *s, *args[6];
 	int doprintoptions = 0;
@@ -528,8 +628,7 @@
 	
 	initcontrols();
 	
-	c = chancreate(sizeof(char*), 0);
-	initfe(fe, c);
+	initfe(fe);
 	midend_new_game(fe->me);
 	resizecontrolset(fe->cs);
 	
@@ -545,27 +644,41 @@
 				x = atoi(args[2]+1) - fe->ZP.x; /* ignore '[' */
 				y = atoi(args[3]) - fe->ZP.y;
 				n = atoi(args[4]);
-				if (n&1)
-					midend_process_key(fe->me, x, y, LEFT_BUTTON);
-				if (n&2)
-					midend_process_key(fe->me, x, y, MIDDLE_BUTTON);
-				if (n&4)
-					midend_process_key(fe->me, x, y, RIGHT_BUTTON);
+				r = -1;
+				if ( (lastmouse&1) && !(n&1))
+					r = midend_process_key(fe->me, x, y, LEFT_RELEASE);
+				if (!(lastmouse&1) &&  (n&1))
+					r = midend_process_key(fe->me, x, y, LEFT_BUTTON);
+				if ( (lastmouse&2) && !(n&2))
+					r = midend_process_key(fe->me, x, y, MIDDLE_RELEASE);
+				if (!(lastmouse&2) &&  (n&2))
+					r = midend_process_key(fe->me, x, y, MIDDLE_BUTTON);
+				if ( (lastmouse&4) && !(n&4))
+					r = midend_process_key(fe->me, x, y, RIGHT_RELEASE);
+				if (!(lastmouse&4) &&  (n&2))
+					r = midend_process_key(fe->me, x, y, RIGHT_BUTTON);
+				if (r >= 0) {
+					chanprint(fe->cs->ctl, showcmd);
+				}
+				lastmouse = n;
 			} else
 			if (strcmp(args[1], "key") == 0) {
 				l = strtol(args[2], nil, 0);
 				if (keyev(l))
 					break;
-			} else
-			print("c_game event: %s\n", args[1]);
+			}
 		} else
 		if (strcmp(args[0], "b_game:") == 0) {
-			print("b_game pressed\n");
 			showframe(0);
+			chanprint(fe->cs->ctl, "b_game value 0");
 		} else
 		if (strcmp(args[0], "b_settings:") == 0) {
-			print("b_settings pressed\n");
 			showframe(1);
+			chanprint(fe->cs->ctl, "b_settings value 0");
+		} else
+		if (strcmp(args[0], "tick:") == 0) {
+			l = strtol(args[1], nil, 0);
+			tick(l / 1000.);
 		} else
 			print("event from %s: %s\n", args[0], args[1]);
 	}