<URL: http://bugs.freeciv.org/Ticket/Display.html?id=39959 >

Harmonized S2_1 with S2_2 client_options_iterate().

Committed S2_1 revision 14161.
Committed S2_2 revision 14162.
Committed trunk revision 14163.

Index: server/stdinhand.c
===================================================================
--- server/stdinhand.c  (revision 14160)
+++ server/stdinhand.c  (working copy)
@@ -1698,8 +1698,8 @@
        packet.default_val = setting->int_default_value;
        break;
       case SSET_STRING:
-       strcpy(packet.strval, setting->string_value);
-       strcpy(packet.default_strval, setting->string_default_value);
+       sz_strlcpy(packet.strval, setting->string_value);
+       sz_strlcpy(packet.default_strval, setting->string_default_value);
        break;
       };
     }
Index: client/options.h
===================================================================
--- client/options.h    (revision 14160)
+++ client/options.h    (working copy)
@@ -90,7 +90,6 @@
   /* volatile */
   void *p_gui_data;
 } client_option;
-extern client_option *options;
 
 #define GEN_INT_OPTION(oname, desc, help, category)                        \
   { #oname, desc, help, category, COT_INT,                                 \
@@ -104,18 +103,19 @@
   { #oname, desc, help, category, COT_STR,                         \
       NULL, NULL, oname, sizeof(oname), callback, str_defaults, NULL }
 
-extern int num_options;
+/* Initialization and iteration */
+struct client_option *client_option_array_first(void);
+const struct client_option *client_option_array_last(void);
 
-#define client_options_iterate(o)                                           \
-{                                                                           \
-  int _i;                                                                   \
-  for (_i = 0; _i < num_options; _i++) {                                    \
-    client_option *o = options + _i;                                        \
-    {
+#define client_options_iterate(_p)                                     \
+{                                                                      \
+  struct client_option *_p = client_option_array_first();              \
+  if (NULL != _p) {                                                    \
+    for (; _p <= client_option_array_last(); _p++) {
 
-#define client_options_iterate_end                                          \
-    }                                                                       \
-  }                                                                         \
+#define client_options_iterate_end                                     \
+    }                                                                  \
+  }                                                                    \
 }
 
 /* GUI-specific options declared in gui-xxx but handled by common code. */
@@ -176,6 +176,7 @@
 
 void load_general_options(void);
 void load_ruleset_specific_options(void);
+void load_settable_options(bool send_it);
 void save_options(void);
 
 /* Callback functions for changing options. */
Index: client/gui-gtk-2.0/repodlgs.c
===================================================================
--- client/gui-gtk-2.0/repodlgs.c       (revision 14160)
+++ client/gui-gtk-2.0/repodlgs.c       (working copy)
@@ -27,6 +27,7 @@
 #include "fcintl.h"
 #include "game.h"
 #include "government.h"
+#include "log.h"
 #include "packets.h"
 #include "shared.h"
 #include "support.h"
@@ -1213,21 +1214,22 @@
     k = 0;
     memset(&unittotals, '\0', sizeof(unittotals));
     unit_type_iterate(punittype) {
-      if (unitarray[punittype->index].active_count > 0
-         || unitarray[punittype->index].building_count > 0) {
+      Unit_type_id uti = punittype->index;
+      if (unitarray[uti].active_count > 0
+         || unitarray[uti].building_count > 0) {
        can = (can_upgrade_unittype(game.player_ptr, punittype) != NULL);
        
         gtk_list_store_append(activeunits_store, &it);
        gtk_list_store_set(activeunits_store, &it,
                1, can,
-               2, unitarray[punittype->index].building_count,
-               3, unitarray[punittype->index].active_count,
-               4, unitarray[punittype->index].upkeep[O_SHIELD],
-               5, unitarray[punittype->index].upkeep[O_FOOD],
-               6, unitarray[punittype->index].upkeep[O_GOLD],
+               2, unitarray[uti].building_count,
+               3, unitarray[uti].active_count,
+               4, unitarray[uti].upkeep[O_SHIELD],
+               5, unitarray[uti].upkeep[O_FOOD],
+               6, unitarray[uti].upkeep[O_GOLD],
                7, TRUE,
-               8, ((unitarray[punittype->index].active_count > 0)
-                   ? punittype->index : U_LAST),
+               8, ((unitarray[uti].active_count > 0)
+                   ? uti : U_LAST),
                -1);
        g_value_init(&value, G_TYPE_STRING);
        g_value_set_static_string(&value, utype_name_translation(punittype));
@@ -1235,12 +1237,11 @@
        g_value_unset(&value);
 
        k++;
-       unittotals.active_count += unitarray[punittype->index].active_count;
+       unittotals.active_count += unitarray[uti].active_count;
        output_type_iterate(o) {
-         unittotals.upkeep[o] += unitarray[punittype->index].upkeep[o];        
  
+         unittotals.upkeep[o] += unitarray[uti].upkeep[o];
        } output_type_iterate_end;
-       unittotals.building_count
-         += unitarray[punittype->index].building_count;
+       unittotals.building_count += unitarray[uti].building_count;
       }
     } unit_type_iterate_end;
 
@@ -1386,37 +1387,59 @@
 *************************************************************************/
 static void option_changed_callback(GtkWidget *widget, gpointer data) 
 {
-  g_object_set_data(G_OBJECT(widget), "changed", (gpointer)TRUE); 
+  /* pass along the pointer to the changed option */
+  g_object_set_data(G_OBJECT(widget), "changed", data); 
 }
 
 /*************************************************************************
   helper function for server options dialog
 *************************************************************************/
-static void set_options(GtkWidget *w)
+static void settable_options_processing(GtkWidget *final)
 {
-  GtkWidget *tmp;
+  char buffer[MAX_LEN_MSG];
+  const char *desired_string;
+  GtkWidget *w = final;
 
-  /* if the entry has been changed, then send the changes to the server */
-  if (g_object_get_data(G_OBJECT(w), "changed")) {
-    char buffer[MAX_LEN_MSG];
+  while (NULL != w) {
+    struct options_settable *o =
+      (struct options_settable *)g_object_get_data(G_OBJECT(w), "changed");
 
-    /* append the name of the option */
-    my_snprintf(buffer, MAX_LEN_MSG, "/set %s ", gtk_widget_get_name(w));
+    /* if the entry has been changed, then send the changes to the server */
+    if (NULL != o) {
+      /* append the name of the option */
+      my_snprintf(buffer, sizeof(buffer), "/set %s ", gtk_widget_get_name(w));
 
-    /* append the setting */
-    if (GTK_IS_ENTRY(w)) {
-      sz_strlcat(buffer, gtk_entry_get_text(GTK_ENTRY(w)));
-    } else {
-      bool active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w));
-      sz_strlcat(buffer, active ? "1" : "0");
+      /* append the setting */
+      switch (o->stype) {
+      case SSET_BOOL:
+        o->desired_val = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w));
+        sz_strlcat(buffer, o->desired_val ? "1" : "0");
+        break;
+      case SSET_INT:
+        o->desired_val = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(w));
+        sz_strlcat(buffer, gtk_entry_get_text(GTK_ENTRY(w)));
+        break;
+      case SSET_STRING:
+        desired_string = gtk_entry_get_text(GTK_ENTRY(w));
+        if (NULL != desired_string) {
+          if (NULL != o->desired_strval) {
+            free(o->desired_strval);
+          }
+          o->desired_strval = mystrdup(desired_string);
+          sz_strlcat(buffer, desired_string);
+        }
+        break;
+      default:
+        freelog(LOG_ERROR,
+                "settable_options_processing() bad type %d.",
+                o->stype);
+        break;
+      };
+      send_chat(buffer);
     }
-    send_chat(buffer);
-  }
 
-  /* using the linked list, work backwards and check the previous widget */
-  tmp = (GtkWidget *)g_object_get_data(G_OBJECT(w), "prev");
-  if (tmp) {
-    set_options(tmp);
+    /* using the linked list, work backwards and check the previous widget */
+    w = (GtkWidget *)g_object_get_data(G_OBJECT(w), "prev");
   }
 }
 
