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;
}
}