shithub: puzzles

Download patch

ref: 8a03fbfdfacb4b1d1a3dc6aaeafe9078bd5164c4
parent: 3224333549a381765671e17c31043211ac6bd4c4
author: sirjofri <sirjofri@sirjofri.de>
date: Tue May 14 12:39:34 EDT 2024

adds initial config support

--- a/plan9.c
+++ b/plan9.c
@@ -24,6 +24,7 @@
 	Point ZP;
 	Controlset *cs;
 	Channel *c;
+	Channel *settingschan;
 	int showframe;
 	int timeractive;
 };
@@ -359,7 +360,6 @@
 	chanprint(cs->ctl, "b_settings text settings");
 	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);
 	
 	createlabel(cs, "l_status");
@@ -396,6 +396,7 @@
 	}
 	free(colors);
 	
+	fe->settingschan = chancreate(sizeof(char*), 0);
 	c = chancreate(sizeof(Mouse), 0);
 	d = chancreate(sizeof(Rune), 0);
 	fe->cs = newcontrolset(screen, d, c, mousectl->resizec);
@@ -565,6 +566,146 @@
 }
 
 void
+addoption(config_item *cfg)
+{
+	char buf[128];
+	int isnew;
+	Control *label, *entry;
+	
+	snprint(buf, 128, "l_%s", cfg->name);
+	label = controlcalled(buf);
+	isnew = 0;
+	if (!label) {
+		label = createlabel(fe->cs, buf);
+		isnew = 1;
+	}
+	chanprint(fe->cs->ctl, "%q value %q", buf, cfg->name);
+	chanprint(fe->cs->ctl, "%q align center", buf);
+	chanprint(fe->cs->ctl, "%q size 100 %d 500 %d", buf, font->height*2, font->height*2);
+	if (isnew)
+		chanprint(fe->cs->ctl, "c_settings add %q", buf);
+	snprint(buf, 128, "e_%s", cfg->name);
+	
+	isnew = 0;
+	entry = controlcalled(buf);
+	if (!entry)
+		isnew = 1;
+	switch (cfg->type) {
+	case C_STRING:
+		if (!entry)
+			entry = createentry(fe->cs, buf);
+		chanprint(fe->cs->ctl, "%q border 1", buf);
+		chanprint(fe->cs->ctl, "%q size 100 %d 500 %d", buf, font->height, font->height);
+		chanprint(fe->cs->ctl, "%q value %q", buf, cfg->u.string.sval);
+		break;
+	case C_BOOLEAN:
+		if (!entry)
+			entry = createbutton(fe->cs, buf);
+		chanprint(fe->cs->ctl, "%q border 1", buf);
+		chanprint(fe->cs->ctl, "%q size 100 %d 500 %d", buf, font->height, font->height);
+		chanprint(fe->cs->ctl, "%q value %d", buf, cfg->u.boolean.bval);
+		break;
+	case C_CHOICES:
+		// todo
+		break;
+	}
+	if (entry && isnew) {
+		controlwire(entry, "event", fe->settingschan);
+		activate(entry);
+		chanprint(fe->cs->ctl, "c_settings add %q", buf);
+	}
+}
+
+int configcats[] = { CFG_SETTINGS, /* CFG_SEED, */ CFG_PREFS };
+config_item *configs[] = { nil, /* nil, */ nil };
+
+void
+loadoptions(void)
+{
+	char *t;
+	config_item *cfg;
+	Control *c, *info;
+	
+	for (int i = 0; i < nelem(configcats); i++) {
+		cfg = midend_get_config(fe->me, configcats[i], &t);
+		if (configs[i]) {
+			//free_cfg(configs[i]);
+			configs[i] = nil;
+		}
+		configs[i] = cfg;
+		
+		while (cfg && cfg->type != C_END) {
+			addoption(cfg);
+			cfg++;
+		}
+	}
+	
+	c = controlcalled("b_savecfg");
+	/* if already set up, early return */
+	if (c)
+		return;
+	
+	info = createlabel(fe->cs, "l_cfginfo");
+	chanprint(fe->cs->ctl, "l_cfginfo align centerleft");
+	chanprint(fe->cs->ctl, "l_cfginfo size 50 %d 500 %d", font->height, font->height);
+	chanprint(fe->cs->ctl, "c_settings add l_cfginfo");
+	
+	c = createtextbutton(fe->cs, "b_savecfg");
+	chanprint(fe->cs->ctl, "b_savecfg text Save");
+	chanprint(fe->cs->ctl, "b_savecfg border 1");
+	chanprint(fe->cs->ctl, "b_savecfg align center");
+	chanprint(fe->cs->ctl, "b_savecfg size 50 %d 100 %d", font->height, font->height);
+	chanprint(fe->cs->ctl, "c_settings add b_savecfg");
+	controlwire(c, "event", fe->c);
+	activate(c);
+}
+
+int
+saveoptions(void)
+{
+	char *s;
+	int r = 1;
+	for (int i = 0; i < nelem(configcats); i++) {
+		s = midend_set_config(fe->me, configcats[i], configs[i]);
+		if (s) {
+			chanprint(fe->cs->ctl, "l_cfginfo value %q", s);
+			r = 0;
+		}
+	}
+	loadoptions();
+	return r;
+}
+
+void
+setoption(char *name, char *value)
+{
+	int n;
+	config_item *cfg;
+	for (int i = 0; i < nelem(configs); i++) {
+		cfg = configs[i];
+		while (cfg && cfg->type != C_END) {
+			if (strcmp(cfg->name, name) == 0)
+				goto Found;
+			cfg++;
+		}
+	}
+	return;
+Found:
+	switch (cfg->type) {
+	case C_STRING:
+		cfg->u.string.sval = value;
+		break;
+	case C_BOOLEAN:
+		n = atoi(value);
+		cfg->u.boolean.bval = n ? 1 : 0;
+		break;
+	case C_CHOICES:
+		// todo
+		break;
+	}
+}
+
+void
 showframe(int frame)
 {
 	if (frame == GAME)
@@ -576,6 +717,11 @@
 int
 keyev(Rune k)
 {
+	if (fe->showframe != GAME) {
+		send(fe->cs->kbdc, &k);
+		return 0;
+	}
+	
 	switch (k) {
 	case 'q':
 	case 127:
@@ -695,6 +841,7 @@
 		{ nil, &delta, CHANRCV },
 		{ nil, &m, CHANRCV },
 		{ nil, &rune, CHANRCV },
+		{ nil, &s, CHANRCV },
 		{ nil, nil, CHANEND },
 	};
 	
@@ -739,6 +886,7 @@
 	initcontrols();
 	
 	initfe(fe, mousectl);
+	loadoptions();
 	midend_new_game(fe->me);
 	resizecontrolset(fe->cs);
 	
@@ -746,6 +894,7 @@
 	a[1].c = chancreate(sizeof(float), 0);
 	a[2].c = mousectl->c;
 	a[3].c = keyboardctl->c;
+	a[4].c = fe->settingschan;
 	
 	proccreate(timerproc, a[1].c, 4096);
 	
@@ -754,9 +903,6 @@
 		case 0: /* libcontrol event channel */	
 			tokenize(s, args, nelem(args));
 			
-			if (strcmp(args[0], "c_settings:") == 0) {
-				print("c_settings event: %s\n", args[1]);
-			} else
 			if (strcmp(args[0], "b_game:") == 0) {
 				showframe(GAME);
 				chanprint(fe->cs->ctl, "b_game value 0");
@@ -764,6 +910,14 @@
 			if (strcmp(args[0], "b_settings:") == 0) {
 				showframe(SETTINGS);
 				chanprint(fe->cs->ctl, "b_settings value 0");
+			} else
+			if (strcmp(args[0], "b_savecfg:") == 0) {
+				chanprint(fe->cs->ctl, "b_savecfg value 0");
+				if (saveoptions()) {
+					midend_new_game(fe->me);
+					showframe(GAME);
+					resizecontrolset(fe->cs);
+				}
 			}
 			break;
 		case 1: /* timer */
@@ -775,6 +929,12 @@
 		case 3: /* keyboard */
 			if (keyev(rune))
 				goto Out;
+			break;
+		case 4: /* settings */
+			tokenize(s, args, nelem(args));
+			s = args[0] + 2; /* get rid of "e_" */
+			s[strlen(s)-1] = 0; /* get rid of sender ":" */
+			setoption(s, args[2]);
 			break;
 		}
 	}