@@ -1426,7 +1449,7 @@
 static void settable_options_callback(GtkWidget *win, gint rid, GtkWidget *w)
 {
   if (rid == GTK_RESPONSE_OK) {
-    set_options(w);
+    settable_options_processing(w);
   }
   gtk_widget_destroy(win);
 }
@@ -1436,15 +1459,14 @@
 *************************************************************************/
 static void create_settable_options_dialog(void)
 {
-  GtkWidget *win, *book, **vbox, *label, *prev_widget = NULL;
-  GtkTooltips *tips;
-  bool *used;
   int i;
+  GtkWidget *win, *book, **vbox, *label;
+  GtkWidget *prev_widget = NULL;
+  GtkTooltips *tips = gtk_tooltips_new();
+  bool *used = fc_calloc(num_options_categories, sizeof(*used));
 
-  used = fc_calloc(num_options_categories, sizeof(*used));
-
-  tips = gtk_tooltips_new();
-  settable_options_dialog_shell = gtk_dialog_new_with_buttons(_("Game 
Settings"),
+  settable_options_dialog_shell =
+    gtk_dialog_new_with_buttons(_("Game Settings"),
       NULL, 0,
       GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
       GTK_STOCK_OK, GTK_RESPONSE_OK,
@@ -1510,7 +1532,7 @@
        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ent), o->val);
 
        g_signal_connect(ent, "toggled", 
-                        G_CALLBACK(option_changed_callback), NULL);
+                        G_CALLBACK(option_changed_callback), o);
        break;
 
       case SSET_INT:
@@ -1530,7 +1552,7 @@
        gtk_spin_button_set_value(GTK_SPIN_BUTTON(ent), o->val);
 
        g_signal_connect(ent, "changed", 
-                        G_CALLBACK(option_changed_callback), NULL);
+                        G_CALLBACK(option_changed_callback), o);
        break;
       case SSET_STRING:
        /* string */
