ref: de67801b0fd3dfa11777c1ef86cd617baf376b7b
parent: eeb2db283de9115f7256fa4cc49597d63e06b0ab
author: Simon Tatham <anakin@pobox.com>
date: Sun Oct 1 09:38:35 EDT 2017
Use a proper union in struct config_item. This allows me to use different types for the mutable, dynamically allocated string value in a C_STRING control and the fixed constant list of option names in a C_CHOICES.
--- a/blackbox.c
+++ b/blackbox.c
@@ -148,14 +148,12 @@
ret[0].name = "Width";
ret[0].type = C_STRING;
sprintf(buf, "%d", params->w);
- ret[0].sval = dupstr(buf);
- ret[0].ival = 0;
+ ret[0].u.string.sval = dupstr(buf);
ret[1].name = "Height";
ret[1].type = C_STRING;
sprintf(buf, "%d", params->h);
- ret[1].sval = dupstr(buf);
- ret[1].ival = 0;
+ ret[1].u.string.sval = dupstr(buf);
ret[2].name = "No. of balls";
ret[2].type = C_STRING;
@@ -163,13 +161,10 @@
sprintf(buf, "%d", params->minballs);
else
sprintf(buf, "%d-%d", params->minballs, params->maxballs);
- ret[2].sval = dupstr(buf);
- ret[2].ival = 0;
+ ret[2].u.string.sval = dupstr(buf);
ret[3].name = NULL;
ret[3].type = C_END;
- ret[3].sval = NULL;
- ret[3].ival = 0;
return ret;
}
@@ -178,12 +173,13 @@
{
game_params *ret = snew(game_params);
- ret->w = atoi(cfg[0].sval);
- ret->h = atoi(cfg[1].sval);
+ ret->w = atoi(cfg[0].u.string.sval);
+ ret->h = atoi(cfg[1].u.string.sval);
/* Allow 'a-b' for a range, otherwise assume a single number. */
- if (sscanf(cfg[2].sval, "%d-%d", &ret->minballs, &ret->maxballs) < 2)
- ret->minballs = ret->maxballs = atoi(cfg[2].sval);
+ if (sscanf(cfg[2].u.string.sval, "%d-%d",
+ &ret->minballs, &ret->maxballs) < 2)
+ ret->minballs = ret->maxballs = atoi(cfg[2].u.string.sval);
return ret;
}
--- a/bridges.c
+++ b/bridges.c
@@ -742,44 +742,40 @@
ret[0].name = "Width";
ret[0].type = C_STRING;
sprintf(buf, "%d", params->w);
- ret[0].sval = dupstr(buf);
- ret[0].ival = 0;
+ ret[0].u.string.sval = dupstr(buf);
ret[1].name = "Height";
ret[1].type = C_STRING;
sprintf(buf, "%d", params->h);
- ret[1].sval = dupstr(buf);
- ret[1].ival = 0;
+ ret[1].u.string.sval = dupstr(buf);
ret[2].name = "Difficulty";
ret[2].type = C_CHOICES;
- ret[2].sval = ":Easy:Medium:Hard";
- ret[2].ival = params->difficulty;
+ ret[2].u.choices.choicenames = ":Easy:Medium:Hard";
+ ret[2].u.choices.selected = params->difficulty;
ret[3].name = "Allow loops";
ret[3].type = C_BOOLEAN;
- ret[3].sval = NULL;
- ret[3].ival = params->allowloops;
+ ret[3].u.boolean.bval = params->allowloops;
ret[4].name = "Max. bridges per direction";
ret[4].type = C_CHOICES;
- ret[4].sval = ":1:2:3:4"; /* keep up-to-date with MAX_BRIDGES */
- ret[4].ival = params->maxb - 1;
+ ret[4].u.choices.choicenames = ":1:2:3:4"; /* keep up-to-date with
+ * MAX_BRIDGES */
+ ret[4].u.choices.selected = params->maxb - 1;
ret[5].name = "%age of island squares";
ret[5].type = C_CHOICES;
- ret[5].sval = ":5%:10%:15%:20%:25%:30%";
- ret[5].ival = (params->islands / 5)-1;
+ ret[5].u.choices.choicenames = ":5%:10%:15%:20%:25%:30%";
+ ret[5].u.choices.selected = (params->islands / 5)-1;
ret[6].name = "Expansion factor (%age)";
ret[6].type = C_CHOICES;
- ret[6].sval = ":0%:10%:20%:30%:40%:50%:60%:70%:80%:90%:100%";
- ret[6].ival = params->expansion / 10;
+ ret[6].u.choices.choicenames = ":0%:10%:20%:30%:40%:50%:60%:70%:80%:90%:100%";
+ ret[6].u.choices.selected = params->expansion / 10;
ret[7].name = NULL;
ret[7].type = C_END;
- ret[7].sval = NULL;
- ret[7].ival = 0;
return ret;
}
@@ -788,13 +784,13 @@
{
game_params *ret = snew(game_params);
- ret->w = atoi(cfg[0].sval);
- ret->h = atoi(cfg[1].sval);
- ret->difficulty = cfg[2].ival;
- ret->allowloops = cfg[3].ival;
- ret->maxb = cfg[4].ival + 1;
- ret->islands = (cfg[5].ival + 1) * 5;
- ret->expansion = cfg[6].ival * 10;
+ ret->w = atoi(cfg[0].u.string.sval);
+ ret->h = atoi(cfg[1].u.string.sval);
+ ret->difficulty = cfg[2].u.choices.selected;
+ ret->allowloops = cfg[3].u.boolean.bval;
+ ret->maxb = cfg[4].u.choices.selected + 1;
+ ret->islands = (cfg[5].u.choices.selected + 1) * 5;
+ ret->expansion = cfg[6].u.choices.selected * 10;
return ret;
}
--- a/cube.c
+++ b/cube.c
@@ -489,25 +489,21 @@
ret[0].name = "Type of solid";
ret[0].type = C_CHOICES;
- ret[0].sval = ":Tetrahedron:Cube:Octahedron:Icosahedron";
- ret[0].ival = params->solid;
+ ret[0].u.choices.choicenames = ":Tetrahedron:Cube:Octahedron:Icosahedron";
+ ret[0].u.choices.selected = params->solid;
ret[1].name = "Width / top";
ret[1].type = C_STRING;
sprintf(buf, "%d", params->d1);
- ret[1].sval = dupstr(buf);
- ret[1].ival = 0;
+ ret[1].u.string.sval = dupstr(buf);
ret[2].name = "Height / bottom";
ret[2].type = C_STRING;
sprintf(buf, "%d", params->d2);
- ret[2].sval = dupstr(buf);
- ret[2].ival = 0;
+ ret[2].u.string.sval = dupstr(buf);
ret[3].name = NULL;
ret[3].type = C_END;
- ret[3].sval = NULL;
- ret[3].ival = 0;
return ret;
}
@@ -516,9 +512,9 @@
{
game_params *ret = snew(game_params);
- ret->solid = cfg[0].ival;
- ret->d1 = atoi(cfg[1].sval);
- ret->d2 = atoi(cfg[2].sval);
+ ret->solid = cfg[0].u.choices.selected;
+ ret->d1 = atoi(cfg[1].u.string.sval);
+ ret->d2 = atoi(cfg[2].u.string.sval);
return ret;
}
--- a/devel.but
+++ b/devel.but
@@ -555,16 +555,15 @@
\c char *name;
\c int type;
-\c char *sval;
-\c int ival;
+\c union { /* type-specific fields */ } u;
+\e iiiiiiiiiiiiiiiiiiiiiiiiii
\c{name} is an ASCII string giving the textual label for a GUI
control. It is \e{not} expected to be dynamically allocated.
\c{type} contains one of a small number of \c{enum} values defining
-what type of control is being described. The meaning of the \c{sval}
-and \c{ival} fields depends on the value in \c{type}. The valid
-values are:
+what type of control is being described. The usable member of the
+union field \c{u} depends on \c{type}. The valid type values are:
\dt \c{C_STRING}
@@ -572,38 +571,64 @@
input. The back end does not bother informing the front end that the
box is numeric rather than textual; some front ends do have the
capacity to take this into account, but I decided it wasn't worth
-the extra complexity in the interface.) For this type, \c{ival} is
-unused, and \c{sval} contains a dynamically allocated string
-representing the contents of the input box.
+the extra complexity in the interface.)
+\lcont{
+
+For controls of this type, \c{u.string} contains a single field
+
+\c char *sval;
+
+which stores a dynamically allocated string representing the contents
+of the input box.
+
+}
+
\dt \c{C_BOOLEAN}
-\dd Describes a simple checkbox. For this type, \c{sval} is unused,
-and \c{ival} is \cw{TRUE} or \cw{FALSE}.
+\dd Describes a simple checkbox.
+\lcont{
+
+For controls of this type, \c{u.boolean} contains a single field
+
+\c int bval;
+
+which is either \cw{TRUE} or \cw{FALSE}.
+
+}
+
\dt \c{C_CHOICES}
\dd Describes a drop-down list presenting one of a small number of
-fixed choices. For this type, \c{sval} contains a list of strings
-describing the choices; the very first character of \c{sval} is used
-as a delimiter when processing the rest (so that the strings
-\cq{:zero:one:two}, \cq{!zero!one!two} and \cq{xzeroxonextwo} all
-define a three-element list containing \cq{zero}, \cq{one} and
-\cq{two}). \c{ival} contains the index of the currently selected
-element, numbering from zero (so that in the above example, 0 would
-mean \cq{zero} and 2 would mean \cq{two}).
+fixed choices.
\lcont{
-Note that for this control type, \c{sval} is \e{not} dynamically
-allocated, whereas it was for \c{C_STRING}.
+For controls of this type, \c{u.choices} contains two fields:
+\c const char *choicenames;
+\c int selected;
+
+\c{choicenames} contains a list of strings describing the choices. The
+very first character of \c{sval} is used as a delimiter when
+processing the rest (so that the strings \cq{:zero:one:two},
+\cq{!zero!one!two} and \cq{xzeroxonextwo} all define a three-element
+list containing \cq{zero}, \cq{one} and \cq{two}).
+
+\c{selected} contains the index of the currently selected element,
+numbering from zero (so that in the above example, 0 would mean
+\cq{zero} and 2 would mean \cq{two}).
+
+Note that \c{u.choices.choicenames} is \e{not} dynamically allocated,
+unlike \c{u.string.sval}.
+
}
\dt \c{C_END}
-\dd Marks the end of the array of \c{config_item}s. All other fields
-are unused.
+\dd Marks the end of the array of \c{config_item}s. There is no
+associated member of the union field \c{u} for this type.
The array returned from this function is expected to have filled in
the initial values of all the controls according to the input
@@ -3737,10 +3762,10 @@
\c void free_cfg(config_item *cfg);
-This function correctly frees an array of \c{config_item}s,
-including walking the array until it gets to the end and freeing
-precisely those \c{sval} fields which are expected to be dynamically
-allocated.
+This function correctly frees an array of \c{config_item}s, including
+walking the array until it gets to the end and freeing any subsidiary
+data items in each \c{u} sub-union which are expected to be
+dynamically allocated.
(See \k{backend-configure} for details of the \c{config_item}
structure.)
--- a/dominosa.c
+++ b/dominosa.c
@@ -169,18 +169,14 @@
ret[0].name = "Maximum number on dominoes";
ret[0].type = C_STRING;
sprintf(buf, "%d", params->n);
- ret[0].sval = dupstr(buf);
- ret[0].ival = 0;
+ ret[0].u.string.sval = dupstr(buf);
ret[1].name = "Ensure unique solution";
ret[1].type = C_BOOLEAN;
- ret[1].sval = NULL;
- ret[1].ival = params->unique;
+ ret[1].u.boolean.bval = params->unique;
ret[2].name = NULL;
ret[2].type = C_END;
- ret[2].sval = NULL;
- ret[2].ival = 0;
return ret;
}
@@ -189,8 +185,8 @@
{
game_params *ret = snew(game_params);
- ret->n = atoi(cfg[0].sval);
- ret->unique = cfg[1].ival;
+ ret->n = atoi(cfg[0].u.string.sval);
+ ret->unique = cfg[1].u.boolean.bval;
return ret;
}
--- a/emcc.c
+++ b/emcc.c
@@ -599,13 +599,14 @@
for (i = 0; cfg[i].type != C_END; i++) {
switch (cfg[i].type) {
case C_STRING:
- js_dialog_string(i, cfg[i].name, cfg[i].sval);
+ js_dialog_string(i, cfg[i].name, cfg[i].u.string.sval);
break;
case C_BOOLEAN:
- js_dialog_boolean(i, cfg[i].name, cfg[i].ival);
+ js_dialog_boolean(i, cfg[i].name, cfg[i].u.boolean.bval);
break;
case C_CHOICES:
- js_dialog_choices(i, cfg[i].name, cfg[i].sval, cfg[i].ival);
+ js_dialog_choices(i, cfg[i].name, cfg[i].u.choices.choicenames,
+ cfg[i].u.choices.selected);
break;
}
}
@@ -619,12 +620,29 @@
*/
void dlg_return_sval(int index, const char *val)
{
- sfree(cfg[index].sval);
- cfg[index].sval = dupstr(val);
+ config_item *i = cfg + index;
+ switch (i->type) {
+ case C_STRING:
+ sfree(i->u.string.sval);
+ i->u.string.sval = dupstr(val);
+ break;
+ default:
+ assert(0 && "Bad type for return_sval");
+ }
}
void dlg_return_ival(int index, int val)
{
- cfg[index].ival = val;
+ config_item *i = cfg + index;
+ switch (i->type) {
+ case C_BOOLEAN:
+ i->u.boolean.bval = val;
+ break;
+ case C_CHOICES:
+ i->u.choices.selected = val;
+ break;
+ default:
+ assert(0 && "Bad type for return_ival");
+ }
}
/*
--- a/fifteen.c
+++ b/fifteen.c
@@ -111,19 +111,15 @@
ret[0].name = "Width";
ret[0].type = C_STRING;
sprintf(buf, "%d", params->w);
- ret[0].sval = dupstr(buf);
- ret[0].ival = 0;
+ ret[0].u.string.sval = dupstr(buf);
ret[1].name = "Height";
ret[1].type = C_STRING;
sprintf(buf, "%d", params->h);
- ret[1].sval = dupstr(buf);
- ret[1].ival = 0;
+ ret[1].u.string.sval = dupstr(buf);
ret[2].name = NULL;
ret[2].type = C_END;
- ret[2].sval = NULL;
- ret[2].ival = 0;
return ret;
}
@@ -132,8 +128,8 @@
{
game_params *ret = snew(game_params);
- ret->w = atoi(cfg[0].sval);
- ret->h = atoi(cfg[1].sval);
+ ret->w = atoi(cfg[0].u.string.sval);
+ ret->h = atoi(cfg[1].u.string.sval);
return ret;
}
--- a/filling.c
+++ b/filling.c
@@ -161,19 +161,15 @@
ret[0].name = "Width";
ret[0].type = C_STRING;
sprintf(buf, "%d", params->w);
- ret[0].sval = dupstr(buf);
- ret[0].ival = 0;
+ ret[0].u.string.sval = dupstr(buf);
ret[1].name = "Height";
ret[1].type = C_STRING;
sprintf(buf, "%d", params->h);
- ret[1].sval = dupstr(buf);
- ret[1].ival = 0;
+ ret[1].u.string.sval = dupstr(buf);
ret[2].name = NULL;
ret[2].type = C_END;
- ret[2].sval = NULL;
- ret[2].ival = 0;
return ret;
}
@@ -182,8 +178,8 @@
{
game_params *ret = snew(game_params);
- ret->w = atoi(cfg[0].sval);
- ret->h = atoi(cfg[1].sval);
+ ret->w = atoi(cfg[0].u.string.sval);
+ ret->h = atoi(cfg[1].u.string.sval);
return ret;
}
--- a/flip.c
+++ b/flip.c
@@ -149,24 +149,20 @@
ret[0].name = "Width";
ret[0].type = C_STRING;
sprintf(buf, "%d", params->w);
- ret[0].sval = dupstr(buf);
- ret[0].ival = 0;
+ ret[0].u.string.sval = dupstr(buf);
ret[1].name = "Height";
ret[1].type = C_STRING;
sprintf(buf, "%d", params->h);
- ret[1].sval = dupstr(buf);
- ret[1].ival = 0;
+ ret[1].u.string.sval = dupstr(buf);
ret[2].name = "Shape type";
ret[2].type = C_CHOICES;
- ret[2].sval = ":Crosses:Random";
- ret[2].ival = params->matrix_type;
+ ret[2].u.choices.choicenames = ":Crosses:Random";
+ ret[2].u.choices.selected = params->matrix_type;
ret[3].name = NULL;
ret[3].type = C_END;
- ret[3].sval = NULL;
- ret[3].ival = 0;
return ret;
}
@@ -175,9 +171,9 @@
{
game_params *ret = snew(game_params);
- ret->w = atoi(cfg[0].sval);
- ret->h = atoi(cfg[1].sval);
- ret->matrix_type = cfg[2].ival;
+ ret->w = atoi(cfg[0].u.string.sval);
+ ret->h = atoi(cfg[1].u.string.sval);
+ ret->matrix_type = cfg[2].u.choices.selected;
return ret;
}
--- a/flood.c
+++ b/flood.c
@@ -170,31 +170,25 @@
ret[0].name = "Width";
ret[0].type = C_STRING;
sprintf(buf, "%d", params->w);
- ret[0].sval = dupstr(buf);
- ret[0].ival = 0;
+ ret[0].u.string.sval = dupstr(buf);
ret[1].name = "Height";
ret[1].type = C_STRING;
sprintf(buf, "%d", params->h);
- ret[1].sval = dupstr(buf);
- ret[1].ival = 0;
+ ret[1].u.string.sval = dupstr(buf);
ret[2].name = "Colours";
ret[2].type = C_STRING;
sprintf(buf, "%d", params->colours);
- ret[2].sval = dupstr(buf);
- ret[2].ival = 0;
+ ret[2].u.string.sval = dupstr(buf);
ret[3].name = "Extra moves permitted";
ret[3].type = C_STRING;
sprintf(buf, "%d", params->leniency);
- ret[3].sval = dupstr(buf);
- ret[3].ival = 0;
+ ret[3].u.string.sval = dupstr(buf);
ret[4].name = NULL;
ret[4].type = C_END;
- ret[4].sval = NULL;
- ret[4].ival = 0;
return ret;
}
@@ -203,10 +197,10 @@
{
game_params *ret = snew(game_params);
- ret->w = atoi(cfg[0].sval);
- ret->h = atoi(cfg[1].sval);
- ret->colours = atoi(cfg[2].sval);
- ret->leniency = atoi(cfg[3].sval);
+ ret->w = atoi(cfg[0].u.string.sval);
+ ret->h = atoi(cfg[1].u.string.sval);
+ ret->colours = atoi(cfg[2].u.string.sval);
+ ret->leniency = atoi(cfg[3].u.string.sval);
return ret;
}
--- a/galaxies.c
+++ b/galaxies.c
@@ -248,24 +248,20 @@
ret[0].name = "Width";
ret[0].type = C_STRING;
sprintf(buf, "%d", params->w);
- ret[0].sval = dupstr(buf);
- ret[0].ival = 0;
+ ret[0].u.string.sval = dupstr(buf);
ret[1].name = "Height";
ret[1].type = C_STRING;
sprintf(buf, "%d", params->h);
- ret[1].sval = dupstr(buf);
- ret[1].ival = 0;
+ ret[1].u.string.sval = dupstr(buf);
ret[2].name = "Difficulty";
ret[2].type = C_CHOICES;
- ret[2].sval = DIFFCONFIG;
- ret[2].ival = params->diff;
+ ret[2].u.choices.choicenames = DIFFCONFIG;
+ ret[2].u.choices.selected = params->diff;
ret[3].name = NULL;
ret[3].type = C_END;
- ret[3].sval = NULL;
- ret[3].ival = 0;
return ret;
}
@@ -274,9 +270,9 @@
{
game_params *ret = snew(game_params);
- ret->w = atoi(cfg[0].sval);
- ret->h = atoi(cfg[1].sval);
- ret->diff = cfg[2].ival;
+ ret->w = atoi(cfg[0].u.string.sval);
+ ret->h = atoi(cfg[1].u.string.sval);
+ ret->diff = cfg[2].u.choices.selected;
return ret;
}
--- a/gtk.c
+++ b/gtk.c
@@ -1641,8 +1641,9 @@
{
config_item *i = (config_item *)data;
- sfree(i->sval);
- i->sval = dupstr(gtk_entry_get_text(GTK_ENTRY(ed)));
+ assert(i->type == C_STRING);
+ sfree(i->u.string.sval);
+ i->u.string.sval = dupstr(gtk_entry_get_text(GTK_ENTRY(ed)));
}
static void button_toggled(GtkToggleButton *tb, gpointer data)
@@ -1649,7 +1650,8 @@
{
config_item *i = (config_item *)data;
- i->ival = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(tb));
+ assert(i->type == C_BOOLEAN);
+ i->u.boolean.bval = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(tb));
}
static void droplist_sel(GtkComboBox *combo, gpointer data)
@@ -1656,7 +1658,8 @@
{
config_item *i = (config_item *)data;
- i->ival = gtk_combo_box_get_active(combo);
+ assert(i->type == C_CHOICES);
+ i->u.choices.selected = gtk_combo_box_get_active(combo);
}
static int get_config(frontend *fe, int which)
@@ -1751,7 +1754,7 @@
GTK_EXPAND | GTK_SHRINK | GTK_FILL,
3, 3);
#endif
- gtk_entry_set_text(GTK_ENTRY(w), i->sval);
+ gtk_entry_set_text(GTK_ENTRY(w), i->u.string.sval);
g_signal_connect(G_OBJECT(w), "changed",
G_CALLBACK(editbox_changed), i);
g_signal_connect(G_OBJECT(w), "key_press_event",
@@ -1776,7 +1779,8 @@
GTK_EXPAND | GTK_SHRINK | GTK_FILL,
3, 3);
#endif
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), i->ival);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w),
+ i->u.boolean.bval);
gtk_widget_show(w);
break;
@@ -1799,7 +1803,8 @@
{
int c;
- char *p, *q, *name;
+ const char *p, *q;
+ char *name;
GtkListStore *model;
GtkCellRenderer *cr;
GtkTreeIter iter;
@@ -1806,8 +1811,8 @@
model = gtk_list_store_new(1, G_TYPE_STRING);
- c = *i->sval;
- p = i->sval+1;
+ c = *i->u.choices.choicenames;
+ p = i->u.choices.choicenames+1;
while (*p) {
q = p;
@@ -1828,7 +1833,8 @@
w = gtk_combo_box_new_with_model(GTK_TREE_MODEL(model));
- gtk_combo_box_set_active(GTK_COMBO_BOX(w), i->ival);
+ gtk_combo_box_set_active(GTK_COMBO_BOX(w),
+ i->u.choices.selected);
cr = gtk_cell_renderer_text_new();
gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(w), cr, TRUE);
--- a/guess.c
+++ b/guess.c
@@ -166,35 +166,28 @@
ret[0].name = "Colours";
ret[0].type = C_STRING;
sprintf(buf, "%d", params->ncolours);
- ret[0].sval = dupstr(buf);
- ret[0].ival = 0;
+ ret[0].u.string.sval = dupstr(buf);
ret[1].name = "Pegs per guess";
ret[1].type = C_STRING;
sprintf(buf, "%d", params->npegs);
- ret[1].sval = dupstr(buf);
- ret[1].ival = 0;
+ ret[1].u.string.sval = dupstr(buf);
ret[2].name = "Guesses";
ret[2].type = C_STRING;
sprintf(buf, "%d", params->nguesses);
- ret[2].sval = dupstr(buf);
- ret[2].ival = 0;
+ ret[2].u.string.sval = dupstr(buf);
ret[3].name = "Allow blanks";
ret[3].type = C_BOOLEAN;
- ret[3].sval = NULL;
- ret[3].ival = params->allow_blank;
+ ret[3].u.boolean.bval = params->allow_blank;
ret[4].name = "Allow duplicates";
ret[4].type = C_BOOLEAN;
- ret[4].sval = NULL;
- ret[4].ival = params->allow_multiple;
+ ret[4].u.boolean.bval = params->allow_multiple;
ret[5].name = NULL;
ret[5].type = C_END;
- ret[5].sval = NULL;
- ret[5].ival = 0;
return ret;
}
@@ -203,12 +196,12 @@
{
game_params *ret = snew(game_params);
- ret->ncolours = atoi(cfg[0].sval);
- ret->npegs = atoi(cfg[1].sval);
- ret->nguesses = atoi(cfg[2].sval);
+ ret->ncolours = atoi(cfg[0].u.string.sval);
+ ret->npegs = atoi(cfg[1].u.string.sval);
+ ret->nguesses = atoi(cfg[2].u.string.sval);
- ret->allow_blank = cfg[3].ival;
- ret->allow_multiple = cfg[4].ival;
+ ret->allow_blank = cfg[3].u.boolean.bval;
+ ret->allow_multiple = cfg[4].u.boolean.bval;
return ret;
}
--- a/inertia.c
+++ b/inertia.c
@@ -168,19 +168,15 @@
ret[0].name = "Width";
ret[0].type = C_STRING;
sprintf(buf, "%d", params->w);
- ret[0].sval = dupstr(buf);
- ret[0].ival = 0;
+ ret[0].u.string.sval = dupstr(buf);
ret[1].name = "Height";
ret[1].type = C_STRING;
sprintf(buf, "%d", params->h);
- ret[1].sval = dupstr(buf);
- ret[1].ival = 0;
+ ret[1].u.string.sval = dupstr(buf);
ret[2].name = NULL;
ret[2].type = C_END;
- ret[2].sval = NULL;
- ret[2].ival = 0;
return ret;
}
@@ -189,8 +185,8 @@
{
game_params *ret = snew(game_params);
- ret->w = atoi(cfg[0].sval);
- ret->h = atoi(cfg[1].sval);
+ ret->w = atoi(cfg[0].u.string.sval);
+ ret->h = atoi(cfg[1].u.string.sval);
return ret;
}
--- a/keen.c
+++ b/keen.c
@@ -183,23 +183,19 @@
ret[0].name = "Grid size";
ret[0].type = C_STRING;
sprintf(buf, "%d", params->w);
- ret[0].sval = dupstr(buf);
- ret[0].ival = 0;
+ ret[0].u.string.sval = dupstr(buf);
ret[1].name = "Difficulty";
ret[1].type = C_CHOICES;
- ret[1].sval = DIFFCONFIG;
- ret[1].ival = params->diff;
+ ret[1].u.choices.choicenames = DIFFCONFIG;
+ ret[1].u.choices.selected = params->diff;
ret[2].name = "Multiplication only";
ret[2].type = C_BOOLEAN;
- ret[2].sval = NULL;
- ret[2].ival = params->multiplication_only;
+ ret[2].u.boolean.bval = params->multiplication_only;
ret[3].name = NULL;
ret[3].type = C_END;
- ret[3].sval = NULL;
- ret[3].ival = 0;
return ret;
}
@@ -208,9 +204,9 @@
{
game_params *ret = snew(game_params);
- ret->w = atoi(cfg[0].sval);
- ret->diff = cfg[1].ival;
- ret->multiplication_only = cfg[2].ival;
+ ret->w = atoi(cfg[0].u.string.sval);
+ ret->diff = cfg[1].u.choices.selected;
+ ret->multiplication_only = cfg[2].u.boolean.bval;
return ret;
}
--- a/lightup.c
+++ b/lightup.c
@@ -299,37 +299,32 @@
ret[0].name = "Width";
ret[0].type = C_STRING;
sprintf(buf, "%d", params->w);
- ret[0].sval = dupstr(buf);
- ret[0].ival = 0;
+ ret[0].u.string.sval = dupstr(buf);
ret[1].name = "Height";
ret[1].type = C_STRING;
sprintf(buf, "%d", params->h);
- ret[1].sval = dupstr(buf);
- ret[1].ival = 0;
+ ret[1].u.string.sval = dupstr(buf);
ret[2].name = "%age of black squares";
ret[2].type = C_STRING;
sprintf(buf, "%d", params->blackpc);
- ret[2].sval = dupstr(buf);
- ret[2].ival = 0;
+ ret[2].u.string.sval = dupstr(buf);
ret[3].name = "Symmetry";
ret[3].type = C_CHOICES;
- ret[3].sval = ":None"
+ ret[3].u.choices.choicenames = ":None"
":2-way mirror:2-way rotational"
":4-way mirror:4-way rotational";
- ret[3].ival = params->symm;
+ ret[3].u.choices.selected = params->symm;
ret[4].name = "Difficulty";
ret[4].type = C_CHOICES;
- ret[4].sval = ":Easy:Tricky:Hard";
- ret[4].ival = params->difficulty;
+ ret[4].u.choices.choicenames = ":Easy:Tricky:Hard";
+ ret[4].u.choices.selected = params->difficulty;
ret[5].name = NULL;
ret[5].type = C_END;
- ret[5].sval = NULL;
- ret[5].ival = 0;
return ret;
}
@@ -338,11 +333,11 @@
{
game_params *ret = snew(game_params);
- ret->w = atoi(cfg[0].sval);
- ret->h = atoi(cfg[1].sval);
- ret->blackpc = atoi(cfg[2].sval);
- ret->symm = cfg[3].ival;
- ret->difficulty = cfg[4].ival;
+ ret->w = atoi(cfg[0].u.string.sval);
+ ret->h = atoi(cfg[1].u.string.sval);
+ ret->blackpc = atoi(cfg[2].u.string.sval);
+ ret->symm = cfg[3].u.choices.selected;
+ ret->difficulty = cfg[4].u.choices.selected;
return ret;
}
--- a/loopy.c
+++ b/loopy.c
@@ -640,29 +640,25 @@
ret[0].name = "Width";
ret[0].type = C_STRING;
sprintf(buf, "%d", params->w);
- ret[0].sval = dupstr(buf);
- ret[0].ival = 0;
+ ret[0].u.string.sval = dupstr(buf);
ret[1].name = "Height";
ret[1].type = C_STRING;
sprintf(buf, "%d", params->h);
- ret[1].sval = dupstr(buf);
- ret[1].ival = 0;
+ ret[1].u.string.sval = dupstr(buf);
ret[2].name = "Grid type";
ret[2].type = C_CHOICES;
- ret[2].sval = GRID_CONFIGS;
- ret[2].ival = params->type;
+ ret[2].u.choices.choicenames = GRID_CONFIGS;
+ ret[2].u.choices.selected = params->type;
ret[3].name = "Difficulty";
ret[3].type = C_CHOICES;
- ret[3].sval = DIFFCONFIG;
- ret[3].ival = params->diff;
+ ret[3].u.choices.choicenames = DIFFCONFIG;
+ ret[3].u.choices.selected = params->diff;
ret[4].name = NULL;
ret[4].type = C_END;
- ret[4].sval = NULL;
- ret[4].ival = 0;
return ret;
}
@@ -671,10 +667,10 @@
{
game_params *ret = snew(game_params);
- ret->w = atoi(cfg[0].sval);
- ret->h = atoi(cfg[1].sval);
- ret->type = cfg[2].ival;
- ret->diff = cfg[3].ival;
+ ret->w = atoi(cfg[0].u.string.sval);
+ ret->h = atoi(cfg[1].u.string.sval);
+ ret->type = cfg[2].u.choices.selected;
+ ret->diff = cfg[3].u.choices.selected;
return ret;
}
--- a/magnets.c
+++ b/magnets.c
@@ -193,29 +193,24 @@
ret[0].name = "Width";
ret[0].type = C_STRING;
sprintf(buf, "%d", params->w);
- ret[0].sval = dupstr(buf);
- ret[0].ival = 0;
+ ret[0].u.string.sval = dupstr(buf);
ret[1].name = "Height";
ret[1].type = C_STRING;
sprintf(buf, "%d", params->h);
- ret[1].sval = dupstr(buf);
- ret[1].ival = 0;
+ ret[1].u.string.sval = dupstr(buf);
ret[2].name = "Difficulty";
ret[2].type = C_CHOICES;
- ret[2].sval = DIFFCONFIG;
- ret[2].ival = params->diff;
+ ret[2].u.choices.choicenames = DIFFCONFIG;
+ ret[2].u.choices.selected = params->diff;
ret[3].name = "Strip clues";
ret[3].type = C_BOOLEAN;
- ret[3].sval = NULL;
- ret[3].ival = params->stripclues;
+ ret[3].u.boolean.bval = params->stripclues;
ret[4].name = NULL;
ret[4].type = C_END;
- ret[4].sval = NULL;
- ret[4].ival = 0;
return ret;
}
@@ -224,10 +219,10 @@
{
game_params *ret = snew(game_params);
- ret->w = atoi(cfg[0].sval);
- ret->h = atoi(cfg[1].sval);
- ret->diff = cfg[2].ival;
- ret->stripclues = cfg[3].ival;
+ ret->w = atoi(cfg[0].u.string.sval);
+ ret->h = atoi(cfg[1].u.string.sval);
+ ret->diff = cfg[2].u.choices.selected;
+ ret->stripclues = cfg[3].u.boolean.bval;
return ret;
}
--- a/map.c
+++ b/map.c
@@ -213,30 +213,25 @@
ret[0].name = "Width";
ret[0].type = C_STRING;
sprintf(buf, "%d", params->w);
- ret[0].sval = dupstr(buf);
- ret[0].ival = 0;
+ ret[0].u.string.sval = dupstr(buf);
ret[1].name = "Height";
ret[1].type = C_STRING;
sprintf(buf, "%d", params->h);
- ret[1].sval = dupstr(buf);
- ret[1].ival = 0;
+ ret[1].u.string.sval = dupstr(buf);
ret[2].name = "Regions";
ret[2].type = C_STRING;
sprintf(buf, "%d", params->n);
- ret[2].sval = dupstr(buf);
- ret[2].ival = 0;
+ ret[2].u.string.sval = dupstr(buf);
ret[3].name = "Difficulty";
ret[3].type = C_CHOICES;
- ret[3].sval = DIFFCONFIG;
- ret[3].ival = params->diff;
+ ret[3].u.choices.choicenames = DIFFCONFIG;
+ ret[3].u.choices.selected = params->diff;
ret[4].name = NULL;
ret[4].type = C_END;
- ret[4].sval = NULL;
- ret[4].ival = 0;
return ret;
}
@@ -245,10 +240,10 @@
{
game_params *ret = snew(game_params);
- ret->w = atoi(cfg[0].sval);
- ret->h = atoi(cfg[1].sval);
- ret->n = atoi(cfg[2].sval);
- ret->diff = cfg[3].ival;
+ ret->w = atoi(cfg[0].u.string.sval);
+ ret->h = atoi(cfg[1].u.string.sval);
+ ret->n = atoi(cfg[2].u.string.sval);
+ ret->diff = cfg[3].u.choices.selected;
return ret;
}
--- a/midend.c
+++ b/midend.c
@@ -1360,7 +1360,6 @@
ret[0].name = "Game random seed";
else
ret[0].name = "Game ID";
- ret[0].ival = 0;
/*
* For CFG_DESC the text going in here will be a string
* encoding of the restricted parameters, plus a colon,
@@ -1379,13 +1378,12 @@
rest = me->seedstr ? me->seedstr : "";
sep = '#';
}
- ret[0].sval = snewn(strlen(parstr) + strlen(rest) + 2, char);
- sprintf(ret[0].sval, "%s%c%s", parstr, sep, rest);
+ ret[0].u.string.sval = snewn(strlen(parstr) + strlen(rest) + 2, char);
+ sprintf(ret[0].u.string.sval, "%s%c%s", parstr, sep, rest);
sfree(parstr);
ret[1].type = C_END;
- ret[1].name = ret[1].sval = NULL;
- ret[1].ival = 0;
+ ret[1].name = NULL;
return ret;
}
@@ -1620,7 +1618,7 @@
case CFG_SEED:
case CFG_DESC:
- error = midend_game_id_int(me, cfg[0].sval,
+ error = midend_game_id_int(me, cfg[0].u.string.sval,
(which == CFG_SEED ? DEF_SEED : DEF_DESC));
if (error)
return error;
--- a/mines.c
+++ b/mines.c
@@ -203,30 +203,24 @@
ret[0].name = "Width";
ret[0].type = C_STRING;
sprintf(buf, "%d", params->w);
- ret[0].sval = dupstr(buf);
- ret[0].ival = 0;
+ ret[0].u.string.sval = dupstr(buf);
ret[1].name = "Height";
ret[1].type = C_STRING;
sprintf(buf, "%d", params->h);
- ret[1].sval = dupstr(buf);
- ret[1].ival = 0;
+ ret[1].u.string.sval = dupstr(buf);
ret[2].name = "Mines";
ret[2].type = C_STRING;
sprintf(buf, "%d", params->n);
- ret[2].sval = dupstr(buf);
- ret[2].ival = 0;
+ ret[2].u.string.sval = dupstr(buf);
ret[3].name = "Ensure solubility";
ret[3].type = C_BOOLEAN;
- ret[3].sval = NULL;
- ret[3].ival = params->unique;
+ ret[3].u.boolean.bval = params->unique;
ret[4].name = NULL;
ret[4].type = C_END;
- ret[4].sval = NULL;
- ret[4].ival = 0;
return ret;
}
@@ -235,12 +229,12 @@
{
game_params *ret = snew(game_params);
- ret->w = atoi(cfg[0].sval);
- ret->h = atoi(cfg[1].sval);
- ret->n = atoi(cfg[2].sval);
- if (strchr(cfg[2].sval, '%'))
+ ret->w = atoi(cfg[0].u.string.sval);
+ ret->h = atoi(cfg[1].u.string.sval);
+ ret->n = atoi(cfg[2].u.string.sval);
+ if (strchr(cfg[2].u.string.sval, '%'))
ret->n = ret->n * (ret->w * ret->h) / 100;
- ret->unique = cfg[3].ival;
+ ret->unique = cfg[3].u.boolean.bval;
return ret;
}
--- a/misc.c
+++ b/misc.c
@@ -17,7 +17,7 @@
for (i = cfg; i->type != C_END; i++)
if (i->type == C_STRING)
- sfree(i->sval);
+ sfree(i->u.string.sval);
sfree(cfg);
}
--- a/nestedvm.c
+++ b/nestedvm.c
@@ -273,19 +273,22 @@
void jcallback_config_set_string(int item_ptr, int char_ptr) {
config_item *i = (config_item *)item_ptr;
char* newval = (char*) char_ptr;
- sfree(i->sval);
- i->sval = dupstr(newval);
+ assert(i->type == C_STRING);
+ sfree(i->u.string.sval);
+ i->u.string.sval = dupstr(newval);
free(newval);
}
void jcallback_config_set_boolean(int item_ptr, int selected) {
config_item *i = (config_item *)item_ptr;
- i->ival = selected != 0 ? TRUE : FALSE;
+ assert(i->type == C_BOOLEAN);
+ i->u.boolean.bval = selected != 0 ? TRUE : FALSE;
}
void jcallback_config_set_choice(int item_ptr, int selected) {
config_item *i = (config_item *)item_ptr;
- i->ival = selected;
+ assert(i->type == C_CHOICES);
+ i->u.choices.selected = selected;
}
static int get_config(frontend *fe, int which)
@@ -298,7 +301,18 @@
_call_java(10, (int)title, 0, 0);
for (i = fe->cfg; i->type != C_END; i++) {
_call_java(5, (int)i, i->type, (int)i->name);
- _call_java(11, (int)i->sval, i->ival, 0);
+ switch (i->type) {
+ case C_STRING:
+ _call_java(11, (int)i->u.string.sval, 0, 0);
+ break;
+ case C_BOOLEAN:
+ _call_java(11, 0, i->u.boolean.bval, 0);
+ break;
+ case C_CHOICES:
+ _call_java(11, (int)i->u.choices.choicenames,
+ i->u.choices.selected, 0);
+ break;
+ }
}
_call_java(12,0,0,0);
free_cfg(fe->cfg);
--- a/net.c
+++ b/net.c
@@ -267,35 +267,28 @@
ret[0].name = "Width";
ret[0].type = C_STRING;
sprintf(buf, "%d", params->width);
- ret[0].sval = dupstr(buf);
- ret[0].ival = 0;
+ ret[0].u.string.sval = dupstr(buf);
ret[1].name = "Height";
ret[1].type = C_STRING;
sprintf(buf, "%d", params->height);
- ret[1].sval = dupstr(buf);
- ret[1].ival = 0;
+ ret[1].u.string.sval = dupstr(buf);
ret[2].name = "Walls wrap around";
ret[2].type = C_BOOLEAN;
- ret[2].sval = NULL;
- ret[2].ival = params->wrapping;
+ ret[2].u.boolean.bval = params->wrapping;
ret[3].name = "Barrier probability";
ret[3].type = C_STRING;
sprintf(buf, "%g", params->barrier_probability);
- ret[3].sval = dupstr(buf);
- ret[3].ival = 0;
+ ret[3].u.string.sval = dupstr(buf);
ret[4].name = "Ensure unique solution";
ret[4].type = C_BOOLEAN;
- ret[4].sval = NULL;
- ret[4].ival = params->unique;
+ ret[4].u.boolean.bval = params->unique;
ret[5].name = NULL;
ret[5].type = C_END;
- ret[5].sval = NULL;
- ret[5].ival = 0;
return ret;
}
@@ -304,11 +297,11 @@
{
game_params *ret = snew(game_params);
- ret->width = atoi(cfg[0].sval);
- ret->height = atoi(cfg[1].sval);
- ret->wrapping = cfg[2].ival;
- ret->barrier_probability = (float)atof(cfg[3].sval);
- ret->unique = cfg[4].ival;
+ ret->width = atoi(cfg[0].u.string.sval);
+ ret->height = atoi(cfg[1].u.string.sval);
+ ret->wrapping = cfg[2].u.boolean.bval;
+ ret->barrier_probability = (float)atof(cfg[3].u.string.sval);
+ ret->unique = cfg[4].u.boolean.bval;
return ret;
}
--- a/netslide.c
+++ b/netslide.c
@@ -262,36 +262,29 @@
ret[0].name = "Width";
ret[0].type = C_STRING;
sprintf(buf, "%d", params->width);
- ret[0].sval = dupstr(buf);
- ret[0].ival = 0;
+ ret[0].u.string.sval = dupstr(buf);
ret[1].name = "Height";
ret[1].type = C_STRING;
sprintf(buf, "%d", params->height);
- ret[1].sval = dupstr(buf);
- ret[1].ival = 0;
+ ret[1].u.string.sval = dupstr(buf);
ret[2].name = "Walls wrap around";
ret[2].type = C_BOOLEAN;
- ret[2].sval = NULL;
- ret[2].ival = params->wrapping;
+ ret[2].u.boolean.bval = params->wrapping;
ret[3].name = "Barrier probability";
ret[3].type = C_STRING;
sprintf(buf, "%g", params->barrier_probability);
- ret[3].sval = dupstr(buf);
- ret[3].ival = 0;
+ ret[3].u.string.sval = dupstr(buf);
ret[4].name = "Number of shuffling moves";
ret[4].type = C_STRING;
sprintf(buf, "%d", params->movetarget);
- ret[4].sval = dupstr(buf);
- ret[4].ival = 0;
+ ret[4].u.string.sval = dupstr(buf);
ret[5].name = NULL;
ret[5].type = C_END;
- ret[5].sval = NULL;
- ret[5].ival = 0;
return ret;
}
@@ -300,11 +293,11 @@
{
game_params *ret = snew(game_params);
- ret->width = atoi(cfg[0].sval);
- ret->height = atoi(cfg[1].sval);
- ret->wrapping = cfg[2].ival;
- ret->barrier_probability = (float)atof(cfg[3].sval);
- ret->movetarget = atoi(cfg[4].sval);
+ ret->width = atoi(cfg[0].u.string.sval);
+ ret->height = atoi(cfg[1].u.string.sval);
+ ret->wrapping = cfg[2].u.boolean.bval;
+ ret->barrier_probability = (float)atof(cfg[3].u.string.sval);
+ ret->movetarget = atoi(cfg[4].u.string.sval);
return ret;
}
--- a/osx.m
+++ b/osx.m
@@ -1103,7 +1103,8 @@
[tf setEditable:YES];
[tf setSelectable:YES];
[tf setBordered:YES];
- [[tf cell] setTitle:[NSString stringWithUTF8String:i->sval]];
+ [[tf cell] setTitle:[NSString
+ stringWithUTF8String:i->u.string.sval]];
[tf sizeToFit];
rect = [tf frame];
/*
@@ -1132,7 +1133,7 @@
[b setButtonType:NSSwitchButton];
[b setTitle:[NSString stringWithUTF8String:i->name]];
[b sizeToFit];
- [b setState:(i->ival ? NSOnState : NSOffState)];
+ [b setState:(i->u.boolean.bval ? NSOnState : NSOffState)];
rect = [b frame];
if (totalw < rect.size.width + 1) totalw = rect.size.width + 1;
if (thish < rect.size.height + 1) thish = rect.size.height + 1;
@@ -1161,12 +1162,14 @@
pb = [[NSPopUpButton alloc] initWithFrame:tmprect pullsDown:NO];
[pb setBezelStyle:NSRoundedBezelStyle];
{
- char c, *p;
+ char c;
+ const char *p;
- p = i->sval;
+ p = i->u.choices.choicenames;
c = *p++;
while (*p) {
- char *q, *copy;
+ const char *q;
+ char *copy;
q = p;
while (*p && *p != c) p++;
@@ -1180,7 +1183,7 @@
if (*p) p++;
}
}
- [pb selectItemAtIndex:i->ival];
+ [pb selectItemAtIndex:i->u.choices.selected];
[pb sizeToFit];
rect = [pb frame];
@@ -1303,17 +1306,18 @@
for (i = cfg; i->type != C_END; i++) {
switch (i->type) {
case C_STRING:
- sfree(i->sval);
- i->sval = dupstr([[[(id)cfg_controls[k+1] cell]
+ sfree(i->u.string.sval);
+ i->u.string.sval = dupstr([[[(id)cfg_controls[k+1] cell]
title] UTF8String]);
k += 2;
break;
case C_BOOLEAN:
- i->ival = [(id)cfg_controls[k] state] == NSOnState;
+ i->u.boolean.bval = [(id)cfg_controls[k] state] == NSOnState;
k++;
break;
case C_CHOICES:
- i->ival = [(id)cfg_controls[k+1] indexOfSelectedItem];
+ i->u.choices.selected =
+ [(id)cfg_controls[k+1] indexOfSelectedItem];
k += 2;
break;
}
--- a/palisade.c
+++ b/palisade.c
@@ -119,11 +119,21 @@
{
config_item *ret = snewn(4, config_item);
- CONFIG(0, "Width", C_STRING, 0, string(20, "%d", params->w));
- CONFIG(1, "Height", C_STRING, 0, string(20, "%d", params->h));
- CONFIG(2, "Region size", C_STRING, 0, string(20, "%d", params->k));
- CONFIG(3, NULL, C_END, 0, NULL);
+ ret[0].name = "Width";
+ ret[0].type = C_STRING;
+ ret[0].u.string.sval = string(20, "%d", params->w);
+ ret[1].name = "Height";
+ ret[1].type = C_STRING;
+ ret[1].u.string.sval = string(20, "%d", params->h);
+
+ ret[2].name = "Region size";
+ ret[2].type = C_STRING;
+ ret[2].u.string.sval = string(20, "%d", params->k);
+
+ ret[3].name = NULL;
+ ret[3].type = C_END;
+
return ret;
}
@@ -131,9 +141,9 @@
{
game_params *params = snew(game_params);
- params->w = atoi(cfg[0].sval);
- params->h = atoi(cfg[1].sval);
- params->k = atoi(cfg[2].sval);
+ params->w = atoi(cfg[0].u.string.sval);
+ params->h = atoi(cfg[1].u.string.sval);
+ params->k = atoi(cfg[2].u.string.sval);
return params;
}
--- a/pattern.c
+++ b/pattern.c
@@ -148,19 +148,15 @@
ret[0].name = "Width";
ret[0].type = C_STRING;
sprintf(buf, "%d", params->w);
- ret[0].sval = dupstr(buf);
- ret[0].ival = 0;
+ ret[0].u.string.sval = dupstr(buf);
ret[1].name = "Height";
ret[1].type = C_STRING;
sprintf(buf, "%d", params->h);
- ret[1].sval = dupstr(buf);
- ret[1].ival = 0;
+ ret[1].u.string.sval = dupstr(buf);
ret[2].name = NULL;
ret[2].type = C_END;
- ret[2].sval = NULL;
- ret[2].ival = 0;
return ret;
}
@@ -169,8 +165,8 @@
{
game_params *ret = snew(game_params);
- ret->w = atoi(cfg[0].sval);
- ret->h = atoi(cfg[1].sval);
+ ret->w = atoi(cfg[0].u.string.sval);
+ ret->h = atoi(cfg[1].u.string.sval);
return ret;
}
--- a/pearl.c
+++ b/pearl.c
@@ -234,29 +234,24 @@
ret[0].name = "Width";
ret[0].type = C_STRING;
sprintf(buf, "%d", params->w);
- ret[0].sval = dupstr(buf);
- ret[0].ival = 0;
+ ret[0].u.string.sval = dupstr(buf);
ret[1].name = "Height";
ret[1].type = C_STRING;
sprintf(buf, "%d", params->h);
- ret[1].sval = dupstr(buf);
- ret[1].ival = 0;
+ ret[1].u.string.sval = dupstr(buf);
ret[2].name = "Difficulty";
ret[2].type = C_CHOICES;
- ret[2].sval = DIFFCONFIG;
- ret[2].ival = params->difficulty;
+ ret[2].u.choices.choicenames = DIFFCONFIG;
+ ret[2].u.choices.selected = params->difficulty;
ret[3].name = "Allow unsoluble";
ret[3].type = C_BOOLEAN;
- ret[3].sval = NULL;
- ret[3].ival = params->nosolve;
+ ret[3].u.boolean.bval = params->nosolve;
ret[4].name = NULL;
ret[4].type = C_END;
- ret[4].sval = NULL;
- ret[4].ival = 0;
return ret;
}
@@ -265,10 +260,10 @@
{
game_params *ret = snew(game_params);
- ret->w = atoi(cfg[0].sval);
- ret->h = atoi(cfg[1].sval);
- ret->difficulty = cfg[2].ival;
- ret->nosolve = cfg[3].ival;
+ ret->w = atoi(cfg[0].u.string.sval);
+ ret->h = atoi(cfg[1].u.string.sval);
+ ret->difficulty = cfg[2].u.choices.selected;
+ ret->nosolve = cfg[3].u.boolean.bval;
return ret;
}
--- a/pegs.c
+++ b/pegs.c
@@ -149,24 +149,20 @@
ret[0].name = "Width";
ret[0].type = C_STRING;
sprintf(buf, "%d", params->w);
- ret[0].sval = dupstr(buf);
- ret[0].ival = 0;
+ ret[0].u.string.sval = dupstr(buf);
ret[1].name = "Height";
ret[1].type = C_STRING;
sprintf(buf, "%d", params->h);
- ret[1].sval = dupstr(buf);
- ret[1].ival = 0;
+ ret[1].u.string.sval = dupstr(buf);
ret[2].name = "Board type";
ret[2].type = C_CHOICES;
- ret[2].sval = TYPECONFIG;
- ret[2].ival = params->type;
+ ret[2].u.choices.choicenames = TYPECONFIG;
+ ret[2].u.choices.selected = params->type;
ret[3].name = NULL;
ret[3].type = C_END;
- ret[3].sval = NULL;
- ret[3].ival = 0;
return ret;
}
@@ -175,9 +171,9 @@
{
game_params *ret = snew(game_params);
- ret->w = atoi(cfg[0].sval);
- ret->h = atoi(cfg[1].sval);
- ret->type = cfg[2].ival;
+ ret->w = atoi(cfg[0].u.string.sval);
+ ret->h = atoi(cfg[1].u.string.sval);
+ ret->type = cfg[2].u.choices.selected;
return ret;
}
--- a/puzzles.h
+++ b/puzzles.h
@@ -137,30 +137,36 @@
*/
enum { C_STRING, C_CHOICES, C_BOOLEAN, C_END };
struct config_item {
- /*
- * `name' is never dynamically allocated.
- */
- char *name;
- /*
- * `type' contains one of the above values.
- */
+ /* Not dynamically allocated */
+ const char *name;
+ /* Value from the above C_* enum */
int type;
- /*
- * For C_STRING, `sval' is always dynamically allocated and
- * non-NULL. For C_BOOLEAN and C_END, `sval' is always NULL.
- * For C_CHOICES, `sval' is non-NULL, _not_ dynamically
- * allocated, and contains a set of option strings separated by
- * a delimiter. The delimeter is also the first character in
- * the string, so for example ":Foo:Bar:Baz" gives three
- * options `Foo', `Bar' and `Baz'.
- */
- char *sval;
- /*
- * For C_BOOLEAN, this is TRUE or FALSE. For C_CHOICES, it
- * indicates the chosen index from the `sval' list. In the
- * above example, 0==Foo, 1==Bar and 2==Baz.
- */
- int ival;
+ union {
+ struct { /* if type == C_STRING */
+ /* Always dynamically allocated and non-NULL */
+ char *sval;
+ } string;
+ struct { /* if type == C_CHOICES */
+ /*
+ * choicenames is non-NULL, not dynamically allocated, and
+ * contains a set of option strings separated by a
+ * delimiter. The delimiter is also the first character in
+ * the string, so for example ":Foo:Bar:Baz" gives three
+ * options `Foo', `Bar' and `Baz'.
+ */
+ const char *choicenames;
+ /*
+ * Indicates the chosen index from the options in
+ * choicenames. In the above example, 0==Foo, 1==Bar and
+ * 2==Baz.
+ */
+ int selected;
+ } choices;
+ struct {
+ /* just TRUE or FALSE */
+ int bval;
+ } boolean;
+ } u;
};
/*
--- a/range.c
+++ b/range.c
@@ -170,18 +170,14 @@
ret[0].name = "Width";
ret[0].type = C_STRING;
- ret[0].sval = nfmtstr(10, "%d", params->w);
- ret[0].ival = 0;
+ ret[0].u.string.sval = nfmtstr(10, "%d", params->w);
ret[1].name = "Height";
ret[1].type = C_STRING;
- ret[1].sval = nfmtstr(10, "%d", params->h);
- ret[1].ival = 0;
+ ret[1].u.string.sval = nfmtstr(10, "%d", params->h);
ret[2].name = NULL;
ret[2].type = C_END;
- ret[2].sval = NULL;
- ret[2].ival = 0;
return ret;
}
@@ -189,8 +185,8 @@
static game_params *custom_params(const config_item *configuration)
{
game_params *ret = snew(game_params);
- ret->w = atoi(configuration[0].sval);
- ret->h = atoi(configuration[1].sval);
+ ret->w = atoi(configuration[0].u.string.sval);
+ ret->h = atoi(configuration[1].u.string.sval);
return ret;
}
--- a/rect.c
+++ b/rect.c
@@ -180,30 +180,24 @@
ret[0].name = "Width";
ret[0].type = C_STRING;
sprintf(buf, "%d", params->w);
- ret[0].sval = dupstr(buf);
- ret[0].ival = 0;
+ ret[0].u.string.sval = dupstr(buf);
ret[1].name = "Height";
ret[1].type = C_STRING;
sprintf(buf, "%d", params->h);
- ret[1].sval = dupstr(buf);
- ret[1].ival = 0;
+ ret[1].u.string.sval = dupstr(buf);
ret[2].name = "Expansion factor";
ret[2].type = C_STRING;
sprintf(buf, "%g", params->expandfactor);
- ret[2].sval = dupstr(buf);
- ret[2].ival = 0;
+ ret[2].u.string.sval = dupstr(buf);
ret[3].name = "Ensure unique solution";
ret[3].type = C_BOOLEAN;
- ret[3].sval = NULL;
- ret[3].ival = params->unique;
+ ret[3].u.boolean.bval = params->unique;
ret[4].name = NULL;
ret[4].type = C_END;
- ret[4].sval = NULL;
- ret[4].ival = 0;
return ret;
}
@@ -212,10 +206,10 @@
{
game_params *ret = snew(game_params);
- ret->w = atoi(cfg[0].sval);
- ret->h = atoi(cfg[1].sval);
- ret->expandfactor = (float)atof(cfg[2].sval);
- ret->unique = cfg[3].ival;
+ ret->w = atoi(cfg[0].u.string.sval);
+ ret->h = atoi(cfg[1].u.string.sval);
+ ret->expandfactor = (float)atof(cfg[2].u.string.sval);
+ ret->unique = cfg[3].u.boolean.bval;
return ret;
}
--- a/samegame.c
+++ b/samegame.c
@@ -241,35 +241,29 @@
ret[0].name = "Width";
ret[0].type = C_STRING;
sprintf(buf, "%d", params->w);
- ret[0].sval = dupstr(buf);
- ret[0].ival = 0;
+ ret[0].u.string.sval = dupstr(buf);
ret[1].name = "Height";
ret[1].type = C_STRING;
sprintf(buf, "%d", params->h);
- ret[1].sval = dupstr(buf);
- ret[1].ival = 0;
+ ret[1].u.string.sval = dupstr(buf);
ret[2].name = "No. of colours";
ret[2].type = C_STRING;
sprintf(buf, "%d", params->ncols);
- ret[2].sval = dupstr(buf);
- ret[2].ival = 0;
+ ret[2].u.string.sval = dupstr(buf);
ret[3].name = "Scoring system";
ret[3].type = C_CHOICES;
- ret[3].sval = ":(n-1)^2:(n-2)^2";
- ret[3].ival = params->scoresub-1;
+ ret[3].u.choices.choicenames = ":(n-1)^2:(n-2)^2";
+ ret[3].u.choices.selected = params->scoresub-1;
ret[4].name = "Ensure solubility";
ret[4].type = C_BOOLEAN;
- ret[4].sval = NULL;
- ret[4].ival = params->soluble;
+ ret[4].u.boolean.bval = params->soluble;
ret[5].name = NULL;
ret[5].type = C_END;
- ret[5].sval = NULL;
- ret[5].ival = 0;
return ret;
}
@@ -278,11 +272,11 @@
{
game_params *ret = snew(game_params);
- ret->w = atoi(cfg[0].sval);
- ret->h = atoi(cfg[1].sval);
- ret->ncols = atoi(cfg[2].sval);
- ret->scoresub = cfg[3].ival + 1;
- ret->soluble = cfg[4].ival;
+ ret->w = atoi(cfg[0].u.string.sval);
+ ret->h = atoi(cfg[1].u.string.sval);
+ ret->ncols = atoi(cfg[2].u.string.sval);
+ ret->scoresub = cfg[3].u.choices.selected + 1;
+ ret->soluble = cfg[4].u.boolean.bval;
return ret;
}
--- a/signpost.c
+++ b/signpost.c
@@ -387,24 +387,19 @@
ret[0].name = "Width";
ret[0].type = C_STRING;
sprintf(buf, "%d", params->w);
- ret[0].sval = dupstr(buf);
- ret[0].ival = 0;
+ ret[0].u.string.sval = dupstr(buf);
ret[1].name = "Height";
ret[1].type = C_STRING;
sprintf(buf, "%d", params->h);
- ret[1].sval = dupstr(buf);
- ret[1].ival = 0;
+ ret[1].u.string.sval = dupstr(buf);
ret[2].name = "Start and end in corners";
ret[2].type = C_BOOLEAN;
- ret[2].sval = NULL;
- ret[2].ival = params->force_corner_start;
+ ret[2].u.boolean.bval = params->force_corner_start;
ret[3].name = NULL;
ret[3].type = C_END;
- ret[3].sval = NULL;
- ret[3].ival = 0;
return ret;
}
@@ -413,9 +408,9 @@
{
game_params *ret = snew(game_params);
- ret->w = atoi(cfg[0].sval);
- ret->h = atoi(cfg[1].sval);
- ret->force_corner_start = cfg[2].ival;
+ ret->w = atoi(cfg[0].u.string.sval);
+ ret->h = atoi(cfg[1].u.string.sval);
+ ret->force_corner_start = cfg[2].u.boolean.bval;
return ret;
}
--- a/singles.c
+++ b/singles.c
@@ -222,24 +222,20 @@
ret[0].name = "Width";
ret[0].type = C_STRING;
sprintf(buf, "%d", params->w);
- ret[0].sval = dupstr(buf);
- ret[0].ival = 0;
+ ret[0].u.string.sval = dupstr(buf);
ret[1].name = "Height";
ret[1].type = C_STRING;
sprintf(buf, "%d", params->h);
- ret[1].sval = dupstr(buf);
- ret[1].ival = 0;
+ ret[1].u.string.sval = dupstr(buf);
ret[2].name = "Difficulty";
ret[2].type = C_CHOICES;
- ret[2].sval = DIFFCONFIG;
- ret[2].ival = params->diff;
+ ret[2].u.choices.choicenames = DIFFCONFIG;
+ ret[2].u.choices.selected = params->diff;
ret[3].name = NULL;
ret[3].type = C_END;
- ret[3].sval = NULL;
- ret[3].ival = 0;
return ret;
}
@@ -248,9 +244,9 @@
{
game_params *ret = snew(game_params);
- ret->w = atoi(cfg[0].sval);
- ret->h = atoi(cfg[1].sval);
- ret->diff = cfg[2].ival;
+ ret->w = atoi(cfg[0].u.string.sval);
+ ret->h = atoi(cfg[1].u.string.sval);
+ ret->diff = cfg[2].u.choices.selected;
return ret;
}
--- a/sixteen.c
+++ b/sixteen.c
@@ -140,25 +140,20 @@
ret[0].name = "Width";
ret[0].type = C_STRING;
sprintf(buf, "%d", params->w);
- ret[0].sval = dupstr(buf);
- ret[0].ival = 0;
+ ret[0].u.string.sval = dupstr(buf);
ret[1].name = "Height";
ret[1].type = C_STRING;
sprintf(buf, "%d", params->h);
- ret[1].sval = dupstr(buf);
- ret[1].ival = 0;
+ ret[1].u.string.sval = dupstr(buf);
ret[2].name = "Number of shuffling moves";
ret[2].type = C_STRING;
sprintf(buf, "%d", params->movetarget);
- ret[2].sval = dupstr(buf);
- ret[2].ival = 0;
+ ret[2].u.string.sval = dupstr(buf);
ret[3].name = NULL;
ret[3].type = C_END;
- ret[3].sval = NULL;
- ret[3].ival = 0;
return ret;
}
@@ -167,9 +162,9 @@
{
game_params *ret = snew(game_params);
- ret->w = atoi(cfg[0].sval);
- ret->h = atoi(cfg[1].sval);
- ret->movetarget = atoi(cfg[2].sval);
+ ret->w = atoi(cfg[0].u.string.sval);
+ ret->h = atoi(cfg[1].u.string.sval);
+ ret->movetarget = atoi(cfg[2].u.string.sval);
return ret;
}
--- a/slant.c
+++ b/slant.c
@@ -184,24 +184,20 @@
ret[0].name = "Width";
ret[0].type = C_STRING;
sprintf(buf, "%d", params->w);
- ret[0].sval = dupstr(buf);
- ret[0].ival = 0;
+ ret[0].u.string.sval = dupstr(buf);
ret[1].name = "Height";
ret[1].type = C_STRING;
sprintf(buf, "%d", params->h);
- ret[1].sval = dupstr(buf);
- ret[1].ival = 0;
+ ret[1].u.string.sval = dupstr(buf);
ret[2].name = "Difficulty";
ret[2].type = C_CHOICES;
- ret[2].sval = DIFFCONFIG;
- ret[2].ival = params->diff;
+ ret[2].u.choices.choicenames = DIFFCONFIG;
+ ret[2].u.choices.selected = params->diff;
ret[3].name = NULL;
ret[3].type = C_END;
- ret[3].sval = NULL;
- ret[3].ival = 0;
return ret;
}
@@ -210,9 +206,9 @@
{
game_params *ret = snew(game_params);
- ret->w = atoi(cfg[0].sval);
- ret->h = atoi(cfg[1].sval);
- ret->diff = cfg[2].ival;
+ ret->w = atoi(cfg[0].u.string.sval);
+ ret->h = atoi(cfg[1].u.string.sval);
+ ret->diff = cfg[2].u.choices.selected;
return ret;
}
--- a/solo.c
+++ b/solo.c
@@ -445,46 +445,39 @@
ret[0].name = "Columns of sub-blocks";
ret[0].type = C_STRING;
sprintf(buf, "%d", params->c);
- ret[0].sval = dupstr(buf);
- ret[0].ival = 0;
+ ret[0].u.string.sval = dupstr(buf);
ret[1].name = "Rows of sub-blocks";
ret[1].type = C_STRING;
sprintf(buf, "%d", params->r);
- ret[1].sval = dupstr(buf);
- ret[1].ival = 0;
+ ret[1].u.string.sval = dupstr(buf);
ret[2].name = "\"X\" (require every number in each main diagonal)";
ret[2].type = C_BOOLEAN;
- ret[2].sval = NULL;
- ret[2].ival = params->xtype;
+ ret[2].u.boolean.bval = params->xtype;
ret[3].name = "Jigsaw (irregularly shaped sub-blocks)";
ret[3].type = C_BOOLEAN;
- ret[3].sval = NULL;
- ret[3].ival = (params->r == 1);
+ ret[3].u.boolean.bval = (params->r == 1);
ret[4].name = "Killer (digit sums)";
ret[4].type = C_BOOLEAN;
- ret[4].sval = NULL;
- ret[4].ival = params->killer;
+ ret[4].u.boolean.bval = params->killer;
ret[5].name = "Symmetry";
ret[5].type = C_CHOICES;
- ret[5].sval = ":None:2-way rotation:4-way rotation:2-way mirror:"
+ ret[5].u.choices.choicenames = ":None:2-way rotation:4-way rotation:2-way mirror:"
"2-way diagonal mirror:4-way mirror:4-way diagonal mirror:"
"8-way mirror";
- ret[5].ival = params->symm;
+ ret[5].u.choices.selected = params->symm;
ret[6].name = "Difficulty";
ret[6].type = C_CHOICES;
- ret[6].sval = ":Trivial:Basic:Intermediate:Advanced:Extreme:Unreasonable";
- ret[6].ival = params->diff;
+ ret[6].u.choices.choicenames = ":Trivial:Basic:Intermediate:Advanced:Extreme:Unreasonable";
+ ret[6].u.choices.selected = params->diff;
ret[7].name = NULL;
ret[7].type = C_END;
- ret[7].sval = NULL;
- ret[7].ival = 0;
return ret;
}
@@ -493,16 +486,16 @@
{
game_params *ret = snew(game_params);
- ret->c = atoi(cfg[0].sval);
- ret->r = atoi(cfg[1].sval);
- ret->xtype = cfg[2].ival;
- if (cfg[3].ival) {
+ ret->c = atoi(cfg[0].u.string.sval);
+ ret->r = atoi(cfg[1].u.string.sval);
+ ret->xtype = cfg[2].u.boolean.bval;
+ if (cfg[3].u.boolean.bval) {
ret->c *= ret->r;
ret->r = 1;
}
- ret->killer = cfg[4].ival;
- ret->symm = cfg[5].ival;
- ret->diff = cfg[6].ival;
+ ret->killer = cfg[4].u.boolean.bval;
+ ret->symm = cfg[5].u.choices.selected;
+ ret->diff = cfg[6].u.choices.selected;
ret->kdiff = DIFF_KINTERSECT;
return ret;
--- a/tents.c
+++ b/tents.c
@@ -371,24 +371,20 @@
ret[0].name = "Width";
ret[0].type = C_STRING;
sprintf(buf, "%d", params->w);
- ret[0].sval = dupstr(buf);
- ret[0].ival = 0;
+ ret[0].u.string.sval = dupstr(buf);
ret[1].name = "Height";
ret[1].type = C_STRING;
sprintf(buf, "%d", params->h);
- ret[1].sval = dupstr(buf);
- ret[1].ival = 0;
+ ret[1].u.string.sval = dupstr(buf);
ret[2].name = "Difficulty";
ret[2].type = C_CHOICES;
- ret[2].sval = DIFFCONFIG;
- ret[2].ival = params->diff;
+ ret[2].u.choices.choicenames = DIFFCONFIG;
+ ret[2].u.choices.selected = params->diff;
ret[3].name = NULL;
ret[3].type = C_END;
- ret[3].sval = NULL;
- ret[3].ival = 0;
return ret;
}
@@ -397,9 +393,9 @@
{
game_params *ret = snew(game_params);
- ret->w = atoi(cfg[0].sval);
- ret->h = atoi(cfg[1].sval);
- ret->diff = cfg[2].ival;
+ ret->w = atoi(cfg[0].u.string.sval);
+ ret->h = atoi(cfg[1].u.string.sval);
+ ret->diff = cfg[2].u.choices.selected;
return ret;
}
--- a/towers.c
+++ b/towers.c
@@ -212,18 +212,15 @@
ret[0].name = "Grid size";
ret[0].type = C_STRING;
sprintf(buf, "%d", params->w);
- ret[0].sval = dupstr(buf);
- ret[0].ival = 0;
+ ret[0].u.string.sval = dupstr(buf);
ret[1].name = "Difficulty";
ret[1].type = C_CHOICES;
- ret[1].sval = DIFFCONFIG;
- ret[1].ival = params->diff;
+ ret[1].u.choices.choicenames = DIFFCONFIG;
+ ret[1].u.choices.selected = params->diff;
ret[2].name = NULL;
ret[2].type = C_END;
- ret[2].sval = NULL;
- ret[2].ival = 0;
return ret;
}
@@ -232,8 +229,8 @@
{
game_params *ret = snew(game_params);
- ret->w = atoi(cfg[0].sval);
- ret->diff = cfg[1].ival;
+ ret->w = atoi(cfg[0].u.string.sval);
+ ret->diff = cfg[1].u.choices.selected;
return ret;
}
--- a/tracks.c
+++ b/tracks.c
@@ -148,28 +148,24 @@
ret[0].name = "Width";
ret[0].type = C_STRING;
sprintf(buf, "%d", params->w);
- ret[0].sval = dupstr(buf);
- ret[0].ival = 0;
+ ret[0].u.string.sval = dupstr(buf);
ret[1].name = "Height";
ret[1].type = C_STRING;
sprintf(buf, "%d", params->h);
- ret[1].sval = dupstr(buf);
- ret[1].ival = 0;
+ ret[1].u.string.sval = dupstr(buf);
ret[2].name = "Difficulty";
ret[2].type = C_CHOICES;
- ret[2].sval = DIFFCONFIG;
- ret[2].ival = params->diff;
+ ret[2].u.choices.choicenames = DIFFCONFIG;
+ ret[2].u.choices.selected = params->diff;
ret[3].name = "Disallow consecutive 1 clues";
ret[3].type = C_BOOLEAN;
- ret[3].ival = params->single_ones;
+ ret[3].u.boolean.bval = params->single_ones;
ret[4].name = NULL;
ret[4].type = C_END;
- ret[4].sval = NULL;
- ret[4].ival = 0;
return ret;
}
@@ -178,10 +174,10 @@
{
game_params *ret = snew(game_params);
- ret->w = atoi(cfg[0].sval);
- ret->h = atoi(cfg[1].sval);
- ret->diff = cfg[2].ival;
- ret->single_ones = cfg[3].ival;
+ ret->w = atoi(cfg[0].u.string.sval);
+ ret->h = atoi(cfg[1].u.string.sval);
+ ret->diff = cfg[2].u.choices.selected;
+ ret->single_ones = cfg[3].u.boolean.bval;
return ret;
}
--- a/twiddle.c
+++ b/twiddle.c
@@ -156,41 +156,33 @@
ret[0].name = "Width";
ret[0].type = C_STRING;
sprintf(buf, "%d", params->w);
- ret[0].sval = dupstr(buf);
- ret[0].ival = 0;
+ ret[0].u.string.sval = dupstr(buf);
ret[1].name = "Height";
ret[1].type = C_STRING;
sprintf(buf, "%d", params->h);
- ret[1].sval = dupstr(buf);
- ret[1].ival = 0;
+ ret[1].u.string.sval = dupstr(buf);
ret[2].name = "Rotating block size";
ret[2].type = C_STRING;
sprintf(buf, "%d", params->n);
- ret[2].sval = dupstr(buf);
- ret[2].ival = 0;
+ ret[2].u.string.sval = dupstr(buf);
ret[3].name = "One number per row";
ret[3].type = C_BOOLEAN;
- ret[3].sval = NULL;
- ret[3].ival = params->rowsonly;
+ ret[3].u.boolean.bval = params->rowsonly;
ret[4].name = "Orientation matters";
ret[4].type = C_BOOLEAN;
- ret[4].sval = NULL;
- ret[4].ival = params->orientable;
+ ret[4].u.boolean.bval = params->orientable;
ret[5].name = "Number of shuffling moves";
ret[5].type = C_STRING;
sprintf(buf, "%d", params->movetarget);
- ret[5].sval = dupstr(buf);
- ret[5].ival = 0;
+ ret[5].u.string.sval = dupstr(buf);
ret[6].name = NULL;
ret[6].type = C_END;
- ret[6].sval = NULL;
- ret[6].ival = 0;
return ret;
}
@@ -199,12 +191,12 @@
{
game_params *ret = snew(game_params);
- ret->w = atoi(cfg[0].sval);
- ret->h = atoi(cfg[1].sval);
- ret->n = atoi(cfg[2].sval);
- ret->rowsonly = cfg[3].ival;
- ret->orientable = cfg[4].ival;
- ret->movetarget = atoi(cfg[5].sval);
+ ret->w = atoi(cfg[0].u.string.sval);
+ ret->h = atoi(cfg[1].u.string.sval);
+ ret->n = atoi(cfg[2].u.string.sval);
+ ret->rowsonly = cfg[3].u.boolean.bval;
+ ret->orientable = cfg[4].u.boolean.bval;
+ ret->movetarget = atoi(cfg[5].u.string.sval);
return ret;
}
--- a/undead.c
+++ b/undead.c
@@ -163,24 +163,20 @@
ret[0].name = "Width";
ret[0].type = C_STRING;
sprintf(buf, "%d", params->w);
- ret[0].sval = dupstr(buf);
- ret[0].ival = 0;
+ ret[0].u.string.sval = dupstr(buf);
ret[1].name = "Height";
ret[1].type = C_STRING;
sprintf(buf, "%d", params->h);
- ret[1].sval = dupstr(buf);
- ret[1].ival = 0;
+ ret[1].u.string.sval = dupstr(buf);
ret[2].name = "Difficulty";
ret[2].type = C_CHOICES;
- ret[2].sval = DIFFCONFIG;
- ret[2].ival = params->diff;
+ ret[2].u.choices.choicenames = DIFFCONFIG;
+ ret[2].u.choices.selected = params->diff;
ret[3].name = NULL;
ret[3].type = C_END;
- ret[3].sval = NULL;
- ret[3].ival = 0;
return ret;
}
@@ -189,9 +185,9 @@
{
game_params *ret = snew(game_params);
- ret->w = atoi(cfg[0].sval);
- ret->h = atoi(cfg[1].sval);
- ret->diff = cfg[2].ival;
+ ret->w = atoi(cfg[0].u.string.sval);
+ ret->h = atoi(cfg[1].u.string.sval);
+ ret->diff = cfg[2].u.choices.selected;
return ret;
}
--- a/unequal.c
+++ b/unequal.c
@@ -218,24 +218,21 @@
ret[0].name = "Mode";
ret[0].type = C_CHOICES;
- ret[0].sval = ":Unequal:Adjacent";
- ret[0].ival = params->adjacent;
+ ret[0].u.choices.choicenames = ":Unequal:Adjacent";
+ ret[0].u.choices.selected = params->adjacent;
ret[1].name = "Size (s*s)";
ret[1].type = C_STRING;
sprintf(buf, "%d", params->order);
- ret[1].sval = dupstr(buf);
- ret[1].ival = 0;
+ ret[1].u.string.sval = dupstr(buf);
ret[2].name = "Difficulty";
ret[2].type = C_CHOICES;
- ret[2].sval = DIFFCONFIG;
- ret[2].ival = params->diff;
+ ret[2].u.choices.choicenames = DIFFCONFIG;
+ ret[2].u.choices.selected = params->diff;
ret[3].name = NULL;
ret[3].type = C_END;
- ret[3].sval = NULL;
- ret[3].ival = 0;
return ret;
}
@@ -244,9 +241,9 @@
{
game_params *ret = snew(game_params);
- ret->adjacent = cfg[0].ival;
- ret->order = atoi(cfg[1].sval);
- ret->diff = cfg[2].ival;
+ ret->adjacent = cfg[0].u.choices.selected;
+ ret->order = atoi(cfg[1].u.string.sval);
+ ret->diff = cfg[2].u.choices.selected;
return ret;
}
--- a/unfinished/group.c
+++ b/unfinished/group.c
@@ -212,23 +212,19 @@
ret[0].name = "Grid size";
ret[0].type = C_STRING;
sprintf(buf, "%d", params->w);
- ret[0].sval = dupstr(buf);
- ret[0].ival = 0;
+ ret[0].u.string.sval = dupstr(buf);
ret[1].name = "Difficulty";
ret[1].type = C_CHOICES;
- ret[1].sval = DIFFCONFIG;
- ret[1].ival = params->diff;
+ ret[1].u.choices.choicenames = DIFFCONFIG;
+ ret[1].u.choices.selected = params->diff;
ret[2].name = "Show identity";
ret[2].type = C_BOOLEAN;
- ret[2].sval = NULL;
- ret[2].ival = params->id;
+ ret[2].u.boolean.bval = params->id;
ret[3].name = NULL;
ret[3].type = C_END;
- ret[3].sval = NULL;
- ret[3].ival = 0;
return ret;
}
@@ -237,9 +233,9 @@
{
game_params *ret = snew(game_params);
- ret->w = atoi(cfg[0].sval);
- ret->diff = cfg[1].ival;
- ret->id = cfg[2].ival;
+ ret->w = atoi(cfg[0].u.string.sval);
+ ret->diff = cfg[1].u.choices.selected;
+ ret->id = cfg[2].u.boolean.bval;
return ret;
}
--- a/unfinished/slide.c
+++ b/unfinished/slide.c
@@ -244,25 +244,20 @@
ret[0].name = "Width";
ret[0].type = C_STRING;
sprintf(buf, "%d", params->w);
- ret[0].sval = dupstr(buf);
- ret[0].ival = 0;
+ ret[0].u.string.sval = dupstr(buf);
ret[1].name = "Height";
ret[1].type = C_STRING;
sprintf(buf, "%d", params->h);
- ret[1].sval = dupstr(buf);
- ret[1].ival = 0;
+ ret[1].u.string.sval = dupstr(buf);
ret[2].name = "Solution length limit";
ret[2].type = C_STRING;
sprintf(buf, "%d", params->maxmoves);
- ret[2].sval = dupstr(buf);
- ret[2].ival = 0;
+ ret[2].u.string.sval = dupstr(buf);
ret[3].name = NULL;
ret[3].type = C_END;
- ret[3].sval = NULL;
- ret[3].ival = 0;
return ret;
}
@@ -271,9 +266,9 @@
{
game_params *ret = snew(game_params);
- ret->w = atoi(cfg[0].sval);
- ret->h = atoi(cfg[1].sval);
- ret->maxmoves = atoi(cfg[2].sval);
+ ret->w = atoi(cfg[0].u.string.sval);
+ ret->h = atoi(cfg[1].u.string.sval);
+ ret->maxmoves = atoi(cfg[2].u.string.sval);
return ret;
}
--- a/unfinished/sokoban.c
+++ b/unfinished/sokoban.c
@@ -210,19 +210,15 @@
ret[0].name = "Width";
ret[0].type = C_STRING;
sprintf(buf, "%d", params->w);
- ret[0].sval = dupstr(buf);
- ret[0].ival = 0;
+ ret[0].u.string.sval = dupstr(buf);
ret[1].name = "Height";
ret[1].type = C_STRING;
sprintf(buf, "%d", params->h);
- ret[1].sval = dupstr(buf);
- ret[1].ival = 0;
+ ret[1].u.string.sval = dupstr(buf);
ret[2].name = NULL;
ret[2].type = C_END;
- ret[2].sval = NULL;
- ret[2].ival = 0;
return ret;
}
@@ -231,8 +227,8 @@
{
game_params *ret = snew(game_params);
- ret->w = atoi(cfg[0].sval);
- ret->h = atoi(cfg[1].sval);
+ ret->w = atoi(cfg[0].u.string.sval);
+ ret->h = atoi(cfg[1].u.string.sval);
return ret;
}
--- a/unruly.c
+++ b/unruly.c
@@ -239,28 +239,24 @@
ret[0].name = "Width";
ret[0].type = C_STRING;
sprintf(buf, "%d", params->w2);
- ret[0].sval = dupstr(buf);
- ret[0].ival = 0;
+ ret[0].u.string.sval = dupstr(buf);
ret[1].name = "Height";
ret[1].type = C_STRING;
sprintf(buf, "%d", params->h2);
- ret[1].sval = dupstr(buf);
- ret[1].ival = 0;
+ ret[1].u.string.sval = dupstr(buf);
ret[2].name = "Unique rows and columns";
ret[2].type = C_BOOLEAN;
- ret[2].ival = params->unique;
+ ret[2].u.boolean.bval = params->unique;
ret[3].name = "Difficulty";
ret[3].type = C_CHOICES;
- ret[3].sval = DIFFCONFIG;
- ret[3].ival = params->diff;
+ ret[3].u.choices.choicenames = DIFFCONFIG;
+ ret[3].u.choices.selected = params->diff;
ret[4].name = NULL;
ret[4].type = C_END;
- ret[4].sval = NULL;
- ret[4].ival = 0;
return ret;
}
@@ -269,10 +265,10 @@
{
game_params *ret = snew(game_params);
- ret->w2 = atoi(cfg[0].sval);
- ret->h2 = atoi(cfg[1].sval);
- ret->unique = cfg[2].ival;
- ret->diff = cfg[3].ival;
+ ret->w2 = atoi(cfg[0].u.string.sval);
+ ret->h2 = atoi(cfg[1].u.string.sval);
+ ret->unique = cfg[2].u.boolean.bval;
+ ret->diff = cfg[3].u.choices.selected;
return ret;
}
--- a/untangle.c
+++ b/untangle.c
@@ -185,13 +185,10 @@
ret[0].name = "Number of points";
ret[0].type = C_STRING;
sprintf(buf, "%d", params->n);
- ret[0].sval = dupstr(buf);
- ret[0].ival = 0;
+ ret[0].u.string.sval = dupstr(buf);
ret[1].name = NULL;
ret[1].type = C_END;
- ret[1].sval = NULL;
- ret[1].ival = 0;
return ret;
}
@@ -200,7 +197,7 @@
{
game_params *ret = snew(game_params);
- ret->n = atoi(cfg[0].sval);
+ ret->n = atoi(cfg[0].u.string.sval);
return ret;
}
--- a/windows.c
+++ b/windows.c
@@ -2057,52 +2057,43 @@
ret[i].name = "Number of puzzles to print";
ret[i].type = C_STRING;
- ret[i].sval = dupstr("1");
- ret[i].ival = 0;
+ ret[i].u.string.sval = dupstr("1");
i++;
ret[i].name = "Number of puzzles across the page";
ret[i].type = C_STRING;
- ret[i].sval = dupstr("1");
- ret[i].ival = 0;
+ ret[i].u.string.sval = dupstr("1");
i++;
ret[i].name = "Number of puzzles down the page";
ret[i].type = C_STRING;
- ret[i].sval = dupstr("1");
- ret[i].ival = 0;
+ ret[i].u.string.sval = dupstr("1");
i++;
ret[i].name = "Percentage of standard size";
ret[i].type = C_STRING;
- ret[i].sval = dupstr("100.0");
- ret[i].ival = 0;
+ ret[i].u.string.sval = dupstr("100.0");
i++;
ret[i].name = "Include currently shown puzzle";
ret[i].type = C_BOOLEAN;
- ret[i].sval = NULL;
- ret[i].ival = TRUE;
+ ret[i].u.boolean.bval = TRUE;
i++;
ret[i].name = "Print solutions";
ret[i].type = C_BOOLEAN;
- ret[i].sval = NULL;
- ret[i].ival = FALSE;
+ ret[i].u.boolean.bval = FALSE;
i++;
if (fe->game->can_print_in_colour) {
ret[i].name = "Print in colour";
ret[i].type = C_BOOLEAN;
- ret[i].sval = NULL;
- ret[i].ival = FALSE;
+ ret[i].u.boolean.bval = FALSE;
i++;
}
ret[i].name = NULL;
ret[i].type = C_END;
- ret[i].sval = NULL;
- ret[i].ival = 0;
i++;
return ret;
@@ -2117,17 +2108,18 @@
if (which < CFG_FRONTEND_SPECIFIC) {
return midend_set_config(fe->me, which, cfg);
} else if (which == CFG_PRINT) {
- if ((fe->printcount = atoi(cfg[0].sval)) <= 0)
+ if ((fe->printcount = atoi(cfg[0].u.string.sval)) <= 0)
return "Number of puzzles to print should be at least one";
- if ((fe->printw = atoi(cfg[1].sval)) <= 0)
+ if ((fe->printw = atoi(cfg[1].u.string.sval)) <= 0)
return "Number of puzzles across the page should be at least one";
- if ((fe->printh = atoi(cfg[2].sval)) <= 0)
+ if ((fe->printh = atoi(cfg[2].u.string.sval)) <= 0)
return "Number of puzzles down the page should be at least one";
- if ((fe->printscale = (float)atof(cfg[3].sval)) <= 0)
+ if ((fe->printscale = (float)atof(cfg[3].u.string.sval)) <= 0)
return "Print size should be positive";
- fe->printcurr = cfg[4].ival;
- fe->printsolns = cfg[5].ival;
- fe->printcolour = fe->game->can_print_in_colour && cfg[6].ival;
+ fe->printcurr = cfg[4].u.boolean.bval;
+ fe->printsolns = cfg[5].u.boolean.bval;
+ fe->printcolour = fe->game->can_print_in_colour &&
+ cfg[6].u.boolean.bval;
return NULL;
} else {
assert(!"We should never get here");
@@ -2191,7 +2183,7 @@
mkctrl(fe, col2l, col2r, y, y + 12,
TEXT("EDIT"), WS_BORDER | WS_TABSTOP | ES_AUTOHSCROLL,
0, "", (j->ctlid = id++));
- SetDlgItemTextA(fe->cfgbox, j->ctlid, i->sval);
+ SetDlgItemTextA(fe->cfgbox, j->ctlid, i->u.string.sval);
break;
case C_BOOLEAN:
@@ -2201,7 +2193,7 @@
mkctrl(fe, col1l, col2r, y + 1, y + 11, TEXT("BUTTON"),
BS_NOTIFY | BS_AUTOCHECKBOX | WS_TABSTOP,
0, i->name, (j->ctlid = id++));
- CheckDlgButton(fe->cfgbox, j->ctlid, (i->ival != 0));
+ CheckDlgButton(fe->cfgbox, j->ctlid, (i->u.boolean.bval != 0));
break;
case C_CHOICES:
@@ -2215,9 +2207,11 @@
CBS_DROPDOWNLIST | CBS_HASSTRINGS,
0, "", (j->ctlid = id++));
{
- char c, *p, *q, *str;
+ char c;
+ const char *p, *q;
+ char *str;
- p = i->sval;
+ p = i->u.choices.choicenames;
c = *p++;
while (*p) {
q = p;
@@ -2236,7 +2230,7 @@
p = q;
}
}
- SendMessage(ctl, CB_SETCURSEL, i->ival, 0);
+ SendMessage(ctl, CB_SETCURSEL, i->u.choices.selected, 0);
break;
}
@@ -2324,16 +2318,16 @@
GetDlgItemText(fe->cfgbox, j->ctlid, buffer, lenof(buffer));
#endif
buffer[lenof(buffer)-1] = '\0';
- sfree(i->sval);
- i->sval = dupstr(buffer);
+ sfree(i->u.string.sval);
+ i->u.string.sval = dupstr(buffer);
} else if (i->type == C_BOOLEAN &&
(HIWORD(wParam) == BN_CLICKED ||
HIWORD(wParam) == BN_DBLCLK)) {
- i->ival = IsDlgButtonChecked(fe->cfgbox, j->ctlid);
+ i->u.boolean.bval = IsDlgButtonChecked(fe->cfgbox, j->ctlid);
} else if (i->type == C_CHOICES &&
HIWORD(wParam) == CBN_SELCHANGE) {
- i->ival = SendDlgItemMessage(fe->cfgbox, j->ctlid,
- CB_GETCURSEL, 0, 0);
+ i->u.choices.selected = SendDlgItemMessage(fe->cfgbox, j->ctlid,
+ CB_GETCURSEL, 0, 0);
}
return 0;
@@ -2683,7 +2677,7 @@
ctl = mkctrl(fe, col2l, col2r, y, y+height*3/2,
"EDIT", WS_TABSTOP | ES_AUTOHSCROLL,
WS_EX_CLIENTEDGE, "", (j->ctlid = id++));
- SetWindowText(ctl, i->sval);
+ SetWindowText(ctl, i->u.string.sval);
y += height*3/2;
break;
@@ -2694,7 +2688,7 @@
mkctrl(fe, col1l, col2r, y, y+height, "BUTTON",
BS_NOTIFY | BS_AUTOCHECKBOX | WS_TABSTOP,
0, i->name, (j->ctlid = id++));
- CheckDlgButton(fe->cfgbox, j->ctlid, (i->ival != 0));
+ CheckDlgButton(fe->cfgbox, j->ctlid, (i->u.boolean.bval != 0));
y += height;
break;
@@ -2709,10 +2703,12 @@
CBS_DROPDOWNLIST | CBS_HASSTRINGS,
WS_EX_CLIENTEDGE, "", (j->ctlid = id++));
{
- char c, *p, *q, *str;
+ char c;
+ const char *p, *q;
+ char *str;
SendMessage(ctl, CB_RESETCONTENT, 0, 0);
- p = i->sval;
+ p = i->u.choices.choicenames;
c = *p++;
while (*p) {
q = p;
@@ -2727,7 +2723,7 @@
}
}
- SendMessage(ctl, CB_SETCURSEL, i->ival, 0);
+ SendMessage(ctl, CB_SETCURSEL, i->u.choices.selected, 0);
y += height*3/2;
break;