Remove hard limitation that AI wonder cities never build settlers
[freeciv.git] / client / options.c
blob18a070b0a0ca9e3b2101264ae53d451d8b40b369
1 /***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12 ***********************************************************************/
14 #ifdef HAVE_CONFIG_H
15 #include <fc_config.h>
16 #endif
18 #include <stdarg.h>
19 #include <string.h>
20 #include <sys/stat.h>
21 #include <sys/types.h>
23 /* utility */
24 #include "fcintl.h"
25 #include "ioz.h"
26 #include "log.h"
27 #include "mem.h"
28 #include "registry.h"
29 #include "shared.h"
30 #include "string_vector.h"
31 #include "support.h"
33 /* common */
34 #include "events.h"
35 #include "version.h"
37 /* client/agents */
38 #include "cma_fec.h"
40 /* client/include */
41 #include "chatline_g.h"
42 #include "dialogs_g.h"
43 #include "gui_main_g.h"
44 #include "menu_g.h"
45 #include "optiondlg_g.h"
46 #include "repodlgs_g.h"
47 #include "voteinfo_bar_g.h"
49 /* client */
50 #include "audio.h"
51 #include "cityrepdata.h"
52 #include "client_main.h"
53 #include "climisc.h"
54 #include "connectdlg_common.h"
55 #include "global_worklist.h"
56 #include "mapctrl_common.h"
57 #include "mapview_common.h"
58 #include "music.h"
59 #include "overview_common.h"
60 #include "packhand_gen.h"
61 #include "plrdlg_common.h"
62 #include "repodlgs_common.h"
63 #include "servers.h"
64 #include "themes_common.h"
65 #include "tilespec.h"
67 #include "options.h"
70 struct client_options gui_options = {
71 /** Defaults for options normally on command line **/
73 .default_user_name = "\0",
74 .default_server_host = "localhost",
75 .default_server_port = DEFAULT_SOCK_PORT,
76 .default_metaserver = DEFAULT_METASERVER_OPTION,
77 .default_tileset_overhead_name = "\0",
78 .default_tileset_iso_name = "\0",
79 .default_tileset_hex_name = "\0",
80 .default_tileset_isohex_name = "\0",
81 .default_sound_set_name = "stdsounds",
82 .default_music_set_name = "stdmusic",
83 .default_sound_plugin_name = "\0",
84 .default_chat_logfile = GUI_DEFAULT_CHAT_LOGFILE,
86 .save_options_on_exit = TRUE,
88 .use_prev_server = FALSE,
89 .heartbeat_enabled = FALSE,
91 /** Migrations **/
92 .first_boot = FALSE,
93 .default_tileset_name = "\0",
94 .gui_gtk3_22_migrated_from_gtk3 = FALSE,
95 .gui_gtk3_migrated_from_gtk2 = FALSE,
96 .gui_sdl2_migrated_from_sdl = FALSE,
97 .gui_gtk2_migrated_from_2_5 = FALSE,
98 .gui_gtk3_migrated_from_2_5 = FALSE,
99 .gui_qt_migrated_from_2_5 = FALSE,
101 .migrate_fullscreen = FALSE,
103 /** Local Options: **/
105 .solid_color_behind_units = FALSE,
106 .sound_bell_at_new_turn = FALSE,
107 .smooth_move_unit_msec = 30,
108 .smooth_center_slide_msec = 200,
109 .smooth_combat_step_msec = 10,
110 .ai_manual_turn_done = TRUE,
111 .auto_center_on_unit = TRUE,
112 .auto_center_on_automated = TRUE,
113 .auto_center_on_combat = FALSE,
114 .auto_center_each_turn = TRUE,
115 .wakeup_focus = TRUE,
116 .goto_into_unknown = TRUE,
117 .center_when_popup_city = TRUE,
118 .concise_city_production = FALSE,
119 .auto_turn_done = FALSE,
120 .meta_accelerators = TRUE,
121 .ask_city_name = TRUE,
122 .popup_new_cities = TRUE,
123 .popup_actor_arrival = TRUE,
124 .keyboardless_goto = TRUE,
125 .enable_cursor_changes = TRUE,
126 .separate_unit_selection = FALSE,
127 .unit_selection_clears_orders = TRUE,
128 .highlight_our_names = FT_COLOR("#000000", "#FFFF00"),
130 .voteinfo_bar_use = TRUE,
131 .voteinfo_bar_always_show = FALSE,
132 .voteinfo_bar_hide_when_not_player = FALSE,
133 .voteinfo_bar_new_at_front = FALSE,
135 .autoaccept_tileset_suggestion = FALSE,
136 .autoaccept_soundset_suggestion = FALSE,
137 .autoaccept_musicset_suggestion = FALSE,
139 .sound_enable_effects = TRUE,
140 .sound_enable_menu_music = TRUE,
141 .sound_enable_game_music = TRUE,
143 /* This option is currently set by the client - not by the user. */
144 .update_city_text_in_refresh_tile = TRUE,
146 .draw_city_outlines = TRUE,
147 .draw_city_output = FALSE,
148 .draw_map_grid = FALSE,
149 .draw_city_names = TRUE,
150 .draw_city_growth = TRUE,
151 .draw_city_productions = TRUE,
152 .draw_city_buycost = FALSE,
153 .draw_city_trade_routes = FALSE,
154 .draw_terrain = TRUE,
155 .draw_coastline = FALSE,
156 .draw_roads_rails = TRUE,
157 .draw_irrigation = TRUE,
158 .draw_mines = TRUE,
159 .draw_fortress_airbase = TRUE,
160 .draw_specials = TRUE,
161 .draw_huts = TRUE,
162 .draw_pollution = TRUE,
163 .draw_cities = TRUE,
164 .draw_units = TRUE,
165 .draw_focus_unit = FALSE,
166 .draw_fog_of_war = TRUE,
167 .draw_borders = TRUE,
168 .draw_native = FALSE,
169 .draw_full_citybar = TRUE,
170 .draw_unit_shields = TRUE,
171 .player_dlg_show_dead_players = TRUE,
172 .reqtree_show_icons = TRUE,
173 .reqtree_curved_lines = FALSE,
175 /* options for map images */
176 /* .mapimg_format, */
177 .mapimg_zoom = 2,
178 /* See the definition of MAPIMG_LAYER in mapimg.h. */
179 .mapimg_layer = {
180 FALSE, /* a - MAPIMG_LAYER_AREA */
181 TRUE, /* b - MAPIMG_LAYER_BORDERS */
182 TRUE, /* c - MAPIMG_LAYER_CITIES */
183 TRUE, /* f - MAPIMG_LAYER_FOGOFWAR */
184 TRUE, /* k - MAPIMG_LAYER_KNOWLEDGE */
185 TRUE, /* t - MAPIMG_LAYER_TERRAIN */
186 TRUE /* u - MAPIMG_LAYER_UNITS */
188 /* .mapimg_filename, */
190 .zoom_set = FALSE,
191 .zoom_default_level = 1.0,
193 /* gui-gtk-2.0 client specific options. */
194 .gui_gtk2_default_theme_name = FC_GTK2_DEFAULT_THEME_NAME,
195 .gui_gtk2_fullscreen = FALSE,
196 .gui_gtk2_map_scrollbars = FALSE,
197 .gui_gtk2_dialogs_on_top = TRUE,
198 .gui_gtk2_show_task_icons = TRUE,
199 .gui_gtk2_enable_tabs = TRUE,
200 .gui_gtk2_better_fog = TRUE,
201 .gui_gtk2_show_chat_message_time = FALSE,
202 .gui_gtk2_new_messages_go_to_top = FALSE,
203 .gui_gtk2_show_message_window_buttons = TRUE,
204 .gui_gtk2_metaserver_tab_first = FALSE,
205 .gui_gtk2_allied_chat_only = FALSE,
206 .gui_gtk2_message_chat_location = GUI_GTK_MSGCHAT_MERGED,
207 .gui_gtk2_small_display_layout = TRUE,
208 .gui_gtk2_mouse_over_map_focus = FALSE,
209 .gui_gtk2_chatline_autocompletion = TRUE,
210 .gui_gtk2_citydlg_xsize = GUI_GTK2_CITYDLG_DEFAULT_XSIZE,
211 .gui_gtk2_citydlg_ysize = GUI_GTK2_CITYDLG_DEFAULT_YSIZE,
212 .gui_gtk2_popup_tech_help = GUI_POPUP_TECH_HELP_RULESET,
213 .gui_gtk2_font_city_label = "Monospace 8",
214 .gui_gtk2_font_notify_label = "Monospace Bold 9",
215 .gui_gtk2_font_spaceship_label = "Monospace 8",
216 .gui_gtk2_font_help_label = "Sans Bold 10",
217 .gui_gtk2_font_help_link = "Sans 9",
218 .gui_gtk2_font_help_text = "Monospace 8",
219 .gui_gtk2_font_chatline = "Monospace 8",
220 .gui_gtk2_font_beta_label = "Sans Italic 10",
221 .gui_gtk2_font_small = "Sans 9",
222 .gui_gtk2_font_comment_label = "Sans Italic 9",
223 .gui_gtk2_font_city_names = "Sans Bold 10",
224 .gui_gtk2_font_city_productions = "Serif 10",
225 .gui_gtk2_font_reqtree_text = "Serif 10",
227 /* gui-gtk-3.0 client specific options. */
228 .gui_gtk3_default_theme_name = FC_GTK3_DEFAULT_THEME_NAME,
229 .gui_gtk3_fullscreen = FALSE,
230 .gui_gtk3_map_scrollbars = FALSE,
231 .gui_gtk3_dialogs_on_top = TRUE,
232 .gui_gtk3_show_task_icons = TRUE,
233 .gui_gtk3_enable_tabs = TRUE,
234 .gui_gtk3_show_chat_message_time = FALSE,
235 .gui_gtk3_new_messages_go_to_top = FALSE,
236 .gui_gtk3_show_message_window_buttons = TRUE,
237 .gui_gtk3_metaserver_tab_first = FALSE,
238 .gui_gtk3_allied_chat_only = FALSE,
239 .gui_gtk3_message_chat_location = GUI_GTK_MSGCHAT_MERGED,
240 .gui_gtk3_small_display_layout = TRUE,
241 .gui_gtk3_mouse_over_map_focus = FALSE,
242 .gui_gtk3_chatline_autocompletion = TRUE,
243 .gui_gtk3_citydlg_xsize = GUI_GTK3_CITYDLG_DEFAULT_XSIZE,
244 .gui_gtk3_citydlg_ysize = GUI_GTK3_CITYDLG_DEFAULT_YSIZE,
245 .gui_gtk3_popup_tech_help = GUI_POPUP_TECH_HELP_RULESET,
246 .gui_gtk3_governor_range_min = -20,
247 .gui_gtk3_governor_range_max = 20,
248 .gui_gtk3_font_city_label = "Monospace 8",
249 .gui_gtk3_font_notify_label = "Monospace Bold 9",
250 .gui_gtk3_font_spaceship_label = "Monospace 8",
251 .gui_gtk3_font_help_label = "Sans Bold 10",
252 .gui_gtk3_font_help_link = "Sans 9",
253 .gui_gtk3_font_help_text = "Monospace 8",
254 .gui_gtk3_font_chatline = "Monospace 8",
255 .gui_gtk3_font_beta_label = "Sans Italic 10",
256 .gui_gtk3_font_small = "Sans 9",
257 .gui_gtk3_font_comment_label = "Sans Italic 9",
258 .gui_gtk3_font_city_names = "Sans Bold 10",
259 .gui_gtk3_font_city_productions = "Serif 10",
260 .gui_gtk3_font_reqtree_text = "Serif 10",
262 /* gui-gtk-3.22 client specific options. */
263 .gui_gtk3_22_default_theme_name = FC_GTK3_DEFAULT_THEME_NAME,
264 .gui_gtk3_22_fullscreen = FALSE,
265 .gui_gtk3_22_map_scrollbars = FALSE,
266 .gui_gtk3_22_dialogs_on_top = TRUE,
267 .gui_gtk3_22_show_task_icons = TRUE,
268 .gui_gtk3_22_enable_tabs = TRUE,
269 .gui_gtk3_22_show_chat_message_time = FALSE,
270 .gui_gtk3_22_new_messages_go_to_top = FALSE,
271 .gui_gtk3_22_show_message_window_buttons = TRUE,
272 .gui_gtk3_22_metaserver_tab_first = FALSE,
273 .gui_gtk3_22_allied_chat_only = FALSE,
274 .gui_gtk3_22_message_chat_location = GUI_GTK_MSGCHAT_MERGED,
275 .gui_gtk3_22_small_display_layout = TRUE,
276 .gui_gtk3_22_mouse_over_map_focus = FALSE,
277 .gui_gtk3_22_chatline_autocompletion = TRUE,
278 .gui_gtk3_22_citydlg_xsize = GUI_GTK3_CITYDLG_DEFAULT_XSIZE,
279 .gui_gtk3_22_citydlg_ysize = GUI_GTK3_CITYDLG_DEFAULT_YSIZE,
280 .gui_gtk3_22_popup_tech_help = GUI_POPUP_TECH_HELP_RULESET,
281 .gui_gtk3_22_governor_range_min = -20,
282 .gui_gtk3_22_governor_range_max = 20,
283 .gui_gtk3_22_font_city_label = "Monospace 8",
284 .gui_gtk3_22_font_notify_label = "Monospace Bold 9",
285 .gui_gtk3_22_font_spaceship_label = "Monospace 8",
286 .gui_gtk3_22_font_help_label = "Sans Bold 10",
287 .gui_gtk3_22_font_help_link = "Sans 9",
288 .gui_gtk3_22_font_help_text = "Monospace 8",
289 .gui_gtk3_22_font_chatline = "Monospace 8",
290 .gui_gtk3_22_font_beta_label = "Sans Italic 10",
291 .gui_gtk3_22_font_small = "Sans 9",
292 .gui_gtk3_22_font_comment_label = "Sans Italic 9",
293 .gui_gtk3_22_font_city_names = "Sans Bold 10",
294 .gui_gtk3_22_font_city_productions = "Serif 10",
295 .gui_gtk3_22_font_reqtree_text = "Serif 10",
297 /* gui-sdl client specific options. */
298 .gui_sdl_default_theme_name = FC_SDL_DEFAULT_THEME_NAME,
299 .gui_sdl_fullscreen = FALSE,
300 .gui_sdl_screen = VIDEO_MODE(640, 480),
301 .gui_sdl_do_cursor_animation = TRUE,
302 .gui_sdl_use_color_cursors = TRUE,
304 /* gui-sdl2 client specific options. */
305 .gui_sdl2_default_theme_name = FC_SDL2_DEFAULT_THEME_NAME,
306 .gui_sdl2_fullscreen = FALSE,
307 .gui_sdl2_screen = VIDEO_MODE(640, 480),
308 .gui_sdl2_swrenderer = FALSE,
309 .gui_sdl2_do_cursor_animation = TRUE,
310 .gui_sdl2_use_color_cursors = TRUE,
312 /* gui-qt client specific options. */
313 .gui_qt_fullscreen = FALSE,
314 .gui_qt_show_preview = TRUE,
315 .gui_qt_sidebar_left = TRUE,
316 .gui_qt_default_theme_name = FC_QT_DEFAULT_THEME_NAME,
317 .gui_qt_font_city_label = "Monospace,8,-1,5,50,0,0,0,0,0",
318 .gui_qt_font_default = "Sans Serif,10,-1,5,75,0,0,0,0,0",
319 .gui_qt_font_notify_label = "Monospace,8,-1,5,75,0,0,0,0,0",
320 .gui_qt_font_spaceship_label = "Monospace,8,-1,5,50,0,0,0,0,0",
321 .gui_qt_font_help_label = "Sans Serif,9,-1,5,50,0,0,0,0,0",
322 .gui_qt_font_help_link = "Sans Serif,9,-1,5,50,0,0,0,0,0",
323 .gui_qt_font_help_text = "Monospace,8,-1,5,50,0,0,0,0,0",
324 .gui_qt_font_help_title = "Sans Serif,10,-1,5,75,0,0,0,0,0",
325 .gui_qt_font_chatline = "Monospace,8,-1,5,50,0,0,0,0,0",
326 .gui_qt_font_beta_label = "Sans Serif,10,-1,5,50,1,0,0,0,0",
327 .gui_qt_font_small = "Sans Serif,9,-1,5,50,0,0,0,0,0",
328 .gui_qt_font_comment_label = "Sans Serif,9,-1,5,50,1,0,0,0,0",
329 .gui_qt_font_city_names = "Sans Serif,10,-1,5,75,0,0,0,0,0",
330 .gui_qt_font_city_productions = "Sans Serif,10,-1,5,50,1,0,0,0,0",
331 .gui_qt_font_reqtree_text = "Sans Serif,10,-1,5,50,1,0,0,0,0",
332 .gui_qt_show_titlebar = TRUE,
333 .gui_qt_wakeup_text = "Wake up %1"
336 /* Set to TRUE after the first call to options_init(), to avoid the usage
337 * of non-initialized datas when calling the changed callback. */
338 static bool options_fully_initialized = FALSE;
340 static const struct strvec *get_mapimg_format_list(const struct option *poption);
342 /****************************************************************************
343 Option set structure.
344 ****************************************************************************/
345 struct option_set {
346 struct option * (*option_by_number) (int);
347 struct option * (*option_first) (void);
349 int (*category_number) (void);
350 const char * (*category_name) (int);
353 /****************************************************************************
354 Returns the option corresponding of the number in this option set.
355 ****************************************************************************/
356 struct option *optset_option_by_number(const struct option_set *poptset,
357 int id)
359 fc_assert_ret_val(NULL != poptset, NULL);
361 return poptset->option_by_number(id);
364 /****************************************************************************
365 Returns the option corresponding of the name in this option set.
366 ****************************************************************************/
367 struct option *optset_option_by_name(const struct option_set *poptset,
368 const char *name)
370 fc_assert_ret_val(NULL != poptset, NULL);
372 options_iterate(poptset, poption) {
373 if (0 == strcmp(option_name(poption), name)) {
374 return poption;
376 } options_iterate_end;
377 return NULL;
380 /****************************************************************************
381 Returns the first option of this option set.
382 ****************************************************************************/
383 struct option *optset_option_first(const struct option_set *poptset)
385 fc_assert_ret_val(NULL != poptset, NULL);
387 return poptset->option_first();
390 /****************************************************************************
391 Returns the number of categories of this option set.
392 ****************************************************************************/
393 int optset_category_number(const struct option_set *poptset)
395 fc_assert_ret_val(NULL != poptset, 0);
397 return poptset->category_number();
400 /****************************************************************************
401 Returns the name (translated) of the category of this option set.
402 ****************************************************************************/
403 const char *optset_category_name(const struct option_set *poptset,
404 int category)
406 fc_assert_ret_val(NULL != poptset, NULL);
408 return poptset->category_name(category);
412 /****************************************************************************
413 The base class for options.
414 ****************************************************************************/
415 struct option {
416 /* A link to the option set. */
417 const struct option_set *poptset;
418 /* Type of the option. */
419 enum option_type type;
421 /* Common accessors. */
422 const struct option_common_vtable {
423 int (*number) (const struct option *);
424 const char * (*name) (const struct option *);
425 const char * (*description) (const struct option *);
426 const char * (*help_text) (const struct option *);
427 int (*category) (const struct option *);
428 bool (*is_changeable) (const struct option *);
429 struct option * (*next) (const struct option *);
430 } *common_vtable;
431 /* Specific typed accessors. */
432 union {
433 /* Specific boolean accessors (OT_BOOLEAN == type). */
434 const struct option_bool_vtable {
435 bool (*get) (const struct option *);
436 bool (*def) (const struct option *);
437 bool (*set) (struct option *, bool);
438 } *bool_vtable;
439 /* Specific integer accessors (OT_INTEGER == type). */
440 const struct option_int_vtable {
441 int (*get) (const struct option *);
442 int (*def) (const struct option *);
443 int (*minimum) (const struct option *);
444 int (*maximum) (const struct option *);
445 bool (*set) (struct option *, int);
446 } *int_vtable;
447 /* Specific string accessors (OT_STRING == type). */
448 const struct option_str_vtable {
449 const char * (*get) (const struct option *);
450 const char * (*def) (const struct option *);
451 const struct strvec * (*values) (const struct option *);
452 bool (*set) (struct option *, const char *);
453 } *str_vtable;
454 /* Specific enum accessors (OT_ENUM == type). */
455 const struct option_enum_vtable {
456 int (*get) (const struct option *);
457 int (*def) (const struct option *);
458 const struct strvec * (*values) (const struct option *);
459 bool (*set) (struct option *, int);
460 int (*cmp) (const char *, const char *);
461 } *enum_vtable;
462 /* Specific bitwise accessors (OT_BITWISE == type). */
463 const struct option_bitwise_vtable {
464 unsigned (*get) (const struct option *);
465 unsigned (*def) (const struct option *);
466 const struct strvec * (*values) (const struct option *);
467 bool (*set) (struct option *, unsigned);
468 } *bitwise_vtable;
469 /* Specific font accessors (OT_FONT == type). */
470 const struct option_font_vtable {
471 const char * (*get) (const struct option *);
472 const char * (*def) (const struct option *);
473 const char * (*target) (const struct option *);
474 bool (*set) (struct option *, const char *);
475 } *font_vtable;
476 /* Specific color accessors (OT_COLOR == type). */
477 const struct option_color_vtable {
478 struct ft_color (*get) (const struct option *);
479 struct ft_color (*def) (const struct option *);
480 bool (*set) (struct option *, struct ft_color);
481 } *color_vtable;
482 /* Specific video mode accessors (OT_VIDEO_MODE == type). */
483 const struct option_video_mode_vtable {
484 struct video_mode (*get) (const struct option *);
485 struct video_mode (*def) (const struct option *);
486 bool (*set) (struct option *, struct video_mode);
487 } *video_mode_vtable;
490 /* Called after the value changed. */
491 void (*changed_callback) (struct option *option);
493 int callback_data;
495 /* Volatile. */
496 void *gui_data;
499 #define OPTION(poption) ((struct option *) (poption))
501 #define OPTION_INIT(optset, spec_type, spec_table_var, common_table, \
502 spec_table, changed_cb, cb_data) { \
503 .poptset = optset, \
504 .type = spec_type, \
505 .common_vtable = &common_table, \
506 INIT_BRACE_BEGIN \
507 .spec_table_var = &spec_table \
508 INIT_BRACE_END, \
509 .changed_callback = changed_cb, \
510 .callback_data = cb_data, \
511 .gui_data = NULL \
513 #define OPTION_BOOL_INIT(optset, common_table, bool_table, changed_cb) \
514 OPTION_INIT(optset, OT_BOOLEAN, bool_vtable, common_table, bool_table, \
515 changed_cb, 0)
516 #define OPTION_INT_INIT(optset, common_table, int_table, changed_cb) \
517 OPTION_INIT(optset, OT_INTEGER, int_vtable, common_table, int_table, \
518 changed_cb, 0)
519 #define OPTION_STR_INIT(optset, common_table, str_table, changed_cb, cb_data) \
520 OPTION_INIT(optset, OT_STRING, str_vtable, common_table, str_table, \
521 changed_cb, cb_data)
522 #define OPTION_ENUM_INIT(optset, common_table, enum_table, changed_cb) \
523 OPTION_INIT(optset, OT_ENUM, enum_vtable, common_table, enum_table, \
524 changed_cb, 0)
525 #define OPTION_BITWISE_INIT(optset, common_table, bitwise_table, \
526 changed_cb) \
527 OPTION_INIT(optset, OT_BITWISE, bitwise_vtable, common_table, \
528 bitwise_table, changed_cb, 0)
529 #define OPTION_FONT_INIT(optset, common_table, font_table, changed_cb) \
530 OPTION_INIT(optset, OT_FONT, font_vtable, common_table, font_table, \
531 changed_cb, 0)
532 #define OPTION_COLOR_INIT(optset, common_table, color_table, changed_cb) \
533 OPTION_INIT(optset, OT_COLOR, color_vtable, common_table, color_table, \
534 changed_cb, 0)
535 #define OPTION_VIDEO_MODE_INIT(optset, common_table, video_mode_table, \
536 changed_cb) \
537 OPTION_INIT(optset, OT_VIDEO_MODE, video_mode_vtable, common_table, \
538 video_mode_table, changed_cb, 0)
541 /****************************************************************************
542 Returns the option set owner of this option.
543 ****************************************************************************/
544 const struct option_set *option_optset(const struct option *poption)
546 fc_assert_ret_val(NULL != poption, NULL);
548 return poption->poptset;
551 /****************************************************************************
552 Returns the number of the option.
553 ****************************************************************************/
554 int option_number(const struct option *poption)
556 fc_assert_ret_val(NULL != poption, -1);
558 return poption->common_vtable->number(poption);
561 /****************************************************************************
562 Returns the name of the option.
563 ****************************************************************************/
564 const char *option_name(const struct option *poption)
566 fc_assert_ret_val(NULL != poption, NULL);
568 return poption->common_vtable->name(poption);
571 /****************************************************************************
572 Returns the description (translated) of the option.
573 ****************************************************************************/
574 const char *option_description(const struct option *poption)
576 fc_assert_ret_val(NULL != poption, NULL);
578 return poption->common_vtable->description(poption);
581 /****************************************************************************
582 Returns the help text (translated) of the option.
583 ****************************************************************************/
584 const char *option_help_text(const struct option *poption)
586 fc_assert_ret_val(NULL != poption, NULL);
588 return poption->common_vtable->help_text(poption);
591 /****************************************************************************
592 Returns the type of the option.
593 ****************************************************************************/
594 enum option_type option_type(const struct option *poption)
596 fc_assert_ret_val(NULL != poption, -1);
598 return poption->type;
601 /****************************************************************************
602 Returns the category of the option.
603 ****************************************************************************/
604 int option_category(const struct option *poption)
606 fc_assert_ret_val(NULL != poption, -1);
608 return poption->common_vtable->category(poption);
611 /****************************************************************************
612 Returns the name (tranlated) of the category of the option.
613 ****************************************************************************/
614 const char *option_category_name(const struct option *poption)
616 fc_assert_ret_val(NULL != poption, NULL);
618 return optset_category_name(poption->poptset,
619 poption->common_vtable->category(poption));
622 /****************************************************************************
623 Returns TRUE if this option can be modified.
624 ****************************************************************************/
625 bool option_is_changeable(const struct option *poption)
627 fc_assert_ret_val(NULL != poption, FALSE);
629 return poption->common_vtable->is_changeable(poption);
632 /****************************************************************************
633 Returns the next option or NULL if this is the last.
634 ****************************************************************************/
635 struct option *option_next(const struct option *poption)
637 fc_assert_ret_val(NULL != poption, NULL);
639 return poption->common_vtable->next(poption);
642 /****************************************************************************
643 Set the option to its default value. Returns TRUE if the option changed.
644 ****************************************************************************/
645 bool option_reset(struct option *poption)
647 fc_assert_ret_val(NULL != poption, FALSE);
649 switch (option_type(poption)) {
650 case OT_BOOLEAN:
651 return option_bool_set(poption, option_bool_def(poption));
652 case OT_INTEGER:
653 return option_int_set(poption, option_int_def(poption));
654 case OT_STRING:
655 return option_str_set(poption, option_str_def(poption));
656 case OT_ENUM:
657 return option_enum_set_int(poption, option_enum_def_int(poption));
658 case OT_BITWISE:
659 return option_bitwise_set(poption, option_bitwise_def(poption));
660 case OT_FONT:
661 return option_font_set(poption, option_font_def(poption));
662 case OT_COLOR:
663 return option_color_set(poption, option_color_def(poption));
664 case OT_VIDEO_MODE:
665 return option_video_mode_set(poption, option_video_mode_def(poption));
667 return FALSE;
670 /****************************************************************************
671 Set the function to call every time this option changes. Can be NULL.
672 ****************************************************************************/
673 void option_set_changed_callback(struct option *poption,
674 void (*callback) (struct option *))
676 fc_assert_ret(NULL != poption);
678 poption->changed_callback = callback;
681 /****************************************************************************
682 Force to use the option changed callback.
683 ****************************************************************************/
684 void option_changed(struct option *poption)
686 fc_assert_ret(NULL != poption);
688 if (!options_fully_initialized) {
689 /* Prevent to use non-initialized datas. */
690 return;
693 if (poption->changed_callback) {
694 poption->changed_callback(poption);
697 option_gui_update(poption);
700 /****************************************************************************
701 Set the gui data for this option.
702 ****************************************************************************/
703 void option_set_gui_data(struct option *poption, void *data)
705 fc_assert_ret(NULL != poption);
707 poption->gui_data = data;
710 /****************************************************************************
711 Returns the gui data of this option.
712 ****************************************************************************/
713 void *option_get_gui_data(const struct option *poption)
715 fc_assert_ret_val(NULL != poption, NULL);
717 return poption->gui_data;
720 /****************************************************************************
721 Returns the callback data of this option.
722 ****************************************************************************/
723 int option_get_cb_data(const struct option *poption)
725 fc_assert_ret_val(NULL != poption, 0);
727 return poption->callback_data;
730 /****************************************************************************
731 Returns the current value of this boolean option.
732 ****************************************************************************/
733 bool option_bool_get(const struct option *poption)
735 fc_assert_ret_val(NULL != poption, FALSE);
736 fc_assert_ret_val(OT_BOOLEAN == poption->type, FALSE);
738 return poption->bool_vtable->get(poption);
741 /****************************************************************************
742 Returns the default value of this boolean option.
743 ****************************************************************************/
744 bool option_bool_def(const struct option *poption)
746 fc_assert_ret_val(NULL != poption, FALSE);
747 fc_assert_ret_val(OT_BOOLEAN == poption->type, FALSE);
749 return poption->bool_vtable->def(poption);
752 /****************************************************************************
753 Sets the value of this boolean option. Returns TRUE if the value changed.
754 ****************************************************************************/
755 bool option_bool_set(struct option *poption, bool val)
757 fc_assert_ret_val(NULL != poption, FALSE);
758 fc_assert_ret_val(OT_BOOLEAN == poption->type, FALSE);
760 if (poption->bool_vtable->set(poption, val)) {
761 option_changed(poption);
762 return TRUE;
764 return FALSE;
767 /****************************************************************************
768 Returns the current value of this integer option.
769 ****************************************************************************/
770 int option_int_get(const struct option *poption)
772 fc_assert_ret_val(NULL != poption, 0);
773 fc_assert_ret_val(OT_INTEGER == poption->type, 0);
775 return poption->int_vtable->get(poption);
778 /****************************************************************************
779 Returns the default value of this integer option.
780 ****************************************************************************/
781 int option_int_def(const struct option *poption)
783 fc_assert_ret_val(NULL != poption, 0);
784 fc_assert_ret_val(OT_INTEGER == poption->type, 0);
786 return poption->int_vtable->def(poption);
789 /****************************************************************************
790 Returns the minimal value of this integer option.
791 ****************************************************************************/
792 int option_int_min(const struct option *poption)
794 fc_assert_ret_val(NULL != poption, 0);
795 fc_assert_ret_val(OT_INTEGER == poption->type, 0);
797 return poption->int_vtable->minimum(poption);
800 /****************************************************************************
801 Returns the maximal value of this integer option.
802 ****************************************************************************/
803 int option_int_max(const struct option *poption)
805 fc_assert_ret_val(NULL != poption, 0);
806 fc_assert_ret_val(OT_INTEGER == poption->type, 0);
808 return poption->int_vtable->maximum(poption);
811 /****************************************************************************
812 Sets the value of this integer option. Returns TRUE if the value changed.
813 ****************************************************************************/
814 bool option_int_set(struct option *poption, int val)
816 fc_assert_ret_val(NULL != poption, FALSE);
817 fc_assert_ret_val(OT_INTEGER == poption->type, FALSE);
819 if (poption->int_vtable->set(poption, val)) {
820 option_changed(poption);
821 return TRUE;
823 return FALSE;
826 /****************************************************************************
827 Returns the current value of this string option.
828 ****************************************************************************/
829 const char *option_str_get(const struct option *poption)
831 fc_assert_ret_val(NULL != poption, NULL);
832 fc_assert_ret_val(OT_STRING == poption->type, NULL);
834 return poption->str_vtable->get(poption);
837 /****************************************************************************
838 Returns the default value of this string option.
839 ****************************************************************************/
840 const char *option_str_def(const struct option *poption)
842 fc_assert_ret_val(NULL != poption, NULL);
843 fc_assert_ret_val(OT_STRING == poption->type, NULL);
845 return poption->str_vtable->def(poption);
848 /****************************************************************************
849 Returns the possible string values of this string option.
850 ****************************************************************************/
851 const struct strvec *option_str_values(const struct option *poption)
853 fc_assert_ret_val(NULL != poption, NULL);
854 fc_assert_ret_val(OT_STRING == poption->type, NULL);
856 return poption->str_vtable->values(poption);
859 /****************************************************************************
860 Sets the value of this string option. Returns TRUE if the value changed.
861 ****************************************************************************/
862 bool option_str_set(struct option *poption, const char *str)
864 fc_assert_ret_val(NULL != poption, FALSE);
865 fc_assert_ret_val(OT_STRING == poption->type, FALSE);
866 fc_assert_ret_val(NULL != str, FALSE);
868 if (poption->str_vtable->set(poption, str)) {
869 option_changed(poption);
870 return TRUE;
872 return FALSE;
875 /****************************************************************************
876 Returns the value corresponding to the user-visible (translatable but not
877 translated) string. Returns -1 if not matched.
878 ****************************************************************************/
879 int option_enum_str_to_int(const struct option *poption, const char *str)
881 const struct strvec *values;
882 int val;
884 fc_assert_ret_val(NULL != poption, -1);
885 fc_assert_ret_val(OT_ENUM == poption->type, -1);
886 values = poption->enum_vtable->values(poption);
887 fc_assert_ret_val(NULL != values, -1);
889 for (val = 0; val < strvec_size(values); val++) {
890 if (0 == poption->enum_vtable->cmp(strvec_get(values, val), str)) {
891 return val;
894 return -1;
897 /****************************************************************************
898 Returns the user-visible (translatable but not translated) string
899 corresponding to the value. Returns NULL on error.
900 ****************************************************************************/
901 const char *option_enum_int_to_str(const struct option *poption, int val)
903 const struct strvec *values;
905 fc_assert_ret_val(NULL != poption, NULL);
906 fc_assert_ret_val(OT_ENUM == poption->type, NULL);
907 values = poption->enum_vtable->values(poption);
908 fc_assert_ret_val(NULL != values, NULL);
910 return strvec_get(values, val);
913 /****************************************************************************
914 Returns the current value of this enum option (as an integer).
915 ****************************************************************************/
916 int option_enum_get_int(const struct option *poption)
918 fc_assert_ret_val(NULL != poption, -1);
919 fc_assert_ret_val(OT_ENUM == poption->type, -1);
921 return poption->enum_vtable->get(poption);
924 /****************************************************************************
925 Returns the current value of this enum option as a user-visible
926 (translatable but not translated) string.
927 ****************************************************************************/
928 const char *option_enum_get_str(const struct option *poption)
930 fc_assert_ret_val(NULL != poption, NULL);
931 fc_assert_ret_val(OT_ENUM == poption->type, NULL);
933 return strvec_get(poption->enum_vtable->values(poption),
934 poption->enum_vtable->get(poption));
937 /****************************************************************************
938 Returns the default value of this enum option (as an integer).
939 ****************************************************************************/
940 int option_enum_def_int(const struct option *poption)
942 fc_assert_ret_val(NULL != poption, -1);
943 fc_assert_ret_val(OT_ENUM == poption->type, -1);
945 return poption->enum_vtable->def(poption);
948 /****************************************************************************
949 Returns the default value of this enum option as a user-visible
950 (translatable but not translated) string.
951 ****************************************************************************/
952 const char *option_enum_def_str(const struct option *poption)
954 fc_assert_ret_val(NULL != poption, NULL);
955 fc_assert_ret_val(OT_ENUM == poption->type, NULL);
957 return strvec_get(poption->enum_vtable->values(poption),
958 poption->enum_vtable->def(poption));
961 /****************************************************************************
962 Returns the possible string values of this enum option, as user-visible
963 (translatable but not translated) strings.
964 ****************************************************************************/
965 const struct strvec *option_enum_values(const struct option *poption)
967 fc_assert_ret_val(NULL != poption, NULL);
968 fc_assert_ret_val(OT_ENUM == poption->type, NULL);
970 return poption->enum_vtable->values(poption);
973 /****************************************************************************
974 Sets the value of this enum option. Returns TRUE if the value changed.
975 ****************************************************************************/
976 bool option_enum_set_int(struct option *poption, int val)
978 fc_assert_ret_val(NULL != poption, FALSE);
979 fc_assert_ret_val(OT_ENUM == poption->type, FALSE);
981 if (poption->enum_vtable->set(poption, val)) {
982 option_changed(poption);
983 return TRUE;
985 return FALSE;
988 /****************************************************************************
989 Sets the value of this enum option from a string, which is matched as a
990 user-visible (translatable but not translated) string. Returns TRUE if the
991 value changed.
992 ****************************************************************************/
993 bool option_enum_set_str(struct option *poption, const char *str)
995 fc_assert_ret_val(NULL != poption, FALSE);
996 fc_assert_ret_val(OT_ENUM == poption->type, FALSE);
997 fc_assert_ret_val(NULL != str, FALSE);
999 if (poption->enum_vtable->set(poption,
1000 option_enum_str_to_int(poption, str))) {
1001 option_changed(poption);
1002 return TRUE;
1004 return FALSE;
1007 /****************************************************************************
1008 Returns the current value of this bitwise option.
1009 ****************************************************************************/
1010 unsigned option_bitwise_get(const struct option *poption)
1012 fc_assert_ret_val(NULL != poption, 0);
1013 fc_assert_ret_val(OT_BITWISE == poption->type, 0);
1015 return poption->bitwise_vtable->get(poption);
1018 /****************************************************************************
1019 Returns the default value of this bitwise option.
1020 ****************************************************************************/
1021 unsigned option_bitwise_def(const struct option *poption)
1023 fc_assert_ret_val(NULL != poption, 0);
1024 fc_assert_ret_val(OT_BITWISE == poption->type, 0);
1026 return poption->bitwise_vtable->def(poption);
1029 /****************************************************************************
1030 Returns the mask of this bitwise option.
1031 ****************************************************************************/
1032 unsigned option_bitwise_mask(const struct option *poption)
1034 const struct strvec *values;
1036 fc_assert_ret_val(NULL != poption, 0);
1037 fc_assert_ret_val(OT_BITWISE == poption->type, 0);
1039 values = poption->bitwise_vtable->values(poption);
1040 fc_assert_ret_val(NULL != values, 0);
1042 return (1 << strvec_size(values)) - 1;
1045 /****************************************************************************
1046 Returns a vector of strings describing every bit of this option, as
1047 user-visible (translatable but not translated) strings.
1048 ****************************************************************************/
1049 const struct strvec *option_bitwise_values(const struct option *poption)
1051 fc_assert_ret_val(NULL != poption, NULL);
1052 fc_assert_ret_val(OT_BITWISE == poption->type, NULL);
1054 return poption->bitwise_vtable->values(poption);
1057 /****************************************************************************
1058 Sets the value of this bitwise option. Returns TRUE if the value changed.
1059 ****************************************************************************/
1060 bool option_bitwise_set(struct option *poption, unsigned val)
1062 fc_assert_ret_val(NULL != poption, FALSE);
1063 fc_assert_ret_val(OT_BITWISE == poption->type, FALSE);
1065 if (0 != (val & ~option_bitwise_mask(poption))
1066 || !poption->bitwise_vtable->set(poption, val)) {
1067 return FALSE;
1070 option_changed(poption);
1071 return TRUE;
1074 /****************************************************************************
1075 Returns the current value of this font option.
1076 ****************************************************************************/
1077 const char *option_font_get(const struct option *poption)
1079 fc_assert_ret_val(NULL != poption, NULL);
1080 fc_assert_ret_val(OT_FONT == poption->type, NULL);
1082 return poption->font_vtable->get(poption);
1085 /****************************************************************************
1086 Returns the default value of this font option.
1087 ****************************************************************************/
1088 const char *option_font_def(const struct option *poption)
1090 fc_assert_ret_val(NULL != poption, NULL);
1091 fc_assert_ret_val(OT_FONT == poption->type, NULL);
1093 return poption->font_vtable->def(poption);
1096 /****************************************************************************
1097 Returns the target style name of this font option.
1098 ****************************************************************************/
1099 const char *option_font_target(const struct option *poption)
1101 fc_assert_ret_val(NULL != poption, NULL);
1102 fc_assert_ret_val(OT_FONT == poption->type, NULL);
1104 return poption->font_vtable->target(poption);
1107 /****************************************************************************
1108 Sets the value of this font option. Returns TRUE if the value changed.
1109 ****************************************************************************/
1110 bool option_font_set(struct option *poption, const char *font)
1112 fc_assert_ret_val(NULL != poption, FALSE);
1113 fc_assert_ret_val(OT_FONT == poption->type, FALSE);
1114 fc_assert_ret_val(NULL != font, FALSE);
1116 if (poption->font_vtable->set(poption, font)) {
1117 option_changed(poption);
1118 return TRUE;
1120 return FALSE;
1123 /****************************************************************************
1124 Returns the current value of this color option.
1125 ****************************************************************************/
1126 struct ft_color option_color_get(const struct option *poption)
1128 fc_assert_ret_val(NULL != poption, ft_color_construct(NULL, NULL));
1129 fc_assert_ret_val(OT_COLOR == poption->type, ft_color_construct(NULL, NULL));
1131 return poption->color_vtable->get(poption);
1134 /****************************************************************************
1135 Returns the default value of this color option.
1136 ****************************************************************************/
1137 struct ft_color option_color_def(const struct option *poption)
1139 fc_assert_ret_val(NULL != poption, ft_color_construct(NULL, NULL));
1140 fc_assert_ret_val(OT_COLOR == poption->type, ft_color_construct(NULL, NULL));
1142 return poption->color_vtable->def(poption);
1145 /****************************************************************************
1146 Sets the value of this color option. Returns TRUE if the value
1147 changed.
1148 ****************************************************************************/
1149 bool option_color_set(struct option *poption, struct ft_color color)
1151 fc_assert_ret_val(NULL != poption, FALSE);
1152 fc_assert_ret_val(OT_COLOR == poption->type, FALSE);
1154 if (poption->color_vtable->set(poption, color)) {
1155 option_changed(poption);
1156 return TRUE;
1158 return FALSE;
1161 /****************************************************************************
1162 Returns the current value of this video mode option.
1163 ****************************************************************************/
1164 struct video_mode option_video_mode_get(const struct option *poption)
1166 fc_assert_ret_val(NULL != poption, video_mode_construct(-1, -1));
1167 fc_assert_ret_val(OT_VIDEO_MODE == poption->type,
1168 video_mode_construct(-1, -1));
1170 return poption->video_mode_vtable->get(poption);
1173 /****************************************************************************
1174 Returns the default value of this video mode option.
1175 ****************************************************************************/
1176 struct video_mode option_video_mode_def(const struct option *poption)
1178 fc_assert_ret_val(NULL != poption, video_mode_construct(-1, -1));
1179 fc_assert_ret_val(OT_VIDEO_MODE == poption->type,
1180 video_mode_construct(-1, -1));
1182 return poption->video_mode_vtable->def(poption);
1185 /****************************************************************************
1186 Sets the value of this video mode option. Returns TRUE if the value
1187 changed.
1188 ****************************************************************************/
1189 bool option_video_mode_set(struct option *poption, struct video_mode mode)
1191 fc_assert_ret_val(NULL != poption, FALSE);
1192 fc_assert_ret_val(OT_VIDEO_MODE == poption->type, FALSE);
1194 if (poption->video_mode_vtable->set(poption, mode)) {
1195 option_changed(poption);
1196 return TRUE;
1198 return FALSE;
1202 /****************************************************************************
1203 Client option set.
1204 ****************************************************************************/
1205 static struct option *client_optset_option_by_number(int id);
1206 static struct option *client_optset_option_first(void);
1207 static int client_optset_category_number(void);
1208 static const char *client_optset_category_name(int category);
1210 static struct option_set client_optset_static = {
1211 .option_by_number = client_optset_option_by_number,
1212 .option_first = client_optset_option_first,
1213 .category_number = client_optset_category_number,
1214 .category_name = client_optset_category_name
1216 const struct option_set *client_optset = &client_optset_static;
1218 struct copt_val_name {
1219 const char *support; /* Untranslated long support name, used
1220 * for saving. */
1221 const char *pretty; /* Translated, used to display to the
1222 * users. */
1225 /****************************************************************************
1226 Virtuals tables for the client options.
1227 ****************************************************************************/
1228 static int client_option_number(const struct option *poption);
1229 static const char *client_option_name(const struct option *poption);
1230 static const char *client_option_description(const struct option *poption);
1231 static const char *client_option_help_text(const struct option *poption);
1232 static int client_option_category(const struct option *poption);
1233 static bool client_option_is_changeable(const struct option *poption);
1234 static struct option *client_option_next(const struct option *poption);
1235 static void client_option_adjust_defaults(void);
1237 static const struct option_common_vtable client_option_common_vtable = {
1238 .number = client_option_number,
1239 .name = client_option_name,
1240 .description = client_option_description,
1241 .help_text = client_option_help_text,
1242 .category = client_option_category,
1243 .is_changeable = client_option_is_changeable,
1244 .next = client_option_next
1247 static bool client_option_bool_get(const struct option *poption);
1248 static bool client_option_bool_def(const struct option *poption);
1249 static bool client_option_bool_set(struct option *poption, bool val);
1251 static const struct option_bool_vtable client_option_bool_vtable = {
1252 .get = client_option_bool_get,
1253 .def = client_option_bool_def,
1254 .set = client_option_bool_set
1257 static int client_option_int_get(const struct option *poption);
1258 static int client_option_int_def(const struct option *poption);
1259 static int client_option_int_min(const struct option *poption);
1260 static int client_option_int_max(const struct option *poption);
1261 static bool client_option_int_set(struct option *poption, int val);
1263 static const struct option_int_vtable client_option_int_vtable = {
1264 .get = client_option_int_get,
1265 .def = client_option_int_def,
1266 .minimum = client_option_int_min,
1267 .maximum = client_option_int_max,
1268 .set = client_option_int_set
1271 static const char *client_option_str_get(const struct option *poption);
1272 static const char *client_option_str_def(const struct option *poption);
1273 static const struct strvec *
1274 client_option_str_values(const struct option *poption);
1275 static bool client_option_str_set(struct option *poption, const char *str);
1277 static const struct option_str_vtable client_option_str_vtable = {
1278 .get = client_option_str_get,
1279 .def = client_option_str_def,
1280 .values = client_option_str_values,
1281 .set = client_option_str_set
1284 static int client_option_enum_get(const struct option *poption);
1285 static int client_option_enum_def(const struct option *poption);
1286 static const struct strvec *
1287 client_option_enum_pretty_names(const struct option *poption);
1288 static bool client_option_enum_set(struct option *poption, int val);
1290 static const struct option_enum_vtable client_option_enum_vtable = {
1291 .get = client_option_enum_get,
1292 .def = client_option_enum_def,
1293 .values = client_option_enum_pretty_names,
1294 .set = client_option_enum_set,
1295 .cmp = fc_strcasecmp
1298 #if 0 /* There's no bitwise options currently */
1299 static unsigned client_option_bitwise_get(const struct option *poption);
1300 static unsigned client_option_bitwise_def(const struct option *poption);
1301 static const struct strvec *
1302 client_option_bitwise_pretty_names(const struct option *poption);
1303 static bool client_option_bitwise_set(struct option *poption, unsigned val);
1305 static const struct option_bitwise_vtable client_option_bitwise_vtable = {
1306 .get = client_option_bitwise_get,
1307 .def = client_option_bitwise_def,
1308 .values = client_option_bitwise_pretty_names,
1309 .set = client_option_bitwise_set
1311 #endif /* 0 */
1313 static const char *client_option_font_get(const struct option *poption);
1314 static const char *client_option_font_def(const struct option *poption);
1315 static const char *client_option_font_target(const struct option *poption);
1316 static bool client_option_font_set(struct option *poption, const char *font);
1318 static const struct option_font_vtable client_option_font_vtable = {
1319 .get = client_option_font_get,
1320 .def = client_option_font_def,
1321 .target = client_option_font_target,
1322 .set = client_option_font_set
1325 static struct ft_color client_option_color_get(const struct option *poption);
1326 static struct ft_color client_option_color_def(const struct option *poption);
1327 static bool client_option_color_set(struct option *poption,
1328 struct ft_color color);
1330 static const struct option_color_vtable client_option_color_vtable = {
1331 .get = client_option_color_get,
1332 .def = client_option_color_def,
1333 .set = client_option_color_set
1336 static struct video_mode
1337 client_option_video_mode_get(const struct option *poption);
1338 static struct video_mode
1339 client_option_video_mode_def(const struct option *poption);
1340 static bool client_option_video_mode_set(struct option *poption,
1341 struct video_mode mode);
1343 static const struct option_video_mode_vtable client_option_video_mode_vtable = {
1344 .get = client_option_video_mode_get,
1345 .def = client_option_video_mode_def,
1346 .set = client_option_video_mode_set
1349 enum client_option_category {
1350 COC_GRAPHICS,
1351 COC_OVERVIEW,
1352 COC_SOUND,
1353 COC_INTERFACE,
1354 COC_MAPIMG,
1355 COC_NETWORK,
1356 COC_FONT,
1357 COC_MAX
1360 /****************************************************************************
1361 Derived class client option, inherinting of base class option.
1362 ****************************************************************************/
1363 struct client_option {
1364 struct option base_option; /* Base structure, must be the first! */
1366 const char *name; /* Short name - used as an identifier */
1367 const char *description; /* One-line description */
1368 const char *help_text; /* Paragraph-length help text */
1369 enum client_option_category category;
1370 enum gui_type specific; /* GUI_STUB for common options. */
1372 union {
1373 /* OT_BOOLEAN type option. */
1374 struct {
1375 bool *const pvalue;
1376 const bool def;
1377 } boolean;
1378 /* OT_INTEGER type option. */
1379 struct {
1380 int *const pvalue;
1381 const int def, min, max;
1382 } integer;
1383 /* OT_STRING type option. */
1384 struct {
1385 char *const pvalue;
1386 const size_t size;
1387 const char *const def;
1389 * A function to return a string vector of possible string values,
1390 * or NULL for none.
1392 const struct strvec *(*const val_accessor) (const struct option *);
1393 } string;
1394 /* OT_ENUM type option. */
1395 struct {
1396 int *const pvalue;
1397 const int def;
1398 struct strvec *support_names, *pretty_names; /* untranslated */
1399 const struct copt_val_name * (*const name_accessor) (int value);
1400 } enumerator;
1401 /* OT_BITWISE type option. */
1402 struct {
1403 unsigned *const pvalue;
1404 const unsigned def;
1405 struct strvec *support_names, *pretty_names; /* untranslated */
1406 const struct copt_val_name * (*const name_accessor) (int value);
1407 } bitwise;
1408 /* OT_FONT type option. */
1409 struct {
1410 char *const pvalue;
1411 const size_t size;
1412 const char *const def;
1413 const char *const target;
1414 } font;
1415 /* OT_COLOR type option. */
1416 struct {
1417 struct ft_color *const pvalue;
1418 const struct ft_color def;
1419 } color;
1420 /* OT_VIDEO_MODE type option. */
1421 struct {
1422 struct video_mode *const pvalue;
1423 const struct video_mode def;
1424 } video_mode;
1428 #define CLIENT_OPTION(poption) ((struct client_option *) (poption))
1431 * Generate a client option of type OT_BOOLEAN.
1433 * oname: The option data. Note it is used as name to be loaded or saved.
1434 * So, you shouldn't change the name of this variable in any case.
1435 * odesc: A short description of the client option. Should be used with the
1436 * N_() macro.
1437 * ohelp: The help text for the client option. Should be used with the N_()
1438 * macro.
1439 * ocat: The client_option_class of this client option.
1440 * ospec: A gui_type enumerator which determin for what particular client
1441 * gui this option is for. Sets to GUI_STUB for common options.
1442 * odef: The default value of this client option (FALSE or TRUE).
1443 * ocb: A callback function of type void (*)(struct option *) called when
1444 * the option changed.
1446 #define GEN_BOOL_OPTION(oname, odesc, ohelp, ocat, ospec, odef, ocb) \
1448 .base_option = OPTION_BOOL_INIT(&client_optset_static, \
1449 client_option_common_vtable, \
1450 client_option_bool_vtable, ocb), \
1451 .name = #oname, \
1452 .description = odesc, \
1453 .help_text = ohelp, \
1454 .category = ocat, \
1455 .specific = ospec, \
1456 INIT_BRACE_BEGIN \
1457 .boolean = { \
1458 .pvalue = &gui_options.oname, \
1459 .def = odef, \
1461 INIT_BRACE_END \
1465 * Generate a client option of type OT_INTEGER.
1467 * oname: The option data. Note it is used as name to be loaded or saved.
1468 * So, you shouldn't change the name of this variable in any case.
1469 * odesc: A short description of the client option. Should be used with the
1470 * N_() macro.
1471 * ohelp: The help text for the client option. Should be used with the N_()
1472 * macro.
1473 * ocat: The client_option_class of this client option.
1474 * ospec: A gui_type enumerator which determin for what particular client
1475 * gui this option is for. Sets to GUI_STUB for common options.
1476 * odef: The default value of this client option.
1477 * omin: The minimal value of this client option.
1478 * omax: The maximal value of this client option.
1479 * ocb: A callback function of type void (*)(struct option *) called when
1480 * the option changed.
1482 #define GEN_INT_OPTION(oname, odesc, ohelp, ocat, ospec, odef, omin, omax, ocb) \
1484 .base_option = OPTION_INT_INIT(&client_optset_static, \
1485 client_option_common_vtable, \
1486 client_option_int_vtable, ocb), \
1487 .name = #oname, \
1488 .description = odesc, \
1489 .help_text = ohelp, \
1490 .category = ocat, \
1491 .specific = ospec, \
1492 INIT_BRACE_BEGIN \
1493 .integer = { \
1494 .pvalue = &gui_options.oname, \
1495 .def = odef, \
1496 .min = omin, \
1497 .max = omax \
1499 INIT_BRACE_END \
1503 * Generate a client option of type OT_STRING.
1505 * oname: The option data. Note it is used as name to be loaded or saved.
1506 * So, you shouldn't change the name of this variable in any case.
1507 * Be sure to pass the array variable and not a pointer to it because
1508 * the size is calculated with sizeof().
1509 * odesc: A short description of the client option. Should be used with the
1510 * N_() macro.
1511 * ohelp: The help text for the client option. Should be used with the N_()
1512 * macro.
1513 * ocat: The client_option_class of this client option.
1514 * ospec: A gui_type enumerator which determines for what particular client
1515 * gui this option is for. Set to GUI_STUB for common options.
1516 * odef: The default string for this client option.
1517 * ocb: A callback function of type void (*)(struct option *) called when
1518 * the option changed.
1520 #define GEN_STR_OPTION(oname, odesc, ohelp, ocat, ospec, odef, ocb, cbd) \
1522 .base_option = OPTION_STR_INIT(&client_optset_static, \
1523 client_option_common_vtable, \
1524 client_option_str_vtable, ocb, cbd), \
1525 .name = #oname, \
1526 .description = odesc, \
1527 .help_text = ohelp, \
1528 .category = ocat, \
1529 .specific = ospec, \
1530 INIT_BRACE_BEGIN \
1531 .string = { \
1532 .pvalue = gui_options.oname, \
1533 .size = sizeof(gui_options.oname), \
1534 .def = odef, \
1535 .val_accessor = NULL \
1537 INIT_BRACE_END \
1541 * Generate a client option of type OT_STRING with a string accessor
1542 * function.
1544 * oname: The option data. Note it is used as name to be loaded or saved.
1545 * So, you shouldn't change the name of this variable in any case.
1546 * Be sure to pass the array variable and not a pointer to it because
1547 * the size is calculated with sizeof().
1548 * odesc: A short description of the client option. Should be used with the
1549 * N_() macro.
1550 * ohelp: The help text for the client option. Should be used with the N_()
1551 * macro.
1552 * ocat: The client_option_class of this client option.
1553 * ospec: A gui_type enumerator which determin for what particular client
1554 * gui this option is for. Sets to GUI_STUB for common options.
1555 * odef: The default string for this client option.
1556 * oacc: The string accessor where to find the allowed values of type
1557 * 'const struct strvec * (*) (void)'.
1558 * ocb: A callback function of type void (*)(struct option *) called when
1559 * the option changed.
1561 #define GEN_STR_LIST_OPTION(oname, odesc, ohelp, ocat, ospec, odef, oacc, ocb, cbd) \
1563 .base_option = OPTION_STR_INIT(&client_optset_static, \
1564 client_option_common_vtable, \
1565 client_option_str_vtable, ocb, cbd), \
1566 .name = #oname, \
1567 .description = odesc, \
1568 .help_text = ohelp, \
1569 .category = ocat, \
1570 .specific = ospec, \
1571 INIT_BRACE_BEGIN \
1572 .string = { \
1573 .pvalue = gui_options.oname, \
1574 .size = sizeof(gui_options.oname), \
1575 .def = odef, \
1576 .val_accessor = oacc \
1578 INIT_BRACE_END \
1582 * Generate a client option of type OT_ENUM.
1584 * oname: The option data. Note it is used as name to be loaded or saved.
1585 * So, you shouldn't change the name of this variable in any case.
1586 * odesc: A short description of the client option. Should be used with the
1587 * N_() macro.
1588 * ohelp: The help text for the client option. Should be used with the N_()
1589 * macro.
1590 * ocat: The client_option_class of this client option.
1591 * ospec: A gui_type enumerator which determin for what particular client
1592 * gui this option is for. Sets to GUI_STUB for common options.
1593 * odef: The default value for this client option.
1594 * oacc: The name accessor of type 'const struct copt_val_name * (*) (int)'.
1595 * ocb: A callback function of type void (*) (struct option *) called when
1596 * the option changed.
1598 #define GEN_ENUM_OPTION(oname, odesc, ohelp, ocat, ospec, odef, oacc, ocb) \
1600 .base_option = OPTION_ENUM_INIT(&client_optset_static, \
1601 client_option_common_vtable, \
1602 client_option_enum_vtable, ocb), \
1603 .name = #oname, \
1604 .description = odesc, \
1605 .help_text = ohelp, \
1606 .category = ocat, \
1607 .specific = ospec, \
1608 INIT_BRACE_BEGIN \
1609 .enumerator = { \
1610 .pvalue = (int *) &gui_options.oname, \
1611 .def = odef, \
1612 .support_names = NULL, /* Set in options_init(). */ \
1613 .pretty_names = NULL, \
1614 .name_accessor = oacc \
1616 INIT_BRACE_END \
1620 * Generate a client option of type OT_BITWISE.
1622 * oname: The option data. Note it is used as name to be loaded or saved.
1623 * So, you shouldn't change the name of this variable in any case.
1624 * odesc: A short description of the client option. Should be used with the
1625 * N_() macro.
1626 * ohelp: The help text for the client option. Should be used with the N_()
1627 * macro.
1628 * ocat: The client_option_class of this client option.
1629 * ospec: A gui_type enumerator which determin for what particular client
1630 * gui this option is for. Sets to GUI_STUB for common options.
1631 * odef: The default value for this client option.
1632 * oacc: The name accessor of type 'const struct copt_val_name * (*) (int)'.
1633 * ocb: A callback function of type void (*) (struct option *) called when
1634 * the option changed.
1636 #define GEN_BITWISE_OPTION(oname, odesc, ohelp, ocat, ospec, odef, oacc, \
1637 ocb) \
1639 .base_option = OPTION_BITWISE_INIT(&client_optset_static, \
1640 client_option_common_vtable, \
1641 client_option_bitwise_vtable, ocb), \
1642 .name = #oname, \
1643 .description = odesc, \
1644 .help_text = ohelp, \
1645 .category = ocat, \
1646 .specific = ospec, \
1647 INIT_BRACE_BEGIN \
1648 .bitwise = { \
1649 .pvalue = &gui_options.oname, \
1650 .def = odef, \
1651 .support_names = NULL, /* Set in options_init(). */ \
1652 .pretty_names = NULL, \
1653 .name_accessor = oacc \
1655 INIT_BRACE_END \
1659 * Generate a client option of type OT_FONT.
1661 * oname: The option data. Note it is used as name to be loaded or saved.
1662 * So, you shouldn't change the name of this variable in any case.
1663 * Be sure to pass the array variable and not a pointer to it because
1664 * the size is calculated with sizeof().
1665 * otgt: The target widget style.
1666 * odesc: A short description of the client option. Should be used with the
1667 * N_() macro.
1668 * ohelp: The help text for the client option. Should be used with the N_()
1669 * macro.
1670 * ocat: The client_option_class of this client option.
1671 * ospec: A gui_type enumerator which determin for what particular client
1672 * gui this option is for. Sets to GUI_STUB for common options.
1673 * odef: The default string for this client option.
1674 * ocb: A callback function of type void (*)(struct option *) called when
1675 * the option changed.
1677 #define GEN_FONT_OPTION(oname, otgt, odesc, ohelp, ocat, ospec, odef, ocb) \
1679 .base_option = OPTION_FONT_INIT(&client_optset_static, \
1680 client_option_common_vtable, \
1681 client_option_font_vtable, ocb), \
1682 .name = #oname, \
1683 .description = odesc, \
1684 .help_text = ohelp, \
1685 .category = ocat, \
1686 .specific = ospec, \
1687 INIT_BRACE_BEGIN \
1688 .font = { \
1689 .pvalue = gui_options.oname, \
1690 .size = sizeof(gui_options.oname), \
1691 .def = odef, \
1692 .target = otgt, \
1694 INIT_BRACE_END \
1698 * Generate a client option of type OT_COLOR.
1700 * oname: The option data. Note it is used as name to be loaded or saved.
1701 * So, you shouldn't change the name of this variable in any case.
1702 * odesc: A short description of the client option. Should be used with the
1703 * N_() macro.
1704 * ohelp: The help text for the client option. Should be used with the N_()
1705 * macro.
1706 * ocat: The client_option_class of this client option.
1707 * ospec: A gui_type enumerator which determin for what particular client
1708 * gui this option is for. Sets to GUI_STUB for common options.
1709 * odef_fg, odef_bg: The default values for this client option.
1710 * ocb: A callback function of type void (*)(struct option *) called when
1711 * the option changed.
1713 #define GEN_COLOR_OPTION(oname, odesc, ohelp, ocat, ospec, odef_fg, \
1714 odef_bg, ocb) \
1716 .base_option = OPTION_COLOR_INIT(&client_optset_static, \
1717 client_option_common_vtable, \
1718 client_option_color_vtable, ocb), \
1719 .name = #oname, \
1720 .description = odesc, \
1721 .help_text = ohelp, \
1722 .category = ocat, \
1723 .specific = ospec, \
1724 INIT_BRACE_BEGIN \
1725 .color = { \
1726 .pvalue = &gui_options.oname, \
1727 .def = FT_COLOR(odef_fg, odef_bg) \
1729 INIT_BRACE_END \
1733 * Generate a client option of type OT_VIDEO_MODE.
1735 * oname: The option data. Note it is used as name to be loaded or saved.
1736 * So, you shouldn't change the name of this variable in any case.
1737 * odesc: A short description of the client option. Should be used with the
1738 * N_() macro.
1739 * ohelp: The help text for the client option. Should be used with the N_()
1740 * macro.
1741 * ocat: The client_option_class of this client option.
1742 * ospec: A gui_type enumerator which determin for what particular client
1743 * gui this option is for. Sets to GUI_STUB for common options.
1744 * odef_width, odef_height: The default values for this client option.
1745 * ocb: A callback function of type void (*)(struct option *) called when
1746 * the option changed.
1748 #define GEN_VIDEO_OPTION(oname, odesc, ohelp, ocat, ospec, odef_width, \
1749 odef_height, ocb) \
1751 .base_option = OPTION_VIDEO_MODE_INIT(&client_optset_static, \
1752 client_option_common_vtable, \
1753 client_option_video_mode_vtable, \
1754 ocb), \
1755 .name = #oname, \
1756 .description = odesc, \
1757 .help_text = ohelp, \
1758 .category = ocat, \
1759 .specific = ospec, \
1760 INIT_BRACE_BEGIN \
1761 .video_mode = { \
1762 .pvalue = &gui_options.oname, \
1763 .def = VIDEO_MODE(odef_width, odef_height) \
1765 INIT_BRACE_END \
1768 /****************************************************************************
1769 Enumerator name accessors.
1770 ****************************************************************************/
1772 /****************************************************************************
1773 GTK message/chat layout setting names accessor.
1774 ****************************************************************************/
1775 static const struct copt_val_name
1776 *gui_gtk_message_chat_location_name(int value)
1778 /* Order must match enum GUI_GTK_MSGCHAT_* */
1779 static const struct copt_val_name names[] = {
1780 /* TRANS: enum value for 'gui_gtk2/gtk3_message_chat_location' */
1781 { "SPLIT", N_("Split") },
1782 /* TRANS: enum value for 'gui_gtk2/gtk3_message_chat_location' */
1783 { "SEPARATE", N_("Separate") },
1784 /* TRANS: enum value for 'gui_gtk2/gtk3_message_chat_location' */
1785 { "MERGED", N_("Merged") }
1788 return (0 <= value && value < ARRAY_SIZE(names)
1789 ? names + value : NULL);
1792 /****************************************************************************
1793 Popup tech help setting names accessor.
1794 ****************************************************************************/
1795 static const struct copt_val_name
1796 *gui_popup_tech_help_name(int value)
1798 /* Order must match enum GUI_POPUP_TECH_HELP_* */
1799 static const struct copt_val_name names[] = {
1800 /* TRANS: enum value for 'gui_popup_tech_help' */
1801 { "ENABLED", N_("Enabled") },
1802 /* TRANS: enum value for 'gui_popup_tech_help' */
1803 { "DISABLED", N_("Disabled") },
1804 /* TRANS: enum value for 'gui_popup_tech_help' */
1805 { "RULESET", N_("Ruleset") }
1808 return (0 <= value && value < ARRAY_SIZE(names)
1809 ? names + value : NULL);
1812 /* Some changed callbacks. */
1813 static void reqtree_show_icons_callback(struct option *poption);
1814 static void view_option_changed_callback(struct option *poption);
1815 static void manual_turn_done_callback(struct option *poption);
1816 static void voteinfo_bar_callback(struct option *poption);
1817 static void font_changed_callback(struct option *poption);
1818 static void mapimg_changed_callback(struct option *poption);
1819 static void game_music_enable_callback(struct option *poption);
1820 static void menu_music_enable_callback(struct option *poption);
1822 static struct client_option client_options[] = {
1823 GEN_STR_OPTION(default_user_name,
1824 N_("Login name"),
1825 N_("This is the default login username that will be used "
1826 "in the connection dialogs or with the -a command-line "
1827 "parameter."),
1828 COC_NETWORK, GUI_STUB, NULL, NULL, 0),
1829 GEN_BOOL_OPTION(use_prev_server, N_("Default to previously used server"),
1830 N_("Automatically update \"Server\" and \"Server port\" "
1831 "options to match your latest connection, so by "
1832 "default you connect to the same server you used "
1833 "on the previous run. You should enable "
1834 "saving options on exit too, so that the automatic "
1835 "updates to the options get saved too."),
1836 COC_NETWORK, GUI_STUB, NULL, NULL),
1837 GEN_STR_OPTION(default_server_host,
1838 N_("Server"),
1839 N_("This is the default server hostname that will be used "
1840 "in the connection dialogs or with the -a command-line "
1841 "parameter."),
1842 COC_NETWORK, GUI_STUB, "localhost", NULL, 0),
1843 GEN_INT_OPTION(default_server_port,
1844 N_("Server port"),
1845 N_("This is the default server port that will be used "
1846 "in the connection dialogs or with the -a command-line "
1847 "parameter."),
1848 COC_NETWORK, GUI_STUB, DEFAULT_SOCK_PORT, 0, 65535, NULL),
1849 GEN_STR_OPTION(default_metaserver,
1850 N_("Metaserver"),
1851 N_("The metaserver is a host that the client contacts to "
1852 "find out about games on the internet. Don't change "
1853 "this from its default value unless you know what "
1854 "you're doing."),
1855 COC_NETWORK, GUI_STUB, DEFAULT_METASERVER_OPTION, NULL, 0),
1856 GEN_BOOL_OPTION(heartbeat_enabled, N_("Send heartbeat messages to server"),
1857 N_("Regularly send empty heartbeat message to the server "
1858 "to make sure that the connection is still up. This "
1859 "can be useful if the client otherwise may sit for a "
1860 "long time with no data being sent or received at all."),
1861 COC_NETWORK, GUI_STUB, NULL, NULL),
1862 GEN_STR_LIST_OPTION(default_sound_set_name,
1863 N_("Soundset"),
1864 N_("This is the soundset that will be used. Changing "
1865 "this is the same as using the -S command-line "
1866 "parameter."),
1867 COC_SOUND, GUI_STUB, "stdsounds", get_soundset_list, NULL, 0),
1868 GEN_STR_LIST_OPTION(default_music_set_name,
1869 N_("Musicset"),
1870 N_("This is the musicset that will be used. Changing "
1871 "this is the same as using the -m command-line "
1872 "parameter."),
1873 COC_SOUND, GUI_STUB, "stdmusic",
1874 get_musicset_list, musicspec_reread_callback, 0),
1875 GEN_STR_LIST_OPTION(default_sound_plugin_name,
1876 N_("Sound plugin"),
1877 N_("If you have a problem with sound, try changing "
1878 "the sound plugin. The new plugin won't take "
1879 "effect until you restart Freeciv. Changing this "
1880 "is the same as using the -P command-line option."),
1881 COC_SOUND, GUI_STUB, NULL, get_soundplugin_list, NULL, 0),
1882 GEN_STR_OPTION(default_chat_logfile,
1883 N_("The chat log file"),
1884 N_("The name of the chat log file."),
1885 COC_INTERFACE, GUI_STUB, GUI_DEFAULT_CHAT_LOGFILE, NULL, 0),
1886 /* gui_gtk2/3_default_theme_name and gui_sdl/2_default_theme_name are
1887 * different settings to avoid client crash after loading the
1888 * style for the other gui. Keeps 4 different options! */
1889 GEN_STR_LIST_OPTION(gui_gtk2_default_theme_name, N_("Theme"),
1890 N_("By changing this option you change the "
1891 "active theme."),
1892 COC_GRAPHICS, GUI_GTK2, FC_GTK2_DEFAULT_THEME_NAME,
1893 get_themes_list, theme_reread_callback, 0),
1894 GEN_STR_LIST_OPTION(gui_gtk3_default_theme_name, N_("Theme"),
1895 N_("By changing this option you change the "
1896 "active theme."),
1897 COC_GRAPHICS, GUI_GTK3, FC_GTK3_DEFAULT_THEME_NAME,
1898 get_themes_list, theme_reread_callback, 0),
1899 GEN_STR_LIST_OPTION(gui_gtk3_22_default_theme_name, N_("Theme"),
1900 N_("By changing this option you change the "
1901 "active theme."),
1902 COC_GRAPHICS, GUI_GTK3_22, FC_GTK3_22_DEFAULT_THEME_NAME,
1903 get_themes_list, theme_reread_callback, 0),
1904 GEN_STR_LIST_OPTION(gui_sdl_default_theme_name, N_("Theme"),
1905 N_("By changing this option you change the "
1906 "active theme."),
1907 COC_GRAPHICS, GUI_SDL, FC_SDL_DEFAULT_THEME_NAME,
1908 get_themes_list, theme_reread_callback, 0),
1909 GEN_STR_LIST_OPTION(gui_sdl2_default_theme_name, N_("Theme"),
1910 N_("By changing this option you change the "
1911 "active theme."),
1912 COC_GRAPHICS, GUI_SDL2, FC_SDL2_DEFAULT_THEME_NAME,
1913 get_themes_list, theme_reread_callback, 0),
1914 GEN_STR_LIST_OPTION(gui_qt_default_theme_name, N_("Theme"),
1915 N_("By changing this option you change the "
1916 "active theme."),
1917 COC_GRAPHICS, GUI_QT, FC_QT_DEFAULT_THEME_NAME,
1918 get_themes_list, theme_reread_callback, 0),
1920 /* It's important to give empty string instead of NULL as as default
1921 * value. For NULL value it would default to assigning first value
1922 * from the tileset list returned by get_tileset_list() as default
1923 * tileset. We don't want default tileset assigned at all here, but
1924 * leave it to tilespec code that can handle tileset priority. */
1925 GEN_STR_LIST_OPTION(default_tileset_overhead_name, N_("Tileset (Overhead)"),
1926 N_("Select the tileset used with Overhead maps. "
1927 "This may change currently active tileset, if "
1928 "you are playing on such a map, in which "
1929 "case this is the same as using the -t "
1930 "command-line parameter."),
1931 COC_GRAPHICS, GUI_STUB, "",
1932 get_tileset_list, tilespec_reread_callback, 0),
1933 GEN_STR_LIST_OPTION(default_tileset_iso_name, N_("Tileset (Isometric)"),
1934 N_("Select the tileset used with Isometric maps. "
1935 "This may change currently active tileset, if "
1936 "you are playing on such a map, in which "
1937 "case this is the same as using the -t "
1938 "command-line parameter."),
1939 COC_GRAPHICS, GUI_STUB, "",
1940 get_tileset_list, tilespec_reread_callback, TF_ISO),
1941 GEN_STR_LIST_OPTION(default_tileset_hex_name, N_("Tileset (Hex)"),
1942 N_("Select the tileset used with Hex maps. "
1943 "This may change currently active tileset, if "
1944 "you are playing on such a map, in which "
1945 "case this is the same as using the -t "
1946 "command-line parameter."),
1947 COC_GRAPHICS, GUI_STUB, "",
1948 get_tileset_list, tilespec_reread_callback, TF_HEX),
1949 GEN_STR_LIST_OPTION(default_tileset_isohex_name, N_("Tileset (Isometric Hex)"),
1950 N_("Select the tileset used with Isometric Hex maps. "
1951 "This may change currently active tileset, if "
1952 "you are playing on such a map, in which "
1953 "case this is the same as using the -t "
1954 "command-line parameter."),
1955 COC_GRAPHICS, GUI_STUB, "",
1956 get_tileset_list, tilespec_reread_callback, TF_ISO | TF_HEX),
1958 GEN_BOOL_OPTION(draw_city_outlines, N_("Draw city outlines"),
1959 N_("Setting this option will draw a line at the city "
1960 "workable limit."),
1961 COC_GRAPHICS, GUI_STUB, TRUE,
1962 view_option_changed_callback),
1963 GEN_BOOL_OPTION(draw_city_output, N_("Draw city output"),
1964 N_("Setting this option will draw city output for every "
1965 "citizen."),
1966 COC_GRAPHICS, GUI_STUB, FALSE,
1967 view_option_changed_callback),
1968 GEN_BOOL_OPTION(draw_map_grid, N_("Draw the map grid"),
1969 N_("Setting this option will draw a grid over the map."),
1970 COC_GRAPHICS, GUI_STUB, FALSE,
1971 view_option_changed_callback),
1972 GEN_BOOL_OPTION(draw_full_citybar, N_("Draw the city bar"),
1973 N_("Setting this option will display a 'city bar' "
1974 "containing useful information beneath each city. "
1975 "Disabling this option will display only the city's "
1976 "name and, optionally, production."),
1977 COC_GRAPHICS, GUI_STUB,
1978 TRUE, view_option_changed_callback),
1979 GEN_BOOL_OPTION(draw_city_names, N_("Draw the city names"),
1980 N_("Setting this option will draw the names of the cities "
1981 "on the map."),
1982 COC_GRAPHICS, GUI_STUB, TRUE,
1983 view_option_changed_callback),
1984 GEN_BOOL_OPTION(draw_city_growth, N_("Draw the city growth"),
1985 N_("Setting this option will draw in how many turns the "
1986 "cities will grow or shrink."),
1987 COC_GRAPHICS, GUI_STUB, TRUE,
1988 view_option_changed_callback),
1989 GEN_BOOL_OPTION(draw_city_productions, N_("Draw the city productions"),
1990 N_("Setting this option will draw what the cities are "
1991 "currently building on the map."),
1992 COC_GRAPHICS, GUI_STUB, TRUE,
1993 view_option_changed_callback),
1994 GEN_BOOL_OPTION(draw_city_buycost, N_("Draw the city buy costs"),
1995 N_("Setting this option will draw how much gold is "
1996 "needed to buy the production of the cities."),
1997 COC_GRAPHICS, GUI_STUB, FALSE,
1998 view_option_changed_callback),
1999 GEN_BOOL_OPTION(draw_city_trade_routes, N_("Draw the city trade routes"),
2000 N_("Setting this option will draw trade route lines "
2001 "between cities which have trade routes."),
2002 COC_GRAPHICS, GUI_STUB, FALSE,
2003 view_option_changed_callback),
2004 GEN_BOOL_OPTION(draw_terrain, N_("Draw the terrain"),
2005 N_("Setting this option will draw the terrain."),
2006 COC_GRAPHICS, GUI_STUB, TRUE,
2007 view_option_changed_callback),
2008 GEN_BOOL_OPTION(draw_coastline, N_("Draw the coast line"),
2009 N_("Setting this option will draw a line to separate the "
2010 "land from the ocean."),
2011 COC_GRAPHICS, GUI_STUB, FALSE,
2012 view_option_changed_callback),
2013 GEN_BOOL_OPTION(draw_roads_rails, N_("Draw the roads and the railroads"),
2014 N_("Setting this option will draw the roads and the "
2015 "railroads on the map."),
2016 COC_GRAPHICS, GUI_STUB, TRUE,
2017 view_option_changed_callback),
2018 GEN_BOOL_OPTION(draw_irrigation, N_("Draw the irrigation"),
2019 N_("Setting this option will draw the irrigation systems "
2020 "on the map."),
2021 COC_GRAPHICS, GUI_STUB, TRUE,
2022 view_option_changed_callback),
2023 GEN_BOOL_OPTION(draw_mines, N_("Draw the mines"),
2024 N_("Setting this option will draw the mines on the map."),
2025 COC_GRAPHICS, GUI_STUB, TRUE,
2026 view_option_changed_callback),
2027 GEN_BOOL_OPTION(draw_fortress_airbase, N_("Draw the bases"),
2028 N_("Setting this option will draw the bases on the map."),
2029 COC_GRAPHICS, GUI_STUB, TRUE,
2030 view_option_changed_callback),
2031 GEN_BOOL_OPTION(draw_specials, N_("Draw the resources"),
2032 N_("Setting this option will draw the resources on the "
2033 "map."),
2034 COC_GRAPHICS, GUI_STUB, TRUE,
2035 view_option_changed_callback),
2036 GEN_BOOL_OPTION(draw_huts, N_("Draw the huts"),
2037 N_("Setting this option will draw the huts on the "
2038 "map."),
2039 COC_GRAPHICS, GUI_STUB, TRUE,
2040 view_option_changed_callback),
2041 GEN_BOOL_OPTION(draw_pollution, N_("Draw the pollution/nuclear fallout"),
2042 N_("Setting this option will draw pollution and "
2043 "nuclear fallout on the map."),
2044 COC_GRAPHICS, GUI_STUB, TRUE,
2045 view_option_changed_callback),
2046 GEN_BOOL_OPTION(draw_cities, N_("Draw the cities"),
2047 N_("Setting this option will draw the cities on the map."),
2048 COC_GRAPHICS, GUI_STUB, TRUE,
2049 view_option_changed_callback),
2050 GEN_BOOL_OPTION(draw_units, N_("Draw the units"),
2051 N_("Setting this option will draw the units on the map."),
2052 COC_GRAPHICS, GUI_STUB, TRUE,
2053 view_option_changed_callback),
2054 GEN_BOOL_OPTION(solid_color_behind_units,
2055 N_("Solid unit background color"),
2056 N_("Setting this option will cause units on the map "
2057 "view to be drawn with a solid background color "
2058 "instead of the flag backdrop."),
2059 COC_GRAPHICS, GUI_STUB,
2060 FALSE, view_option_changed_callback),
2061 GEN_BOOL_OPTION(draw_unit_shields, N_("Draw shield graphics for units"),
2062 N_("Setting this option will draw a shield icon "
2063 "as the flags on units. If unset, the full flag will "
2064 "be drawn."),
2065 COC_GRAPHICS, GUI_STUB, TRUE, view_option_changed_callback),
2066 GEN_BOOL_OPTION(draw_focus_unit, N_("Draw the units in focus"),
2067 N_("Setting this option will cause the currently focused "
2068 "unit(s) to always be drawn, even if units are not "
2069 "otherwise being drawn (for instance if 'Draw the units' "
2070 "is unset)."),
2071 COC_GRAPHICS, GUI_STUB, FALSE,
2072 view_option_changed_callback),
2073 GEN_BOOL_OPTION(draw_fog_of_war, N_("Draw the fog of war"),
2074 N_("Setting this option will draw the fog of war."),
2075 COC_GRAPHICS, GUI_STUB, TRUE,
2076 view_option_changed_callback),
2077 GEN_BOOL_OPTION(draw_borders, N_("Draw the borders"),
2078 N_("Setting this option will draw the national borders."),
2079 COC_GRAPHICS, GUI_STUB, TRUE,
2080 view_option_changed_callback),
2081 GEN_BOOL_OPTION(draw_native, N_("Draw whether tiles are native to "
2082 "selected unit"),
2083 N_("Setting this option will highlight tiles that the "
2084 "currently selected unit cannot enter unaided due to "
2085 "non-native terrain. (If multiple units are selected, "
2086 "only tiles that all of them can enter are indicated.)"),
2087 COC_GRAPHICS, GUI_STUB, FALSE,
2088 view_option_changed_callback),
2089 GEN_BOOL_OPTION(player_dlg_show_dead_players,
2090 N_("Show dead players in Nations report"),
2091 N_("This option controls whether defeated nations are "
2092 "shown on the Nations report page."),
2093 COC_GRAPHICS, GUI_STUB, TRUE,
2094 view_option_changed_callback),
2095 GEN_BOOL_OPTION(sound_bell_at_new_turn, N_("Sound bell at new turn"),
2096 N_("Set this option to have a \"bell\" event be generated "
2097 "at the start of a new turn. You can control the "
2098 "behavior of the \"bell\" event by editing the message "
2099 "options."),
2100 COC_SOUND, GUI_STUB, FALSE, NULL),
2101 GEN_INT_OPTION(smooth_move_unit_msec,
2102 N_("Unit movement animation time (milliseconds)"),
2103 N_("This option controls how long unit \"animation\" takes "
2104 "when a unit moves on the map view. Set it to 0 to "
2105 "disable animation entirely."),
2106 COC_GRAPHICS, GUI_STUB, 30, 0, 2000, NULL),
2107 GEN_INT_OPTION(smooth_center_slide_msec,
2108 N_("Mapview recentering time (milliseconds)"),
2109 N_("When the map view is recentered, it will slide "
2110 "smoothly over the map to its new position. This "
2111 "option controls how long this slide lasts. Set it to "
2112 "0 to disable mapview sliding entirely."),
2113 COC_GRAPHICS, GUI_STUB, 200, 0, 5000, NULL),
2114 GEN_INT_OPTION(smooth_combat_step_msec,
2115 N_("Combat animation step time (milliseconds)"),
2116 N_("This option controls the speed of combat animation "
2117 "between units on the mapview. Set it to 0 to disable "
2118 "animation entirely."),
2119 COC_GRAPHICS, GUI_STUB, 10, 0, 100, NULL),
2120 GEN_BOOL_OPTION(reqtree_show_icons,
2121 N_("Show icons in the technology tree"),
2122 N_("Setting this option will display icons "
2123 "on the technology tree diagram. Turning "
2124 "this option off makes the technology tree "
2125 "more compact."),
2126 COC_GRAPHICS, GUI_STUB, TRUE, reqtree_show_icons_callback),
2127 GEN_BOOL_OPTION(reqtree_curved_lines,
2128 N_("Use curved lines in the technology tree"),
2129 N_("Setting this option make the technology tree "
2130 "diagram use curved lines to show technology "
2131 "relations. Turning this option off causes "
2132 "the lines to be drawn straight."),
2133 COC_GRAPHICS, GUI_STUB, FALSE,
2134 reqtree_show_icons_callback),
2135 GEN_COLOR_OPTION(highlight_our_names,
2136 N_("Color to highlight your player/user name"),
2137 N_("If set, your player and user name in the new chat "
2138 "messages will be highlighted using this color as "
2139 "background. If not set, it will just not highlight "
2140 "anything."),
2141 COC_GRAPHICS, GUI_STUB, "#000000", "#FFFF00", NULL),
2142 GEN_BOOL_OPTION(ai_manual_turn_done, N_("Manual Turn Done in AI mode"),
2143 N_("Disable this option if you do not want to "
2144 "press the Turn Done button manually when watching "
2145 "an AI player."),
2146 COC_INTERFACE, GUI_STUB, TRUE, manual_turn_done_callback),
2147 GEN_BOOL_OPTION(auto_center_on_unit, N_("Auto center on units"),
2148 N_("Set this option to have the active unit centered "
2149 "automatically when the unit focus changes."),
2150 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2151 GEN_BOOL_OPTION(auto_center_on_automated, N_("Show automated units"),
2152 N_("Disable this option if you do not want to see "
2153 "automated units autocentered and animated"),
2154 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2155 GEN_BOOL_OPTION(auto_center_on_combat, N_("Auto center on combat"),
2156 N_("Set this option to have any combat be centered "
2157 "automatically. Disabling this will speed up the time "
2158 "between turns but may cause you to miss combat "
2159 "entirely."),
2160 COC_INTERFACE, GUI_STUB, FALSE, NULL),
2161 GEN_BOOL_OPTION(auto_center_each_turn, N_("Auto center on new turn"),
2162 N_("Set this option to have the client automatically "
2163 "recenter the map on a suitable location at the "
2164 "start of each turn."),
2165 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2166 GEN_BOOL_OPTION(wakeup_focus, N_("Focus on awakened units"),
2167 N_("Set this option to have newly awoken units be "
2168 "focused automatically."),
2169 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2170 GEN_BOOL_OPTION(keyboardless_goto, N_("Keyboardless goto"),
2171 N_("If this option is set then a goto may be initiated "
2172 "by left-clicking and then holding down the mouse "
2173 "button while dragging the mouse onto a different "
2174 "tile."),
2175 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2176 GEN_BOOL_OPTION(goto_into_unknown, N_("Allow goto into the unknown"),
2177 N_("Setting this option will make the game consider "
2178 "moving into unknown tiles. If not, then goto routes "
2179 "will detour around or be blocked by unknown tiles."),
2180 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2181 GEN_BOOL_OPTION(center_when_popup_city, N_("Center map when popup city"),
2182 N_("Setting this option makes the mapview center on a "
2183 "city when its city dialog is popped up."),
2184 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2185 GEN_BOOL_OPTION(concise_city_production, N_("Concise city production"),
2186 N_("Set this option to make the city production (as shown "
2187 "in the city dialog) to be more compact."),
2188 COC_INTERFACE, GUI_STUB, FALSE, NULL),
2189 GEN_BOOL_OPTION(auto_turn_done, N_("End turn when done moving"),
2190 N_("Setting this option makes your turn end automatically "
2191 "when all your units are done moving."),
2192 COC_INTERFACE, GUI_STUB, FALSE, NULL),
2193 GEN_BOOL_OPTION(ask_city_name, N_("Prompt for city names"),
2194 N_("Disabling this option will make the names of newly "
2195 "founded cities be chosen automatically by the server."),
2196 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2197 GEN_BOOL_OPTION(popup_new_cities, N_("Pop up city dialog for new cities"),
2198 N_("Setting this option will pop up a newly-founded "
2199 "city's city dialog automatically."),
2200 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2201 GEN_BOOL_OPTION(popup_actor_arrival, N_("Pop up caravan and spy actions"),
2202 N_("If this option is enabled, when a unit arrives at "
2203 "a city where it can perform an action like "
2204 "establishing a trade route, helping build a wonder, or "
2205 "establishing an embassy, a window will pop up asking "
2206 "which action should be performed. "
2207 "Disabling this option means you will have to do the "
2208 "action manually by pressing either 'r' (for a trade "
2209 "route), 'b' (for building a wonder) or 'd' (for a "
2210 "spy action) when the unit is in the city."),
2211 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2212 GEN_BOOL_OPTION(enable_cursor_changes, N_("Enable cursor changing"),
2213 N_("This option controls whether the client should "
2214 "try to change the mouse cursor depending on what "
2215 "is being pointed at, as well as to indicate "
2216 "changes in the client or server state."),
2217 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2218 GEN_BOOL_OPTION(separate_unit_selection, N_("Select cities before units"),
2219 N_("If this option is enabled, when both cities and "
2220 "units are present in the selection rectangle, only "
2221 "cities will be selected. See the help on Controls."),
2222 COC_INTERFACE, GUI_STUB, FALSE, NULL),
2223 GEN_BOOL_OPTION(unit_selection_clears_orders,
2224 N_("Clear unit orders on selection"),
2225 N_("Enabling this option will cause unit orders to be "
2226 "cleared as soon as one or more units are selected. If "
2227 "this option is disabled, busy units will not stop "
2228 "their current activity when selected. Giving them "
2229 "new orders will clear their current ones; pressing "
2230 "<space> once will clear their orders and leave them "
2231 "selected, and pressing <space> a second time will "
2232 "dismiss them."),
2233 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2234 GEN_BOOL_OPTION(voteinfo_bar_use, N_("Enable vote bar"),
2235 N_("If this option is turned on, the vote bar will be "
2236 "displayed to show vote information."),
2237 COC_GRAPHICS, GUI_STUB, TRUE, voteinfo_bar_callback),
2238 GEN_BOOL_OPTION(voteinfo_bar_always_show,
2239 N_("Always display the vote bar"),
2240 N_("If this option is turned on, the vote bar will never "
2241 "be hidden, even if there is no running vote."),
2242 COC_GRAPHICS, GUI_STUB, FALSE, voteinfo_bar_callback),
2243 GEN_BOOL_OPTION(voteinfo_bar_hide_when_not_player,
2244 N_("Do not show vote bar if not a player"),
2245 N_("If this option is enabled, the client won't show the "
2246 "vote bar if you are not a player."),
2247 COC_GRAPHICS, GUI_STUB, FALSE, voteinfo_bar_callback),
2248 GEN_BOOL_OPTION(voteinfo_bar_new_at_front, N_("Set new votes at front"),
2249 N_("If this option is enabled, then new votes will go "
2250 "to the front of the vote list."),
2251 COC_GRAPHICS, GUI_STUB, FALSE, voteinfo_bar_callback),
2252 GEN_BOOL_OPTION(autoaccept_tileset_suggestion,
2253 N_("Autoaccept tileset suggestions"),
2254 N_("If this option is enabled, any tileset suggested by "
2255 "the ruleset is automatically used; otherwise you "
2256 "are prompted to change tileset."),
2257 COC_GRAPHICS, GUI_STUB, FALSE, NULL),
2259 GEN_BOOL_OPTION(sound_enable_effects,
2260 N_("Enable sound effects"),
2261 N_("Play sound effects, assuming there's suitable "
2262 "sound plugin and soundset with the sounds."),
2263 COC_SOUND, GUI_STUB, TRUE, NULL),
2264 GEN_BOOL_OPTION(sound_enable_game_music,
2265 N_("Enable in-game music"),
2266 N_("Play music during the game, assuming there's suitable "
2267 "sound plugin and musicset with in-game tracks."),
2268 COC_SOUND, GUI_STUB, TRUE, game_music_enable_callback),
2269 GEN_BOOL_OPTION(sound_enable_menu_music,
2270 N_("Enable menu music"),
2271 N_("Play music while not in actual game, "
2272 "assuming there's suitable "
2273 "sound plugin and musicset with menu music tracks."),
2274 COC_SOUND, GUI_STUB, TRUE, menu_music_enable_callback),
2275 GEN_BOOL_OPTION(autoaccept_soundset_suggestion,
2276 N_("Autoaccept soundset suggestions"),
2277 N_("If this option is enabled, any soundset suggested by "
2278 "the ruleset is automatically used."),
2279 COC_SOUND, GUI_STUB, FALSE, NULL),
2280 GEN_BOOL_OPTION(autoaccept_musicset_suggestion,
2281 N_("Autoaccept musicset suggestions"),
2282 N_("If this option is enabled, any musicset suggested by "
2283 "the ruleset is automatically used."),
2284 COC_SOUND, GUI_STUB, FALSE, NULL),
2286 GEN_BOOL_OPTION(overview.layers[OLAYER_BACKGROUND],
2287 N_("Background layer"),
2288 N_("The background layer of the overview shows just "
2289 "ocean and land."),
2290 COC_OVERVIEW, GUI_STUB, TRUE, NULL),
2291 GEN_BOOL_OPTION(overview.layers[OLAYER_RELIEF],
2292 N_("Terrain relief map layer"),
2293 N_("The relief layer shows all terrains on the map."),
2294 COC_OVERVIEW, GUI_STUB, FALSE, overview_redraw_callback),
2295 GEN_BOOL_OPTION(overview.layers[OLAYER_BORDERS],
2296 N_("Borders layer"),
2297 N_("The borders layer of the overview shows which tiles "
2298 "are owned by each player."),
2299 COC_OVERVIEW, GUI_STUB, FALSE, overview_redraw_callback),
2300 GEN_BOOL_OPTION(overview.layers[OLAYER_BORDERS_ON_OCEAN],
2301 N_("Borders layer on ocean tiles"),
2302 N_("The borders layer of the overview are drawn on "
2303 "ocean tiles as well (this may look ugly with many "
2304 "islands). This option is only of interest if you "
2305 "have set the option \"Borders layer\" already."),
2306 COC_OVERVIEW, GUI_STUB, TRUE, overview_redraw_callback),
2307 GEN_BOOL_OPTION(overview.layers[OLAYER_UNITS],
2308 N_("Units layer"),
2309 N_("Enabling this will draw units on the overview."),
2310 COC_OVERVIEW, GUI_STUB, TRUE, overview_redraw_callback),
2311 GEN_BOOL_OPTION(overview.layers[OLAYER_CITIES],
2312 N_("Cities layer"),
2313 N_("Enabling this will draw cities on the overview."),
2314 COC_OVERVIEW, GUI_STUB, TRUE, overview_redraw_callback),
2315 GEN_BOOL_OPTION(overview.fog,
2316 N_("Overview fog of war"),
2317 N_("Enabling this will show fog of war on the "
2318 "overview."),
2319 COC_OVERVIEW, GUI_STUB, TRUE, overview_redraw_callback),
2321 /* options for map images */
2322 GEN_STR_LIST_OPTION(mapimg_format,
2323 N_("Image format"),
2324 N_("The image toolkit and file format used for "
2325 "map images."),
2326 COC_MAPIMG, GUI_STUB, NULL, get_mapimg_format_list,
2327 NULL, 0),
2328 GEN_INT_OPTION(mapimg_zoom,
2329 N_("Zoom factor for map images"),
2330 N_("The magnification used for map images."),
2331 COC_MAPIMG, GUI_STUB, 2, 1, 5, mapimg_changed_callback),
2332 GEN_BOOL_OPTION(mapimg_layer[MAPIMG_LAYER_AREA],
2333 N_("Show area within borders"),
2334 N_("If set, the territory of each nation is shown "
2335 "on the saved image."),
2336 COC_MAPIMG, GUI_STUB, FALSE, mapimg_changed_callback),
2337 GEN_BOOL_OPTION(mapimg_layer[MAPIMG_LAYER_BORDERS],
2338 N_("Show borders"),
2339 N_("If set, the border of each nation is shown on the "
2340 "saved image."),
2341 COC_MAPIMG, GUI_STUB, TRUE, mapimg_changed_callback),
2342 GEN_BOOL_OPTION(mapimg_layer[MAPIMG_LAYER_CITIES],
2343 N_("Show cities"),
2344 N_("If set, cities are shown on the saved image."),
2345 COC_MAPIMG, GUI_STUB, TRUE, mapimg_changed_callback),
2346 GEN_BOOL_OPTION(mapimg_layer[MAPIMG_LAYER_FOGOFWAR],
2347 N_("Show fog of war"),
2348 N_("If set, the extent of fog of war is shown on the "
2349 "saved image."),
2350 COC_MAPIMG, GUI_STUB, TRUE, mapimg_changed_callback),
2351 GEN_BOOL_OPTION(mapimg_layer[MAPIMG_LAYER_TERRAIN],
2352 N_("Show full terrain"),
2353 N_("If set, terrain relief is shown with different colors "
2354 "in the saved image; otherwise, only land and water are "
2355 "distinguished."),
2356 COC_MAPIMG, GUI_STUB, TRUE, mapimg_changed_callback),
2357 GEN_BOOL_OPTION(mapimg_layer[MAPIMG_LAYER_UNITS],
2358 N_("Show units"),
2359 N_("If set, units are shown in the saved image."),
2360 COC_MAPIMG, GUI_STUB, TRUE, mapimg_changed_callback),
2361 GEN_STR_OPTION(mapimg_filename,
2362 N_("Map image file name"),
2363 N_("The base part of the filename for saved map images. "
2364 "A string identifying the game turn and map options will "
2365 "be appended."),
2366 COC_MAPIMG, GUI_STUB, GUI_DEFAULT_MAPIMG_FILENAME, NULL, 0),
2368 /* gui-gtk-2.0 client specific options. */
2369 GEN_BOOL_OPTION(gui_gtk2_fullscreen, N_("Fullscreen"),
2370 N_("If this option is set the client will use the "
2371 "whole screen area for drawing."),
2372 COC_INTERFACE, GUI_GTK2, FALSE, NULL),
2373 GEN_BOOL_OPTION(gui_gtk2_map_scrollbars, N_("Show map scrollbars"),
2374 N_("Disable this option to hide the scrollbars on the "
2375 "map view."),
2376 COC_INTERFACE, GUI_GTK2, FALSE, NULL),
2377 GEN_BOOL_OPTION(gui_gtk2_dialogs_on_top, N_("Keep dialogs on top"),
2378 N_("If this option is set then dialog windows will always "
2379 "remain in front of the main Freeciv window. "
2380 "Disabling this has no effect in fullscreen mode."),
2381 COC_INTERFACE, GUI_GTK2, TRUE, NULL),
2382 GEN_BOOL_OPTION(gui_gtk2_show_task_icons, N_("Show worklist task icons"),
2383 N_("Disabling this will turn off the unit and building "
2384 "icons in the worklist dialog and the production "
2385 "tab of the city dialog."),
2386 COC_GRAPHICS, GUI_GTK2, TRUE, NULL),
2387 GEN_BOOL_OPTION(gui_gtk2_enable_tabs, N_("Enable status report tabs"),
2388 N_("If this option is enabled then report dialogs will "
2389 "be shown as separate tabs rather than in popup "
2390 "dialogs."),
2391 COC_INTERFACE, GUI_GTK2, TRUE, NULL),
2392 GEN_BOOL_OPTION(gui_gtk2_better_fog,
2393 N_("Better fog-of-war drawing"),
2394 N_("If this is enabled then a better method is used "
2395 "for drawing fog-of-war. It is not any slower but "
2396 "will consume about twice as much memory."),
2397 COC_GRAPHICS, GUI_GTK2,
2398 TRUE, view_option_changed_callback),
2399 GEN_BOOL_OPTION(gui_gtk2_show_chat_message_time,
2400 N_("Show time for each chat message"),
2401 N_("If this option is enabled then all chat messages "
2402 "will be prefixed by a time string of the form "
2403 "[hour:minute:second]."),
2404 COC_INTERFACE, GUI_GTK2, FALSE, NULL),
2405 GEN_BOOL_OPTION(gui_gtk2_new_messages_go_to_top,
2406 N_("New message events go to top of list"),
2407 N_("If this option is enabled, new events in the "
2408 "message window will appear at the top of the list, "
2409 "rather than being appended at the bottom."),
2410 COC_INTERFACE, GUI_GTK2, FALSE, NULL),
2411 GEN_BOOL_OPTION(gui_gtk2_show_message_window_buttons,
2412 N_("Show extra message window buttons"),
2413 N_("If this option is enabled, there will be two "
2414 "buttons displayed in the message window for "
2415 "inspecting a city and going to a location. If this "
2416 "option is disabled, these buttons will not appear "
2417 "(you can still double-click with the left mouse "
2418 "button or right-click on a row to inspect or goto "
2419 "respectively). This option will only take effect "
2420 "once the message window is closed and reopened."),
2421 COC_INTERFACE, GUI_GTK2, TRUE, NULL),
2422 GEN_BOOL_OPTION(gui_gtk2_metaserver_tab_first,
2423 N_("Metaserver tab first in network page"),
2424 N_("If this option is enabled, the metaserver tab will "
2425 "be the first notebook tab in the network page. This "
2426 "option requires a restart in order to take effect."),
2427 COC_NETWORK, GUI_GTK2, FALSE, NULL),
2428 GEN_BOOL_OPTION(gui_gtk2_allied_chat_only,
2429 N_("Plain chat messages are sent to allies only"),
2430 N_("If this option is enabled, then plain messages "
2431 "typed into the chat entry while the game is "
2432 "running will only be sent to your allies. "
2433 "Otherwise plain messages will be sent as "
2434 "public chat messages. To send a public chat "
2435 "message with this option enabled, prefix the "
2436 "message with a single colon ':'. This option "
2437 "can also be set using a toggle button beside "
2438 "the chat entry (only visible in multiplayer "
2439 "games)."),
2440 COC_INTERFACE, GUI_GTK2, FALSE, NULL),
2441 GEN_ENUM_OPTION(gui_gtk2_message_chat_location,
2442 N_("Messages and Chat reports location"),
2443 /* TRANS: The strings used in the UI for 'Split' etc are
2444 * tagged 'gui_gtk2/gtk3_message_chat_location' */
2445 N_("Controls where the Messages and Chat reports "
2446 "appear relative to the main view containing the map.\n"
2447 "'Split' allows all three to be seen simultaneously, "
2448 "which is best for multiplayer, but requires a large "
2449 "window to be usable.\n"
2450 "'Separate' puts Messages and Chat in a notebook "
2451 "separate from the main view, so that one of them "
2452 "can always be seen alongside the main view.\n"
2453 "'Merged' makes the Messages and Chat reports into "
2454 "tabs alongside the map and other reports; this "
2455 "allows a larger map view on small screens.\n"
2456 "This option requires a restart in order to take "
2457 "effect."), COC_INTERFACE, GUI_GTK2,
2458 GUI_GTK_MSGCHAT_MERGED /* Ignored! See options_load(). */,
2459 gui_gtk_message_chat_location_name, NULL),
2460 GEN_BOOL_OPTION(gui_gtk2_small_display_layout,
2461 N_("Arrange widgets for small displays"),
2462 N_("If this option is enabled, widgets in the main "
2463 "window will be arranged so that they take up the "
2464 "least amount of total screen space. Specifically, "
2465 "the left panel containing the overview, player "
2466 "status, and the unit information box will be "
2467 "extended over the entire left side of the window. "
2468 "This option requires a restart in order to take "
2469 "effect."), COC_INTERFACE, GUI_GTK2, TRUE, NULL),
2470 GEN_BOOL_OPTION(gui_gtk2_mouse_over_map_focus,
2471 N_("Mouse over the map widget selects it automatically"),
2472 N_("If this option is enabled, then the map will be "
2473 "focused when the mouse hovers over it."),
2474 COC_INTERFACE, GUI_GTK2, FALSE, NULL),
2475 GEN_BOOL_OPTION(gui_gtk2_chatline_autocompletion,
2476 N_("Player or user name autocompletion"),
2477 N_("If this option is turned on, the tabulation key "
2478 "will be used in the chatline to complete the word you "
2479 "are typing with the name of a player or a user."),
2480 COC_INTERFACE, GUI_GTK2, TRUE, NULL),
2481 GEN_INT_OPTION(gui_gtk2_citydlg_xsize,
2482 N_("Width of the city dialog"),
2483 N_("This value is only used if the width of the city "
2484 "dialog is saved."),
2485 COC_INTERFACE, GUI_GTK2, GUI_GTK2_CITYDLG_DEFAULT_XSIZE,
2486 GUI_GTK2_CITYDLG_MIN_XSIZE, GUI_GTK2_CITYDLG_MAX_XSIZE,
2487 NULL),
2488 GEN_INT_OPTION(gui_gtk2_citydlg_ysize,
2489 N_("Height of the city dialog"),
2490 N_("This value is only used if the height of the city "
2491 "dialog is saved."),
2492 COC_INTERFACE, GUI_GTK2, GUI_GTK2_CITYDLG_DEFAULT_YSIZE,
2493 GUI_GTK2_CITYDLG_MIN_YSIZE, GUI_GTK2_CITYDLG_MAX_YSIZE,
2494 NULL),
2495 GEN_ENUM_OPTION(gui_gtk2_popup_tech_help,
2496 N_("Popup tech help when gained"),
2497 N_("Controls if tech help should be opened when "
2498 "new tech has been gained.\n"
2499 "'Ruleset' means that behavior suggested by "
2500 "current ruleset is used."), COC_INTERFACE, GUI_GTK2,
2501 GUI_POPUP_TECH_HELP_RULESET,
2502 gui_popup_tech_help_name, NULL),
2503 GEN_FONT_OPTION(gui_gtk2_font_city_label, "city_label",
2504 N_("City Label"),
2505 N_("This font is used to display the city labels on city "
2506 "dialogs."),
2507 COC_FONT, GUI_GTK2,
2508 "Monospace 8", font_changed_callback),
2509 GEN_FONT_OPTION(gui_gtk2_font_notify_label, "notify_label",
2510 N_("Notify Label"),
2511 N_("This font is used to display server reports such "
2512 "as the demographic report or historian publications."),
2513 COC_FONT, GUI_GTK2,
2514 "Monospace Bold 9", font_changed_callback),
2515 GEN_FONT_OPTION(gui_gtk2_font_spaceship_label, "spaceship_label",
2516 N_("Spaceship Label"),
2517 N_("This font is used to display the spaceship widgets."),
2518 COC_FONT, GUI_GTK2,
2519 "Monospace 8", font_changed_callback),
2520 GEN_FONT_OPTION(gui_gtk2_font_help_label, "help_label",
2521 N_("Help Label"),
2522 N_("This font is used to display the help headers in the "
2523 "help window."),
2524 COC_FONT, GUI_GTK2,
2525 "Sans Bold 10", font_changed_callback),
2526 GEN_FONT_OPTION(gui_gtk2_font_help_link, "help_link",
2527 N_("Help Link"),
2528 N_("This font is used to display the help links in the "
2529 "help window."),
2530 COC_FONT, GUI_GTK2,
2531 "Sans 9", font_changed_callback),
2532 GEN_FONT_OPTION(gui_gtk2_font_help_text, "help_text",
2533 N_("Help Text"),
2534 N_("This font is used to display the help body text in "
2535 "the help window."),
2536 COC_FONT, GUI_GTK2,
2537 "Monospace 8", font_changed_callback),
2538 GEN_FONT_OPTION(gui_gtk2_font_chatline, "chatline",
2539 N_("Chatline Area"),
2540 N_("This font is used to display the text in the "
2541 "chatline area."),
2542 COC_FONT, GUI_GTK2,
2543 "Monospace 8", font_changed_callback),
2544 GEN_FONT_OPTION(gui_gtk2_font_beta_label, "beta_label",
2545 N_("Beta Label"),
2546 N_("This font is used to display the beta label."),
2547 COC_FONT, GUI_GTK2,
2548 "Sans Italic 10", font_changed_callback),
2549 GEN_FONT_OPTION(gui_gtk2_font_small, "small_font",
2550 N_("Small Font"),
2551 N_("This font is used for any small font request. For "
2552 "example, it is used for display the building lists "
2553 "in the city dialog, the Economy report or the Units "
2554 "report."),
2555 COC_FONT, GUI_GTK2,
2556 "Sans 9", NULL),
2557 GEN_FONT_OPTION(gui_gtk2_font_comment_label, "comment_label",
2558 N_("Comment Label"),
2559 N_("This font is used to display comment labels, such as "
2560 "in the governor page of the city dialogs."),
2561 COC_FONT, GUI_GTK2,
2562 "Sans Italic 9", font_changed_callback),
2563 GEN_FONT_OPTION(gui_gtk2_font_city_names, "city_names",
2564 N_("City Names"),
2565 N_("This font is used to the display the city names "
2566 "on the map."),
2567 COC_FONT, GUI_GTK2,
2568 "Sans Bold 10", NULL),
2569 GEN_FONT_OPTION(gui_gtk2_font_city_productions, "city_productions",
2570 N_("City Productions"),
2571 N_("This font is used to the display the city production "
2572 "names on the map."),
2573 COC_FONT, GUI_GTK2,
2574 "Serif 10", NULL),
2575 GEN_FONT_OPTION(gui_gtk2_font_reqtree_text, "reqtree_text",
2576 N_("Requirement Tree"),
2577 N_("This font is used to the display the requirement tree "
2578 "in the Research report."),
2579 COC_FONT, GUI_GTK2,
2580 "Serif 10", NULL),
2582 /* gui-gtk-3.0 client specific options. */
2583 GEN_BOOL_OPTION(gui_gtk3_fullscreen, N_("Fullscreen"),
2584 N_("If this option is set the client will use the "
2585 "whole screen area for drawing."),
2586 COC_INTERFACE, GUI_GTK3, FALSE, NULL),
2587 GEN_BOOL_OPTION(gui_gtk3_map_scrollbars, N_("Show map scrollbars"),
2588 N_("Disable this option to hide the scrollbars on the "
2589 "map view."),
2590 COC_INTERFACE, GUI_GTK3, FALSE, NULL),
2591 GEN_BOOL_OPTION(gui_gtk3_dialogs_on_top, N_("Keep dialogs on top"),
2592 N_("If this option is set then dialog windows will always "
2593 "remain in front of the main Freeciv window. "
2594 "Disabling this has no effect in fullscreen mode."),
2595 COC_INTERFACE, GUI_GTK3, TRUE, NULL),
2596 GEN_BOOL_OPTION(gui_gtk3_show_task_icons, N_("Show worklist task icons"),
2597 N_("Disabling this will turn off the unit and building "
2598 "icons in the worklist dialog and the production "
2599 "tab of the city dialog."),
2600 COC_GRAPHICS, GUI_GTK3, TRUE, NULL),
2601 GEN_BOOL_OPTION(gui_gtk3_enable_tabs, N_("Enable status report tabs"),
2602 N_("If this option is enabled then report dialogs will "
2603 "be shown as separate tabs rather than in popup "
2604 "dialogs."),
2605 COC_INTERFACE, GUI_GTK3, TRUE, NULL),
2606 GEN_BOOL_OPTION(gui_gtk3_show_chat_message_time,
2607 N_("Show time for each chat message"),
2608 N_("If this option is enabled then all chat messages "
2609 "will be prefixed by a time string of the form "
2610 "[hour:minute:second]."),
2611 COC_INTERFACE, GUI_GTK3, FALSE, NULL),
2612 GEN_BOOL_OPTION(gui_gtk3_new_messages_go_to_top,
2613 N_("New message events go to top of list"),
2614 N_("If this option is enabled, new events in the "
2615 "message window will appear at the top of the list, "
2616 "rather than being appended at the bottom."),
2617 COC_INTERFACE, GUI_GTK3, FALSE, NULL),
2618 GEN_BOOL_OPTION(gui_gtk3_show_message_window_buttons,
2619 N_("Show extra message window buttons"),
2620 N_("If this option is enabled, there will be two "
2621 "buttons displayed in the message window for "
2622 "inspecting a city and going to a location. If this "
2623 "option is disabled, these buttons will not appear "
2624 "(you can still double-click with the left mouse "
2625 "button or right-click on a row to inspect or goto "
2626 "respectively). This option will only take effect "
2627 "once the message window is closed and reopened."),
2628 COC_INTERFACE, GUI_GTK3, TRUE, NULL),
2629 GEN_BOOL_OPTION(gui_gtk3_metaserver_tab_first,
2630 N_("Metaserver tab first in network page"),
2631 N_("If this option is enabled, the metaserver tab will "
2632 "be the first notebook tab in the network page. This "
2633 "option requires a restart in order to take effect."),
2634 COC_NETWORK, GUI_GTK3, FALSE, NULL),
2635 GEN_BOOL_OPTION(gui_gtk3_allied_chat_only,
2636 N_("Plain chat messages are sent to allies only"),
2637 N_("If this option is enabled, then plain messages "
2638 "typed into the chat entry while the game is "
2639 "running will only be sent to your allies. "
2640 "Otherwise plain messages will be sent as "
2641 "public chat messages. To send a public chat "
2642 "message with this option enabled, prefix the "
2643 "message with a single colon ':'. This option "
2644 "can also be set using a toggle button beside "
2645 "the chat entry (only visible in multiplayer "
2646 "games)."),
2647 COC_INTERFACE, GUI_GTK3, FALSE, NULL),
2648 GEN_ENUM_OPTION(gui_gtk3_message_chat_location,
2649 N_("Messages and Chat reports location"),
2650 /* TRANS: The strings used in the UI for 'Split' etc are
2651 * tagged 'gui_gtk2/gtk3_message_chat_location' */
2652 N_("Controls where the Messages and Chat reports "
2653 "appear relative to the main view containing the map.\n"
2654 "'Split' allows all three to be seen simultaneously, "
2655 "which is best for multiplayer, but requires a large "
2656 "window to be usable.\n"
2657 "'Separate' puts Messages and Chat in a notebook "
2658 "separate from the main view, so that one of them "
2659 "can always be seen alongside the main view.\n"
2660 "'Merged' makes the Messages and Chat reports into "
2661 "tabs alongside the map and other reports; this "
2662 "allows a larger map view on small screens.\n"
2663 "This option requires a restart in order to take "
2664 "effect."), COC_INTERFACE, GUI_GTK3,
2665 GUI_GTK_MSGCHAT_MERGED /* Ignored! See options_load(). */,
2666 gui_gtk_message_chat_location_name, NULL),
2667 GEN_BOOL_OPTION(gui_gtk3_small_display_layout,
2668 N_("Arrange widgets for small displays"),
2669 N_("If this option is enabled, widgets in the main "
2670 "window will be arranged so that they take up the "
2671 "least amount of total screen space. Specifically, "
2672 "the left panel containing the overview, player "
2673 "status, and the unit information box will be "
2674 "extended over the entire left side of the window. "
2675 "This option requires a restart in order to take "
2676 "effect."), COC_INTERFACE, GUI_GTK3, TRUE, NULL),
2677 GEN_BOOL_OPTION(gui_gtk3_mouse_over_map_focus,
2678 N_("Mouse over the map widget selects it automatically"),
2679 N_("If this option is enabled, then the map will be "
2680 "focused when the mouse hovers over it."),
2681 COC_INTERFACE, GUI_GTK3, FALSE, NULL),
2682 GEN_BOOL_OPTION(gui_gtk3_chatline_autocompletion,
2683 N_("Player or user name autocompletion"),
2684 N_("If this option is turned on, the tabulation key "
2685 "will be used in the chatline to complete the word you "
2686 "are typing with the name of a player or a user."),
2687 COC_INTERFACE, GUI_GTK3, TRUE, NULL),
2688 GEN_INT_OPTION(gui_gtk3_citydlg_xsize,
2689 N_("Width of the city dialog"),
2690 N_("This value is only used if the width of the city "
2691 "dialog is saved."),
2692 COC_INTERFACE, GUI_GTK3, GUI_GTK3_CITYDLG_DEFAULT_XSIZE,
2693 GUI_GTK3_CITYDLG_MIN_XSIZE, GUI_GTK3_CITYDLG_MAX_XSIZE,
2694 NULL),
2695 GEN_INT_OPTION(gui_gtk3_citydlg_ysize,
2696 N_("Height of the city dialog"),
2697 N_("This value is only used if the height of the city "
2698 "dialog is saved."),
2699 COC_INTERFACE, GUI_GTK3, GUI_GTK3_CITYDLG_DEFAULT_YSIZE,
2700 GUI_GTK3_CITYDLG_MIN_YSIZE, GUI_GTK3_CITYDLG_MAX_YSIZE,
2701 NULL),
2702 GEN_ENUM_OPTION(gui_gtk3_popup_tech_help,
2703 N_("Popup tech help when gained"),
2704 N_("Controls if tech help should be opened when "
2705 "new tech has been gained.\n"
2706 "'Ruleset' means that behavior suggested by "
2707 "current ruleset is used."), COC_INTERFACE, GUI_GTK3,
2708 GUI_POPUP_TECH_HELP_RULESET,
2709 gui_popup_tech_help_name, NULL),
2710 GEN_INT_OPTION(gui_gtk3_governor_range_min,
2711 N_("Minimum surplus for a governor"),
2712 N_("The lower limit of the range for requesting surpluses "
2713 "from the governor."),
2714 COC_INTERFACE, GUI_GTK3, GUI_GTK3_GOV_RANGE_MIN_DEFAULT,
2715 GUI_GTK3_GOV_RANGE_MIN_MIN, GUI_GTK3_GOV_RANGE_MIN_MAX,
2716 NULL),
2717 GEN_INT_OPTION(gui_gtk3_governor_range_max,
2718 N_("Maximum surplus for a governor"),
2719 N_("The higher limit of the range for requesting surpluses "
2720 "from the governor."),
2721 COC_INTERFACE, GUI_GTK3, GUI_GTK3_GOV_RANGE_MAX_DEFAULT,
2722 GUI_GTK3_GOV_RANGE_MAX_MIN, GUI_GTK3_GOV_RANGE_MAX_MAX,
2723 NULL),
2724 GEN_FONT_OPTION(gui_gtk3_font_city_label, "city_label",
2725 N_("City Label"),
2726 N_("This font is used to display the city labels on city "
2727 "dialogs."),
2728 COC_FONT, GUI_GTK3,
2729 "Monospace 8", font_changed_callback),
2730 GEN_FONT_OPTION(gui_gtk3_font_notify_label, "notify_label",
2731 N_("Notify Label"),
2732 N_("This font is used to display server reports such "
2733 "as the demographic report or historian publications."),
2734 COC_FONT, GUI_GTK3,
2735 "Monospace Bold 9", font_changed_callback),
2736 GEN_FONT_OPTION(gui_gtk3_font_spaceship_label, "spaceship_label",
2737 N_("Spaceship Label"),
2738 N_("This font is used to display the spaceship widgets."),
2739 COC_FONT, GUI_GTK3,
2740 "Monospace 8", font_changed_callback),
2741 GEN_FONT_OPTION(gui_gtk3_font_help_label, "help_label",
2742 N_("Help Label"),
2743 N_("This font is used to display the help headers in the "
2744 "help window."),
2745 COC_FONT, GUI_GTK3,
2746 "Sans Bold 10", font_changed_callback),
2747 GEN_FONT_OPTION(gui_gtk3_font_help_link, "help_link",
2748 N_("Help Link"),
2749 N_("This font is used to display the help links in the "
2750 "help window."),
2751 COC_FONT, GUI_GTK3,
2752 "Sans 9", font_changed_callback),
2753 GEN_FONT_OPTION(gui_gtk3_font_help_text, "help_text",
2754 N_("Help Text"),
2755 N_("This font is used to display the help body text in "
2756 "the help window."),
2757 COC_FONT, GUI_GTK3,
2758 "Monospace 8", font_changed_callback),
2759 GEN_FONT_OPTION(gui_gtk3_font_chatline, "chatline",
2760 N_("Chatline Area"),
2761 N_("This font is used to display the text in the "
2762 "chatline area."),
2763 COC_FONT, GUI_GTK3,
2764 "Monospace 8", font_changed_callback),
2765 GEN_FONT_OPTION(gui_gtk3_font_beta_label, "beta_label",
2766 N_("Beta Label"),
2767 N_("This font is used to display the beta label."),
2768 COC_FONT, GUI_GTK3,
2769 "Sans Italic 10", font_changed_callback),
2770 GEN_FONT_OPTION(gui_gtk3_font_small, "small_font",
2771 N_("Small Font"),
2772 N_("This font is used for any small font request. For "
2773 "example, it is used for display the building lists "
2774 "in the city dialog, the Economy report or the Units "
2775 "report."),
2776 COC_FONT, GUI_GTK3,
2777 "Sans 9", NULL),
2778 GEN_FONT_OPTION(gui_gtk3_font_comment_label, "comment_label",
2779 N_("Comment Label"),
2780 N_("This font is used to display comment labels, such as "
2781 "in the governor page of the city dialogs."),
2782 COC_FONT, GUI_GTK3,
2783 "Sans Italic 9", font_changed_callback),
2784 GEN_FONT_OPTION(gui_gtk3_font_city_names, "city_names",
2785 N_("City Names"),
2786 N_("This font is used to the display the city names "
2787 "on the map."),
2788 COC_FONT, GUI_GTK3,
2789 "Sans Bold 10", NULL),
2790 GEN_FONT_OPTION(gui_gtk3_font_city_productions, "city_productions",
2791 N_("City Productions"),
2792 N_("This font is used to the display the city production "
2793 "names on the map."),
2794 COC_FONT, GUI_GTK3,
2795 "Serif 10", NULL),
2796 GEN_FONT_OPTION(gui_gtk3_font_reqtree_text, "reqtree_text",
2797 N_("Requirement Tree"),
2798 N_("This font is used to the display the requirement tree "
2799 "in the Research report."),
2800 COC_FONT, GUI_GTK3,
2801 "Serif 10", NULL),
2803 /* gui-gtk-3.22 client specific options. */
2804 GEN_BOOL_OPTION(gui_gtk3_22_fullscreen, N_("Fullscreen"),
2805 N_("If this option is set the client will use the "
2806 "whole screen area for drawing."),
2807 COC_INTERFACE, GUI_GTK3_22, FALSE, NULL),
2808 GEN_BOOL_OPTION(gui_gtk3_22_map_scrollbars, N_("Show map scrollbars"),
2809 N_("Disable this option to hide the scrollbars on the "
2810 "map view."),
2811 COC_INTERFACE, GUI_GTK3_22, FALSE, NULL),
2812 GEN_BOOL_OPTION(gui_gtk3_22_dialogs_on_top, N_("Keep dialogs on top"),
2813 N_("If this option is set then dialog windows will always "
2814 "remain in front of the main Freeciv window. "
2815 "Disabling this has no effect in fullscreen mode."),
2816 COC_INTERFACE, GUI_GTK3_22, TRUE, NULL),
2817 GEN_BOOL_OPTION(gui_gtk3_22_show_task_icons, N_("Show worklist task icons"),
2818 N_("Disabling this will turn off the unit and building "
2819 "icons in the worklist dialog and the production "
2820 "tab of the city dialog."),
2821 COC_GRAPHICS, GUI_GTK3_22, TRUE, NULL),
2822 GEN_BOOL_OPTION(gui_gtk3_22_enable_tabs, N_("Enable status report tabs"),
2823 N_("If this option is enabled then report dialogs will "
2824 "be shown as separate tabs rather than in popup "
2825 "dialogs."),
2826 COC_INTERFACE, GUI_GTK3_22, TRUE, NULL),
2827 GEN_BOOL_OPTION(gui_gtk3_22_show_chat_message_time,
2828 N_("Show time for each chat message"),
2829 N_("If this option is enabled then all chat messages "
2830 "will be prefixed by a time string of the form "
2831 "[hour:minute:second]."),
2832 COC_INTERFACE, GUI_GTK3_22, FALSE, NULL),
2833 GEN_BOOL_OPTION(gui_gtk3_22_new_messages_go_to_top,
2834 N_("New message events go to top of list"),
2835 N_("If this option is enabled, new events in the "
2836 "message window will appear at the top of the list, "
2837 "rather than being appended at the bottom."),
2838 COC_INTERFACE, GUI_GTK3_22, FALSE, NULL),
2839 GEN_BOOL_OPTION(gui_gtk3_22_show_message_window_buttons,
2840 N_("Show extra message window buttons"),
2841 N_("If this option is enabled, there will be two "
2842 "buttons displayed in the message window for "
2843 "inspecting a city and going to a location. If this "
2844 "option is disabled, these buttons will not appear "
2845 "(you can still double-click with the left mouse "
2846 "button or right-click on a row to inspect or goto "
2847 "respectively). This option will only take effect "
2848 "once the message window is closed and reopened."),
2849 COC_INTERFACE, GUI_GTK3_22, TRUE, NULL),
2850 GEN_BOOL_OPTION(gui_gtk3_22_metaserver_tab_first,
2851 N_("Metaserver tab first in network page"),
2852 N_("If this option is enabled, the metaserver tab will "
2853 "be the first notebook tab in the network page. This "
2854 "option requires a restart in order to take effect."),
2855 COC_NETWORK, GUI_GTK3_22, FALSE, NULL),
2856 GEN_BOOL_OPTION(gui_gtk3_22_allied_chat_only,
2857 N_("Plain chat messages are sent to allies only"),
2858 N_("If this option is enabled, then plain messages "
2859 "typed into the chat entry while the game is "
2860 "running will only be sent to your allies. "
2861 "Otherwise plain messages will be sent as "
2862 "public chat messages. To send a public chat "
2863 "message with this option enabled, prefix the "
2864 "message with a single colon ':'. This option "
2865 "can also be set using a toggle button beside "
2866 "the chat entry (only visible in multiplayer "
2867 "games)."),
2868 COC_INTERFACE, GUI_GTK3_22, FALSE, NULL),
2869 GEN_ENUM_OPTION(gui_gtk3_22_message_chat_location,
2870 N_("Messages and Chat reports location"),
2871 /* TRANS: The strings used in the UI for 'Split' etc are
2872 * tagged 'gui_gtk2/gtk3_message_chat_location' */
2873 N_("Controls where the Messages and Chat reports "
2874 "appear relative to the main view containing the map.\n"
2875 "'Split' allows all three to be seen simultaneously, "
2876 "which is best for multiplayer, but requires a large "
2877 "window to be usable.\n"
2878 "'Separate' puts Messages and Chat in a notebook "
2879 "separate from the main view, so that one of them "
2880 "can always be seen alongside the main view.\n"
2881 "'Merged' makes the Messages and Chat reports into "
2882 "tabs alongside the map and other reports; this "
2883 "allows a larger map view on small screens.\n"
2884 "This option requires a restart in order to take "
2885 "effect."), COC_INTERFACE, GUI_GTK3_22,
2886 GUI_GTK_MSGCHAT_MERGED /* Ignored! See options_load(). */,
2887 gui_gtk_message_chat_location_name, NULL),
2888 GEN_BOOL_OPTION(gui_gtk3_22_small_display_layout,
2889 N_("Arrange widgets for small displays"),
2890 N_("If this option is enabled, widgets in the main "
2891 "window will be arranged so that they take up the "
2892 "least amount of total screen space. Specifically, "
2893 "the left panel containing the overview, player "
2894 "status, and the unit information box will be "
2895 "extended over the entire left side of the window. "
2896 "This option requires a restart in order to take "
2897 "effect."), COC_INTERFACE, GUI_GTK3_22, TRUE, NULL),
2898 GEN_BOOL_OPTION(gui_gtk3_22_mouse_over_map_focus,
2899 N_("Mouse over the map widget selects it automatically"),
2900 N_("If this option is enabled, then the map will be "
2901 "focused when the mouse hovers over it."),
2902 COC_INTERFACE, GUI_GTK3_22, FALSE, NULL),
2903 GEN_BOOL_OPTION(gui_gtk3_22_chatline_autocompletion,
2904 N_("Player or user name autocompletion"),
2905 N_("If this option is turned on, the tabulation key "
2906 "will be used in the chatline to complete the word you "
2907 "are typing with the name of a player or a user."),
2908 COC_INTERFACE, GUI_GTK3_22, TRUE, NULL),
2909 GEN_INT_OPTION(gui_gtk3_22_citydlg_xsize,
2910 N_("Width of the city dialog"),
2911 N_("This value is only used if the width of the city "
2912 "dialog is saved."),
2913 COC_INTERFACE, GUI_GTK3_22, GUI_GTK3_22_CITYDLG_DEFAULT_XSIZE,
2914 GUI_GTK3_22_CITYDLG_MIN_XSIZE, GUI_GTK3_22_CITYDLG_MAX_XSIZE,
2915 NULL),
2916 GEN_INT_OPTION(gui_gtk3_22_citydlg_ysize,
2917 N_("Height of the city dialog"),
2918 N_("This value is only used if the height of the city "
2919 "dialog is saved."),
2920 COC_INTERFACE, GUI_GTK3_22, GUI_GTK3_22_CITYDLG_DEFAULT_YSIZE,
2921 GUI_GTK3_22_CITYDLG_MIN_YSIZE, GUI_GTK3_22_CITYDLG_MAX_YSIZE,
2922 NULL),
2923 GEN_ENUM_OPTION(gui_gtk3_22_popup_tech_help,
2924 N_("Popup tech help when gained"),
2925 N_("Controls if tech help should be opened when "
2926 "new tech has been gained.\n"
2927 "'Ruleset' means that behavior suggested by "
2928 "current ruleset is used."), COC_INTERFACE, GUI_GTK3_22,
2929 GUI_POPUP_TECH_HELP_RULESET,
2930 gui_popup_tech_help_name, NULL),
2931 GEN_INT_OPTION(gui_gtk3_22_governor_range_min,
2932 N_("Minimum surplus for a governor"),
2933 N_("The lower limit of the range for requesting surpluses "
2934 "from the governor."),
2935 COC_INTERFACE, GUI_GTK3_22, GUI_GTK3_22_GOV_RANGE_MIN_DEFAULT,
2936 GUI_GTK3_22_GOV_RANGE_MIN_MIN, GUI_GTK3_22_GOV_RANGE_MIN_MAX,
2937 NULL),
2938 GEN_INT_OPTION(gui_gtk3_22_governor_range_max,
2939 N_("Maximum surplus for a governor"),
2940 N_("The higher limit of the range for requesting surpluses "
2941 "from the governor."),
2942 COC_INTERFACE, GUI_GTK3_22, GUI_GTK3_22_GOV_RANGE_MAX_DEFAULT,
2943 GUI_GTK3_22_GOV_RANGE_MAX_MIN, GUI_GTK3_22_GOV_RANGE_MAX_MAX,
2944 NULL),
2945 GEN_FONT_OPTION(gui_gtk3_22_font_city_label, "city_label",
2946 N_("City Label"),
2947 N_("This font is used to display the city labels on city "
2948 "dialogs."),
2949 COC_FONT, GUI_GTK3_22,
2950 "Monospace 8", font_changed_callback),
2951 GEN_FONT_OPTION(gui_gtk3_22_font_notify_label, "notify_label",
2952 N_("Notify Label"),
2953 N_("This font is used to display server reports such "
2954 "as the demographic report or historian publications."),
2955 COC_FONT, GUI_GTK3_22,
2956 "Monospace Bold 9", font_changed_callback),
2957 GEN_FONT_OPTION(gui_gtk3_22_font_spaceship_label, "spaceship_label",
2958 N_("Spaceship Label"),
2959 N_("This font is used to display the spaceship widgets."),
2960 COC_FONT, GUI_GTK3_22,
2961 "Monospace 8", font_changed_callback),
2962 GEN_FONT_OPTION(gui_gtk3_22_font_help_label, "help_label",
2963 N_("Help Label"),
2964 N_("This font is used to display the help headers in the "
2965 "help window."),
2966 COC_FONT, GUI_GTK3_22,
2967 "Sans Bold 10", font_changed_callback),
2968 GEN_FONT_OPTION(gui_gtk3_22_font_help_link, "help_link",
2969 N_("Help Link"),
2970 N_("This font is used to display the help links in the "
2971 "help window."),
2972 COC_FONT, GUI_GTK3_22,
2973 "Sans 9", font_changed_callback),
2974 GEN_FONT_OPTION(gui_gtk3_22_font_help_text, "help_text",
2975 N_("Help Text"),
2976 N_("This font is used to display the help body text in "
2977 "the help window."),
2978 COC_FONT, GUI_GTK3_22,
2979 "Monospace 8", font_changed_callback),
2980 GEN_FONT_OPTION(gui_gtk3_22_font_chatline, "chatline",
2981 N_("Chatline Area"),
2982 N_("This font is used to display the text in the "
2983 "chatline area."),
2984 COC_FONT, GUI_GTK3_22,
2985 "Monospace 8", font_changed_callback),
2986 GEN_FONT_OPTION(gui_gtk3_22_font_beta_label, "beta_label",
2987 N_("Beta Label"),
2988 N_("This font is used to display the beta label."),
2989 COC_FONT, GUI_GTK3_22,
2990 "Sans Italic 10", font_changed_callback),
2991 GEN_FONT_OPTION(gui_gtk3_22_font_small, "small_font",
2992 N_("Small Font"),
2993 N_("This font is used for any small font request. For "
2994 "example, it is used for display the building lists "
2995 "in the city dialog, the Economy report or the Units "
2996 "report."),
2997 COC_FONT, GUI_GTK3_22,
2998 "Sans 9", NULL),
2999 GEN_FONT_OPTION(gui_gtk3_22_font_comment_label, "comment_label",
3000 N_("Comment Label"),
3001 N_("This font is used to display comment labels, such as "
3002 "in the governor page of the city dialogs."),
3003 COC_FONT, GUI_GTK3_22,
3004 "Sans Italic 9", font_changed_callback),
3005 GEN_FONT_OPTION(gui_gtk3_22_font_city_names, "city_names",
3006 N_("City Names"),
3007 N_("This font is used to the display the city names "
3008 "on the map."),
3009 COC_FONT, GUI_GTK3_22,
3010 "Sans Bold 10", NULL),
3011 GEN_FONT_OPTION(gui_gtk3_22_font_city_productions, "city_productions",
3012 N_("City Productions"),
3013 N_("This font is used to the display the city production "
3014 "names on the map."),
3015 COC_FONT, GUI_GTK3_22,
3016 "Serif 10", NULL),
3017 GEN_FONT_OPTION(gui_gtk3_22_font_reqtree_text, "reqtree_text",
3018 N_("Requirement Tree"),
3019 N_("This font is used to the display the requirement tree "
3020 "in the Research report."),
3021 COC_FONT, GUI_GTK3_22,
3022 "Serif 10", NULL),
3024 /* gui-sdl client specific options. */
3025 GEN_BOOL_OPTION(gui_sdl_fullscreen, N_("Fullscreen"),
3026 N_("If this option is set the client will use the "
3027 "whole screen area for drawing."),
3028 COC_INTERFACE, GUI_SDL, FALSE, NULL),
3029 GEN_VIDEO_OPTION(gui_sdl_screen, N_("Screen resolution"),
3030 N_("This option controls the resolution of the "
3031 "selected screen."),
3032 COC_INTERFACE, GUI_SDL, 640, 480, NULL),
3033 GEN_BOOL_OPTION(gui_sdl_do_cursor_animation, N_("Do cursor animation"),
3034 N_("If this option is disabled, the cursor will "
3035 "always be displayed as static."),
3036 COC_INTERFACE, GUI_SDL, TRUE, NULL),
3037 GEN_BOOL_OPTION(gui_sdl_use_color_cursors, N_("Use color cursors"),
3038 N_("If this option is disabled, the cursor will "
3039 "always be displayed in black and white."),
3040 COC_INTERFACE, GUI_SDL, TRUE, NULL),
3042 /* gui-sdl2 client specific options. */
3043 GEN_BOOL_OPTION(gui_sdl2_fullscreen, N_("Fullscreen"),
3044 N_("If this option is set the client will use the "
3045 "whole screen area for drawing."),
3046 COC_INTERFACE, GUI_SDL2, FALSE, NULL),
3047 GEN_VIDEO_OPTION(gui_sdl2_screen, N_("Screen resolution"),
3048 N_("This option controls the resolution of the "
3049 "selected screen."),
3050 COC_INTERFACE, GUI_SDL2, 640, 480, NULL),
3051 GEN_BOOL_OPTION(gui_sdl2_swrenderer, N_("Use software rendering"),
3052 N_("Usually hardware rendering is used when possible. "
3053 "With this option set, software rendering is always used."),
3054 COC_GRAPHICS, GUI_SDL2, FALSE, NULL),
3055 GEN_BOOL_OPTION(gui_sdl2_do_cursor_animation, N_("Do cursor animation"),
3056 N_("If this option is disabled, the cursor will "
3057 "always be displayed as static."),
3058 COC_INTERFACE, GUI_SDL2, TRUE, NULL),
3059 GEN_BOOL_OPTION(gui_sdl2_use_color_cursors, N_("Use color cursors"),
3060 N_("If this option is disabled, the cursor will "
3061 "always be displayed in black and white."),
3062 COC_INTERFACE, GUI_SDL2, TRUE, NULL),
3064 /* gui-qt client specific options. */
3065 GEN_BOOL_OPTION(gui_qt_fullscreen, N_("Fullscreen"),
3066 N_("If this option is set the client will use the "
3067 "whole screen area for drawing."),
3068 COC_INTERFACE, GUI_QT, FALSE, NULL),
3069 GEN_BOOL_OPTION(gui_qt_show_titlebar, N_("Show titlebar"),
3070 N_("If this option is set the client will show a titlebar. "
3071 "If disabled, then no titlebar will be shown, and "
3072 "minimize/maximize/etc buttons will be placed on the "
3073 "menu bar."),
3074 COC_INTERFACE, GUI_QT, TRUE, NULL),
3075 GEN_FONT_OPTION(gui_qt_font_city_label, "city_label",
3076 N_("City Label"),
3077 N_("This font is used to display the city labels on city "
3078 "dialogs."),
3079 COC_FONT, GUI_QT,
3080 "Monospace,8,-1,5,50,0,0,0,0,0", font_changed_callback),
3081 GEN_FONT_OPTION(gui_qt_font_default, "default_font",
3082 N_("Default font"),
3083 N_("This is default font"),
3084 COC_FONT, GUI_QT,
3085 "Sans Serif,10,-1,5,75,0,0,0,0,0", font_changed_callback),
3086 GEN_FONT_OPTION(gui_qt_font_notify_label, "notify_label",
3087 N_("Notify Label"),
3088 N_("This font is used to display server reports such "
3089 "as the demographic report or historian publications."),
3090 COC_FONT, GUI_QT,
3091 "Monospace,9,-1,5,75,0,0,0,0,0", font_changed_callback),
3092 GEN_FONT_OPTION(gui_qt_font_spaceship_label, "spaceship_label",
3093 N_("Spaceship Label"),
3094 N_("This font is used to display the spaceship widgets."),
3095 COC_FONT, GUI_QT,
3096 "Monospace,8,-1,5,50,0,0,0,0,0", font_changed_callback),
3097 GEN_FONT_OPTION(gui_qt_font_help_label, "help_label",
3098 N_("Help Label"),
3099 N_("This font is used to display the help labels in the "
3100 "help window."),
3101 COC_FONT, GUI_QT,
3102 "Sans Serif,9,-1,5,50,0,0,0,0,0", font_changed_callback),
3103 GEN_FONT_OPTION(gui_qt_font_help_link, "help_link",
3104 N_("Help Link"),
3105 N_("This font is used to display the help links in the "
3106 "help window."),
3107 COC_FONT, GUI_QT,
3108 "Sans Serif,9,-1,5,50,0,0,0,0,0", font_changed_callback),
3109 GEN_FONT_OPTION(gui_qt_font_help_text, "help_text",
3110 N_("Help Text"),
3111 N_("This font is used to display the help body text in "
3112 "the help window."),
3113 COC_FONT, GUI_QT,
3114 "Monospace,8,-1,5,50,0,0,0,0,0", font_changed_callback),
3115 GEN_FONT_OPTION(gui_qt_font_help_title, "help_title",
3116 N_("Help Title"),
3117 N_("This font is used to display the help title in "
3118 "the help window."),
3119 COC_FONT, GUI_QT,
3120 "Sans Serif,10,-1,5,75,0,0,0,0,0", font_changed_callback),
3121 GEN_FONT_OPTION(gui_qt_font_chatline, "chatline",
3122 N_("Chatline Area"),
3123 N_("This font is used to display the text in the "
3124 "chatline area."),
3125 COC_FONT, GUI_QT,
3126 "Monospace,8,-1,5,50,0,0,0,0,0", font_changed_callback),
3127 GEN_FONT_OPTION(gui_qt_font_beta_label, "beta_label",
3128 N_("Beta Label"),
3129 N_("This font is used to display the beta label."),
3130 COC_FONT, GUI_QT,
3131 "Sans Serif,10,-1,5,50,1,0,0,0,0", font_changed_callback),
3132 GEN_FONT_OPTION(gui_qt_font_small, "small_font",
3133 N_("Small Font"),
3134 N_("This font is used for any small font request. For "
3135 "example, it is used for display the building lists "
3136 "in the city dialog, the Economy report or the Units "
3137 "report."),
3138 COC_FONT, GUI_QT,
3139 "Sans Serif,9,-1,5,50,0,0,0,0,0", font_changed_callback),
3140 GEN_FONT_OPTION(gui_qt_font_comment_label, "comment_label",
3141 N_("Comment Label"),
3142 N_("This font is used to display comment labels, such as "
3143 "in the governor page of the city dialogs."),
3144 COC_FONT, GUI_QT,
3145 "Sans Serif,9,-1,5,50,1,0,0,0,0", font_changed_callback),
3146 GEN_FONT_OPTION(gui_qt_font_city_names, "city_names",
3147 N_("City Names"),
3148 N_("This font is used to the display the city names "
3149 "on the map."),
3150 COC_FONT, GUI_QT,
3151 "Sans Serif,10,-1,5,75,0,0,0,0,0", font_changed_callback),
3152 GEN_FONT_OPTION(gui_qt_font_city_productions, "city_productions",
3153 N_("City Productions"),
3154 N_("This font is used to the display the city production "
3155 "names on the map."),
3156 COC_FONT, GUI_QT,
3157 "Sans Serif,10,-1,5,50,1,0,0,0,0", font_changed_callback),
3158 GEN_FONT_OPTION(gui_qt_font_reqtree_text, "reqtree_text",
3159 N_("Requirement Tree"),
3160 N_("This font is used to the display the requirement tree "
3161 "in the Research report."),
3162 COC_FONT, GUI_QT,
3163 "Sans Serif,10,-1,5,50,1,0,0,0,0", font_changed_callback),
3164 GEN_BOOL_OPTION(gui_qt_show_preview, N_("Show savegame information"),
3165 N_("If this option is set the client will show "
3166 "information and map preview about current savegame "),
3167 COC_GRAPHICS, GUI_QT, TRUE, NULL),
3168 GEN_BOOL_OPTION(gui_qt_sidebar_left, N_("Sidebar position"),
3169 N_("If this option is set sidebar will be on left, "
3170 "otherwise it will on right side of map"),
3171 COC_INTERFACE, GUI_QT, TRUE, NULL),
3172 GEN_STR_OPTION(gui_qt_wakeup_text,
3173 N_("Wake up sequence"),
3174 N_("String which will trigger sound in pregame page, "
3175 "%1 stands for nick"),
3176 COC_INTERFACE, GUI_QT, "Wake up %1", NULL, 0)
3179 static const int client_options_num = ARRAY_SIZE(client_options);
3181 /* Iteration loop, including invalid options for the current gui type. */
3182 #define client_options_iterate_all(poption) \
3184 const struct client_option *const poption##_max = \
3185 client_options + client_options_num; \
3186 struct client_option *client_##poption = client_options; \
3187 struct option *poption; \
3188 for (; client_##poption < poption##_max; client_##poption++) { \
3189 poption = OPTION(client_##poption);
3191 #define client_options_iterate_all_end \
3196 /****************************************************************************
3197 Returns the next valid option pointer for the current gui type.
3198 ****************************************************************************/
3199 static struct client_option *
3200 client_option_next_valid(struct client_option *poption)
3202 const struct client_option *const max =
3203 client_options + client_options_num;
3204 const enum gui_type our_type = get_gui_type();
3206 while (poption < max
3207 && poption->specific != GUI_STUB
3208 && poption->specific != our_type) {
3209 poption++;
3212 return (poption < max ? poption : NULL);
3215 /****************************************************************************
3216 Returns the option corresponding to this id.
3217 ****************************************************************************/
3218 static struct option *client_optset_option_by_number(int id)
3220 if (0 > id || id > client_options_num) {
3221 return NULL;
3223 return OPTION(client_options + id);
3226 /****************************************************************************
3227 Returns the first valid option pointer for the current gui type.
3228 ****************************************************************************/
3229 static struct option *client_optset_option_first(void)
3231 return OPTION(client_option_next_valid(client_options));
3234 /****************************************************************************
3235 Returns the number of client option categories.
3236 ****************************************************************************/
3237 static int client_optset_category_number(void)
3239 return COC_MAX;
3242 /****************************************************************************
3243 Returns the name (translated) of the option class.
3244 ****************************************************************************/
3245 static const char *client_optset_category_name(int category)
3247 switch (category) {
3248 case COC_GRAPHICS:
3249 return _("Graphics");
3250 case COC_OVERVIEW:
3251 /* TRANS: Options section for overview map (mini-map) */
3252 return Q_("?map:Overview");
3253 case COC_SOUND:
3254 return _("Sound");
3255 case COC_INTERFACE:
3256 return _("Interface");
3257 case COC_MAPIMG:
3258 return _("Map Image");
3259 case COC_NETWORK:
3260 return _("Network");
3261 case COC_FONT:
3262 return _("Font");
3263 case COC_MAX:
3264 break;
3267 log_error("%s: invalid option category number %d.",
3268 __FUNCTION__, category);
3269 return NULL;
3272 /***************************************************************************
3273 Returns the number of this client option.
3274 ****************************************************************************/
3275 static int client_option_number(const struct option *poption)
3277 return CLIENT_OPTION(poption) - client_options;
3280 /****************************************************************************
3281 Returns the name of this client option.
3282 ****************************************************************************/
3283 static const char *client_option_name(const struct option *poption)
3285 return CLIENT_OPTION(poption)->name;
3288 /****************************************************************************
3289 Returns the description of this client option.
3290 ****************************************************************************/
3291 static const char *client_option_description(const struct option *poption)
3293 return _(CLIENT_OPTION(poption)->description);
3296 /****************************************************************************
3297 Returns the help text for this client option.
3298 ****************************************************************************/
3299 static const char *client_option_help_text(const struct option *poption)
3301 return _(CLIENT_OPTION(poption)->help_text);
3304 /****************************************************************************
3305 Returns the category of this client option.
3306 ****************************************************************************/
3307 static int client_option_category(const struct option *poption)
3309 return CLIENT_OPTION(poption)->category;
3312 /****************************************************************************
3313 Returns TRUE if this client option can be modified.
3314 ****************************************************************************/
3315 static bool client_option_is_changeable(const struct option *poption)
3317 return TRUE;
3320 /****************************************************************************
3321 Returns the next valid option pointer for the current gui type.
3322 ****************************************************************************/
3323 static struct option *client_option_next(const struct option *poption)
3325 return OPTION(client_option_next_valid(CLIENT_OPTION(poption) + 1));
3328 /****************************************************************************
3329 Returns the value of this client option of type OT_BOOLEAN.
3330 ****************************************************************************/
3331 static bool client_option_bool_get(const struct option *poption)
3333 return *(CLIENT_OPTION(poption)->boolean.pvalue);
3336 /****************************************************************************
3337 Returns the default value of this client option of type OT_BOOLEAN.
3338 ****************************************************************************/
3339 static bool client_option_bool_def(const struct option *poption)
3341 return CLIENT_OPTION(poption)->boolean.def;
3344 /****************************************************************************
3345 Set the value of this client option of type OT_BOOLEAN. Returns TRUE if
3346 the value changed.
3347 ****************************************************************************/
3348 static bool client_option_bool_set(struct option *poption, bool val)
3350 struct client_option *pcoption = CLIENT_OPTION(poption);
3352 if (*pcoption->boolean.pvalue == val) {
3353 return FALSE;
3356 *pcoption->boolean.pvalue = val;
3357 return TRUE;
3360 /****************************************************************************
3361 Returns the value of this client option of type OT_INTEGER.
3362 ****************************************************************************/
3363 static int client_option_int_get(const struct option *poption)
3365 return *(CLIENT_OPTION(poption)->integer.pvalue);
3368 /****************************************************************************
3369 Returns the default value of this client option of type OT_INTEGER.
3370 ****************************************************************************/
3371 static int client_option_int_def(const struct option *poption)
3373 return CLIENT_OPTION(poption)->integer.def;
3376 /****************************************************************************
3377 Returns the minimal value for this client option of type OT_INTEGER.
3378 ****************************************************************************/
3379 static int client_option_int_min(const struct option *poption)
3381 return CLIENT_OPTION(poption)->integer.min;
3384 /****************************************************************************
3385 Returns the maximal value for this client option of type OT_INTEGER.
3386 ****************************************************************************/
3387 static int client_option_int_max(const struct option *poption)
3389 return CLIENT_OPTION(poption)->integer.max;
3392 /****************************************************************************
3393 Set the value of this client option of type OT_INTEGER. Returns TRUE if
3394 the value changed.
3395 ****************************************************************************/
3396 static bool client_option_int_set(struct option *poption, int val)
3398 struct client_option *pcoption = CLIENT_OPTION(poption);
3400 if (val < pcoption->integer.min
3401 || val > pcoption->integer.max
3402 || *pcoption->integer.pvalue == val) {
3403 return FALSE;
3406 *pcoption->integer.pvalue = val;
3407 return TRUE;
3410 /****************************************************************************
3411 Returns the value of this client option of type OT_STRING.
3412 ****************************************************************************/
3413 static const char *client_option_str_get(const struct option *poption)
3415 return CLIENT_OPTION(poption)->string.pvalue;
3418 /****************************************************************************
3419 Returns the default value of this client option of type OT_STRING.
3420 ****************************************************************************/
3421 static const char *client_option_str_def(const struct option *poption)
3423 return CLIENT_OPTION(poption)->string.def;
3426 /****************************************************************************
3427 Returns the possible string values of this client option of type
3428 OT_STRING.
3429 ****************************************************************************/
3430 static const struct strvec *
3431 client_option_str_values(const struct option *poption)
3433 return (CLIENT_OPTION(poption)->string.val_accessor
3434 ? CLIENT_OPTION(poption)->string.val_accessor(poption) : NULL);
3437 /****************************************************************************
3438 Set the value of this client option of type OT_STRING. Returns TRUE if
3439 the value changed.
3440 ****************************************************************************/
3441 static bool client_option_str_set(struct option *poption, const char *str)
3443 struct client_option *pcoption = CLIENT_OPTION(poption);
3445 if (strlen(str) >= pcoption->string.size
3446 || 0 == strcmp(pcoption->string.pvalue, str)) {
3447 return FALSE;
3450 fc_strlcpy(pcoption->string.pvalue, str, pcoption->string.size);
3451 return TRUE;
3454 /****************************************************************************
3455 Returns the current value of this client option of type OT_ENUM.
3456 ****************************************************************************/
3457 static int client_option_enum_get(const struct option *poption)
3459 return *(CLIENT_OPTION(poption)->enumerator.pvalue);
3462 /****************************************************************************
3463 Returns the default value of this client option of type OT_ENUM.
3464 ****************************************************************************/
3465 static int client_option_enum_def(const struct option *poption)
3467 return CLIENT_OPTION(poption)->enumerator.def;
3470 /****************************************************************************
3471 Returns the possible values of this client option of type OT_ENUM, as
3472 user-visible (translatable but not translated) strings.
3473 ****************************************************************************/
3474 static const struct strvec *
3475 client_option_enum_pretty_names(const struct option *poption)
3477 return CLIENT_OPTION(poption)->enumerator.pretty_names;
3480 /****************************************************************************
3481 Set the value of this client option of type OT_ENUM. Returns TRUE if
3482 the value changed.
3483 ****************************************************************************/
3484 static bool client_option_enum_set(struct option *poption, int val)
3486 struct client_option *pcoption = CLIENT_OPTION(poption);
3488 if (*pcoption->enumerator.pvalue == val
3489 || 0 > val
3490 || val >= strvec_size(pcoption->enumerator.support_names)) {
3491 return FALSE;
3494 *pcoption->enumerator.pvalue = val;
3495 return TRUE;
3498 /****************************************************************************
3499 Returns the "support" name of the value for this client option of type
3500 OT_ENUM (a string suitable for saving in a file).
3501 The prototype must match the 'secfile_enum_name_data_fn_t' type.
3502 ****************************************************************************/
3503 static const char *client_option_enum_secfile_str(secfile_data_t data,
3504 int val)
3506 const struct strvec *names = CLIENT_OPTION(data)->enumerator.support_names;
3508 return (0 <= val && val < strvec_size(names)
3509 ? strvec_get(names, val) : NULL);
3512 #if 0 /* There's no bitwise options currently */
3513 /****************************************************************************
3514 Returns the current value of this client option of type OT_BITWISE.
3515 ****************************************************************************/
3516 static unsigned client_option_bitwise_get(const struct option *poption)
3518 return *(CLIENT_OPTION(poption)->bitwise.pvalue);
3521 /****************************************************************************
3522 Returns the default value of this client option of type OT_BITWISE.
3523 ****************************************************************************/
3524 static unsigned client_option_bitwise_def(const struct option *poption)
3526 return CLIENT_OPTION(poption)->bitwise.def;
3529 /****************************************************************************
3530 Returns the possible values of this client option of type OT_BITWISE, as
3531 user-visible (translatable but not translated) strings.
3532 ****************************************************************************/
3533 static const struct strvec *
3534 client_option_bitwise_pretty_names(const struct option *poption)
3536 return CLIENT_OPTION(poption)->bitwise.pretty_names;
3539 /****************************************************************************
3540 Set the value of this client option of type OT_BITWISE. Returns TRUE if
3541 the value changed.
3542 ****************************************************************************/
3543 static bool client_option_bitwise_set(struct option *poption, unsigned val)
3545 struct client_option *pcoption = CLIENT_OPTION(poption);
3547 if (*pcoption->bitwise.pvalue == val) {
3548 return FALSE;
3551 *pcoption->bitwise.pvalue = val;
3552 return TRUE;
3554 #endif /* 0 */
3556 /****************************************************************************
3557 Returns the "support" name of a single value for this client option of type
3558 OT_BITWISE (a string suitable for saving in a file).
3559 The prototype must match the 'secfile_enum_name_data_fn_t' type.
3560 ****************************************************************************/
3561 static const char *client_option_bitwise_secfile_str(secfile_data_t data,
3562 int val)
3564 const struct strvec *names = CLIENT_OPTION(data)->bitwise.support_names;
3566 return (0 <= val && val < strvec_size(names)
3567 ? strvec_get(names, val) : NULL);
3570 /****************************************************************************
3571 Returns the value of this client option of type OT_FONT.
3572 ****************************************************************************/
3573 static const char *client_option_font_get(const struct option *poption)
3575 return CLIENT_OPTION(poption)->font.pvalue;
3578 /****************************************************************************
3579 Returns the default value of this client option of type OT_FONT.
3580 ****************************************************************************/
3581 static const char *client_option_font_def(const struct option *poption)
3583 return CLIENT_OPTION(poption)->font.def;
3586 /****************************************************************************
3587 Returns the target style name of this client option of type OT_FONT.
3588 ****************************************************************************/
3589 static const char *client_option_font_target(const struct option *poption)
3591 return CLIENT_OPTION(poption)->font.target;
3594 /****************************************************************************
3595 Set the value of this client option of type OT_FONT. Returns TRUE if
3596 the value changed.
3597 ****************************************************************************/
3598 static bool client_option_font_set(struct option *poption, const char *font)
3600 struct client_option *pcoption = CLIENT_OPTION(poption);
3602 if (strlen(font) >= pcoption->font.size
3603 || 0 == strcmp(pcoption->font.pvalue, font)) {
3604 return FALSE;
3607 fc_strlcpy(pcoption->font.pvalue, font, pcoption->font.size);
3608 return TRUE;
3611 /****************************************************************************
3612 Returns the value of this client option of type OT_COLOR.
3613 ****************************************************************************/
3614 static struct ft_color client_option_color_get(const struct option *poption)
3616 return *CLIENT_OPTION(poption)->color.pvalue;
3619 /****************************************************************************
3620 Returns the default value of this client option of type OT_COLOR.
3621 ****************************************************************************/
3622 static struct ft_color client_option_color_def(const struct option *poption)
3624 return CLIENT_OPTION(poption)->color.def;
3627 /****************************************************************************
3628 Set the value of this client option of type OT_COLOR. Returns TRUE if
3629 the value changed.
3630 ****************************************************************************/
3631 static bool client_option_color_set(struct option *poption,
3632 struct ft_color color)
3634 struct ft_color *pcolor = CLIENT_OPTION(poption)->color.pvalue;
3635 bool changed = FALSE;
3637 #define color_set(color_tgt, color) \
3638 if (NULL == color_tgt) { \
3639 if (NULL != color) { \
3640 color_tgt = fc_strdup(color); \
3641 changed = TRUE; \
3643 } else { \
3644 if (NULL == color) { \
3645 free((void *) color_tgt); \
3646 color_tgt = NULL; \
3647 changed = TRUE; \
3648 } else if (0 != strcmp(color_tgt, color)) { \
3649 free((void *) color_tgt); \
3650 color_tgt = fc_strdup(color); \
3651 changed = TRUE; \
3655 color_set(pcolor->foreground, color.foreground);
3656 color_set(pcolor->background, color.background);
3658 #undef color_set
3660 return changed;
3663 /****************************************************************************
3664 Returns the value of this client option of type OT_VIDEO_MODE.
3665 ****************************************************************************/
3666 static struct video_mode
3667 client_option_video_mode_get(const struct option *poption)
3669 return *CLIENT_OPTION(poption)->video_mode.pvalue;
3672 /****************************************************************************
3673 Returns the default value of this client option of type OT_VIDEO_MODE.
3674 ****************************************************************************/
3675 static struct video_mode
3676 client_option_video_mode_def(const struct option *poption)
3678 return CLIENT_OPTION(poption)->video_mode.def;
3681 /****************************************************************************
3682 Set the value of this client option of type OT_VIDEO_MODE. Returns TRUE
3683 if the value changed.
3684 ****************************************************************************/
3685 static bool client_option_video_mode_set(struct option *poption,
3686 struct video_mode mode)
3688 struct client_option *pcoption = CLIENT_OPTION(poption);
3690 if (0 == memcmp(&mode, pcoption->video_mode.pvalue,
3691 sizeof(struct video_mode))) {
3692 return FALSE;
3695 *pcoption->video_mode.pvalue = mode;
3696 return TRUE;
3699 /****************************************************************************
3700 Load the option from a file. Returns TRUE if the option changed.
3701 ****************************************************************************/
3702 static bool client_option_load(struct option *poption,
3703 struct section_file *sf)
3705 fc_assert_ret_val(NULL != poption, FALSE);
3706 fc_assert_ret_val(NULL != sf, FALSE);
3708 switch (option_type(poption)) {
3709 case OT_BOOLEAN:
3711 bool value;
3713 return (secfile_lookup_bool(sf, &value, "client.%s",
3714 option_name(poption))
3715 && option_bool_set(poption, value));
3717 case OT_INTEGER:
3719 int value;
3721 return (secfile_lookup_int(sf, &value, "client.%s",
3722 option_name(poption))
3723 && option_int_set(poption, value));
3725 case OT_STRING:
3727 const char *string;
3729 return ((string = secfile_lookup_str(sf, "client.%s",
3730 option_name(poption)))
3731 && option_str_set(poption, string));
3733 case OT_ENUM:
3735 int value;
3737 return (secfile_lookup_enum_data(sf, &value, FALSE,
3738 client_option_enum_secfile_str,
3739 poption, "client.%s",
3740 option_name(poption))
3741 && option_enum_set_int(poption, value));
3743 case OT_BITWISE:
3745 int value;
3747 return (secfile_lookup_enum_data(sf, &value, TRUE,
3748 client_option_bitwise_secfile_str,
3749 poption, "client.%s",
3750 option_name(poption))
3751 && option_bitwise_set(poption, value));
3753 case OT_FONT:
3755 const char *string;
3757 return ((string = secfile_lookup_str(sf, "client.%s",
3758 option_name(poption)))
3759 && option_font_set(poption, string));
3761 case OT_COLOR:
3763 struct ft_color color;
3765 return ((color.foreground =
3766 secfile_lookup_str(sf, "client.%s.foreground",
3767 option_name(poption)))
3768 && (color.background =
3769 secfile_lookup_str(sf, "client.%s.background",
3770 option_name(poption)))
3771 && option_color_set(poption, color));
3773 case OT_VIDEO_MODE:
3775 struct video_mode mode;
3777 return (secfile_lookup_int(sf, &mode.width, "client.%s.width",
3778 option_name(poption))
3779 && secfile_lookup_int(sf, &mode.height, "client.%s.height",
3780 option_name(poption))
3781 && option_video_mode_set(poption, mode));
3784 return FALSE;
3787 /****************************************************************************
3788 Save the option to a file.
3789 ****************************************************************************/
3790 static void client_option_save(struct option *poption,
3791 struct section_file *sf)
3793 fc_assert_ret(NULL != poption);
3794 fc_assert_ret(NULL != sf);
3796 switch (option_type(poption)) {
3797 case OT_BOOLEAN:
3798 secfile_insert_bool(sf, option_bool_get(poption),
3799 "client.%s", option_name(poption));
3800 break;
3801 case OT_INTEGER:
3802 secfile_insert_int(sf, option_int_get(poption),
3803 "client.%s", option_name(poption));
3804 break;
3805 case OT_STRING:
3806 secfile_insert_str(sf, option_str_get(poption),
3807 "client.%s", option_name(poption));
3808 break;
3809 case OT_ENUM:
3810 secfile_insert_enum_data(sf, option_enum_get_int(poption), FALSE,
3811 client_option_enum_secfile_str, poption,
3812 "client.%s", option_name(poption));
3813 break;
3814 case OT_BITWISE:
3815 secfile_insert_enum_data(sf, option_bitwise_get(poption), TRUE,
3816 client_option_bitwise_secfile_str, poption,
3817 "client.%s", option_name(poption));
3818 break;
3819 case OT_FONT:
3820 secfile_insert_str(sf, option_font_get(poption),
3821 "client.%s", option_name(poption));
3822 break;
3823 case OT_COLOR:
3825 struct ft_color color = option_color_get(poption);
3827 secfile_insert_str(sf, color.foreground, "client.%s.foreground",
3828 option_name(poption));
3829 secfile_insert_str(sf, color.background, "client.%s.background",
3830 option_name(poption));
3832 break;
3833 case OT_VIDEO_MODE:
3835 struct video_mode mode = option_video_mode_get(poption);
3837 secfile_insert_int(sf, mode.width, "client.%s.width",
3838 option_name(poption));
3839 secfile_insert_int(sf, mode.height, "client.%s.height",
3840 option_name(poption));
3842 break;
3847 /****************************************************************************
3848 Server options variables.
3849 ****************************************************************************/
3850 static char **server_options_categories = NULL;
3851 static struct server_option *server_options = NULL;
3853 static int server_options_categories_num = 0;
3854 static int server_options_num = 0;
3857 /****************************************************************************
3858 Server option set.
3859 ****************************************************************************/
3860 static struct option *server_optset_option_by_number(int id);
3861 static struct option *server_optset_option_first(void);
3862 static int server_optset_category_number(void);
3863 static const char *server_optset_category_name(int category);
3865 static struct option_set server_optset_static = {
3866 .option_by_number = server_optset_option_by_number,
3867 .option_first = server_optset_option_first,
3868 .category_number = server_optset_category_number,
3869 .category_name = server_optset_category_name
3871 const struct option_set *server_optset = &server_optset_static;
3874 /****************************************************************************
3875 Virtuals tables for the client options.
3876 ****************************************************************************/
3877 static int server_option_number(const struct option *poption);
3878 static const char *server_option_name(const struct option *poption);
3879 static const char *server_option_description(const struct option *poption);
3880 static const char *server_option_help_text(const struct option *poption);
3881 static int server_option_category(const struct option *poption);
3882 static bool server_option_is_changeable(const struct option *poption);
3883 static struct option *server_option_next(const struct option *poption);
3885 static const struct option_common_vtable server_option_common_vtable = {
3886 .number = server_option_number,
3887 .name = server_option_name,
3888 .description = server_option_description,
3889 .help_text = server_option_help_text,
3890 .category = server_option_category,
3891 .is_changeable = server_option_is_changeable,
3892 .next = server_option_next
3895 static bool server_option_bool_get(const struct option *poption);
3896 static bool server_option_bool_def(const struct option *poption);
3897 static bool server_option_bool_set(struct option *poption, bool val);
3899 static const struct option_bool_vtable server_option_bool_vtable = {
3900 .get = server_option_bool_get,
3901 .def = server_option_bool_def,
3902 .set = server_option_bool_set
3905 static int server_option_int_get(const struct option *poption);
3906 static int server_option_int_def(const struct option *poption);
3907 static int server_option_int_min(const struct option *poption);
3908 static int server_option_int_max(const struct option *poption);
3909 static bool server_option_int_set(struct option *poption, int val);
3911 static const struct option_int_vtable server_option_int_vtable = {
3912 .get = server_option_int_get,
3913 .def = server_option_int_def,
3914 .minimum = server_option_int_min,
3915 .maximum = server_option_int_max,
3916 .set = server_option_int_set
3919 static const char *server_option_str_get(const struct option *poption);
3920 static const char *server_option_str_def(const struct option *poption);
3921 static const struct strvec *
3922 server_option_str_values(const struct option *poption);
3923 static bool server_option_str_set(struct option *poption, const char *str);
3925 static const struct option_str_vtable server_option_str_vtable = {
3926 .get = server_option_str_get,
3927 .def = server_option_str_def,
3928 .values = server_option_str_values,
3929 .set = server_option_str_set
3932 static int server_option_enum_get(const struct option *poption);
3933 static int server_option_enum_def(const struct option *poption);
3934 static const struct strvec *
3935 server_option_enum_pretty(const struct option *poption);
3936 static bool server_option_enum_set(struct option *poption, int val);
3938 static const struct option_enum_vtable server_option_enum_vtable = {
3939 .get = server_option_enum_get,
3940 .def = server_option_enum_def,
3941 .values = server_option_enum_pretty,
3942 .set = server_option_enum_set,
3943 .cmp = strcmp
3946 static unsigned server_option_bitwise_get(const struct option *poption);
3947 static unsigned server_option_bitwise_def(const struct option *poption);
3948 static const struct strvec *
3949 server_option_bitwise_pretty(const struct option *poption);
3950 static bool server_option_bitwise_set(struct option *poption, unsigned val);
3952 static const struct option_bitwise_vtable server_option_bitwise_vtable = {
3953 .get = server_option_bitwise_get,
3954 .def = server_option_bitwise_def,
3955 .values = server_option_bitwise_pretty,
3956 .set = server_option_bitwise_set
3959 /****************************************************************************
3960 Derived class server option, inheriting from base class option.
3961 ****************************************************************************/
3962 struct server_option {
3963 struct option base_option; /* Base structure, must be the first! */
3965 char *name; /* Short name - used as an identifier */
3966 char *description; /* One-line description */
3967 char *help_text; /* Paragraph-length help text */
3968 unsigned char category;
3969 bool desired_sent;
3970 bool is_changeable;
3971 bool is_visible;
3973 union {
3974 /* OT_BOOLEAN type option. */
3975 struct {
3976 bool value;
3977 bool def;
3978 } boolean;
3979 /* OT_INTEGER type option. */
3980 struct {
3981 int value;
3982 int def, min, max;
3983 } integer;
3984 /* OT_STRING type option. */
3985 struct {
3986 char *value;
3987 char *def;
3988 } string;
3989 /* OT_ENUM type option. */
3990 struct {
3991 int value;
3992 int def;
3993 struct strvec *support_names;
3994 struct strvec *pretty_names; /* untranslated */
3995 } enumerator;
3996 /* OT_BITWISE type option. */
3997 struct {
3998 unsigned value;
3999 unsigned def;
4000 struct strvec *support_names;
4001 struct strvec *pretty_names; /* untranslated */
4002 } bitwise;
4006 #define SERVER_OPTION(poption) ((struct server_option *) (poption))
4008 static void desired_settable_option_send(struct option *poption);
4011 /****************************************************************************
4012 Initialize the server options (not received yet).
4013 ****************************************************************************/
4014 void server_options_init(void)
4016 fc_assert(NULL == server_options_categories);
4017 fc_assert(NULL == server_options);
4018 fc_assert(0 == server_options_categories_num);
4019 fc_assert(0 == server_options_num);
4022 /****************************************************************************
4023 Free one server option.
4024 ****************************************************************************/
4025 static void server_option_free(struct server_option *poption)
4027 switch (poption->base_option.type) {
4028 case OT_STRING:
4029 if (NULL != poption->string.value) {
4030 FC_FREE(poption->string.value);
4032 if (NULL != poption->string.def) {
4033 FC_FREE(poption->string.def);
4035 break;
4037 case OT_ENUM:
4038 if (NULL != poption->enumerator.support_names) {
4039 strvec_destroy(poption->enumerator.support_names);
4040 poption->enumerator.support_names = NULL;
4042 if (NULL != poption->enumerator.pretty_names) {
4043 strvec_destroy(poption->enumerator.pretty_names);
4044 poption->enumerator.pretty_names = NULL;
4046 break;
4048 case OT_BITWISE:
4049 if (NULL != poption->bitwise.support_names) {
4050 strvec_destroy(poption->bitwise.support_names);
4051 poption->bitwise.support_names = NULL;
4053 if (NULL != poption->bitwise.pretty_names) {
4054 strvec_destroy(poption->bitwise.pretty_names);
4055 poption->bitwise.pretty_names = NULL;
4057 break;
4059 case OT_BOOLEAN:
4060 case OT_INTEGER:
4061 case OT_FONT:
4062 case OT_COLOR:
4063 case OT_VIDEO_MODE:
4064 break;
4067 if (NULL != poption->name) {
4068 FC_FREE(poption->name);
4070 if (NULL != poption->description) {
4071 FC_FREE(poption->description);
4073 if (NULL != poption->help_text) {
4074 FC_FREE(poption->help_text);
4078 /****************************************************************************
4079 Free the server options, if already received.
4080 ****************************************************************************/
4081 void server_options_free(void)
4083 int i;
4085 /* Don't keep this dialog open. */
4086 option_dialog_popdown(server_optset);
4088 /* Free the options themselves. */
4089 if (NULL != server_options) {
4090 for (i = 0; i < server_options_num; i++) {
4091 server_option_free(server_options + i);
4093 FC_FREE(server_options);
4094 server_options_num = 0;
4097 /* Free the categories. */
4098 if (NULL != server_options_categories) {
4099 for (i = 0; i < server_options_categories_num; i++) {
4100 if (NULL != server_options_categories[i]) {
4101 FC_FREE(server_options_categories[i]);
4104 FC_FREE(server_options_categories);
4105 server_options_categories_num = 0;
4109 /****************************************************************************
4110 Allocate the server options and categories.
4111 ****************************************************************************/
4112 void handle_server_setting_control
4113 (const struct packet_server_setting_control *packet)
4115 int i;
4117 /* This packet should be received only once. */
4118 fc_assert_ret(NULL == server_options_categories);
4119 fc_assert_ret(NULL == server_options);
4120 fc_assert_ret(0 == server_options_categories_num);
4121 fc_assert_ret(0 == server_options_num);
4123 /* Allocate server option categories. */
4124 if (0 < packet->categories_num) {
4125 server_options_categories_num = packet->categories_num;
4126 server_options_categories =
4127 fc_calloc(server_options_categories_num,
4128 sizeof(*server_options_categories));
4130 for (i = 0; i < server_options_categories_num; i++) {
4131 /* NB: Translate now. */
4132 server_options_categories[i] = fc_strdup(_(packet->category_names[i]));
4136 /* Allocate server options. */
4137 if (0 < packet->settings_num) {
4138 server_options_num = packet->settings_num;
4139 server_options = fc_calloc(server_options_num, sizeof(*server_options));
4143 /****************************************************************************
4144 Receive a server setting info packet.
4145 ****************************************************************************/
4146 void handle_server_setting_const
4147 (const struct packet_server_setting_const *packet)
4149 struct option *poption = server_optset_option_by_number(packet->id);
4150 struct server_option *psoption = SERVER_OPTION(poption);
4152 fc_assert_ret(NULL != poption);
4154 fc_assert(NULL == psoption->name);
4155 psoption->name = fc_strdup(packet->name);
4156 fc_assert(NULL == psoption->description);
4157 /* NB: Translate now. */
4158 psoption->description = fc_strdup(_(packet->short_help));
4159 fc_assert(NULL == psoption->help_text);
4160 /* NB: Translate now. */
4161 psoption->help_text = fc_strdup(_(packet->extra_help));
4162 psoption->category = packet->category;
4165 /****************************************************************************
4166 Common part of handle_server_setting_*() functions. See below.
4167 ****************************************************************************/
4168 #define handle_server_setting_common(psoption, packet) \
4169 psoption->is_changeable = packet->is_changeable; \
4170 if (psoption->is_visible != packet->is_visible) { \
4171 if (psoption->is_visible) { \
4172 need_gui_remove = TRUE; \
4173 } else if (packet->is_visible) { \
4174 need_gui_add = TRUE; \
4176 psoption->is_visible = packet->is_visible; \
4179 if (!psoption->desired_sent \
4180 && psoption->is_visible \
4181 && psoption->is_changeable \
4182 && is_server_running() \
4183 && packet->initial_setting) { \
4184 /* Only send our private settings if we are running \
4185 * on a forked local server, i.e. started by the \
4186 * client with the "Start New Game" button. \
4187 * Do now override settings that are already saved to savegame \
4188 * and now loaded. */ \
4189 desired_settable_option_send(OPTION(poption)); \
4190 psoption->desired_sent = TRUE; \
4193 /* Update the GUI. */ \
4194 if (need_gui_remove) { \
4195 option_gui_remove(poption); \
4196 } else if (need_gui_add) { \
4197 option_gui_add(poption); \
4198 } else { \
4199 option_gui_update(poption); \
4202 /****************************************************************************
4203 Receive a boolean server setting info packet.
4204 ****************************************************************************/
4205 void handle_server_setting_bool
4206 (const struct packet_server_setting_bool *packet)
4208 struct option *poption = server_optset_option_by_number(packet->id);
4209 struct server_option *psoption = SERVER_OPTION(poption);
4210 bool need_gui_remove = FALSE;
4211 bool need_gui_add = FALSE;
4213 fc_assert_ret(NULL != poption);
4215 if (NULL == poption->common_vtable) {
4216 /* Not initialized yet. */
4217 poption->poptset = server_optset;
4218 poption->common_vtable = &server_option_common_vtable;
4219 poption->type = OT_BOOLEAN;
4220 poption->bool_vtable = &server_option_bool_vtable;
4222 fc_assert_ret_msg(OT_BOOLEAN == poption->type,
4223 "Server setting \"%s\" (nb %d) has type %s (%d), "
4224 "expected %s (%d)",
4225 option_name(poption), option_number(poption),
4226 option_type_name(poption->type), poption->type,
4227 option_type_name(OT_BOOLEAN), OT_BOOLEAN);
4229 if (packet->is_visible) {
4230 psoption->boolean.value = packet->val;
4231 psoption->boolean.def = packet->default_val;
4234 handle_server_setting_common(psoption, packet);
4237 /****************************************************************************
4238 Receive a integer server setting info packet.
4239 ****************************************************************************/
4240 void handle_server_setting_int
4241 (const struct packet_server_setting_int *packet)
4243 struct option *poption = server_optset_option_by_number(packet->id);
4244 struct server_option *psoption = SERVER_OPTION(poption);
4245 bool need_gui_remove = FALSE;
4246 bool need_gui_add = FALSE;
4248 fc_assert_ret(NULL != poption);
4250 if (NULL == poption->common_vtable) {
4251 /* Not initialized yet. */
4252 poption->poptset = server_optset;
4253 poption->common_vtable = &server_option_common_vtable;
4254 poption->type = OT_INTEGER;
4255 poption->int_vtable = &server_option_int_vtable;
4257 fc_assert_ret_msg(OT_INTEGER == poption->type,
4258 "Server setting \"%s\" (nb %d) has type %s (%d), "
4259 "expected %s (%d)",
4260 option_name(poption), option_number(poption),
4261 option_type_name(poption->type), poption->type,
4262 option_type_name(OT_INTEGER), OT_INTEGER);
4264 if (packet->is_visible) {
4265 psoption->integer.value = packet->val;
4266 psoption->integer.def = packet->default_val;
4267 psoption->integer.min = packet->min_val;
4268 psoption->integer.max = packet->max_val;
4271 handle_server_setting_common(psoption, packet);
4274 /****************************************************************************
4275 Receive a string server setting info packet.
4276 ****************************************************************************/
4277 void handle_server_setting_str
4278 (const struct packet_server_setting_str *packet)
4280 struct option *poption = server_optset_option_by_number(packet->id);
4281 struct server_option *psoption = SERVER_OPTION(poption);
4282 bool need_gui_remove = FALSE;
4283 bool need_gui_add = FALSE;
4285 fc_assert_ret(NULL != poption);
4287 if (NULL == poption->common_vtable) {
4288 /* Not initialized yet. */
4289 poption->poptset = server_optset;
4290 poption->common_vtable = &server_option_common_vtable;
4291 poption->type = OT_STRING;
4292 poption->str_vtable = &server_option_str_vtable;
4294 fc_assert_ret_msg(OT_STRING == poption->type,
4295 "Server setting \"%s\" (nb %d) has type %s (%d), "
4296 "expected %s (%d)",
4297 option_name(poption), option_number(poption),
4298 option_type_name(poption->type), poption->type,
4299 option_type_name(OT_STRING), OT_STRING);
4301 if (packet->is_visible) {
4302 if (NULL == psoption->string.value) {
4303 psoption->string.value = fc_strdup(packet->val);
4304 } else if (0 != strcmp(packet->val, psoption->string.value)) {
4305 free(psoption->string.value);
4306 psoption->string.value = fc_strdup(packet->val);
4308 if (NULL == psoption->string.def) {
4309 psoption->string.def = fc_strdup(packet->default_val);
4310 } else if (0 != strcmp(packet->default_val, psoption->string.def)) {
4311 free(psoption->string.def);
4312 psoption->string.def = fc_strdup(packet->default_val);
4316 handle_server_setting_common(psoption, packet);
4319 /****************************************************************************
4320 Receive an enumerator server setting info packet.
4321 ****************************************************************************/
4322 void handle_server_setting_enum
4323 (const struct packet_server_setting_enum *packet)
4325 struct option *poption = server_optset_option_by_number(packet->id);
4326 struct server_option *psoption = SERVER_OPTION(poption);
4327 bool need_gui_remove = FALSE;
4328 bool need_gui_add = FALSE;
4330 fc_assert_ret(NULL != poption);
4332 if (NULL == poption->common_vtable) {
4333 /* Not initialized yet. */
4334 poption->poptset = server_optset;
4335 poption->common_vtable = &server_option_common_vtable;
4336 poption->type = OT_ENUM;
4337 poption->enum_vtable = &server_option_enum_vtable;
4339 fc_assert_ret_msg(OT_ENUM == poption->type,
4340 "Server setting \"%s\" (nb %d) has type %s (%d), "
4341 "expected %s (%d)",
4342 option_name(poption), option_number(poption),
4343 option_type_name(poption->type), poption->type,
4344 option_type_name(OT_ENUM), OT_ENUM);
4346 if (packet->is_visible) {
4347 int i;
4349 psoption->enumerator.value = packet->val;
4350 psoption->enumerator.def = packet->default_val;
4352 if (NULL == psoption->enumerator.support_names) {
4353 /* First time we get this packet. */
4354 fc_assert(NULL == psoption->enumerator.pretty_names);
4355 psoption->enumerator.support_names = strvec_new();
4356 strvec_reserve(psoption->enumerator.support_names, packet->values_num);
4357 psoption->enumerator.pretty_names = strvec_new();
4358 strvec_reserve(psoption->enumerator.pretty_names, packet->values_num);
4359 for (i = 0; i < packet->values_num; i++) {
4360 strvec_set(psoption->enumerator.support_names, i,
4361 packet->support_names[i]);
4362 /* Store untranslated string from server. */
4363 strvec_set(psoption->enumerator.pretty_names, i,
4364 packet->pretty_names[i]);
4366 } else if (strvec_size(psoption->enumerator.support_names)
4367 != packet->values_num) {
4368 fc_assert(strvec_size(psoption->enumerator.support_names)
4369 == strvec_size(psoption->enumerator.pretty_names));
4370 /* The number of values have changed, we need to reset the list
4371 * of possible values. */
4372 strvec_reserve(psoption->enumerator.support_names, packet->values_num);
4373 strvec_reserve(psoption->enumerator.pretty_names, packet->values_num);
4374 for (i = 0; i < packet->values_num; i++) {
4375 strvec_set(psoption->enumerator.support_names, i,
4376 packet->support_names[i]);
4377 /* Store untranslated string from server. */
4378 strvec_set(psoption->enumerator.pretty_names, i,
4379 packet->pretty_names[i]);
4381 need_gui_remove = TRUE;
4382 need_gui_add = TRUE;
4383 } else {
4384 /* Check if a value changed, then we need to reset the list
4385 * of possible values. */
4386 const char *str;
4388 for (i = 0; i < packet->values_num; i++) {
4389 str = strvec_get(psoption->enumerator.pretty_names, i);
4390 if (NULL == str || 0 != strcmp(str, packet->pretty_names[i])) {
4391 /* Store untranslated string from server. */
4392 strvec_set(psoption->enumerator.pretty_names, i,
4393 packet->pretty_names[i]);
4394 need_gui_remove = TRUE;
4395 need_gui_add = TRUE;
4397 /* Support names are not visible, we don't need to check if it
4398 * has changed. */
4399 strvec_set(psoption->enumerator.support_names, i,
4400 packet->support_names[i]);
4405 handle_server_setting_common(psoption, packet);
4408 /****************************************************************************
4409 Receive a bitwise server setting info packet.
4410 ****************************************************************************/
4411 void handle_server_setting_bitwise
4412 (const struct packet_server_setting_bitwise *packet)
4414 struct option *poption = server_optset_option_by_number(packet->id);
4415 struct server_option *psoption = SERVER_OPTION(poption);
4416 bool need_gui_remove = FALSE;
4417 bool need_gui_add = FALSE;
4419 fc_assert_ret(NULL != poption);
4421 if (NULL == poption->common_vtable) {
4422 /* Not initialized yet. */
4423 poption->poptset = server_optset;
4424 poption->common_vtable = &server_option_common_vtable;
4425 poption->type = OT_BITWISE;
4426 poption->bitwise_vtable = &server_option_bitwise_vtable;
4428 fc_assert_ret_msg(OT_BITWISE == poption->type,
4429 "Server setting \"%s\" (nb %d) has type %s (%d), "
4430 "expected %s (%d)",
4431 option_name(poption), option_number(poption),
4432 option_type_name(poption->type), poption->type,
4433 option_type_name(OT_BITWISE), OT_BITWISE);
4435 if (packet->is_visible) {
4436 int i;
4438 psoption->bitwise.value = packet->val;
4439 psoption->bitwise.def = packet->default_val;
4441 if (NULL == psoption->bitwise.support_names) {
4442 /* First time we get this packet. */
4443 fc_assert(NULL == psoption->bitwise.pretty_names);
4444 psoption->bitwise.support_names = strvec_new();
4445 strvec_reserve(psoption->bitwise.support_names, packet->bits_num);
4446 psoption->bitwise.pretty_names = strvec_new();
4447 strvec_reserve(psoption->bitwise.pretty_names, packet->bits_num);
4448 for (i = 0; i < packet->bits_num; i++) {
4449 strvec_set(psoption->bitwise.support_names, i,
4450 packet->support_names[i]);
4451 /* Store untranslated string from server. */
4452 strvec_set(psoption->bitwise.pretty_names, i,
4453 packet->pretty_names[i]);
4455 } else if (strvec_size(psoption->bitwise.support_names)
4456 != packet->bits_num) {
4457 fc_assert(strvec_size(psoption->bitwise.support_names)
4458 == strvec_size(psoption->bitwise.pretty_names));
4459 /* The number of values have changed, we need to reset the list
4460 * of possible values. */
4461 strvec_reserve(psoption->bitwise.support_names, packet->bits_num);
4462 strvec_reserve(psoption->bitwise.pretty_names, packet->bits_num);
4463 for (i = 0; i < packet->bits_num; i++) {
4464 strvec_set(psoption->bitwise.support_names, i,
4465 packet->support_names[i]);
4466 /* Store untranslated string from server. */
4467 strvec_set(psoption->bitwise.pretty_names, i,
4468 packet->pretty_names[i]);
4470 need_gui_remove = TRUE;
4471 need_gui_add = TRUE;
4472 } else {
4473 /* Check if a value changed, then we need to reset the list
4474 * of possible values. */
4475 const char *str;
4477 for (i = 0; i < packet->bits_num; i++) {
4478 str = strvec_get(psoption->bitwise.pretty_names, i);
4479 if (NULL == str || 0 != strcmp(str, packet->pretty_names[i])) {
4480 /* Store untranslated string from server. */
4481 strvec_set(psoption->bitwise.pretty_names, i,
4482 packet->pretty_names[i]);
4483 need_gui_remove = TRUE;
4484 need_gui_add = TRUE;
4486 /* Support names are not visible, we don't need to check if it
4487 * has changed. */
4488 strvec_set(psoption->bitwise.support_names, i,
4489 packet->support_names[i]);
4494 handle_server_setting_common(psoption, packet);
4497 /****************************************************************************
4498 Returns the next valid option pointer for the current gui type.
4499 ****************************************************************************/
4500 static struct server_option *
4501 server_option_next_valid(struct server_option *poption)
4503 const struct server_option *const max =
4504 server_options + server_options_num;
4506 while (NULL != poption && poption < max && !poption->is_visible) {
4507 poption++;
4510 return (poption < max ? poption : NULL);
4513 /****************************************************************************
4514 Returns the server option associated to the number
4515 ****************************************************************************/
4516 struct option *server_optset_option_by_number(int id)
4518 if (0 > id || id > server_options_num) {
4519 return NULL;
4521 return OPTION(server_options + id);
4524 /****************************************************************************
4525 Returns the first valid (visible) option pointer.
4526 ****************************************************************************/
4527 struct option *server_optset_option_first(void)
4529 return OPTION(server_option_next_valid(server_options));
4532 /****************************************************************************
4533 Returns the number of server option categories.
4534 ****************************************************************************/
4535 int server_optset_category_number(void)
4537 return server_options_categories_num;
4540 /****************************************************************************
4541 Returns the name (translated) of the server option category.
4542 ****************************************************************************/
4543 const char *server_optset_category_name(int category)
4545 if (0 > category || category >= server_options_categories_num) {
4546 return NULL;
4549 return server_options_categories[category];
4552 /***************************************************************************
4553 Returns the number of this server option.
4554 ****************************************************************************/
4555 static int server_option_number(const struct option *poption)
4557 return SERVER_OPTION(poption) - server_options;
4560 /****************************************************************************
4561 Returns the name of this server option.
4562 ****************************************************************************/
4563 static const char *server_option_name(const struct option *poption)
4565 return SERVER_OPTION(poption)->name;
4568 /****************************************************************************
4569 Returns the (translated) description of this server option.
4570 ****************************************************************************/
4571 static const char *server_option_description(const struct option *poption)
4573 return SERVER_OPTION(poption)->description;
4576 /****************************************************************************
4577 Returns the (translated) help text for this server option.
4578 ****************************************************************************/
4579 static const char *server_option_help_text(const struct option *poption)
4581 return SERVER_OPTION(poption)->help_text;
4584 /****************************************************************************
4585 Returns the category of this server option.
4586 ****************************************************************************/
4587 static int server_option_category(const struct option *poption)
4589 return SERVER_OPTION(poption)->category;
4592 /****************************************************************************
4593 Returns TRUE if this client option can be modified.
4594 ****************************************************************************/
4595 static bool server_option_is_changeable(const struct option *poption)
4597 return SERVER_OPTION(poption)->is_changeable;
4600 /****************************************************************************
4601 Returns the next valid (visible) option pointer.
4602 ****************************************************************************/
4603 static struct option *server_option_next(const struct option *poption)
4605 return OPTION(server_option_next_valid(SERVER_OPTION(poption) + 1));
4608 /****************************************************************************
4609 Returns the value of this server option of type OT_BOOLEAN.
4610 ****************************************************************************/
4611 static bool server_option_bool_get(const struct option *poption)
4613 return SERVER_OPTION(poption)->boolean.value;
4616 /****************************************************************************
4617 Returns the default value of this server option of type OT_BOOLEAN.
4618 ****************************************************************************/
4619 static bool server_option_bool_def(const struct option *poption)
4621 return SERVER_OPTION(poption)->boolean.def;
4624 /****************************************************************************
4625 Set the value of this server option of type OT_BOOLEAN. Returns TRUE if
4626 the value changed.
4627 ****************************************************************************/
4628 static bool server_option_bool_set(struct option *poption, bool val)
4630 struct server_option *psoption = SERVER_OPTION(poption);
4632 if (psoption->boolean.value == val) {
4633 return FALSE;
4636 send_chat_printf("/set %s %s", psoption->name,
4637 val ? "enabled" : "disabled");
4638 return TRUE;
4641 /****************************************************************************
4642 Returns the value of this server option of type OT_INTEGER.
4643 ****************************************************************************/
4644 static int server_option_int_get(const struct option *poption)
4646 return SERVER_OPTION(poption)->integer.value;
4649 /****************************************************************************
4650 Returns the default value of this server option of type OT_INTEGER.
4651 ****************************************************************************/
4652 static int server_option_int_def(const struct option *poption)
4654 return SERVER_OPTION(poption)->integer.def;
4657 /****************************************************************************
4658 Returns the minimal value for this server option of type OT_INTEGER.
4659 ****************************************************************************/
4660 static int server_option_int_min(const struct option *poption)
4662 return SERVER_OPTION(poption)->integer.min;
4665 /****************************************************************************
4666 Returns the maximal value for this server option of type OT_INTEGER.
4667 ****************************************************************************/
4668 static int server_option_int_max(const struct option *poption)
4670 return SERVER_OPTION(poption)->integer.max;
4673 /****************************************************************************
4674 Set the value of this server option of type OT_INTEGER. Returns TRUE if
4675 the value changed.
4676 ****************************************************************************/
4677 static bool server_option_int_set(struct option *poption, int val)
4679 struct server_option *psoption = SERVER_OPTION(poption);
4681 if (val < psoption->integer.min
4682 || val > psoption->integer.max
4683 || psoption->integer.value == val) {
4684 return FALSE;
4687 send_chat_printf("/set %s %d", psoption->name, val);
4688 return TRUE;
4691 /****************************************************************************
4692 Returns the value of this server option of type OT_STRING.
4693 ****************************************************************************/
4694 static const char *server_option_str_get(const struct option *poption)
4696 return SERVER_OPTION(poption)->string.value;
4699 /****************************************************************************
4700 Returns the default value of this server option of type OT_STRING.
4701 ****************************************************************************/
4702 static const char *server_option_str_def(const struct option *poption)
4704 return SERVER_OPTION(poption)->string.def;
4707 /****************************************************************************
4708 Returns the possible string values of this server option of type
4709 OT_STRING.
4710 ****************************************************************************/
4711 static const struct strvec *
4712 server_option_str_values(const struct option *poption)
4714 return NULL;
4717 /****************************************************************************
4718 Set the value of this server option of type OT_STRING. Returns TRUE if
4719 the value changed.
4720 ****************************************************************************/
4721 static bool server_option_str_set(struct option *poption, const char *str)
4723 struct server_option *psoption = SERVER_OPTION(poption);
4725 if (0 == strcmp(psoption->string.value, str)) {
4726 return FALSE;
4729 send_chat_printf("/set %s \"%s\"", psoption->name, str);
4730 return TRUE;
4733 /****************************************************************************
4734 Returns the current value of this server option of type OT_ENUM.
4735 ****************************************************************************/
4736 static int server_option_enum_get(const struct option *poption)
4738 return SERVER_OPTION(poption)->enumerator.value;
4741 /****************************************************************************
4742 Returns the default value of this server option of type OT_ENUM.
4743 ****************************************************************************/
4744 static int server_option_enum_def(const struct option *poption)
4746 return SERVER_OPTION(poption)->enumerator.def;
4749 /****************************************************************************
4750 Returns the user-visible, translatable (but untranslated) "pretty" names
4751 of this server option of type OT_ENUM.
4752 ****************************************************************************/
4753 static const struct strvec *
4754 server_option_enum_pretty(const struct option *poption)
4756 return SERVER_OPTION(poption)->enumerator.pretty_names;
4759 /****************************************************************************
4760 Set the value of this server option of type OT_ENUM. Returns TRUE if
4761 the value changed.
4762 ****************************************************************************/
4763 static bool server_option_enum_set(struct option *poption, int val)
4765 struct server_option *psoption = SERVER_OPTION(poption);
4766 const char *name;
4768 if (val == psoption->enumerator.value
4769 || !(name = strvec_get(psoption->enumerator.support_names, val))) {
4770 return FALSE;
4773 send_chat_printf("/set %s \"%s\"", psoption->name, name);
4774 return TRUE;
4777 /****************************************************************************
4778 Returns the long support names of the values of the server option of type
4779 OT_ENUM.
4780 ****************************************************************************/
4781 static void server_option_enum_support_name(const struct option *poption,
4782 const char **pvalue,
4783 const char **pdefault)
4785 const struct server_option *psoption = SERVER_OPTION(poption);
4786 const struct strvec *values = psoption->enumerator.support_names;
4788 if (NULL != pvalue) {
4789 *pvalue = strvec_get(values, psoption->enumerator.value);
4791 if (NULL != pdefault) {
4792 *pdefault = strvec_get(values, psoption->enumerator.def);
4796 /****************************************************************************
4797 Returns the current value of this server option of type OT_BITWISE.
4798 ****************************************************************************/
4799 static unsigned server_option_bitwise_get(const struct option *poption)
4801 return SERVER_OPTION(poption)->bitwise.value;
4804 /****************************************************************************
4805 Returns the default value of this server option of type OT_BITWISE.
4806 ****************************************************************************/
4807 static unsigned server_option_bitwise_def(const struct option *poption)
4809 return SERVER_OPTION(poption)->bitwise.def;
4812 /****************************************************************************
4813 Returns the user-visible, translatable (but untranslated) "pretty" names
4814 of this server option of type OT_BITWISE.
4815 ****************************************************************************/
4816 static const struct strvec *
4817 server_option_bitwise_pretty(const struct option *poption)
4819 return SERVER_OPTION(poption)->bitwise.pretty_names;
4822 /****************************************************************************
4823 Compute the long support names of a value.
4824 ****************************************************************************/
4825 static void server_option_bitwise_support_base(const struct strvec *values,
4826 unsigned val,
4827 char *buf, size_t buf_len)
4829 int bit;
4831 buf[0] = '\0';
4832 for (bit = 0; bit < strvec_size(values); bit++) {
4833 if ((1 << bit) & val) {
4834 if ('\0' != buf[0]) {
4835 fc_strlcat(buf, "|", buf_len);
4837 fc_strlcat(buf, strvec_get(values, bit), buf_len);
4842 /****************************************************************************
4843 Set the value of this server option of type OT_BITWISE. Returns TRUE if
4844 the value changed.
4845 ****************************************************************************/
4846 static bool server_option_bitwise_set(struct option *poption, unsigned val)
4848 struct server_option *psoption = SERVER_OPTION(poption);
4849 char name[MAX_LEN_MSG];
4851 if (val == psoption->bitwise.value) {
4852 return FALSE;
4855 server_option_bitwise_support_base(psoption->bitwise.support_names, val,
4856 name, sizeof(name));
4857 send_chat_printf("/set %s \"%s\"", psoption->name, name);
4858 return TRUE;
4861 /****************************************************************************
4862 Compute the long support names of the values of the server option of type
4863 OT_BITWISE.
4864 ****************************************************************************/
4865 static void server_option_bitwise_support_name(const struct option *poption,
4866 char *val_buf, size_t val_len,
4867 char *def_buf, size_t def_len)
4869 const struct server_option *psoption = SERVER_OPTION(poption);
4870 const struct strvec *values = psoption->bitwise.support_names;
4872 if (NULL != val_buf && 0 < val_len) {
4873 server_option_bitwise_support_base(values, psoption->bitwise.value,
4874 val_buf, val_len);
4876 if (NULL != def_buf && 0 < def_len) {
4877 server_option_bitwise_support_base(values, psoption->bitwise.def,
4878 def_buf, def_len);
4883 /** Message Options: **/
4885 int messages_where[E_COUNT];
4888 /****************************************************************
4889 These could be a static table initialisation, except
4890 its easier to do it this way.
4891 *****************************************************************/
4892 static void message_options_init(void)
4894 int none[] = {
4895 E_IMP_BUY, E_IMP_SOLD, E_UNIT_BUY,
4896 E_UNIT_LOST_ATT, E_UNIT_WIN_ATT, E_GAME_START,
4897 E_CITY_BUILD, E_NEXT_YEAR,
4898 E_CITY_PRODUCTION_CHANGED,
4899 E_CITY_MAY_SOON_GROW, E_WORKLIST, E_AI_DEBUG
4901 int out_only[] = {
4902 E_NATION_SELECTED, E_CHAT_MSG, E_CHAT_ERROR, E_CONNECTION,
4903 E_LOG_ERROR, E_SETTING, E_VOTE_NEW, E_VOTE_RESOLVED, E_VOTE_ABORTED
4905 int all[] = {
4906 E_LOG_FATAL, E_SCRIPT, E_DEPRECATION_WARNING
4908 int i;
4910 for (i = 0; i <= event_type_max(); i++) {
4911 /* Include possible undefined values. */
4912 messages_where[i] = MW_MESSAGES;
4914 for (i = 0; i < ARRAY_SIZE(none); i++) {
4915 messages_where[none[i]] = 0;
4917 for (i = 0; i < ARRAY_SIZE(out_only); i++) {
4918 messages_where[out_only[i]] = MW_OUTPUT;
4920 for (i = 0; i < ARRAY_SIZE(all); i++) {
4921 messages_where[all[i]] = MW_MESSAGES | MW_POPUP;
4924 events_init();
4927 /****************************************************************
4928 Free resources allocated for message options system
4929 *****************************************************************/
4930 static void message_options_free(void)
4932 events_free();
4935 /****************************************************************
4936 Load the message options; use the function defined by
4937 specnum.h (see also events.h).
4938 *****************************************************************/
4939 static void message_options_load(struct section_file *file,
4940 const char *prefix)
4942 enum event_type event;
4943 int i, num_events;
4944 const char *p;
4946 if (!secfile_lookup_int(file, &num_events, "messages.count")) {
4947 /* version < 2.2 */
4948 /* Order of the events in 2.1. */
4949 const enum event_type old_events[] = {
4950 E_CITY_CANTBUILD, E_CITY_LOST, E_CITY_LOVE, E_CITY_DISORDER,
4951 E_CITY_FAMINE, E_CITY_FAMINE_FEARED, E_CITY_GROWTH,
4952 E_CITY_MAY_SOON_GROW, E_CITY_AQUEDUCT, E_CITY_AQ_BUILDING,
4953 E_CITY_NORMAL, E_CITY_NUKED, E_CITY_CMA_RELEASE, E_CITY_GRAN_THROTTLE,
4954 E_CITY_TRANSFER, E_CITY_BUILD, E_CITY_PRODUCTION_CHANGED,
4955 E_WORKLIST, E_UPRISING, E_CIVIL_WAR, E_ANARCHY, E_FIRST_CONTACT,
4956 E_NEW_GOVERNMENT, E_LOW_ON_FUNDS, E_POLLUTION, E_REVOLT_DONE,
4957 E_REVOLT_START, E_SPACESHIP, E_MY_DIPLOMAT_BRIBE,
4958 E_DIPLOMATIC_INCIDENT, E_MY_DIPLOMAT_ESCAPE, E_MY_DIPLOMAT_EMBASSY,
4959 E_MY_DIPLOMAT_FAILED, E_MY_DIPLOMAT_INCITE, E_MY_DIPLOMAT_POISON,
4960 E_MY_DIPLOMAT_SABOTAGE, E_MY_DIPLOMAT_THEFT, E_ENEMY_DIPLOMAT_BRIBE,
4961 E_ENEMY_DIPLOMAT_EMBASSY, E_ENEMY_DIPLOMAT_FAILED,
4962 E_ENEMY_DIPLOMAT_INCITE, E_ENEMY_DIPLOMAT_POISON,
4963 E_ENEMY_DIPLOMAT_SABOTAGE, E_ENEMY_DIPLOMAT_THEFT,
4964 E_CARAVAN_ACTION, E_SCRIPT, E_BROADCAST_REPORT, E_GAME_END,
4965 E_GAME_START, E_NATION_SELECTED, E_DESTROYED, E_REPORT, E_TURN_BELL,
4966 E_NEXT_YEAR, E_GLOBAL_ECO, E_NUKE, E_HUT_BARB, E_HUT_CITY, E_HUT_GOLD,
4967 E_HUT_BARB_KILLED, E_HUT_MERC, E_HUT_SETTLER, E_HUT_TECH,
4968 E_HUT_BARB_CITY_NEAR, E_IMP_BUY, E_IMP_BUILD, E_IMP_AUCTIONED,
4969 E_IMP_AUTO, E_IMP_SOLD, E_TECH_GAIN, E_TECH_LEARNED, E_TREATY_ALLIANCE,
4970 E_TREATY_BROKEN, E_TREATY_CEASEFIRE, E_TREATY_PEACE,
4971 E_TREATY_SHARED_VISION, E_UNIT_LOST_ATT, E_UNIT_WIN_ATT, E_UNIT_BUY,
4972 E_UNIT_BUILT, E_UNIT_LOST_DEF, E_UNIT_WIN, E_UNIT_BECAME_VET,
4973 E_UNIT_UPGRADED, E_UNIT_RELOCATED, E_UNIT_ORDERS, E_WONDER_BUILD,
4974 E_WONDER_OBSOLETE, E_WONDER_STARTED, E_WONDER_STOPPED,
4975 E_WONDER_WILL_BE_BUILT, E_DIPLOMACY, E_TREATY_EMBASSY,
4976 E_BAD_COMMAND, E_SETTING, E_CHAT_MSG, E_MESSAGE_WALL, E_CHAT_ERROR,
4977 E_CONNECTION, E_AI_DEBUG
4979 const size_t old_events_num = ARRAY_SIZE(old_events);
4981 for (i = 0; i < old_events_num; i++) {
4982 messages_where[old_events[i]] =
4983 secfile_lookup_int_default(file, messages_where[old_events[i]],
4984 "%s.message_where_%02d", prefix, i);
4986 return;
4989 for (i = 0; i < num_events; i++) {
4990 p = secfile_lookup_str(file, "messages.event%d.name", i);
4991 if (NULL == p) {
4992 log_error("Corruption in file %s: %s",
4993 secfile_name(file), secfile_error());
4994 continue;
4996 event = event_type_by_name(p, strcmp);
4997 if (!event_type_is_valid(event)) {
4998 log_error("Event not supported: %s", p);
4999 continue;
5002 if (!secfile_lookup_int(file, &messages_where[event],
5003 "messages.event%d.where", i)) {
5004 log_error("Corruption in file %s: %s",
5005 secfile_name(file), secfile_error());
5010 /****************************************************************
5011 Save the message options; use the function defined by
5012 specnum.h (see also events.h).
5013 *****************************************************************/
5014 static void message_options_save(struct section_file *file,
5015 const char *prefix)
5017 enum event_type event;
5018 int i = 0;
5020 for (event = event_type_begin(); event != event_type_end();
5021 event = event_type_next(event)) {
5022 secfile_insert_str(file, event_type_name(event),
5023 "messages.event%d.name", i);
5024 secfile_insert_int(file, messages_where[i],
5025 "messages.event%d.where", i);
5026 i++;
5029 secfile_insert_int(file, i, "messages.count");
5033 /****************************************************************
5034 Does heavy lifting for looking up a preset.
5035 *****************************************************************/
5036 static void load_cma_preset(struct section_file *file, int i)
5038 struct cm_parameter parameter;
5039 const char *name =
5040 secfile_lookup_str_default(file, "preset",
5041 "cma.preset%d.name", i);
5043 output_type_iterate(o) {
5044 parameter.minimal_surplus[o] =
5045 secfile_lookup_int_default(file, 0, "cma.preset%d.minsurp%d", i, o);
5046 parameter.factor[o] =
5047 secfile_lookup_int_default(file, 0, "cma.preset%d.factor%d", i, o);
5048 } output_type_iterate_end;
5049 parameter.require_happy =
5050 secfile_lookup_bool_default(file, FALSE, "cma.preset%d.reqhappy", i);
5051 parameter.happy_factor =
5052 secfile_lookup_int_default(file, 0, "cma.preset%d.happyfactor", i);
5053 parameter.allow_disorder = FALSE;
5054 parameter.allow_specialists = TRUE;
5056 cmafec_preset_add(name, &parameter);
5059 /****************************************************************
5060 Does heavy lifting for inserting a preset.
5061 *****************************************************************/
5062 static void save_cma_preset(struct section_file *file, int i)
5064 const struct cm_parameter *const pparam = cmafec_preset_get_parameter(i);
5065 char *name = cmafec_preset_get_descr(i);
5067 secfile_insert_str(file, name, "cma.preset%d.name", i);
5069 output_type_iterate(o) {
5070 secfile_insert_int(file, pparam->minimal_surplus[o],
5071 "cma.preset%d.minsurp%d", i, o);
5072 secfile_insert_int(file, pparam->factor[o],
5073 "cma.preset%d.factor%d", i, o);
5074 } output_type_iterate_end;
5075 secfile_insert_bool(file, pparam->require_happy,
5076 "cma.preset%d.reqhappy", i);
5077 secfile_insert_int(file, pparam->happy_factor,
5078 "cma.preset%d.happyfactor", i);
5081 /****************************************************************
5082 Insert all cma presets.
5083 *****************************************************************/
5084 static void save_cma_presets(struct section_file *file)
5086 int i;
5088 secfile_insert_int_comment(file, cmafec_preset_num(),
5089 _("If you add a preset by hand,"
5090 " also update \"number_of_presets\""),
5091 "cma.number_of_presets");
5092 for (i = 0; i < cmafec_preset_num(); i++) {
5093 save_cma_preset(file, i);
5097 /* Old rc file name. */
5098 #define OLD_OPTION_FILE_NAME ".civclientrc"
5099 /* New rc file name. */
5100 #define MID_OPTION_FILE_NAME ".freeciv-client-rc-%d.%d"
5101 #define NEW_OPTION_FILE_NAME "freeciv-client-rc-%d.%d"
5102 #if MINOR_VERSION >= 90
5103 #define MAJOR_NEW_OPTION_FILE_NAME (MAJOR_VERSION + 1)
5104 #define MINOR_NEW_OPTION_FILE_NAME 0
5105 #else /* MINOR_VERSION < 90 */
5106 #define MAJOR_NEW_OPTION_FILE_NAME MAJOR_VERSION
5107 #if IS_DEVEL_VERSION && ! IS_FREEZE_VERSION
5108 #define MINOR_NEW_OPTION_FILE_NAME (MINOR_VERSION + 1)
5109 #else
5110 #define MINOR_NEW_OPTION_FILE_NAME MINOR_VERSION
5111 #endif /* IS_DEVEL_VERSION */
5112 #endif /* MINOR_VERSION >= 90 */
5113 /* The first version the new option name appeared (2.6). */
5114 #define FIRST_MAJOR_NEW_OPTION_FILE_NAME 2
5115 #define FIRST_MINOR_NEW_OPTION_FILE_NAME 6
5116 /* The first version the mid option name appeared (2.2). */
5117 #define FIRST_MAJOR_MID_OPTION_FILE_NAME 2
5118 #define FIRST_MINOR_MID_OPTION_FILE_NAME 2
5119 /* The first version the new boolean values appeared (2.3). */
5120 #define FIRST_MAJOR_NEW_BOOLEAN 2
5121 #define FIRST_MINOR_NEW_BOOLEAN 3
5122 /****************************************************************
5123 Returns pointer to static memory containing name of the current
5124 option file. Usually used for saving.
5125 Ie, based on FREECIV_OPT env var, and home dir. (or a
5126 OPTION_FILE_NAME define defined in fc_config.h)
5127 Or NULL if problem.
5128 *****************************************************************/
5129 static const char *get_current_option_file_name(void)
5131 static char name_buffer[256];
5132 const char *name;
5134 name = getenv("FREECIV_OPT");
5136 if (name) {
5137 sz_strlcpy(name_buffer, name);
5138 } else {
5139 #ifdef OPTION_FILE_NAME
5140 fc_strlcpy(name_buffer, OPTION_FILE_NAME, sizeof(name_buffer));
5141 #else
5142 name = user_home_dir();
5143 if (!name) {
5144 log_error(_("Cannot find your home directory"));
5145 return NULL;
5147 fc_snprintf(name_buffer, sizeof(name_buffer),
5148 "%s" DIR_SEPARATOR ".freeciv" DIR_SEPARATOR NEW_OPTION_FILE_NAME,
5149 name, MAJOR_NEW_OPTION_FILE_NAME, MINOR_NEW_OPTION_FILE_NAME);
5150 #endif /* OPTION_FILE_NAME */
5152 log_verbose("settings file is %s", name_buffer);
5153 return name_buffer;
5156 /****************************************************************************
5157 Check the last option file we saved. Usually used to load. Ie, based on
5158 FREECIV_OPT env var, and home dir. (or a OPTION_FILE_NAME define defined
5159 in fc_config.h), or NULL if not found.
5161 Set in allow_digital_boolean if we should look for old boolean values
5162 (saved as 0 and 1), so if the rc file version is older than 2.3.0.
5163 ****************************************************************************/
5164 static const char *get_last_option_file_name(bool *allow_digital_boolean)
5166 static char name_buffer[256];
5167 const char *name;
5168 static int last_minors[] = {
5169 0, /* There was no 0.x releases */
5170 14, /* 1.14 */
5171 6 /* 2.6 */
5174 FC_STATIC_ASSERT(MAJOR_VERSION < sizeof(last_minors) / sizeof(int), missing_last_minor);
5176 *allow_digital_boolean = FALSE;
5177 name = getenv("FREECIV_OPT");
5178 if (name) {
5179 sz_strlcpy(name_buffer, name);
5180 } else {
5181 #ifdef OPTION_FILE_NAME
5182 fc_strlcpy(name_buffer, OPTION_FILE_NAME, sizeof(name_buffer));
5183 #else
5184 int major, minor;
5185 struct stat buf;
5187 name = user_home_dir();
5188 if (!name) {
5189 log_error(_("Cannot find your home directory"));
5190 return NULL;
5192 for (major = MAJOR_NEW_OPTION_FILE_NAME,
5193 minor = MINOR_NEW_OPTION_FILE_NAME;
5194 major >= FIRST_MAJOR_NEW_OPTION_FILE_NAME; major--) {
5195 for (; (major == FIRST_MAJOR_NEW_OPTION_FILE_NAME
5196 ? minor >= FIRST_MINOR_NEW_OPTION_FILE_NAME
5197 : minor >= 0); minor--) {
5198 fc_snprintf(name_buffer, sizeof(name_buffer),
5199 "%s" DIR_SEPARATOR ".freeciv" DIR_SEPARATOR NEW_OPTION_FILE_NAME,
5200 name, major, minor);
5201 if (0 == fc_stat(name_buffer, &buf)) {
5202 if (MAJOR_NEW_OPTION_FILE_NAME != major
5203 || MINOR_NEW_OPTION_FILE_NAME != minor) {
5204 log_normal(_("Didn't find '%s' option file, "
5205 "loading from '%s' instead."),
5206 get_current_option_file_name() + strlen(name) + 1,
5207 name_buffer + strlen(name) + 1);
5210 return name_buffer;
5213 minor = last_minors[major - 1];
5216 /* minor having max value of FIRST_MINOR_NEW_OPTION_FILE_NAME
5217 * works since MID versioning scheme was used within major version 2
5218 * only (2.2 - 2.6) so the last minor is bigger than any earlier minor. */
5219 for (major = FIRST_MAJOR_MID_OPTION_FILE_NAME,
5220 minor = FIRST_MINOR_NEW_OPTION_FILE_NAME ;
5221 minor >= FIRST_MINOR_MID_OPTION_FILE_NAME ;
5222 minor--) {
5223 fc_snprintf(name_buffer, sizeof(name_buffer),
5224 "%s" DIR_SEPARATOR MID_OPTION_FILE_NAME, name, major, minor);
5225 if (0 == fc_stat(name_buffer, &buf)) {
5226 log_normal(_("Didn't find '%s' option file, "
5227 "loading from '%s' instead."),
5228 get_current_option_file_name() + strlen(name) + 1,
5229 name_buffer + strlen(name) + 1);
5231 if (FIRST_MINOR_NEW_BOOLEAN > minor) {
5232 *allow_digital_boolean = TRUE;
5234 return name_buffer;
5238 /* Try with the old one. */
5239 fc_snprintf(name_buffer, sizeof(name_buffer),
5240 "%s" DIR_SEPARATOR OLD_OPTION_FILE_NAME, name);
5241 if (0 == fc_stat(name_buffer, &buf)) {
5242 log_normal(_("Didn't find '%s' option file, "
5243 "loading from '%s' instead."),
5244 get_current_option_file_name() + strlen(name) + 1,
5245 OLD_OPTION_FILE_NAME);
5246 *allow_digital_boolean = TRUE;
5247 return name_buffer;
5248 } else {
5249 return NULL;
5251 #endif /* OPTION_FILE_NAME */
5253 log_verbose("settings file is %s", name_buffer);
5254 return name_buffer;
5256 #undef OLD_OPTION_FILE_NAME
5257 #undef MID_OPTION_FILE_NAME
5258 #undef NEW_OPTION_FILE_NAME
5259 #undef FIRST_MAJOR_NEW_OPTION_FILE_NAME
5260 #undef FIRST_MINOR_NEW_OPTION_FILE_NAME
5261 #undef FIRST_MAJOR_MID_OPTION_FILE_NAME
5262 #undef FIRST_MINOR_MID_OPTION_FILE_NAME
5263 #undef FIRST_MINOR_NEW_BOOLEAN
5266 /****************************************************************************
5267 Desired settable options.
5268 ****************************************************************************/
5269 #define SPECHASH_TAG settable_options
5270 #define SPECHASH_ASTR_KEY_TYPE
5271 #define SPECHASH_ASTR_DATA_TYPE
5272 #include "spechash.h"
5273 #define settable_options_hash_iterate(hash, name, value) \
5274 TYPED_HASH_ITERATE(const char *, const char *, hash, name, value)
5275 #define settable_options_hash_iterate_end HASH_ITERATE_END
5277 static struct settable_options_hash *settable_options_hash = NULL;
5279 /**************************************************************************
5280 Load the server options.
5281 **************************************************************************/
5282 static void settable_options_load(struct section_file *sf)
5284 char buf[64];
5285 const struct section *psection;
5286 const struct entry_list *entries;
5287 const char *string;
5288 bool bval;
5289 int ival;
5291 fc_assert_ret(NULL != settable_options_hash);
5293 settable_options_hash_clear(settable_options_hash);
5295 psection = secfile_section_by_name(sf, "server");
5296 if (NULL == psection) {
5297 /* Does not exist! */
5298 return;
5301 entries = section_entries(psection);
5302 entry_list_iterate(entries, pentry) {
5303 string = NULL;
5304 switch (entry_type(pentry)) {
5305 case ENTRY_BOOL:
5306 if (entry_bool_get(pentry, &bval)) {
5307 fc_strlcpy(buf, bval ? "enabled" : "disabled", sizeof(buf));
5308 string = buf;
5310 break;
5312 case ENTRY_INT:
5313 if (entry_int_get(pentry, &ival)) {
5314 fc_snprintf(buf, sizeof(buf), "%d", ival);
5315 string = buf;
5317 break;
5319 case ENTRY_STR:
5320 (void) entry_str_get(pentry, &string);
5321 break;
5323 case ENTRY_FLOAT:
5324 case ENTRY_FILEREFERENCE:
5325 /* Not supported yet */
5326 break;
5329 if (NULL == string) {
5330 log_error("Entry type variant of \"%s.%s\" is not supported.",
5331 section_name(psection), entry_name(pentry));
5332 continue;
5335 settable_options_hash_insert(settable_options_hash, entry_name(pentry),
5336 string);
5337 } entry_list_iterate_end;
5340 /****************************************************************
5341 Save the desired server options.
5342 *****************************************************************/
5343 static void settable_options_save(struct section_file *sf)
5345 fc_assert_ret(NULL != settable_options_hash);
5347 settable_options_hash_iterate(settable_options_hash, name, value) {
5348 if (!fc_strcasecmp(name, "gameseed") || !fc_strcasecmp(name, "mapseed")) {
5349 /* Do not save mapseed or gameseed. */
5350 continue;
5352 if (!fc_strcasecmp(name, "topology")) {
5353 /* client_start_server() sets topology based on tileset. Don't store
5354 * its choice. The tileset is already stored. Storing topology leads
5355 * to all sort of breakage:
5356 * - it breaks ruleset default topology.
5357 * - it interacts badly with tileset ruleset change, ruleset tileset
5358 * change and topology tileset change.
5359 * - its value is probably based on what tileset was loaded when
5360 * client_start_server() decided to set topology, not on player
5361 * choice.
5363 continue;
5365 secfile_insert_str(sf, value, "server.%s", name);
5366 } settable_options_hash_iterate_end;
5369 /****************************************************************************
5370 Update the desired settable options hash table from the current
5371 setting configuration.
5372 ****************************************************************************/
5373 void desired_settable_options_update(void)
5375 char val_buf[1024], def_buf[1024];
5376 const char *value, *def_val;
5378 fc_assert_ret(NULL != settable_options_hash);
5380 options_iterate(server_optset, poption) {
5381 value = NULL;
5382 def_val = NULL;
5383 switch (option_type(poption)) {
5384 case OT_BOOLEAN:
5385 fc_strlcpy(val_buf, option_bool_get(poption) ? "enabled" : "disabled",
5386 sizeof(val_buf));
5387 value = val_buf;
5388 fc_strlcpy(def_buf, option_bool_def(poption) ? "enabled" : "disabled",
5389 sizeof(def_buf));
5390 def_val = def_buf;
5391 break;
5392 case OT_INTEGER:
5393 fc_snprintf(val_buf, sizeof(val_buf), "%d", option_int_get(poption));
5394 value = val_buf;
5395 fc_snprintf(def_buf, sizeof(def_buf), "%d", option_int_def(poption));
5396 def_val = def_buf;
5397 break;
5398 case OT_STRING:
5399 value = option_str_get(poption);
5400 def_val = option_str_def(poption);
5401 break;
5402 case OT_ENUM:
5403 server_option_enum_support_name(poption, &value, &def_val);
5404 break;
5405 case OT_BITWISE:
5406 server_option_bitwise_support_name(poption, val_buf, sizeof(val_buf),
5407 def_buf, sizeof(def_buf));
5408 value = val_buf;
5409 def_val = def_buf;
5410 break;
5411 case OT_FONT:
5412 case OT_COLOR:
5413 case OT_VIDEO_MODE:
5414 break;
5417 if (NULL == value || NULL == def_val) {
5418 log_error("Option type %s (%d) not supported for '%s'.",
5419 option_type_name(option_type(poption)), option_type(poption),
5420 option_name(poption));
5421 continue;
5424 if (0 == strcmp(value, def_val)) {
5425 /* Not set, using default... */
5426 settable_options_hash_remove(settable_options_hash,
5427 option_name(poption));
5428 } else {
5429 /* Really desired. */
5430 settable_options_hash_replace(settable_options_hash,
5431 option_name(poption), value);
5433 } options_iterate_end;
5436 /****************************************************************
5437 Update a desired settable option in the hash table from a value
5438 which can be different of the current consiguration.
5439 *****************************************************************/
5440 void desired_settable_option_update(const char *op_name,
5441 const char *op_value,
5442 bool allow_replace)
5444 fc_assert_ret(NULL != settable_options_hash);
5446 if (allow_replace) {
5447 settable_options_hash_replace(settable_options_hash, op_name, op_value);
5448 } else {
5449 settable_options_hash_insert(settable_options_hash, op_name, op_value);
5453 /****************************************************************************
5454 Convert old integer to new values (Freeciv 2.2.x to Freeciv 2.3.x).
5455 Very ugly hack. TODO: Remove this later.
5456 ****************************************************************************/
5457 static bool settable_option_upgrade_value(const struct option *poption,
5458 int old_value,
5459 char *buf, size_t buf_len)
5461 const char *name = option_name(poption);
5463 #define SETTING_CASE(ARG_name, ...) \
5464 if (0 == strcmp(ARG_name, name)) { \
5465 static const char *values[] = { __VA_ARGS__ }; \
5466 if (0 <= old_value && old_value < ARRAY_SIZE(values) \
5467 && NULL != values[old_value]) { \
5468 fc_strlcpy(buf, values[old_value], buf_len); \
5469 return TRUE; \
5470 } else { \
5471 return FALSE; \
5475 SETTING_CASE("topology", "", "WRAPX", "WRAPY", "WRAPX|WRAPY", "ISO",
5476 "WRAPX|ISO", "WRAPY|ISO", "WRAPX|WRAPY|ISO", "HEX",
5477 "WRAPX|HEX", "WRAPY|HEX", "WRAPX|WRAPY|HEX", "ISO|HEX",
5478 "WRAPX|ISO|HEX", "WRAPY|ISO|HEX", "WRAPX|WRAPY|ISO|HEX");
5479 SETTING_CASE("generator", NULL, "RANDOM", "FRACTAL", "ISLAND");
5480 SETTING_CASE("startpos", "DEFAULT", "SINGLE", "2or3", "ALL", "VARIABLE");
5481 SETTING_CASE("borders", "DISABLED", "ENABLED", "SEE_INSIDE", "EXPAND");
5482 SETTING_CASE("diplomacy", "ALL", "HUMAN", "AI", "TEAM", "DISABLED");
5483 SETTING_CASE("citynames", "NO_RESTRICTIONS", "PLAYER_UNIQUE",
5484 "GLOBAL_UNIQUE", "NO_STEALING");
5485 SETTING_CASE("barbarians", "DISABLED", "HUTS_ONLY", "NORMAL", "FREQUENT",
5486 "HORDES");
5487 SETTING_CASE("phasemode", "ALL", "PLAYER", "TEAM");
5488 SETTING_CASE("compresstype", "PLAIN", "LIBZ", "BZIP2");
5490 #undef SETTING_CASE
5491 return FALSE;
5494 /****************************************************************************
5495 Send the desired server options to the server.
5496 ****************************************************************************/
5497 static void desired_settable_option_send(struct option *poption)
5499 char *desired;
5500 int value;
5502 fc_assert_ret(NULL != settable_options_hash);
5504 if (!settable_options_hash_lookup(settable_options_hash,
5505 option_name(poption), &desired)) {
5506 /* No change explicitly desired. */
5507 return;
5510 switch (option_type(poption)) {
5511 case OT_BOOLEAN:
5512 if ((0 == fc_strcasecmp("enabled", desired)
5513 || (str_to_int(desired, &value) && 1 == value))
5514 && !option_bool_get(poption)) {
5515 send_chat_printf("/set %s enabled", option_name(poption));
5516 } else if ((0 == fc_strcasecmp("disabled", desired)
5517 || (str_to_int(desired, &value) && 0 == value))
5518 && option_bool_get(poption)) {
5519 send_chat_printf("/set %s disabled", option_name(poption));
5521 return;
5522 case OT_INTEGER:
5523 if (str_to_int(desired, &value) && value != option_int_get(poption)) {
5524 send_chat_printf("/set %s %d", option_name(poption), value);
5526 return;
5527 case OT_STRING:
5528 if (0 != strcmp(desired, option_str_get(poption))) {
5529 send_chat_printf("/set %s \"%s\"", option_name(poption), desired);
5531 return;
5532 case OT_ENUM:
5534 char desired_buf[256];
5535 const char *value_str;
5537 /* Handle old values. */
5538 if (str_to_int(desired, &value)
5539 && settable_option_upgrade_value(poption, value, desired_buf,
5540 sizeof(desired_buf))) {
5541 desired = desired_buf;
5544 server_option_enum_support_name(poption, &value_str, NULL);
5545 if (0 != strcmp(desired, value_str)) {
5546 send_chat_printf("/set %s \"%s\"", option_name(poption), desired);
5549 return;
5550 case OT_BITWISE:
5552 char desired_buf[256], value_buf[256];
5554 /* Handle old values. */
5555 if (str_to_int(desired, &value)
5556 && settable_option_upgrade_value(poption, value, desired_buf,
5557 sizeof(desired_buf))) {
5558 desired = desired_buf;
5561 server_option_bitwise_support_name(poption, value_buf,
5562 sizeof(value_buf), NULL, 0);
5563 if (0 != strcmp(desired, value_buf)) {
5564 send_chat_printf("/set %s \"%s\"", option_name(poption), desired);
5567 return;
5568 case OT_FONT:
5569 case OT_COLOR:
5570 case OT_VIDEO_MODE:
5571 break;
5574 log_error("Option type %s (%d) not supported for '%s'.",
5575 option_type_name(option_type(poption)), option_type(poption),
5576 option_name(poption));
5580 /****************************************************************************
5581 City and player report dialog options.
5582 ****************************************************************************/
5583 #define SPECHASH_TAG dialog_options
5584 #define SPECHASH_ASTR_KEY_TYPE
5585 #define SPECHASH_IDATA_TYPE bool
5586 #define SPECHASH_UDATA_TO_IDATA FC_INT_TO_PTR
5587 #define SPECHASH_IDATA_TO_UDATA FC_PTR_TO_INT
5588 #include "spechash.h"
5589 #define dialog_options_hash_iterate(hash, column, visible) \
5590 TYPED_HASH_ITERATE(const char *, intptr_t, hash, column, visible)
5591 #define dialog_options_hash_iterate_end HASH_ITERATE_END
5593 static struct dialog_options_hash *dialog_options_hash = NULL;
5595 /****************************************************************************
5596 Load the city and player report dialog options.
5597 ****************************************************************************/
5598 static void options_dialogs_load(struct section_file *sf)
5600 const struct entry_list *entries;
5601 const char *prefixes[] = { "player_dlg_", "city_report_", NULL };
5602 const char **prefix;
5603 bool visible;
5605 fc_assert_ret(NULL != dialog_options_hash);
5607 entries = section_entries(secfile_section_by_name(sf, "client"));
5609 if (NULL != entries) {
5610 entry_list_iterate(entries, pentry) {
5611 for (prefix = prefixes; NULL != *prefix; prefix++) {
5612 if (0 == strncmp(*prefix, entry_name(pentry), strlen(*prefix))
5613 && secfile_lookup_bool(sf, &visible, "client.%s",
5614 entry_name(pentry))) {
5615 dialog_options_hash_replace(dialog_options_hash,
5616 entry_name(pentry), visible);
5617 break;
5620 } entry_list_iterate_end;
5624 /****************************************************************************
5625 Save the city and player report dialog options.
5626 ****************************************************************************/
5627 static void options_dialogs_save(struct section_file *sf)
5629 fc_assert_ret(NULL != dialog_options_hash);
5631 options_dialogs_update();
5632 dialog_options_hash_iterate(dialog_options_hash, column, visible) {
5633 secfile_insert_bool(sf, visible, "client.%s", column);
5634 } dialog_options_hash_iterate_end;
5637 /****************************************************************
5638 This set the city and player report dialog options to the
5639 current ones. It's called when the client goes to
5640 C_S_DISCONNECTED state.
5641 *****************************************************************/
5642 void options_dialogs_update(void)
5644 char buf[64];
5645 int i;
5647 fc_assert_ret(NULL != dialog_options_hash);
5649 /* Player report dialog options. */
5650 for (i = 1; i < num_player_dlg_columns; i++) {
5651 fc_snprintf(buf, sizeof(buf), "player_dlg_%s",
5652 player_dlg_columns[i].tagname);
5653 dialog_options_hash_replace(dialog_options_hash, buf,
5654 player_dlg_columns[i].show);
5657 /* City report dialog options. */
5658 for (i = 0; i < num_city_report_spec(); i++) {
5659 fc_snprintf(buf, sizeof(buf), "city_report_%s",
5660 city_report_spec_tagname(i));
5661 dialog_options_hash_replace(dialog_options_hash, buf,
5662 *city_report_spec_show_ptr(i));
5666 /****************************************************************
5667 This set the city and player report dialog options. It's called
5668 when the client goes to C_S_RUNNING state.
5669 *****************************************************************/
5670 void options_dialogs_set(void)
5672 char buf[64];
5673 bool visible;
5674 int i;
5676 fc_assert_ret(NULL != dialog_options_hash);
5678 /* Player report dialog options. */
5679 for (i = 1; i < num_player_dlg_columns; i++) {
5680 fc_snprintf(buf, sizeof(buf), "player_dlg_%s",
5681 player_dlg_columns[i].tagname);
5682 if (dialog_options_hash_lookup(dialog_options_hash, buf, &visible)) {
5683 player_dlg_columns[i].show = visible;
5687 /* City report dialog options. */
5688 for (i = 0; i < num_city_report_spec(); i++) {
5689 fc_snprintf(buf, sizeof(buf), "city_report_%s",
5690 city_report_spec_tagname(i));
5691 if (dialog_options_hash_lookup(dialog_options_hash, buf, &visible)) {
5692 *city_report_spec_show_ptr(i) = visible;
5698 /****************************************************************
5699 Load from the rc file any options that are not ruleset specific.
5700 It is called after ui_init(), yet before ui_main().
5701 Unfortunately, this means that some clients cannot display.
5702 Instead, use log_*().
5703 *****************************************************************/
5704 void options_load(void)
5706 struct section_file *sf;
5707 bool allow_digital_boolean;
5708 int i, num;
5709 const char *name;
5710 const char *const prefix = "client";
5711 const char *str;
5713 name = get_last_option_file_name(&allow_digital_boolean);
5714 if (!name) {
5715 log_normal(_("Didn't find the option file. Creating a new one."));
5716 client_option_adjust_defaults();
5717 options_fully_initialized = TRUE;
5718 create_default_cma_presets();
5719 gui_options.first_boot = TRUE;
5720 return;
5722 if (!(sf = secfile_load(name, TRUE))) {
5723 log_debug("Error loading option file '%s':\n%s", name, secfile_error());
5724 /* try to create the rc file */
5725 sf = secfile_new(TRUE);
5726 secfile_insert_str(sf, VERSION_STRING, "client.version");
5728 create_default_cma_presets();
5729 save_cma_presets(sf);
5731 /* FIXME: need better messages */
5732 if (!secfile_save(sf, name, 0, FZ_PLAIN)) {
5733 log_error(_("Save failed, cannot write to file %s"), name);
5734 } else {
5735 log_normal(_("Saved settings to file %s"), name);
5737 secfile_destroy(sf);
5738 options_fully_initialized = TRUE;
5739 return;
5741 secfile_allow_digital_boolean(sf, allow_digital_boolean);
5743 /* a "secret" option for the lazy. TODO: make this saveable */
5744 sz_strlcpy(password,
5745 secfile_lookup_str_default(sf, "", "%s.password", prefix));
5747 gui_options.save_options_on_exit =
5748 secfile_lookup_bool_default(sf, gui_options.save_options_on_exit,
5749 "%s.save_options_on_exit", prefix);
5750 gui_options.migrate_fullscreen =
5751 secfile_lookup_bool_default(sf, gui_options.migrate_fullscreen,
5752 "%s.fullscreen_mode", prefix);
5754 /* Settings migrations */
5755 gui_options.gui_gtk3_22_migrated_from_gtk3 =
5756 secfile_lookup_bool_default(sf, gui_options.gui_gtk3_22_migrated_from_gtk3,
5757 "%s.migration_gtk3_22_from_gtk3", prefix);
5758 gui_options.gui_gtk3_migrated_from_gtk2 =
5759 secfile_lookup_bool_default(sf, gui_options.gui_gtk3_migrated_from_gtk2,
5760 "%s.migration_gtk3_from_gtk2", prefix);
5761 gui_options.gui_sdl2_migrated_from_sdl =
5762 secfile_lookup_bool_default(sf, gui_options.gui_sdl2_migrated_from_sdl,
5763 "%s.migration_sdl2_from_sdl", prefix);
5764 gui_options.gui_gtk2_migrated_from_2_5 =
5765 secfile_lookup_bool_default(sf, gui_options.gui_gtk3_migrated_from_2_5,
5766 "%s.migration_gtk2_from_2_5", prefix);
5767 gui_options.gui_gtk3_migrated_from_2_5 =
5768 secfile_lookup_bool_default(sf, gui_options.gui_gtk2_migrated_from_2_5,
5769 "%s.migration_gtk3_from_2_5", prefix);
5770 gui_options.gui_qt_migrated_from_2_5 =
5771 secfile_lookup_bool_default(sf, gui_options.gui_qt_migrated_from_2_5,
5772 "%s.migration_qt_from_2_5", prefix);
5774 /* These are not gui-enabled yet */
5775 gui_options.zoom_set =
5776 secfile_lookup_bool_default(sf, FALSE, "%s.zoom_set", prefix);
5777 gui_options.zoom_default_level =
5778 secfile_lookup_float_default(sf, 1.0,
5779 "%s.zoom_default_level", prefix);
5781 str = secfile_lookup_str_default(sf, NULL, "client.default_tileset_name");
5782 if (str != NULL) {
5783 strncpy(gui_options.default_tileset_name, str,
5784 sizeof(gui_options.default_tileset_name));
5787 /* Backwards compatibility for removed options replaced by entirely "new"
5788 * options. The equivalent "new" option will override these, if set. */
5790 /* Removed in 2.3 */
5791 /* Note: this overrides the previously specified default for
5792 * gui_gtk2_message_chat_location */
5793 /* gtk3 client never had the old form of this option. The overridden
5794 * gui_gtk2_ value will be propagated to gui_gtk3_ later by
5795 * migrate_options_from_gtk2() if necessary. */
5796 if (secfile_lookup_bool_default(sf, FALSE,
5797 "%s.gui_gtk2_merge_notebooks", prefix)) {
5798 gui_options.gui_gtk2_message_chat_location = GUI_GTK_MSGCHAT_MERGED;
5799 } else if (secfile_lookup_bool_default(sf, FALSE,
5800 "%s.gui_gtk2_split_bottom_notebook",
5801 prefix)) {
5802 gui_options.gui_gtk2_message_chat_location = GUI_GTK_MSGCHAT_SPLIT;
5803 } else {
5804 gui_options.gui_gtk2_message_chat_location = GUI_GTK_MSGCHAT_SEPARATE;
5807 /* Renamed in 2.6 */
5808 gui_options.popup_actor_arrival = secfile_lookup_bool_default(sf, TRUE,
5809 "%s.popup_caravan_arrival", prefix);
5811 /* Load all the regular options */
5812 client_options_iterate_all(poption) {
5813 client_option_load(poption, sf);
5814 } client_options_iterate_all_end;
5816 /* More backwards compatibility, for removed options that had been
5817 * folded into then-existing options. Here, the backwards-compatibility
5818 * behaviour overrides the "destination" option. */
5820 /* Removed in 2.4 */
5821 if (!secfile_lookup_bool_default(sf, TRUE,
5822 "%s.do_combat_animation", prefix)) {
5823 gui_options.smooth_combat_step_msec = 0;
5826 message_options_load(sf, prefix);
5827 options_dialogs_load(sf);
5829 /* Load cma presets. If cma.number_of_presets doesn't exist, don't load
5830 * any, the order here should be reversed to keep the order the same */
5831 if (secfile_lookup_int(sf, &num, "cma.number_of_presets")) {
5832 for (i = num - 1; i >= 0; i--) {
5833 load_cma_preset(sf, i);
5835 } else {
5836 create_default_cma_presets();
5839 settable_options_load(sf);
5840 global_worklists_load(sf);
5842 secfile_destroy(sf);
5843 options_fully_initialized = TRUE;
5846 /**************************************************************************
5847 Write messages from option saving to the output window.
5848 **************************************************************************/
5849 static void option_save_output_window_callback(enum log_level lvl,
5850 const char *msg, ...)
5852 va_list args;
5854 va_start(args, msg);
5855 output_window_vprintf(ftc_client, msg, args);
5856 va_end(args);
5859 /**************************************************************************
5860 Save all options.
5861 **************************************************************************/
5862 void options_save(option_save_log_callback log_cb)
5864 struct section_file *sf;
5865 const char *name = get_current_option_file_name();
5866 char dir_name[2048];
5867 int i;
5869 if (log_cb == NULL) {
5870 /* Default callback */
5871 log_cb = option_save_output_window_callback;
5874 if (!name) {
5875 log_cb(LOG_ERROR, _("Save failed, cannot find a filename."));
5876 return;
5879 sf = secfile_new(TRUE);
5880 secfile_insert_str(sf, VERSION_STRING, "client.version");
5882 secfile_insert_bool(sf, gui_options.save_options_on_exit,
5883 "client.save_options_on_exit");
5884 secfile_insert_bool_comment(sf, gui_options.migrate_fullscreen,
5885 "deprecated", "client.fullscreen_mode");
5887 /* Migrations */
5888 secfile_insert_bool(sf, gui_options.gui_gtk3_22_migrated_from_gtk3,
5889 "client.migration_gtk3_22_from_gtk3");
5890 secfile_insert_bool(sf, gui_options.gui_gtk3_migrated_from_gtk2,
5891 "client.migration_gtk3_from_gtk2");
5892 secfile_insert_bool(sf, gui_options.gui_sdl2_migrated_from_sdl,
5893 "client.migration_sdl2_from_sdl");
5894 secfile_insert_bool(sf, gui_options.gui_gtk2_migrated_from_2_5,
5895 "client.migration_gtk2_from_2_5");
5896 secfile_insert_bool(sf, gui_options.gui_gtk3_migrated_from_2_5,
5897 "client.migration_gtk3_from_2_5");
5898 secfile_insert_bool(sf, gui_options.gui_qt_migrated_from_2_5,
5899 "client.migration_qt_from_2_5");
5901 /* gui-enabled options */
5902 client_options_iterate_all(poption) {
5903 client_option_save(poption, sf);
5904 } client_options_iterate_all_end;
5906 /* These are not gui-enabled yet. */
5907 secfile_insert_bool(sf, gui_options.zoom_set, "client.zoom_set");
5908 secfile_insert_float(sf, gui_options.zoom_default_level,
5909 "client.zoom_default_level");
5911 if (gui_options.default_tileset_name[0] != '\0') {
5912 secfile_insert_str(sf, gui_options.default_tileset_name,
5913 "client.default_tileset_name");
5916 message_options_save(sf, "client");
5917 options_dialogs_save(sf);
5919 /* server settings */
5920 save_cma_presets(sf);
5921 settable_options_save(sf);
5923 /* insert global worklists */
5924 global_worklists_save(sf);
5926 /* Directory name */
5927 strncpy(dir_name, name, sizeof(dir_name));
5928 for (i = strlen(dir_name) - 1 ; dir_name[i] != DIR_SEPARATOR_CHAR && i >= 0; i--) {
5929 /* Nothing */
5931 if (i > 0) {
5932 dir_name[i] = '\0';
5933 make_dir(dir_name);
5936 /* save to disk */
5937 if (!secfile_save(sf, name, 0, FZ_PLAIN)) {
5938 log_cb(LOG_ERROR, _("Save failed, cannot write to file %s"), name);
5939 } else {
5940 log_cb(LOG_VERBOSE, _("Saved settings to file %s"), name);
5942 secfile_destroy(sf);
5946 /**************************************************************************
5947 Initialize lists of names for a client option.
5948 **************************************************************************/
5949 static void options_init_names(const struct copt_val_name *(*acc)(int),
5950 struct strvec **support, struct strvec **pretty)
5952 int val;
5953 const struct copt_val_name *name;
5954 fc_assert_ret(NULL != acc);
5955 *support = strvec_new();
5956 *pretty = strvec_new();
5957 for (val=0; (name = acc(val)); val++) {
5958 strvec_append(*support, name->support);
5959 strvec_append(*pretty, name->pretty);
5963 /**************************************************************************
5964 Initialize the option module.
5965 **************************************************************************/
5966 void options_init(void)
5968 message_options_init();
5969 options_extra_init();
5970 global_worklists_init();
5972 settable_options_hash = settable_options_hash_new();
5973 dialog_options_hash = dialog_options_hash_new();
5975 client_options_iterate_all(poption) {
5976 struct client_option *pcoption = CLIENT_OPTION(poption);
5978 switch (option_type(poption)) {
5979 case OT_INTEGER:
5980 if (option_int_def(poption) < option_int_min(poption)
5981 || option_int_def(poption) > option_int_max(poption)) {
5982 int new_default = MAX(MIN(option_int_def(poption),
5983 option_int_max(poption)),
5984 option_int_min(poption));
5986 log_error("option %s has default value of %d, which is "
5987 "out of its range [%d; %d], changing to %d.",
5988 option_name(poption), option_int_def(poption),
5989 option_int_min(poption), option_int_max(poption),
5990 new_default);
5991 *((int *) &(pcoption->integer.def)) = new_default;
5993 break;
5995 case OT_STRING:
5996 if (gui_options.default_user_name == option_str_get(poption)) {
5997 /* Hack to get a default value. */
5998 *((const char **) &(pcoption->string.def)) =
5999 fc_strdup(gui_options.default_user_name);
6002 if (NULL == option_str_def(poption)) {
6003 const struct strvec *values = option_str_values(poption);
6005 if (NULL == values || strvec_size(values) == 0) {
6006 log_error("Invalid NULL default string for option %s.",
6007 option_name(poption));
6008 } else {
6009 *((const char **) &(pcoption->string.def)) =
6010 strvec_get(values, 0);
6013 break;
6015 case OT_ENUM:
6016 fc_assert(NULL == pcoption->enumerator.support_names);
6017 fc_assert(NULL == pcoption->enumerator.pretty_names);
6018 options_init_names(pcoption->enumerator.name_accessor,
6019 &pcoption->enumerator.support_names,
6020 &pcoption->enumerator.pretty_names);
6021 fc_assert(NULL != pcoption->enumerator.support_names);
6022 fc_assert(NULL != pcoption->enumerator.pretty_names);
6023 break;
6025 case OT_BITWISE:
6026 fc_assert(NULL == pcoption->bitwise.support_names);
6027 fc_assert(NULL == pcoption->bitwise.pretty_names);
6028 options_init_names(pcoption->bitwise.name_accessor,
6029 &pcoption->bitwise.support_names,
6030 &pcoption->bitwise.pretty_names);
6031 fc_assert(NULL != pcoption->bitwise.support_names);
6032 fc_assert(NULL != pcoption->bitwise.pretty_names);
6033 break;
6035 case OT_COLOR:
6037 /* Duplicate the string pointers. */
6038 struct ft_color *pcolor = pcoption->color.pvalue;
6040 if (NULL != pcolor->foreground) {
6041 pcolor->foreground = fc_strdup(pcolor->foreground);
6043 if (NULL != pcolor->background) {
6044 pcolor->background = fc_strdup(pcolor->background);
6048 case OT_BOOLEAN:
6049 case OT_FONT:
6050 case OT_VIDEO_MODE:
6051 break;
6054 /* Set to default. */
6055 option_reset(poption);
6056 } client_options_iterate_all_end;
6059 /**************************************************************************
6060 Free the option module.
6061 **************************************************************************/
6062 void options_free(void)
6064 client_options_iterate_all(poption) {
6065 struct client_option *pcoption = CLIENT_OPTION(poption);
6067 switch (option_type(poption)) {
6068 case OT_ENUM:
6069 fc_assert_action(NULL != pcoption->enumerator.support_names, break);
6070 strvec_destroy(pcoption->enumerator.support_names);
6071 pcoption->enumerator.support_names = NULL;
6072 fc_assert_action(NULL != pcoption->enumerator.pretty_names, break);
6073 strvec_destroy(pcoption->enumerator.pretty_names);
6074 pcoption->enumerator.pretty_names = NULL;
6075 break;
6077 case OT_BITWISE:
6078 fc_assert_action(NULL != pcoption->bitwise.support_names, break);
6079 strvec_destroy(pcoption->bitwise.support_names);
6080 pcoption->bitwise.support_names = NULL;
6081 fc_assert_action(NULL != pcoption->bitwise.pretty_names, break);
6082 strvec_destroy(pcoption->bitwise.pretty_names);
6083 pcoption->bitwise.pretty_names = NULL;
6084 break;
6086 case OT_BOOLEAN:
6087 case OT_INTEGER:
6088 case OT_STRING:
6089 case OT_FONT:
6090 case OT_COLOR:
6091 case OT_VIDEO_MODE:
6092 break;
6094 } client_options_iterate_all_end;
6096 if (NULL != settable_options_hash) {
6097 settable_options_hash_destroy(settable_options_hash);
6098 settable_options_hash = NULL;
6101 if (NULL != dialog_options_hash) {
6102 dialog_options_hash_destroy(dialog_options_hash);
6103 dialog_options_hash = NULL;
6106 message_options_free();
6107 global_worklists_free();
6110 /****************************************************************************
6111 Callback when the reqtree show icons option is changed. The tree is
6112 recalculated.
6113 ****************************************************************************/
6114 static void reqtree_show_icons_callback(struct option *poption)
6116 science_report_dialog_redraw();
6119 /****************************************************************************
6120 Callback for when any view option is changed.
6121 ****************************************************************************/
6122 static void view_option_changed_callback(struct option *poption)
6124 menus_init();
6125 update_map_canvas_visible();
6128 /****************************************************************************
6129 Callback for when ai_manual_turn_done is changed.
6130 ****************************************************************************/
6131 static void manual_turn_done_callback(struct option *poption)
6133 update_turn_done_button_state();
6134 if (!gui_options.ai_manual_turn_done && client.conn.playing->ai_controlled) {
6135 if (can_end_turn()) {
6136 user_ended_turn();
6141 /****************************************************************************
6142 Callback for when any voteinfo bar option is changed.
6143 ****************************************************************************/
6144 static void voteinfo_bar_callback(struct option *poption)
6146 voteinfo_gui_update();
6149 /****************************************************************************
6150 Callback for font options.
6151 ****************************************************************************/
6152 static void font_changed_callback(struct option *poption)
6154 fc_assert_ret(OT_FONT == option_type(OPTION(poption)));
6155 gui_update_font(option_font_target(poption), option_font_get(poption));
6158 /****************************************************************************
6159 Callback for mapimg options.
6160 ****************************************************************************/
6161 static void mapimg_changed_callback(struct option *poption)
6163 if (!mapimg_client_define()) {
6164 bool success;
6166 log_normal("Error setting the value for %s (%s). Restoring the default "
6167 "value.", option_name(poption), mapimg_error());
6169 /* Reset the value to the default value. */
6170 success = option_reset(poption);
6171 fc_assert_msg(success == TRUE,
6172 "Failed to reset the option \"%s\".",
6173 option_name(poption));
6174 success = mapimg_client_define();
6175 fc_assert_msg(success == TRUE,
6176 "Failed to restore mapimg definition for option \"%s\".",
6177 option_name(poption));
6181 /****************************************************************************
6182 Callback for music enabling option.
6183 ****************************************************************************/
6184 static void game_music_enable_callback(struct option *poption)
6186 if (client_state() == C_S_RUNNING) {
6187 if (gui_options.sound_enable_game_music) {
6188 start_style_music();
6189 } else {
6190 stop_style_music();
6195 /****************************************************************************
6196 Callback for music enabling option.
6197 ****************************************************************************/
6198 static void menu_music_enable_callback(struct option *poption)
6200 if (client_state() != C_S_RUNNING) {
6201 if (gui_options.sound_enable_menu_music) {
6202 start_menu_music("music_menu", NULL);
6203 } else {
6204 stop_menu_music();
6209 /****************************************************************************
6210 Make dynamic adjustments to first-launch default options.
6211 ****************************************************************************/
6212 static void client_option_adjust_defaults(void)
6214 adjust_default_options();
6217 /****************************************************************************
6218 Convert a video mode to string. Returns TRUE on success.
6219 ****************************************************************************/
6220 bool video_mode_to_string(char *buf, size_t buf_len, struct video_mode *mode)
6222 return (2 < fc_snprintf(buf, buf_len, "%dx%d", mode->width, mode->height));
6225 /****************************************************************************
6226 Convert a string to video mode. Returns TRUE on success.
6227 ****************************************************************************/
6228 bool string_to_video_mode(const char *buf, struct video_mode *mode)
6230 return (2 == sscanf(buf, "%dx%d", &mode->width, &mode->height));
6233 /****************************************************************************
6234 Option framework wrapper for mapimg_get_format_list()
6235 ****************************************************************************/
6236 static const struct strvec *get_mapimg_format_list(const struct option *poption)
6238 return mapimg_get_format_list();
6241 /****************************************************************************
6242 What is the user defined tileset for the given topology
6243 ****************************************************************************/
6244 const char *tileset_name_for_topology(int topology_id)
6246 const char *tsn = NULL;
6248 switch (topology_id & (TF_ISO | TF_HEX)) {
6249 case 0:
6250 tsn = gui_options.default_tileset_overhead_name;
6251 break;
6252 case TF_ISO:
6253 tsn = gui_options.default_tileset_iso_name;
6254 break;
6255 case TF_HEX:
6256 tsn = gui_options.default_tileset_hex_name;
6257 break;
6258 case TF_ISO | TF_HEX:
6259 tsn = gui_options.default_tileset_isohex_name;
6260 break;
6263 if (tsn == NULL) {
6264 tsn = gui_options.default_tileset_name;
6267 return tsn;
6270 /****************************************************************************
6271 Set given tileset as the default for suitable topology
6272 ****************************************************************************/
6273 void option_set_default_ts(struct tileset *t)
6275 const char *optname = "<not set>";
6276 struct option *opt;
6278 switch (tileset_topo_index(t)) {
6279 case TS_TOPO_OVERHEAD:
6280 /* Overhead */
6281 optname = "default_tileset_overhead_name";
6282 break;
6283 case TS_TOPO_ISO:
6284 /* Iso */
6285 optname = "default_tileset_iso_name";
6286 break;
6287 case TS_TOPO_HEX:
6288 /* Hex */
6289 optname = "default_tileset_hex_name";
6290 break;
6291 case TS_TOPO_ISOHEX:
6292 /* Isohex */
6293 optname = "default_tileset_isohex_name";
6294 break;
6297 opt = optset_option_by_name(client_optset, optname);
6299 if (opt == NULL) {
6300 log_error("Unknown option name \"%s\" in option_set_default_ts()", optname);
6301 return;
6304 /* Do not call option_str_set() since we don't want option changed callback
6305 * to reload this tileset. */
6306 opt->str_vtable->set(opt, tileset_basename(t));
6307 option_gui_update(opt);
6310 /****************************************************************************
6311 Does topology-specific tileset option lack value?
6312 ****************************************************************************/
6313 static bool is_ts_option_unset(const char *optname)
6315 struct option *opt;
6316 const char *val;
6318 opt = optset_option_by_name(client_optset, optname);
6320 if (opt == NULL) {
6321 return TRUE;
6324 val = opt->str_vtable->get(opt);
6326 if (val == NULL || val[0] == '\0') {
6327 return TRUE;
6330 return FALSE;
6333 /****************************************************************************
6334 Fill default tilesets for topology-specific settings.
6335 ****************************************************************************/
6336 void fill_topo_ts_default(void)
6338 if (is_ts_option_unset("default_tileset_overhead_name")) {
6339 log_debug("Setting tileset for overhead topology.");
6340 tilespec_try_read(NULL, FALSE, 0, FALSE);
6342 if (is_ts_option_unset("default_tileset_iso_name")) {
6343 log_debug("Setting tileset for iso topology.");
6344 tilespec_try_read(NULL, FALSE, TF_ISO, FALSE);
6346 if (is_ts_option_unset("default_tileset_hex_name")) {
6347 log_debug("Setting tileset for hex topology.");
6348 tilespec_try_read(NULL, FALSE, TF_HEX, FALSE);
6350 if (is_ts_option_unset("default_tileset_isohex_name")) {
6351 log_debug("Setting tileset for isohex topology.");
6352 tilespec_try_read(NULL, FALSE, TF_ISO | TF_HEX, FALSE);