@@ -1538,7 +1560,7 @@
        gtk_entry_set_text(GTK_ENTRY(ent), o->strval);
 
        g_signal_connect(ent, "changed", 
-                        G_CALLBACK(option_changed_callback), NULL);
+                        G_CALLBACK(option_changed_callback), o);
        break;
       }
     } else {
@@ -1567,7 +1589,7 @@
     /* set up a linked list so we can work our way through the widgets */
     gtk_widget_set_name(ent, o->name);
     g_object_set_data(G_OBJECT(ent), "prev", prev_widget);
-    g_object_set_data(G_OBJECT(ent), "changed", FALSE);
+    g_object_set_data(G_OBJECT(ent), "changed", NULL);
     prev_widget = ent;
   }
 
Index: client/repodlgs_common.c
===================================================================
--- client/repodlgs_common.c    (revision 14160)
+++ client/repodlgs_common.c    (working copy)
@@ -30,15 +30,20 @@
 
 #include "civclient.h"         /* can_client_issue_orders */
 #include "control.h"
+#include "options.h"
 #include "repodlgs_common.h"
 #include "packhand_gen.h"
 
-struct options_settable *settable_options;
-int num_settable_options;
 
-char **options_categories;
-int num_options_categories;
+char **options_categories = NULL;
+struct options_settable *settable_options = NULL;
 
