From de67801b0fd3dfa11777c1ef86cd617baf376b7b Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sun, 1 Oct 2017 13:38:35 +0100 Subject: [PATCH] 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. --- blackbox.c | 20 +++++------- bridges.c | 42 +++++++++++------------- cube.c | 18 ++++------- devel.but | 77 +++++++++++++++++++++++++++++--------------- dominosa.c | 12 +++---- emcc.c | 30 +++++++++++++---- fifteen.c | 12 +++---- filling.c | 12 +++---- flip.c | 18 ++++------- flood.c | 22 +++++-------- galaxies.c | 18 ++++------- gtk.c | 26 +++++++++------ guess.c | 27 ++++++---------- inertia.c | 12 +++---- keen.c | 18 ++++------- lightup.c | 29 +++++++---------- loopy.c | 24 ++++++-------- magnets.c | 23 ++++++------- map.c | 23 ++++++------- midend.c | 10 +++--- mines.c | 24 ++++++-------- misc.c | 2 +- nestedvm.c | 24 +++++++++++--- net.c | 27 ++++++---------- netslide.c | 27 ++++++---------- osx.m | 24 ++++++++------ palisade.c | 24 ++++++++++---- pattern.c | 12 +++---- pearl.c | 23 ++++++------- pegs.c | 18 ++++------- puzzles.h | 52 +++++++++++++++++------------- range.c | 12 +++---- rect.c | 22 +++++-------- samegame.c | 28 +++++++--------- signpost.c | 17 ++++------ singles.c | 18 ++++------- sixteen.c | 17 ++++------ slant.c | 18 ++++------- solo.c | 39 +++++++++------------- tents.c | 18 ++++------- towers.c | 13 +++----- tracks.c | 22 ++++++------- twiddle.c | 32 +++++++----------- undead.c | 18 ++++------- unequal.c | 19 +++++------ unfinished/group.c | 18 ++++------- unfinished/slide.c | 17 ++++------ unfinished/sokoban.c | 12 +++---- unruly.c | 22 ++++++------- untangle.c | 7 ++-- windows.c | 72 +++++++++++++++++++---------------------- 51 files changed, 528 insertions(+), 643 deletions(-) diff --git a/blackbox.c b/blackbox.c index 422b752..7af1316 100644 --- a/blackbox.c +++ b/blackbox.c @@ -148,14 +148,12 @@ static config_item *game_configure(const game_params *params) 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 @@ static config_item *game_configure(const game_params *params) 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 @@ static game_params *custom_params(const config_item *cfg) { 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; } diff --git a/bridges.c b/bridges.c index ebf7323..0684b36 100644 --- a/bridges.c +++ b/bridges.c @@ -742,44 +742,40 @@ static config_item *game_configure(const game_params *params) 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 @@ static game_params *custom_params(const config_item *cfg) { 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; } diff --git a/cube.c b/cube.c index a30dc10..249d1ba 100644 --- a/cube.c +++ b/cube.c @@ -489,25 +489,21 @@ static config_item *game_configure(const game_params *params) 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 @@ static game_params *custom_params(const config_item *cfg) { 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; } diff --git a/devel.but b/devel.but index 16aaf02..98724b3 100644 --- a/devel.but +++ b/devel.but @@ -555,16 +555,15 @@ The \cw{config_item} structure contains the following elements: \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 @@ values are: 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 @@ quite everywhere.) \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.) diff --git a/dominosa.c b/dominosa.c index 5a3016b..d26f97a 100644 --- a/dominosa.c +++ b/dominosa.c @@ -169,18 +169,14 @@ static config_item *game_configure(const game_params *params) 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 @@ static game_params *custom_params(const config_item *cfg) { 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; } diff --git a/emcc.c b/emcc.c index 23ab333..c499eef 100644 --- a/emcc.c +++ b/emcc.c @@ -599,13 +599,14 @@ static void cfg_start(int which) 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 @@ static void cfg_start(int which) */ 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"); + } } /* diff --git a/fifteen.c b/fifteen.c index aee8907..9a985e3 100644 --- a/fifteen.c +++ b/fifteen.c @@ -111,19 +111,15 @@ static config_item *game_configure(const game_params *params) 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 @@ static game_params *custom_params(const config_item *cfg) { 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; } diff --git a/filling.c b/filling.c index d0883af..585b4bd 100644 --- a/filling.c +++ b/filling.c @@ -161,19 +161,15 @@ static config_item *game_configure(const game_params *params) 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 @@ static game_params *custom_params(const config_item *cfg) { 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; } diff --git a/flip.c b/flip.c index 68979fe..fc96329 100644 --- a/flip.c +++ b/flip.c @@ -149,24 +149,20 @@ static config_item *game_configure(const game_params *params) 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 @@ static game_params *custom_params(const config_item *cfg) { 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; } diff --git a/flood.c b/flood.c index 247c509..90247fc 100644 --- a/flood.c +++ b/flood.c @@ -170,31 +170,25 @@ static config_item *game_configure(const game_params *params) 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 @@ static game_params *custom_params(const config_item *cfg) { 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; } diff --git a/galaxies.c b/galaxies.c index 03bed9c..629fb89 100644 --- a/galaxies.c +++ b/galaxies.c @@ -248,24 +248,20 @@ static config_item *game_configure(const game_params *params) 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 @@ static game_params *custom_params(const config_item *cfg) { 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; } diff --git a/gtk.c b/gtk.c index b1175ef..c1e5a66 100644 --- a/gtk.c +++ b/gtk.c @@ -1641,22 +1641,25 @@ static void editbox_changed(GtkEditable *ed, gpointer data) { 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) { 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) { 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 @@ static int get_config(frontend *fe, int which) 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 @@ static int get_config(frontend *fe, int which) 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,15 +1803,16 @@ static int get_config(frontend *fe, int which) { int c; - char *p, *q, *name; + const char *p, *q; + char *name; GtkListStore *model; GtkCellRenderer *cr; GtkTreeIter iter; 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 @@ static int get_config(frontend *fe, int which) 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); diff --git a/guess.c b/guess.c index b3d4a9a..af26edc 100644 --- a/guess.c +++ b/guess.c @@ -166,35 +166,28 @@ static config_item *game_configure(const game_params *params) 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 @@ static game_params *custom_params(const config_item *cfg) { 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; } diff --git a/inertia.c b/inertia.c index c22d2e1..f5bf1a1 100644 --- a/inertia.c +++ b/inertia.c @@ -168,19 +168,15 @@ static config_item *game_configure(const game_params *params) 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 @@ static game_params *custom_params(const config_item *cfg) { 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; } diff --git a/keen.c b/keen.c index a3fbb74..8a05659 100644 --- a/keen.c +++ b/keen.c @@ -183,23 +183,19 @@ static config_item *game_configure(const game_params *params) 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 @@ static game_params *custom_params(const config_item *cfg) { 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; } diff --git a/lightup.c b/lightup.c index a56f3a9..c5ee418 100644 --- a/lightup.c +++ b/lightup.c @@ -299,37 +299,32 @@ static config_item *game_configure(const game_params *params) 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 @@ static game_params *custom_params(const config_item *cfg) { 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; } diff --git a/loopy.c b/loopy.c index 92b27ab..8af9a30 100644 --- a/loopy.c +++ b/loopy.c @@ -640,29 +640,25 @@ static config_item *game_configure(const game_params *params) 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 @@ static game_params *custom_params(const config_item *cfg) { 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; } diff --git a/magnets.c b/magnets.c index 354c00a..5a6b661 100644 --- a/magnets.c +++ b/magnets.c @@ -193,29 +193,24 @@ static config_item *game_configure(const game_params *params) 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 @@ static game_params *custom_params(const config_item *cfg) { 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; } diff --git a/map.c b/map.c index c66e7e2..917c525 100644 --- a/map.c +++ b/map.c @@ -213,30 +213,25 @@ static config_item *game_configure(const game_params *params) 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 @@ static game_params *custom_params(const config_item *cfg) { 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; } diff --git a/midend.c b/midend.c index 913b322..1f5f077 100644 --- a/midend.c +++ b/midend.c @@ -1360,7 +1360,6 @@ config_item *midend_get_config(midend *me, int which, char **wintitle) 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 @@ config_item *midend_get_config(midend *me, int which, char **wintitle) 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 @@ char *midend_set_config(midend *me, int which, config_item *cfg) 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; diff --git a/mines.c b/mines.c index 5bae0e8..4612da9 100644 --- a/mines.c +++ b/mines.c @@ -203,30 +203,24 @@ static config_item *game_configure(const game_params *params) 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 @@ static game_params *custom_params(const config_item *cfg) { 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; } diff --git a/misc.c b/misc.c index b44f1b1..d555ad2 100644 --- a/misc.c +++ b/misc.c @@ -17,7 +17,7 @@ void free_cfg(config_item *cfg) for (i = cfg; i->type != C_END; i++) if (i->type == C_STRING) - sfree(i->sval); + sfree(i->u.string.sval); sfree(cfg); } diff --git a/nestedvm.c b/nestedvm.c index f7a2ae8..704f6d1 100644 --- a/nestedvm.c +++ b/nestedvm.c @@ -273,19 +273,22 @@ void jcallback_config_ok() 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 @@ static int get_config(frontend *fe, int which) _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); diff --git a/net.c b/net.c index fc603d1..2b8706d 100644 --- a/net.c +++ b/net.c @@ -267,35 +267,28 @@ static config_item *game_configure(const game_params *params) 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 @@ static game_params *custom_params(const config_item *cfg) { 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; } diff --git a/netslide.c b/netslide.c index d43dc2e..542b571 100644 --- a/netslide.c +++ b/netslide.c @@ -262,36 +262,29 @@ static config_item *game_configure(const game_params *params) 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 @@ static game_params *custom_params(const config_item *cfg) { 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; } diff --git a/osx.m b/osx.m index be29819..4798e49 100644 --- a/osx.m +++ b/osx.m @@ -1103,7 +1103,8 @@ struct frontend { [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 @@ struct frontend { [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 @@ struct frontend { 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 @@ struct frontend { if (*p) p++; } } - [pb selectItemAtIndex:i->ival]; + [pb selectItemAtIndex:i->u.choices.selected]; [pb sizeToFit]; rect = [pb frame]; @@ -1303,17 +1306,18 @@ struct frontend { 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; } diff --git a/palisade.c b/palisade.c index 93c1ad6..3b5878b 100644 --- a/palisade.c +++ b/palisade.c @@ -119,10 +119,20 @@ static config_item *game_configure(const game_params *params) { 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 @@ static game_params *custom_params(const config_item *cfg) { 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; } diff --git a/pattern.c b/pattern.c index 9964dd5..e680553 100644 --- a/pattern.c +++ b/pattern.c @@ -148,19 +148,15 @@ static config_item *game_configure(const game_params *params) 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 @@ static game_params *custom_params(const config_item *cfg) { 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; } diff --git a/pearl.c b/pearl.c index 2241b46..e3e83c5 100644 --- a/pearl.c +++ b/pearl.c @@ -234,29 +234,24 @@ static config_item *game_configure(const game_params *params) 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 @@ static game_params *custom_params(const config_item *cfg) { 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; } diff --git a/pegs.c b/pegs.c index 38e73b7..35f6624 100644 --- a/pegs.c +++ b/pegs.c @@ -149,24 +149,20 @@ static config_item *game_configure(const game_params *params) 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 @@ static game_params *custom_params(const config_item *cfg) { 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; } diff --git a/puzzles.h b/puzzles.h index f43ee83..0a91e31 100644 --- a/puzzles.h +++ b/puzzles.h @@ -137,30 +137,36 @@ typedef struct psdata psdata; */ 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; }; /* diff --git a/range.c b/range.c index 8017f8d..dd7ecbc 100644 --- a/range.c +++ b/range.c @@ -170,18 +170,14 @@ static config_item *game_configure(const game_params *params) 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 config_item *game_configure(const game_params *params) 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; } diff --git a/rect.c b/rect.c index 67cc30a..b31a84e 100644 --- a/rect.c +++ b/rect.c @@ -180,30 +180,24 @@ static config_item *game_configure(const game_params *params) 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 @@ static game_params *custom_params(const config_item *cfg) { 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; } diff --git a/samegame.c b/samegame.c index 7a40fcc..4092282 100644 --- a/samegame.c +++ b/samegame.c @@ -241,35 +241,29 @@ static config_item *game_configure(const game_params *params) 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 @@ static game_params *custom_params(const config_item *cfg) { 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; } diff --git a/signpost.c b/signpost.c index 9d782f0..61bd3c0 100644 --- a/signpost.c +++ b/signpost.c @@ -387,24 +387,19 @@ static config_item *game_configure(const game_params *params) 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 @@ static game_params *custom_params(const config_item *cfg) { 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; } diff --git a/singles.c b/singles.c index ff6960f..32d5965 100644 --- a/singles.c +++ b/singles.c @@ -222,24 +222,20 @@ static config_item *game_configure(const game_params *params) 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 @@ static game_params *custom_params(const config_item *cfg) { 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; } diff --git a/sixteen.c b/sixteen.c index 562eeb8..0381edf 100644 --- a/sixteen.c +++ b/sixteen.c @@ -140,25 +140,20 @@ static config_item *game_configure(const game_params *params) 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 @@ static game_params *custom_params(const config_item *cfg) { 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; } diff --git a/slant.c b/slant.c index 5980eb2..02f19fc 100644 --- a/slant.c +++ b/slant.c @@ -184,24 +184,20 @@ static config_item *game_configure(const game_params *params) 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 @@ static game_params *custom_params(const config_item *cfg) { 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; } diff --git a/solo.c b/solo.c index b40901d..83bc12c 100644 --- a/solo.c +++ b/solo.c @@ -445,46 +445,39 @@ static config_item *game_configure(const game_params *params) 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 @@ static game_params *custom_params(const config_item *cfg) { 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; diff --git a/tents.c b/tents.c index e17a893..1d987fa 100644 --- a/tents.c +++ b/tents.c @@ -371,24 +371,20 @@ static config_item *game_configure(const game_params *params) 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 @@ static game_params *custom_params(const config_item *cfg) { 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; } diff --git a/towers.c b/towers.c index 06b7279..3892d8e 100644 --- a/towers.c +++ b/towers.c @@ -212,18 +212,15 @@ static config_item *game_configure(const game_params *params) 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 @@ static game_params *custom_params(const config_item *cfg) { 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; } diff --git a/tracks.c b/tracks.c index f5f3e0b..78355cb 100644 --- a/tracks.c +++ b/tracks.c @@ -148,28 +148,24 @@ static config_item *game_configure(const game_params *params) 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 @@ static game_params *custom_params(const config_item *cfg) { 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; } diff --git a/twiddle.c b/twiddle.c index f52e999..70f768d 100644 --- a/twiddle.c +++ b/twiddle.c @@ -156,41 +156,33 @@ static config_item *game_configure(const game_params *params) 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 @@ static game_params *custom_params(const config_item *cfg) { 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; } diff --git a/undead.c b/undead.c index 2710223..a9343e8 100644 --- a/undead.c +++ b/undead.c @@ -163,24 +163,20 @@ static config_item *game_configure(const game_params *params) 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 @@ static game_params *custom_params(const config_item *cfg) { 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; } diff --git a/unequal.c b/unequal.c index 6342318..d4441e5 100644 --- a/unequal.c +++ b/unequal.c @@ -218,24 +218,21 @@ static config_item *game_configure(const game_params *params) 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 @@ static game_params *custom_params(const config_item *cfg) { 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; } diff --git a/unfinished/group.c b/unfinished/group.c index 0d2f915..a9ae704 100644 --- a/unfinished/group.c +++ b/unfinished/group.c @@ -212,23 +212,19 @@ static config_item *game_configure(const game_params *params) 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 @@ static game_params *custom_params(const config_item *cfg) { 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; } diff --git a/unfinished/slide.c b/unfinished/slide.c index 51ac7cb..05a3f8b 100644 --- a/unfinished/slide.c +++ b/unfinished/slide.c @@ -244,25 +244,20 @@ static config_item *game_configure(const game_params *params) 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 @@ static game_params *custom_params(const config_item *cfg) { 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; } diff --git a/unfinished/sokoban.c b/unfinished/sokoban.c index 2f0af35..edd0f28 100644 --- a/unfinished/sokoban.c +++ b/unfinished/sokoban.c @@ -210,19 +210,15 @@ static config_item *game_configure(const game_params *params) 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 @@ static game_params *custom_params(const config_item *cfg) { 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; } diff --git a/unruly.c b/unruly.c index 51b168a..ac5c565 100644 --- a/unruly.c +++ b/unruly.c @@ -239,28 +239,24 @@ static config_item *game_configure(const game_params *params) 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 @@ static game_params *custom_params(const config_item *cfg) { 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; } diff --git a/untangle.c b/untangle.c index 4dd93be..4dfe208 100644 --- a/untangle.c +++ b/untangle.c @@ -185,13 +185,10 @@ static config_item *game_configure(const game_params *params) 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 @@ static game_params *custom_params(const config_item *cfg) { game_params *ret = snew(game_params); - ret->n = atoi(cfg[0].sval); + ret->n = atoi(cfg[0].u.string.sval); return ret; } diff --git a/windows.c b/windows.c index df1db4f..5b70285 100644 --- a/windows.c +++ b/windows.c @@ -2057,52 +2057,43 @@ static config_item *frontend_get_config(frontend *fe, int which, 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 @@ static char *frontend_set_config(frontend *fe, int which, config_item *cfg) 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 @@ static void create_config_controls(frontend * fe) 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 @@ static void create_config_controls(frontend * fe) 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 @@ static void create_config_controls(frontend * fe) 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 @@ static void create_config_controls(frontend * fe) p = q; } } - SendMessage(ctl, CB_SETCURSEL, i->ival, 0); + SendMessage(ctl, CB_SETCURSEL, i->u.choices.selected, 0); break; } @@ -2324,16 +2318,16 @@ static int CALLBACK ConfigDlgProc(HWND hwnd, UINT msg, 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 @@ static int get_config(frontend *fe, int which) 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 @@ static int get_config(frontend *fe, int which) 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 @@ static int get_config(frontend *fe, int which) 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 @@ static int get_config(frontend *fe, int which) } } - SendMessage(ctl, CB_SETCURSEL, i->ival, 0); + SendMessage(ctl, CB_SETCURSEL, i->u.choices.selected, 0); y += height*3/2; break; -- 2.30.2