+int num_options_categories = 0;
+int num_settable_options = 0;
+
+static bool settable_options_loaded = FALSE;   /* desired options from file */
+
+
 /****************************************************************
   Fills out the array of struct improvement_entry given by
   entries. The array must be able to hold at least B_LAST entries.
@@ -193,6 +198,8 @@
 *******************************************************************/
 void settable_options_init(void)
 {
+  settable_options_loaded = FALSE;
+
   settable_options = NULL;
   num_settable_options = 0;
 
@@ -201,6 +208,33 @@
 }
 
 /******************************************************************
+ free and clear all settable_option packet strings
+*******************************************************************/
+static void settable_option_strings_free(struct options_settable *o)
+{
+  if (NULL != o->name) {
+    free(o->name);
+    o->name = NULL;
+  }
+  if (NULL != o->short_help) {
+    free(o->short_help);
+    o->short_help = NULL;
+  }
+  if (NULL != o->extra_help) {
+    free(o->extra_help);
+    o->extra_help = NULL;
+  }
+  if (NULL != o->strval) {
+    free(o->strval);
+    o->strval = NULL;
+  }
+  if (NULL != o->default_strval) {
+    free(o->default_strval);
+    o->default_strval = NULL;
+  }
+}
+
+/******************************************************************
  free settable_options[] and options_categories[]
 *******************************************************************/
 void settable_options_free(void)
@@ -209,22 +243,13 @@
 
   for (i = 0; i < num_settable_options; i++) {
     struct options_settable *o = &settable_options[i];
+    settable_option_strings_free(o);
 
-    if (o->name) {
-      free(o->name);
+    /* special handling for non-packet strings */
+    if (NULL != o->desired_strval) {
+      free(o->desired_strval);
+      o->desired_strval = NULL;
     }
-    if (o->short_help) {
-      free(o->short_help);
-    }
-    if (o->extra_help) {
-      free(o->extra_help);
-    }
-    if (o->strval) {
-      free(o->strval);
-    }
-    if (o->default_strval) {
-      free(o->default_strval);
-    }
   }
   free(settable_options);
 
@@ -286,39 +311,31 @@
   o->scategory = packet->scategory;
   o->sclass = packet->sclass;
 
+  o->val = packet->val;
+  o->default_val = packet->default_val;
+  if (!settable_options_loaded) {
+    o->desired_val = packet->default_val;
+    /* desired_val is loaded later */
+  }
+  o->min = packet->min;
+  o->max = packet->max;
+
+  /* ensure packet string fields are NULL for repeat calls */
+  settable_option_strings_free(o);
+
   switch (o->stype) {
   case SSET_BOOL:
-    o->val = packet->val;
-    o->default_val = packet->default_val;
     o->min = FALSE;
     o->max = TRUE;                             /* server sent FALSE */
-    o->strval = NULL;
-    o->default_strval = NULL;
     break;
   case SSET_INT:
-    o->val = packet->val;
-    o->default_val = packet->default_val;
-    o->min = packet->min;
-    o->max = packet->max;
-    o->strval = NULL;
-    o->default_strval = NULL;
     break;
   case SSET_STRING:
-    o->val = packet->val;
-    o->default_val = packet->default_val;
-    o->min = packet->min;
-    o->max = packet->max;
     o->strval = mystrdup(packet->strval);
     o->default_strval = mystrdup(packet->default_strval);
+    /* desired_strval is loaded later */
     break;
   default:
-    /* ensure string fields are NULL for free */
-    o->name = NULL;
-    o->short_help = NULL;
-    o->extra_help = NULL;
-    o->strval = NULL;
-    o->default_strval = NULL;
-
     freelog(LOG_ERROR,
            "handle_options_settable() bad type %d.",
            packet->stype);
@@ -330,6 +347,12 @@
   o->name = mystrdup(packet->name);
   o->short_help = mystrdup(packet->short_help);
   o->extra_help = mystrdup(packet->extra_help);
+
+  /* have no proper final packet, test for the last instead */
+  if (i == (num_settable_options - 1) && !settable_options_loaded) {
+    load_settable_options(TRUE);
+    settable_options_loaded = TRUE;
+  }
 }
 
 /****************************************************************************
Index: client/repodlgs_common.h
===================================================================
--- client/repodlgs_common.h    (revision 14160)
+++ client/repodlgs_common.h    (working copy)
@@ -57,11 +57,13 @@
 
   int val;
   int default_val;
+  int desired_val;
   int min;
   int max;
 
   char *strval;
   char *default_strval;
+  char *desired_strval;
 
   char *name;
   char *short_help;
Index: client/clinet.c
===================================================================
--- client/clinet.c     (revision 14160)
+++ client/clinet.c     (working copy)
@@ -285,6 +285,9 @@
   if (with_ggz) {
     client_exit();
   }
+  if (save_options_on_exit) {
+    save_options();
+  }
 }  
 
 /**************************************************************************
Index: client/options.c
===================================================================
--- client/options.c    (revision 14160)
+++ client/options.c    (working copy)
@@ -39,10 +39,17 @@
 #include "options.h"
 #include "overview_common.h"
 #include "plrdlg_common.h"
+#include "repodlgs_common.h"
 #include "servers.h"
 #include "themes_common.h"
 #include "tilespec.h"
 
+/****************************************************************
+ The "options" file handles actual "options", and also view options,
+ message options, dialog/report settings, cma settings, server settings,
+ and global worklists.
+*****************************************************************/
+
 /** Defaults for options normally on command line **/
 
 char default_user_name[512] = "\0";
@@ -266,8 +273,8 @@
 #undef GEN_BOOL_OPTION
 #undef GEN_STR_OPTION
 
-int num_options;
-client_option *options;
+static client_option *fc_options;
+static int num_options;
 
 /** View Options: **/
 
@@ -327,6 +334,29 @@
 
 unsigned int messages_where[E_LAST];
 
+
+/**************************************************************************
+  Return the first item of fc_options.
+**************************************************************************/
+struct client_option *client_option_array_first(void)
+{
+  if (num_options > 0) {
+    return fc_options;
+  }
+  return NULL;
+}
+
+/**************************************************************************
+  Return the last item of fc_options.
+**************************************************************************/
+const struct client_option *client_option_array_last(void)
+{
+  if (num_options > 0) {
+    return &fc_options[num_options - 1];
+  }
+  return NULL;
+}
+
 /****************************************************************
   These could be a static table initialisation, except
   its easier to do it this way.
@@ -397,18 +427,72 @@
 }
 
 
-static void save_cma_preset(struct section_file *file, char *name,
-                           const struct cm_parameter *const pparam,
-                           int inx);
-static void load_cma_preset(struct section_file *file, int inx);
+/****************************************************************
+ Does heavy lifting for looking up a preset.
+*****************************************************************/
+static void load_cma_preset(struct section_file *file, int i)
+{
+  struct cm_parameter parameter;
+  const char *name =
+    secfile_lookup_str_default(file, "preset",
+                               "cma.preset%d.name", i);
 
+  output_type_iterate(o) {
+    parameter.minimal_surplus[o] =
+        secfile_lookup_int_default(file, 0, "cma.preset%d.minsurp%d", i, o);
+    parameter.factor[o] =
+        secfile_lookup_int_default(file, 0, "cma.preset%d.factor%d", i, o);
+  } output_type_iterate_end;
+  parameter.require_happy =
+      secfile_lookup_bool_default(file, FALSE, "cma.preset%d.reqhappy", i);
+  parameter.happy_factor =
+      secfile_lookup_int_default(file, 0, "cma.preset%d.happyfactor", i);
+  parameter.allow_disorder = FALSE;
+  parameter.allow_specialists = TRUE;
+
+  cmafec_preset_add(name, &parameter);
+}
+
 /****************************************************************
- The "options" file handles actual "options", and also view options,
- message options, city report settings, cma settings, and 
- saved global worklists
+ Does heavy lifting for inserting a preset.
 *****************************************************************/
+static void save_cma_preset(struct section_file *file, int i)
+{
+  const struct cm_parameter *const pparam = cmafec_preset_get_parameter(i);
+  char *name = cmafec_preset_get_descr(i);
 
+  secfile_insert_str(file, name, "cma.preset%d.name", i);
+
+  output_type_iterate(o) {
+    secfile_insert_int(file, pparam->minimal_surplus[o],
+                       "cma.preset%d.minsurp%d", i, o);
+    secfile_insert_int(file, pparam->factor[o],
+                       "cma.preset%d.factor%d", i, o);
+  } output_type_iterate_end;
+  secfile_insert_bool(file, pparam->require_happy,
+                      "cma.preset%d.reqhappy", i);
+  secfile_insert_int(file, pparam->happy_factor,
+                     "cma.preset%d.happyfactor", i);
+}
+
 /****************************************************************
+ Insert all cma presets.
+*****************************************************************/
+static void save_cma_presets(struct section_file *file)
+{
+  int i;
+
+  secfile_insert_int_comment(file, cmafec_preset_num(),
+                             _("If you add a preset by hand,"
+                               " also update \"number_of_presets\""),
+                             "cma.number_of_presets");
+  for (i = 0; i < cmafec_preset_num(); i++) {
+    save_cma_preset(file, i);
+  }
+}
+
+
+/****************************************************************
  Returns pointer to static memory containing name of option file.
  Ie, based on FREECIV_OPT env var, and home dir. (or a
  OPTION_FILE_NAME define defined in config.h)
@@ -427,7 +511,7 @@
 #ifndef OPTION_FILE_NAME
     name = user_home_dir();
     if (!name) {
-      append_output_window(_("Cannot find your home directory"));
+      freelog(LOG_ERROR, _("Cannot find your home directory"));
       return NULL;
     }
     mystrlcpy(name_buffer, name, 231);
@@ -439,34 +523,162 @@
   freelog(LOG_VERBOSE, "settings file is %s", name_buffer);
   return name_buffer;
 }
-  
+
+
 /****************************************************************
- this loads from the rc file any options which are not ruleset specific 
- it is called on client init.
+ Load settable per connection/server options.
 *****************************************************************/
+void load_settable_options(bool send_it)
+{
+  char buffer[MAX_LEN_MSG];
+  struct section_file sf;
+  char *name;
+  char *desired_string;
+  int i = 0;
+
+  name = option_file_name();
+  if (!name) {
+    /* fail silently */
+    return;
+  }
+  if (!section_file_load(&sf, name))
+    return;
+
+  for (; i < num_settable_options; i++) {
+    struct options_settable *o = &settable_options[i];
+    bool changed = FALSE;
+
+    my_snprintf(buffer, sizeof(buffer), "/set %s ", o->name);
+
+    switch (o->stype) {
+    case SSET_BOOL:
+      o->desired_val = secfile_lookup_bool_default(&sf, o->default_val,
+                                                   "server.%s", o->name);
+      changed = (o->desired_val != o->default_val
+              && o->desired_val != o->val);
+      if (changed) {
+        sz_strlcat(buffer, o->desired_val ? "1" : "0");
+      }
+      break;
+    case SSET_INT:
+      o->desired_val = secfile_lookup_int_default(&sf, o->default_val,
+                                                  "server.%s", o->name);
+      changed = (o->desired_val != o->default_val
+              && o->desired_val != o->val);
+      if (changed) {
+        cat_snprintf(buffer, sizeof(buffer), "%d", o->desired_val);
+      }
+      break;
+    case SSET_STRING:
+      desired_string = secfile_lookup_str_default(&sf, o->default_strval,
+                                                  "server.%s", o->name);
+      if (NULL != desired_string) {
+        if (NULL != o->desired_strval) {
+          free(o->desired_strval);
+        }
+        o->desired_strval = mystrdup(desired_string);
+        changed = (0 != strcmp(desired_string, o->default_strval)
+                && 0 != strcmp(desired_string, o->strval));
+        if (changed) {
+          sz_strlcat(buffer, desired_string);
+        }
+      }
+      break;
+    default:
+      freelog(LOG_ERROR,
+              "load_settable_options() bad type %d.",
+              o->stype);
+      break;
+    };
+
+    if (changed && send_it) {
+      send_chat(buffer);
+    }
+  }
+
+  section_file_free(&sf);
+}
+
+/****************************************************************
+ Save settable per connection/server options.
+*****************************************************************/
+static void save_settable_options(struct section_file *sf)
+{
+  int i = 0;
+
+  for (; i < num_settable_options; i++) {
+    struct options_settable *o = &settable_options[i];
+
+    switch (o->stype) {
+    case SSET_BOOL:
+      if (o->desired_val != o->default_val) {
+        secfile_insert_bool(sf, o->desired_val, "server.%s", o->name);
+      }
+      break;
+    case SSET_INT:
+      if (o->desired_val != o->default_val) {
+        secfile_insert_int(sf, o->desired_val, "server.%s",  o->name);
+      }
+      break;
+    case SSET_STRING:
+      if (NULL != o->desired_strval
+       && 0 != strcmp(o->desired_strval, o->default_strval)) {
+        secfile_insert_str(sf, o->desired_strval, "server.%s", o->name);
+      }
+      break;
+    default:
+      freelog(LOG_ERROR,
+              "save_settable_options() bad type %d.",
+              o->stype);
+      break;
+    };
+  }
+}
+
+
+/****************************************************************
+ Load from the rc file any options that are not ruleset specific.
+ It is called after ui_init(), yet before ui_main().
+ Unfortunately, this means that some clients cannot display.
+ Instead, use freelog().
+*****************************************************************/
 void load_general_options(void)
 {
   struct section_file sf;
-  const char * const prefix = "client";
-  char *name;
   int i, num;
   view_option *v;
+  char *name;
+  const char * const prefix = "client";
 
-  assert(options == NULL);
+  assert(fc_options == NULL);
   num_options = ARRAY_SIZE(common_options) + num_gui_options;
-  options = fc_malloc(num_options * sizeof(*options));
-  memcpy(options, common_options, sizeof(common_options));
-  memcpy(options + ARRAY_SIZE(common_options), gui_options,
-        num_gui_options * sizeof(*options));
+  fc_options = fc_calloc(num_options, sizeof(*fc_options));
+  memcpy(fc_options, common_options, sizeof(common_options));
+  memcpy(fc_options + ARRAY_SIZE(common_options), gui_options,
+        num_gui_options * sizeof(*fc_options));
 
   name = option_file_name();
   if (!name) {
-    /* fail silently */
+    /* FIXME: need better messages */
+    freelog(LOG_ERROR, _("Save failed, cannot find a filename."));
     return;
   }
   if (!section_file_load(&sf, name)) {
+    /* try to create the rc file */
+    section_file_init(&sf);
+    secfile_insert_str(&sf, VERSION_STRING, "client.version");
+
     create_default_cma_presets();
-    return;  
+    save_cma_presets(&sf);
+
+    /* FIXME: need better messages */
+    if (!section_file_save(&sf, name, 0)) {
+      freelog(LOG_ERROR, _("Save failed, cannot write to file %s"), name);
+    } else {
+      freelog(LOG_NORMAL, _("Saved settings to file %s"), name);
+    }
+    section_file_free(&sf);
+    return;
   }
 
   /* a "secret" option for the lazy. TODO: make this saveable */
@@ -481,7 +693,7 @@
                                "%s.fullscreen_mode", prefix);
 
   for (i = 0; i < num_options; i++) {
-    client_option *o = options + i;
+    client_option *o = fc_options + i;
 
     switch (o->type) {
     case COT_BOOL:
@@ -538,10 +750,9 @@
 void load_ruleset_specific_options(void)
 {
   struct section_file sf;
-  char *name;
   int i;
+  char *name = option_file_name();
 
-  name = option_file_name();
   if (!name) {
     /* fail silently */
     return;
@@ -574,10 +785,10 @@
 void save_options(void)
 {
   struct section_file sf;
-  char *name = option_file_name();
   char output_buffer[256];
+  int i;
   view_option *v;
-  int i;
+  char *name = option_file_name();
 
   if(!name) {
     append_output_window(_("Save failed, cannot find a filename."));
@@ -591,7 +802,7 @@
   secfile_insert_bool(&sf, fullscreen_mode, "client.fullscreen_mode");
 
   for (i = 0; i < num_options; i++) {
-    client_option *o = options + i;
+    client_option *o = fc_options + i;
 
     switch (o->type) {
     case COT_BOOL:
@@ -624,7 +835,11 @@
                         "client.player_dlg_%s",
                         player_dlg_columns[i].tagname);
   }
-  
+
+  /* server settings */
+  save_cma_presets(&sf);
+  save_settable_options(&sf);
+
   /* insert global worklists */
   if (game.player_ptr) {
     for(i = 0; i < MAX_NUM_WORKLISTS; i++){
@@ -636,17 +851,6 @@
     }
   }
 
-
-  /* insert cma presets */
-  secfile_insert_int_comment(&sf, cmafec_preset_num(),
-                            _("If you add a preset by "
-                              "hand, also update \"number_of_presets\""),
-                            "cma.number_of_presets");
-  for (i = 0; i < cmafec_preset_num(); i++) {
-    save_cma_preset(&sf, cmafec_preset_get_descr(i),
-                   cmafec_preset_get_parameter(i), i);
-  }
-
   /* save to disk */
   if (!section_file_save(&sf, name, 0)) {
     my_snprintf(output_buffer, sizeof(output_buffer),
@@ -655,57 +859,10 @@
     my_snprintf(output_buffer, sizeof(output_buffer),
                _("Saved settings to file %s"), name);
   }
-
   append_output_window(output_buffer);
   section_file_free(&sf);
 }
 
-/****************************************************************
- Does heavy lifting for looking up a preset.
-*****************************************************************/
-static void load_cma_preset(struct section_file *file, int inx)
-{
-  struct cm_parameter parameter;
-  const char *name;
-
-  name = secfile_lookup_str_default(file, "preset", 
-                                   "cma.preset%d.name", inx);
-  output_type_iterate(i) {
-    parameter.minimal_surplus[i] =
-       secfile_lookup_int_default(file, 0, "cma.preset%d.minsurp%d", inx, i);
-    parameter.factor[i] =
-       secfile_lookup_int_default(file, 0, "cma.preset%d.factor%d", inx, i);
-  } output_type_iterate_end;
-  parameter.require_happy =
-      secfile_lookup_bool_default(file, FALSE, "cma.preset%d.reqhappy", inx);
-  parameter.happy_factor =
-      secfile_lookup_int_default(file, 0, "cma.preset%d.happyfactor", inx);
-  parameter.allow_disorder = FALSE;
-  parameter.allow_specialists = TRUE;
-
-  cmafec_preset_add(name, &parameter);
-}
-
-/****************************************************************
- Does heavy lifting for inserting a preset.
-*****************************************************************/
-static void save_cma_preset(struct section_file *file, char *name,
-                           const struct cm_parameter *const pparam,
-                           int inx)
-{
-  secfile_insert_str(file, name, "cma.preset%d.name", inx);
-  output_type_iterate(i) {
-    secfile_insert_int(file, pparam->minimal_surplus[i],
-                      "cma.preset%d.minsurp%d", inx, i);
-    secfile_insert_int(file, pparam->factor[i],
-                      "cma.preset%d.factor%d", inx, i);
-  } output_type_iterate_end;
-  secfile_insert_bool(file, pparam->require_happy,
-                     "cma.preset%d.reqhappy", inx);
-  secfile_insert_int(file, pparam->happy_factor,
-                    "cma.preset%d.happyfactor", inx);
-}
-
 /****************************************************************************
   Callback when a mapview graphics option is changed (redraws the canvas).
 ****************************************************************************/
_______________________________________________
Freeciv-dev mailing list
Freeciv-dev@gna.org
https://mail.gna.org/listinfo/freeciv-dev

Reply via email to