Rulesave saves trade.type and trade.bonus correctly.
[freeciv.git] / client / options.c
blob027b802a95f787a000c763b9cf4282bab4cf513b
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 "mapview_common.h"
57 #include "music.h"
58 #include "overview_common.h"
59 #include "packhand_gen.h"
60 #include "plrdlg_common.h"
61 #include "repodlgs_common.h"
62 #include "servers.h"
63 #include "themes_common.h"
64 #include "tilespec.h"
66 #include "options.h"
69 struct client_options gui_options = {
70 /** Defaults for options normally on command line **/
72 .default_user_name = "\0",
73 .default_server_host = "localhost",
74 .default_server_port = DEFAULT_SOCK_PORT,
75 .default_metaserver = DEFAULT_METASERVER_OPTION,
76 .default_tileset_overhead_name = "\0",
77 .default_tileset_iso_name = "\0",
78 .default_tileset_hex_name = "\0",
79 .default_tileset_isohex_name = "\0",
80 .default_sound_set_name = "stdsounds",
81 .default_music_set_name = "stdmusic",
82 .default_sound_plugin_name = "\0",
83 .default_chat_logfile = GUI_DEFAULT_CHAT_LOGFILE,
85 .save_options_on_exit = TRUE,
87 .use_prev_server = FALSE,
88 .heartbeat_enabled = FALSE,
90 /** Migrations **/
91 .first_boot = FALSE,
92 .default_tileset_name = "\0",
93 .gui_gtk3_22_migrated_from_gtk3 = FALSE,
94 .gui_gtk3_migrated_from_gtk2 = FALSE,
95 .gui_sdl2_migrated_from_sdl = FALSE,
96 .gui_gtk2_migrated_from_2_5 = FALSE,
97 .gui_gtk3_migrated_from_2_5 = FALSE,
98 .gui_qt_migrated_from_2_5 = FALSE,
100 .migrate_fullscreen = FALSE,
102 /** Local Options: **/
104 .solid_color_behind_units = FALSE,
105 .sound_bell_at_new_turn = FALSE,
106 .smooth_move_unit_msec = 30,
107 .smooth_center_slide_msec = 200,
108 .smooth_combat_step_msec = 10,
109 .ai_manual_turn_done = TRUE,
110 .auto_center_on_unit = TRUE,
111 .auto_center_on_automated = TRUE,
112 .auto_center_on_combat = FALSE,
113 .auto_center_each_turn = TRUE,
114 .wakeup_focus = TRUE,
115 .goto_into_unknown = TRUE,
116 .center_when_popup_city = TRUE,
117 .concise_city_production = FALSE,
118 .auto_turn_done = FALSE,
119 .meta_accelerators = TRUE,
120 .ask_city_name = TRUE,
121 .popup_new_cities = TRUE,
122 .popup_actor_arrival = TRUE,
123 .keyboardless_goto = TRUE,
124 .enable_cursor_changes = TRUE,
125 .separate_unit_selection = FALSE,
126 .unit_selection_clears_orders = TRUE,
127 .highlight_our_names = FT_COLOR("#000000", "#FFFF00"),
129 .voteinfo_bar_use = TRUE,
130 .voteinfo_bar_always_show = FALSE,
131 .voteinfo_bar_hide_when_not_player = FALSE,
132 .voteinfo_bar_new_at_front = FALSE,
134 .autoaccept_tileset_suggestion = FALSE,
135 .autoaccept_soundset_suggestion = FALSE,
136 .autoaccept_musicset_suggestion = FALSE,
138 .sound_enable_effects = TRUE,
139 .sound_enable_menu_music = TRUE,
140 .sound_enable_game_music = TRUE,
142 /* This option is currently set by the client - not by the user. */
143 .update_city_text_in_refresh_tile = TRUE,
145 .draw_city_outlines = TRUE,
146 .draw_city_output = FALSE,
147 .draw_map_grid = FALSE,
148 .draw_city_names = TRUE,
149 .draw_city_growth = TRUE,
150 .draw_city_productions = TRUE,
151 .draw_city_buycost = FALSE,
152 .draw_city_trade_routes = FALSE,
153 .draw_terrain = TRUE,
154 .draw_coastline = FALSE,
155 .draw_roads_rails = TRUE,
156 .draw_irrigation = TRUE,
157 .draw_mines = TRUE,
158 .draw_fortress_airbase = TRUE,
159 .draw_specials = TRUE,
160 .draw_huts = TRUE,
161 .draw_pollution = TRUE,
162 .draw_cities = TRUE,
163 .draw_units = TRUE,
164 .draw_focus_unit = FALSE,
165 .draw_fog_of_war = TRUE,
166 .draw_borders = TRUE,
167 .draw_native = FALSE,
168 .draw_full_citybar = TRUE,
169 .draw_unit_shields = TRUE,
170 .player_dlg_show_dead_players = TRUE,
171 .reqtree_show_icons = TRUE,
172 .reqtree_curved_lines = FALSE,
174 /* options for map images */
175 /* .mapimg_format, */
176 .mapimg_zoom = 2,
177 /* See the definition of MAPIMG_LAYER in mapimg.h. */
178 .mapimg_layer = {
179 FALSE, /* a - MAPIMG_LAYER_AREA */
180 TRUE, /* b - MAPIMG_LAYER_BORDERS */
181 TRUE, /* c - MAPIMG_LAYER_CITIES */
182 TRUE, /* f - MAPIMG_LAYER_FOGOFWAR */
183 TRUE, /* k - MAPIMG_LAYER_KNOWLEDGE */
184 TRUE, /* t - MAPIMG_LAYER_TERRAIN */
185 TRUE /* u - MAPIMG_LAYER_UNITS */
187 /* .mapimg_filename, */
189 .zoom_set = FALSE,
190 .zoom_default_level = 1.0,
192 /* gui-gtk-2.0 client specific options. */
193 .gui_gtk2_default_theme_name = FC_GTK2_DEFAULT_THEME_NAME,
194 .gui_gtk2_fullscreen = FALSE,
195 .gui_gtk2_map_scrollbars = FALSE,
196 .gui_gtk2_dialogs_on_top = TRUE,
197 .gui_gtk2_show_task_icons = TRUE,
198 .gui_gtk2_enable_tabs = TRUE,
199 .gui_gtk2_better_fog = TRUE,
200 .gui_gtk2_show_chat_message_time = FALSE,
201 .gui_gtk2_new_messages_go_to_top = FALSE,
202 .gui_gtk2_show_message_window_buttons = TRUE,
203 .gui_gtk2_metaserver_tab_first = FALSE,
204 .gui_gtk2_allied_chat_only = FALSE,
205 .gui_gtk2_message_chat_location = GUI_GTK_MSGCHAT_MERGED,
206 .gui_gtk2_small_display_layout = TRUE,
207 .gui_gtk2_mouse_over_map_focus = FALSE,
208 .gui_gtk2_chatline_autocompletion = TRUE,
209 .gui_gtk2_citydlg_xsize = GUI_GTK2_CITYDLG_DEFAULT_XSIZE,
210 .gui_gtk2_citydlg_ysize = GUI_GTK2_CITYDLG_DEFAULT_YSIZE,
211 .gui_gtk2_popup_tech_help = GUI_POPUP_TECH_HELP_RULESET,
212 .gui_gtk2_font_city_label = "Monospace 8",
213 .gui_gtk2_font_notify_label = "Monospace Bold 9",
214 .gui_gtk2_font_spaceship_label = "Monospace 8",
215 .gui_gtk2_font_help_label = "Sans Bold 10",
216 .gui_gtk2_font_help_link = "Sans 9",
217 .gui_gtk2_font_help_text = "Monospace 8",
218 .gui_gtk2_font_chatline = "Monospace 8",
219 .gui_gtk2_font_beta_label = "Sans Italic 10",
220 .gui_gtk2_font_small = "Sans 9",
221 .gui_gtk2_font_comment_label = "Sans Italic 9",
222 .gui_gtk2_font_city_names = "Sans Bold 10",
223 .gui_gtk2_font_city_productions = "Serif 10",
224 .gui_gtk2_font_reqtree_text = "Serif 10",
226 /* gui-gtk-3.0 client specific options. */
227 .gui_gtk3_default_theme_name = FC_GTK3_DEFAULT_THEME_NAME,
228 .gui_gtk3_fullscreen = FALSE,
229 .gui_gtk3_map_scrollbars = FALSE,
230 .gui_gtk3_dialogs_on_top = TRUE,
231 .gui_gtk3_show_task_icons = TRUE,
232 .gui_gtk3_enable_tabs = TRUE,
233 .gui_gtk3_show_chat_message_time = FALSE,
234 .gui_gtk3_new_messages_go_to_top = FALSE,
235 .gui_gtk3_show_message_window_buttons = TRUE,
236 .gui_gtk3_metaserver_tab_first = FALSE,
237 .gui_gtk3_allied_chat_only = FALSE,
238 .gui_gtk3_message_chat_location = GUI_GTK_MSGCHAT_MERGED,
239 .gui_gtk3_small_display_layout = TRUE,
240 .gui_gtk3_mouse_over_map_focus = FALSE,
241 .gui_gtk3_chatline_autocompletion = TRUE,
242 .gui_gtk3_citydlg_xsize = GUI_GTK3_CITYDLG_DEFAULT_XSIZE,
243 .gui_gtk3_citydlg_ysize = GUI_GTK3_CITYDLG_DEFAULT_YSIZE,
244 .gui_gtk3_popup_tech_help = GUI_POPUP_TECH_HELP_RULESET,
245 .gui_gtk3_governor_range_min = -20,
246 .gui_gtk3_governor_range_max = 20,
247 .gui_gtk3_font_city_label = "Monospace 8",
248 .gui_gtk3_font_notify_label = "Monospace Bold 9",
249 .gui_gtk3_font_spaceship_label = "Monospace 8",
250 .gui_gtk3_font_help_label = "Sans Bold 10",
251 .gui_gtk3_font_help_link = "Sans 9",
252 .gui_gtk3_font_help_text = "Monospace 8",
253 .gui_gtk3_font_chatline = "Monospace 8",
254 .gui_gtk3_font_beta_label = "Sans Italic 10",
255 .gui_gtk3_font_small = "Sans 9",
256 .gui_gtk3_font_comment_label = "Sans Italic 9",
257 .gui_gtk3_font_city_names = "Sans Bold 10",
258 .gui_gtk3_font_city_productions = "Serif 10",
259 .gui_gtk3_font_reqtree_text = "Serif 10",
261 /* gui-gtk-3.22 client specific options. */
262 .gui_gtk3_22_default_theme_name = FC_GTK3_DEFAULT_THEME_NAME,
263 .gui_gtk3_22_fullscreen = FALSE,
264 .gui_gtk3_22_map_scrollbars = FALSE,
265 .gui_gtk3_22_dialogs_on_top = TRUE,
266 .gui_gtk3_22_show_task_icons = TRUE,
267 .gui_gtk3_22_enable_tabs = TRUE,
268 .gui_gtk3_22_show_chat_message_time = FALSE,
269 .gui_gtk3_22_new_messages_go_to_top = FALSE,
270 .gui_gtk3_22_show_message_window_buttons = TRUE,
271 .gui_gtk3_22_metaserver_tab_first = FALSE,
272 .gui_gtk3_22_allied_chat_only = FALSE,
273 .gui_gtk3_22_message_chat_location = GUI_GTK_MSGCHAT_MERGED,
274 .gui_gtk3_22_small_display_layout = TRUE,
275 .gui_gtk3_22_mouse_over_map_focus = FALSE,
276 .gui_gtk3_22_chatline_autocompletion = TRUE,
277 .gui_gtk3_22_citydlg_xsize = GUI_GTK3_CITYDLG_DEFAULT_XSIZE,
278 .gui_gtk3_22_citydlg_ysize = GUI_GTK3_CITYDLG_DEFAULT_YSIZE,
279 .gui_gtk3_22_popup_tech_help = GUI_POPUP_TECH_HELP_RULESET,
280 .gui_gtk3_22_governor_range_min = -20,
281 .gui_gtk3_22_governor_range_max = 20,
282 .gui_gtk3_22_font_city_label = "Monospace 8",
283 .gui_gtk3_22_font_notify_label = "Monospace Bold 9",
284 .gui_gtk3_22_font_spaceship_label = "Monospace 8",
285 .gui_gtk3_22_font_help_label = "Sans Bold 10",
286 .gui_gtk3_22_font_help_link = "Sans 9",
287 .gui_gtk3_22_font_help_text = "Monospace 8",
288 .gui_gtk3_22_font_chatline = "Monospace 8",
289 .gui_gtk3_22_font_beta_label = "Sans Italic 10",
290 .gui_gtk3_22_font_small = "Sans 9",
291 .gui_gtk3_22_font_comment_label = "Sans Italic 9",
292 .gui_gtk3_22_font_city_names = "Sans Bold 10",
293 .gui_gtk3_22_font_city_productions = "Serif 10",
294 .gui_gtk3_22_font_reqtree_text = "Serif 10",
296 /* gui-sdl client specific options. */
297 .gui_sdl_default_theme_name = FC_SDL_DEFAULT_THEME_NAME,
298 .gui_sdl_fullscreen = FALSE,
299 .gui_sdl_screen = VIDEO_MODE(640, 480),
300 .gui_sdl_do_cursor_animation = TRUE,
301 .gui_sdl_use_color_cursors = TRUE,
303 /* gui-sdl2 client specific options. */
304 .gui_sdl2_default_theme_name = FC_SDL2_DEFAULT_THEME_NAME,
305 .gui_sdl2_fullscreen = FALSE,
306 .gui_sdl2_screen = VIDEO_MODE(640, 480),
307 .gui_sdl2_swrenderer = FALSE,
308 .gui_sdl2_do_cursor_animation = TRUE,
309 .gui_sdl2_use_color_cursors = TRUE,
311 /* gui-qt client specific options. */
312 .gui_qt_fullscreen = FALSE,
313 .gui_qt_show_preview = TRUE,
314 .gui_qt_sidebar_left = TRUE,
315 .gui_qt_default_theme_name = FC_QT_DEFAULT_THEME_NAME,
316 .gui_qt_font_city_label = "Monospace,8,-1,5,50,0,0,0,0,0",
317 .gui_qt_font_default = "Sans Serif,10,-1,5,75,0,0,0,0,0",
318 .gui_qt_font_notify_label = "Monospace,8,-1,5,75,0,0,0,0,0",
319 .gui_qt_font_spaceship_label = "Monospace,8,-1,5,50,0,0,0,0,0",
320 .gui_qt_font_help_label = "Sans Serif,9,-1,5,50,0,0,0,0,0",
321 .gui_qt_font_help_link = "Sans Serif,9,-1,5,50,0,0,0,0,0",
322 .gui_qt_font_help_text = "Monospace,8,-1,5,50,0,0,0,0,0",
323 .gui_qt_font_help_title = "Sans Serif,10,-1,5,75,0,0,0,0,0",
324 .gui_qt_font_chatline = "Monospace,8,-1,5,50,0,0,0,0,0",
325 .gui_qt_font_beta_label = "Sans Serif,10,-1,5,50,1,0,0,0,0",
326 .gui_qt_font_small = "Sans Serif,9,-1,5,50,0,0,0,0,0",
327 .gui_qt_font_comment_label = "Sans Serif,9,-1,5,50,1,0,0,0,0",
328 .gui_qt_font_city_names = "Sans Serif,10,-1,5,75,0,0,0,0,0",
329 .gui_qt_font_city_productions = "Sans Serif,10,-1,5,50,1,0,0,0,0",
330 .gui_qt_font_reqtree_text = "Sans Serif,10,-1,5,50,1,0,0,0,0",
331 .gui_qt_show_titlebar = TRUE,
332 .gui_qt_wakeup_text = "Wake up %1"
335 /* Set to TRUE after the first call to options_init(), to avoid the usage
336 * of non-initialized datas when calling the changed callback. */
337 static bool options_fully_initialized = FALSE;
339 static const struct strvec *get_mapimg_format_list(const struct option *poption);
341 /****************************************************************************
342 Option set structure.
343 ****************************************************************************/
344 struct option_set {
345 struct option * (*option_by_number) (int);
346 struct option * (*option_first) (void);
348 int (*category_number) (void);
349 const char * (*category_name) (int);
352 /****************************************************************************
353 Returns the option corresponding of the number in this option set.
354 ****************************************************************************/
355 struct option *optset_option_by_number(const struct option_set *poptset,
356 int id)
358 fc_assert_ret_val(NULL != poptset, NULL);
360 return poptset->option_by_number(id);
363 /****************************************************************************
364 Returns the option corresponding of the name in this option set.
365 ****************************************************************************/
366 struct option *optset_option_by_name(const struct option_set *poptset,
367 const char *name)
369 fc_assert_ret_val(NULL != poptset, NULL);
371 options_iterate(poptset, poption) {
372 if (0 == strcmp(option_name(poption), name)) {
373 return poption;
375 } options_iterate_end;
376 return NULL;
379 /****************************************************************************
380 Returns the first option of this option set.
381 ****************************************************************************/
382 struct option *optset_option_first(const struct option_set *poptset)
384 fc_assert_ret_val(NULL != poptset, NULL);
386 return poptset->option_first();
389 /****************************************************************************
390 Returns the number of categories of this option set.
391 ****************************************************************************/
392 int optset_category_number(const struct option_set *poptset)
394 fc_assert_ret_val(NULL != poptset, 0);
396 return poptset->category_number();
399 /****************************************************************************
400 Returns the name (translated) of the category of this option set.
401 ****************************************************************************/
402 const char *optset_category_name(const struct option_set *poptset,
403 int category)
405 fc_assert_ret_val(NULL != poptset, NULL);
407 return poptset->category_name(category);
411 /****************************************************************************
412 The base class for options.
413 ****************************************************************************/
414 struct option {
415 /* A link to the option set. */
416 const struct option_set *poptset;
417 /* Type of the option. */
418 enum option_type type;
420 /* Common accessors. */
421 const struct option_common_vtable {
422 int (*number) (const struct option *);
423 const char * (*name) (const struct option *);
424 const char * (*description) (const struct option *);
425 const char * (*help_text) (const struct option *);
426 int (*category) (const struct option *);
427 bool (*is_changeable) (const struct option *);
428 struct option * (*next) (const struct option *);
429 } *common_vtable;
430 /* Specific typed accessors. */
431 union {
432 /* Specific boolean accessors (OT_BOOLEAN == type). */
433 const struct option_bool_vtable {
434 bool (*get) (const struct option *);
435 bool (*def) (const struct option *);
436 bool (*set) (struct option *, bool);
437 } *bool_vtable;
438 /* Specific integer accessors (OT_INTEGER == type). */
439 const struct option_int_vtable {
440 int (*get) (const struct option *);
441 int (*def) (const struct option *);
442 int (*minimum) (const struct option *);
443 int (*maximum) (const struct option *);
444 bool (*set) (struct option *, int);
445 } *int_vtable;
446 /* Specific string accessors (OT_STRING == type). */
447 const struct option_str_vtable {
448 const char * (*get) (const struct option *);
449 const char * (*def) (const struct option *);
450 const struct strvec * (*values) (const struct option *);
451 bool (*set) (struct option *, const char *);
452 } *str_vtable;
453 /* Specific enum accessors (OT_ENUM == type). */
454 const struct option_enum_vtable {
455 int (*get) (const struct option *);
456 int (*def) (const struct option *);
457 const struct strvec * (*values) (const struct option *);
458 bool (*set) (struct option *, int);
459 int (*cmp) (const char *, const char *);
460 } *enum_vtable;
461 /* Specific bitwise accessors (OT_BITWISE == type). */
462 const struct option_bitwise_vtable {
463 unsigned (*get) (const struct option *);
464 unsigned (*def) (const struct option *);
465 const struct strvec * (*values) (const struct option *);
466 bool (*set) (struct option *, unsigned);
467 } *bitwise_vtable;
468 /* Specific font accessors (OT_FONT == type). */
469 const struct option_font_vtable {
470 const char * (*get) (const struct option *);
471 const char * (*def) (const struct option *);
472 const char * (*target) (const struct option *);
473 bool (*set) (struct option *, const char *);
474 } *font_vtable;
475 /* Specific color accessors (OT_COLOR == type). */
476 const struct option_color_vtable {
477 struct ft_color (*get) (const struct option *);
478 struct ft_color (*def) (const struct option *);
479 bool (*set) (struct option *, struct ft_color);
480 } *color_vtable;
481 /* Specific video mode accessors (OT_VIDEO_MODE == type). */
482 const struct option_video_mode_vtable {
483 struct video_mode (*get) (const struct option *);
484 struct video_mode (*def) (const struct option *);
485 bool (*set) (struct option *, struct video_mode);
486 } *video_mode_vtable;
489 /* Called after the value changed. */
490 void (*changed_callback) (struct option *option);
492 int callback_data;
494 /* Volatile. */
495 void *gui_data;
498 #define OPTION(poption) ((struct option *) (poption))
500 #define OPTION_INIT(optset, spec_type, spec_table_var, common_table, \
501 spec_table, changed_cb, cb_data) { \
502 .poptset = optset, \
503 .type = spec_type, \
504 .common_vtable = &common_table, \
505 INIT_BRACE_BEGIN \
506 .spec_table_var = &spec_table \
507 INIT_BRACE_END, \
508 .changed_callback = changed_cb, \
509 .callback_data = cb_data, \
510 .gui_data = NULL \
512 #define OPTION_BOOL_INIT(optset, common_table, bool_table, changed_cb) \
513 OPTION_INIT(optset, OT_BOOLEAN, bool_vtable, common_table, bool_table, \
514 changed_cb, 0)
515 #define OPTION_INT_INIT(optset, common_table, int_table, changed_cb) \
516 OPTION_INIT(optset, OT_INTEGER, int_vtable, common_table, int_table, \
517 changed_cb, 0)
518 #define OPTION_STR_INIT(optset, common_table, str_table, changed_cb, cb_data) \
519 OPTION_INIT(optset, OT_STRING, str_vtable, common_table, str_table, \
520 changed_cb, cb_data)
521 #define OPTION_ENUM_INIT(optset, common_table, enum_table, changed_cb) \
522 OPTION_INIT(optset, OT_ENUM, enum_vtable, common_table, enum_table, \
523 changed_cb, 0)
524 #define OPTION_BITWISE_INIT(optset, common_table, bitwise_table, \
525 changed_cb) \
526 OPTION_INIT(optset, OT_BITWISE, bitwise_vtable, common_table, \
527 bitwise_table, changed_cb, 0)
528 #define OPTION_FONT_INIT(optset, common_table, font_table, changed_cb) \
529 OPTION_INIT(optset, OT_FONT, font_vtable, common_table, font_table, \
530 changed_cb, 0)
531 #define OPTION_COLOR_INIT(optset, common_table, color_table, changed_cb) \
532 OPTION_INIT(optset, OT_COLOR, color_vtable, common_table, color_table, \
533 changed_cb, 0)
534 #define OPTION_VIDEO_MODE_INIT(optset, common_table, video_mode_table, \
535 changed_cb) \
536 OPTION_INIT(optset, OT_VIDEO_MODE, video_mode_vtable, common_table, \
537 video_mode_table, changed_cb, 0)
540 /****************************************************************************
541 Returns the option set owner of this option.
542 ****************************************************************************/
543 const struct option_set *option_optset(const struct option *poption)
545 fc_assert_ret_val(NULL != poption, NULL);
547 return poption->poptset;
550 /****************************************************************************
551 Returns the number of the option.
552 ****************************************************************************/
553 int option_number(const struct option *poption)
555 fc_assert_ret_val(NULL != poption, -1);
557 return poption->common_vtable->number(poption);
560 /****************************************************************************
561 Returns the name of the option.
562 ****************************************************************************/
563 const char *option_name(const struct option *poption)
565 fc_assert_ret_val(NULL != poption, NULL);
567 return poption->common_vtable->name(poption);
570 /****************************************************************************
571 Returns the description (translated) of the option.
572 ****************************************************************************/
573 const char *option_description(const struct option *poption)
575 fc_assert_ret_val(NULL != poption, NULL);
577 return poption->common_vtable->description(poption);
580 /****************************************************************************
581 Returns the help text (translated) of the option.
582 ****************************************************************************/
583 const char *option_help_text(const struct option *poption)
585 fc_assert_ret_val(NULL != poption, NULL);
587 return poption->common_vtable->help_text(poption);
590 /****************************************************************************
591 Returns the type of the option.
592 ****************************************************************************/
593 enum option_type option_type(const struct option *poption)
595 fc_assert_ret_val(NULL != poption, -1);
597 return poption->type;
600 /****************************************************************************
601 Returns the category of the option.
602 ****************************************************************************/
603 int option_category(const struct option *poption)
605 fc_assert_ret_val(NULL != poption, -1);
607 return poption->common_vtable->category(poption);
610 /****************************************************************************
611 Returns the name (tranlated) of the category of the option.
612 ****************************************************************************/
613 const char *option_category_name(const struct option *poption)
615 fc_assert_ret_val(NULL != poption, NULL);
617 return optset_category_name(poption->poptset,
618 poption->common_vtable->category(poption));
621 /****************************************************************************
622 Returns TRUE if this option can be modified.
623 ****************************************************************************/
624 bool option_is_changeable(const struct option *poption)
626 fc_assert_ret_val(NULL != poption, FALSE);
628 return poption->common_vtable->is_changeable(poption);
631 /****************************************************************************
632 Returns the next option or NULL if this is the last.
633 ****************************************************************************/
634 struct option *option_next(const struct option *poption)
636 fc_assert_ret_val(NULL != poption, NULL);
638 return poption->common_vtable->next(poption);
641 /****************************************************************************
642 Set the option to its default value. Returns TRUE if the option changed.
643 ****************************************************************************/
644 bool option_reset(struct option *poption)
646 fc_assert_ret_val(NULL != poption, FALSE);
648 switch (option_type(poption)) {
649 case OT_BOOLEAN:
650 return option_bool_set(poption, option_bool_def(poption));
651 case OT_INTEGER:
652 return option_int_set(poption, option_int_def(poption));
653 case OT_STRING:
654 return option_str_set(poption, option_str_def(poption));
655 case OT_ENUM:
656 return option_enum_set_int(poption, option_enum_def_int(poption));
657 case OT_BITWISE:
658 return option_bitwise_set(poption, option_bitwise_def(poption));
659 case OT_FONT:
660 return option_font_set(poption, option_font_def(poption));
661 case OT_COLOR:
662 return option_color_set(poption, option_color_def(poption));
663 case OT_VIDEO_MODE:
664 return option_video_mode_set(poption, option_video_mode_def(poption));
666 return FALSE;
669 /****************************************************************************
670 Set the function to call every time this option changes. Can be NULL.
671 ****************************************************************************/
672 void option_set_changed_callback(struct option *poption,
673 void (*callback) (struct option *))
675 fc_assert_ret(NULL != poption);
677 poption->changed_callback = callback;
680 /****************************************************************************
681 Force to use the option changed callback.
682 ****************************************************************************/
683 void option_changed(struct option *poption)
685 fc_assert_ret(NULL != poption);
687 if (!options_fully_initialized) {
688 /* Prevent to use non-initialized datas. */
689 return;
692 if (poption->changed_callback) {
693 poption->changed_callback(poption);
696 option_gui_update(poption);
699 /****************************************************************************
700 Set the gui data for this option.
701 ****************************************************************************/
702 void option_set_gui_data(struct option *poption, void *data)
704 fc_assert_ret(NULL != poption);
706 poption->gui_data = data;
709 /****************************************************************************
710 Returns the gui data of this option.
711 ****************************************************************************/
712 void *option_get_gui_data(const struct option *poption)
714 fc_assert_ret_val(NULL != poption, NULL);
716 return poption->gui_data;
719 /****************************************************************************
720 Returns the callback data of this option.
721 ****************************************************************************/
722 int option_get_cb_data(const struct option *poption)
724 fc_assert_ret_val(NULL != poption, 0);
726 return poption->callback_data;
729 /****************************************************************************
730 Returns the current value of this boolean option.
731 ****************************************************************************/
732 bool option_bool_get(const struct option *poption)
734 fc_assert_ret_val(NULL != poption, FALSE);
735 fc_assert_ret_val(OT_BOOLEAN == poption->type, FALSE);
737 return poption->bool_vtable->get(poption);
740 /****************************************************************************
741 Returns the default value of this boolean option.
742 ****************************************************************************/
743 bool option_bool_def(const struct option *poption)
745 fc_assert_ret_val(NULL != poption, FALSE);
746 fc_assert_ret_val(OT_BOOLEAN == poption->type, FALSE);
748 return poption->bool_vtable->def(poption);
751 /****************************************************************************
752 Sets the value of this boolean option. Returns TRUE if the value changed.
753 ****************************************************************************/
754 bool option_bool_set(struct option *poption, bool val)
756 fc_assert_ret_val(NULL != poption, FALSE);
757 fc_assert_ret_val(OT_BOOLEAN == poption->type, FALSE);
759 if (poption->bool_vtable->set(poption, val)) {
760 option_changed(poption);
761 return TRUE;
763 return FALSE;
766 /****************************************************************************
767 Returns the current value of this integer option.
768 ****************************************************************************/
769 int option_int_get(const struct option *poption)
771 fc_assert_ret_val(NULL != poption, 0);
772 fc_assert_ret_val(OT_INTEGER == poption->type, 0);
774 return poption->int_vtable->get(poption);
777 /****************************************************************************
778 Returns the default value of this integer option.
779 ****************************************************************************/
780 int option_int_def(const struct option *poption)
782 fc_assert_ret_val(NULL != poption, 0);
783 fc_assert_ret_val(OT_INTEGER == poption->type, 0);
785 return poption->int_vtable->def(poption);
788 /****************************************************************************
789 Returns the minimal value of this integer option.
790 ****************************************************************************/
791 int option_int_min(const struct option *poption)
793 fc_assert_ret_val(NULL != poption, 0);
794 fc_assert_ret_val(OT_INTEGER == poption->type, 0);
796 return poption->int_vtable->minimum(poption);
799 /****************************************************************************
800 Returns the maximal value of this integer option.
801 ****************************************************************************/
802 int option_int_max(const struct option *poption)
804 fc_assert_ret_val(NULL != poption, 0);
805 fc_assert_ret_val(OT_INTEGER == poption->type, 0);
807 return poption->int_vtable->maximum(poption);
810 /****************************************************************************
811 Sets the value of this integer option. Returns TRUE if the value changed.
812 ****************************************************************************/
813 bool option_int_set(struct option *poption, int val)
815 fc_assert_ret_val(NULL != poption, FALSE);
816 fc_assert_ret_val(OT_INTEGER == poption->type, FALSE);
818 if (poption->int_vtable->set(poption, val)) {
819 option_changed(poption);
820 return TRUE;
822 return FALSE;
825 /****************************************************************************
826 Returns the current value of this string option.
827 ****************************************************************************/
828 const char *option_str_get(const struct option *poption)
830 fc_assert_ret_val(NULL != poption, NULL);
831 fc_assert_ret_val(OT_STRING == poption->type, NULL);
833 return poption->str_vtable->get(poption);
836 /****************************************************************************
837 Returns the default value of this string option.
838 ****************************************************************************/
839 const char *option_str_def(const struct option *poption)
841 fc_assert_ret_val(NULL != poption, NULL);
842 fc_assert_ret_val(OT_STRING == poption->type, NULL);
844 return poption->str_vtable->def(poption);
847 /****************************************************************************
848 Returns the possible string values of this string option.
849 ****************************************************************************/
850 const struct strvec *option_str_values(const struct option *poption)
852 fc_assert_ret_val(NULL != poption, NULL);
853 fc_assert_ret_val(OT_STRING == poption->type, NULL);
855 return poption->str_vtable->values(poption);
858 /****************************************************************************
859 Sets the value of this string option. Returns TRUE if the value changed.
860 ****************************************************************************/
861 bool option_str_set(struct option *poption, const char *str)
863 fc_assert_ret_val(NULL != poption, FALSE);
864 fc_assert_ret_val(OT_STRING == poption->type, FALSE);
865 fc_assert_ret_val(NULL != str, FALSE);
867 if (poption->str_vtable->set(poption, str)) {
868 option_changed(poption);
869 return TRUE;
871 return FALSE;
874 /****************************************************************************
875 Returns the value corresponding to the user-visible (translatable but not
876 translated) string. Returns -1 if not matched.
877 ****************************************************************************/
878 int option_enum_str_to_int(const struct option *poption, const char *str)
880 const struct strvec *values;
881 int val;
883 fc_assert_ret_val(NULL != poption, -1);
884 fc_assert_ret_val(OT_ENUM == poption->type, -1);
885 values = poption->enum_vtable->values(poption);
886 fc_assert_ret_val(NULL != values, -1);
888 for (val = 0; val < strvec_size(values); val++) {
889 if (0 == poption->enum_vtable->cmp(strvec_get(values, val), str)) {
890 return val;
893 return -1;
896 /****************************************************************************
897 Returns the user-visible (translatable but not translated) string
898 corresponding to the value. Returns NULL on error.
899 ****************************************************************************/
900 const char *option_enum_int_to_str(const struct option *poption, int val)
902 const struct strvec *values;
904 fc_assert_ret_val(NULL != poption, NULL);
905 fc_assert_ret_val(OT_ENUM == poption->type, NULL);
906 values = poption->enum_vtable->values(poption);
907 fc_assert_ret_val(NULL != values, NULL);
909 return strvec_get(values, val);
912 /****************************************************************************
913 Returns the current value of this enum option (as an integer).
914 ****************************************************************************/
915 int option_enum_get_int(const struct option *poption)
917 fc_assert_ret_val(NULL != poption, -1);
918 fc_assert_ret_val(OT_ENUM == poption->type, -1);
920 return poption->enum_vtable->get(poption);
923 /****************************************************************************
924 Returns the current value of this enum option as a user-visible
925 (translatable but not translated) string.
926 ****************************************************************************/
927 const char *option_enum_get_str(const struct option *poption)
929 fc_assert_ret_val(NULL != poption, NULL);
930 fc_assert_ret_val(OT_ENUM == poption->type, NULL);
932 return strvec_get(poption->enum_vtable->values(poption),
933 poption->enum_vtable->get(poption));
936 /****************************************************************************
937 Returns the default value of this enum option (as an integer).
938 ****************************************************************************/
939 int option_enum_def_int(const struct option *poption)
941 fc_assert_ret_val(NULL != poption, -1);
942 fc_assert_ret_val(OT_ENUM == poption->type, -1);
944 return poption->enum_vtable->def(poption);
947 /****************************************************************************
948 Returns the default value of this enum option as a user-visible
949 (translatable but not translated) string.
950 ****************************************************************************/
951 const char *option_enum_def_str(const struct option *poption)
953 fc_assert_ret_val(NULL != poption, NULL);
954 fc_assert_ret_val(OT_ENUM == poption->type, NULL);
956 return strvec_get(poption->enum_vtable->values(poption),
957 poption->enum_vtable->def(poption));
960 /****************************************************************************
961 Returns the possible string values of this enum option, as user-visible
962 (translatable but not translated) strings.
963 ****************************************************************************/
964 const struct strvec *option_enum_values(const struct option *poption)
966 fc_assert_ret_val(NULL != poption, NULL);
967 fc_assert_ret_val(OT_ENUM == poption->type, NULL);
969 return poption->enum_vtable->values(poption);
972 /****************************************************************************
973 Sets the value of this enum option. Returns TRUE if the value changed.
974 ****************************************************************************/
975 bool option_enum_set_int(struct option *poption, int val)
977 fc_assert_ret_val(NULL != poption, FALSE);
978 fc_assert_ret_val(OT_ENUM == poption->type, FALSE);
980 if (poption->enum_vtable->set(poption, val)) {
981 option_changed(poption);
982 return TRUE;
984 return FALSE;
987 /****************************************************************************
988 Sets the value of this enum option from a string, which is matched as a
989 user-visible (translatable but not translated) string. Returns TRUE if the
990 value changed.
991 ****************************************************************************/
992 bool option_enum_set_str(struct option *poption, const char *str)
994 fc_assert_ret_val(NULL != poption, FALSE);
995 fc_assert_ret_val(OT_ENUM == poption->type, FALSE);
996 fc_assert_ret_val(NULL != str, FALSE);
998 if (poption->enum_vtable->set(poption,
999 option_enum_str_to_int(poption, str))) {
1000 option_changed(poption);
1001 return TRUE;
1003 return FALSE;
1006 /****************************************************************************
1007 Returns the current value of this bitwise option.
1008 ****************************************************************************/
1009 unsigned option_bitwise_get(const struct option *poption)
1011 fc_assert_ret_val(NULL != poption, 0);
1012 fc_assert_ret_val(OT_BITWISE == poption->type, 0);
1014 return poption->bitwise_vtable->get(poption);
1017 /****************************************************************************
1018 Returns the default value of this bitwise option.
1019 ****************************************************************************/
1020 unsigned option_bitwise_def(const struct option *poption)
1022 fc_assert_ret_val(NULL != poption, 0);
1023 fc_assert_ret_val(OT_BITWISE == poption->type, 0);
1025 return poption->bitwise_vtable->def(poption);
1028 /****************************************************************************
1029 Returns the mask of this bitwise option.
1030 ****************************************************************************/
1031 unsigned option_bitwise_mask(const struct option *poption)
1033 const struct strvec *values;
1035 fc_assert_ret_val(NULL != poption, 0);
1036 fc_assert_ret_val(OT_BITWISE == poption->type, 0);
1038 values = poption->bitwise_vtable->values(poption);
1039 fc_assert_ret_val(NULL != values, 0);
1041 return (1 << strvec_size(values)) - 1;
1044 /****************************************************************************
1045 Returns a vector of strings describing every bit of this option, as
1046 user-visible (translatable but not translated) strings.
1047 ****************************************************************************/
1048 const struct strvec *option_bitwise_values(const struct option *poption)
1050 fc_assert_ret_val(NULL != poption, NULL);
1051 fc_assert_ret_val(OT_BITWISE == poption->type, NULL);
1053 return poption->bitwise_vtable->values(poption);
1056 /****************************************************************************
1057 Sets the value of this bitwise option. Returns TRUE if the value changed.
1058 ****************************************************************************/
1059 bool option_bitwise_set(struct option *poption, unsigned val)
1061 fc_assert_ret_val(NULL != poption, FALSE);
1062 fc_assert_ret_val(OT_BITWISE == poption->type, FALSE);
1064 if (0 != (val & ~option_bitwise_mask(poption))
1065 || !poption->bitwise_vtable->set(poption, val)) {
1066 return FALSE;
1069 option_changed(poption);
1070 return TRUE;
1073 /****************************************************************************
1074 Returns the current value of this font option.
1075 ****************************************************************************/
1076 const char *option_font_get(const struct option *poption)
1078 fc_assert_ret_val(NULL != poption, NULL);
1079 fc_assert_ret_val(OT_FONT == poption->type, NULL);
1081 return poption->font_vtable->get(poption);
1084 /****************************************************************************
1085 Returns the default value of this font option.
1086 ****************************************************************************/
1087 const char *option_font_def(const struct option *poption)
1089 fc_assert_ret_val(NULL != poption, NULL);
1090 fc_assert_ret_val(OT_FONT == poption->type, NULL);
1092 return poption->font_vtable->def(poption);
1095 /****************************************************************************
1096 Returns the target style name of this font option.
1097 ****************************************************************************/
1098 const char *option_font_target(const struct option *poption)
1100 fc_assert_ret_val(NULL != poption, NULL);
1101 fc_assert_ret_val(OT_FONT == poption->type, NULL);
1103 return poption->font_vtable->target(poption);
1106 /****************************************************************************
1107 Sets the value of this font option. Returns TRUE if the value changed.
1108 ****************************************************************************/
1109 bool option_font_set(struct option *poption, const char *font)
1111 fc_assert_ret_val(NULL != poption, FALSE);
1112 fc_assert_ret_val(OT_FONT == poption->type, FALSE);
1113 fc_assert_ret_val(NULL != font, FALSE);
1115 if (poption->font_vtable->set(poption, font)) {
1116 option_changed(poption);
1117 return TRUE;
1119 return FALSE;
1122 /****************************************************************************
1123 Returns the current value of this color option.
1124 ****************************************************************************/
1125 struct ft_color option_color_get(const struct option *poption)
1127 fc_assert_ret_val(NULL != poption, ft_color_construct(NULL, NULL));
1128 fc_assert_ret_val(OT_COLOR == poption->type, ft_color_construct(NULL, NULL));
1130 return poption->color_vtable->get(poption);
1133 /****************************************************************************
1134 Returns the default value of this color option.
1135 ****************************************************************************/
1136 struct ft_color option_color_def(const struct option *poption)
1138 fc_assert_ret_val(NULL != poption, ft_color_construct(NULL, NULL));
1139 fc_assert_ret_val(OT_COLOR == poption->type, ft_color_construct(NULL, NULL));
1141 return poption->color_vtable->def(poption);
1144 /****************************************************************************
1145 Sets the value of this color option. Returns TRUE if the value
1146 changed.
1147 ****************************************************************************/
1148 bool option_color_set(struct option *poption, struct ft_color color)
1150 fc_assert_ret_val(NULL != poption, FALSE);
1151 fc_assert_ret_val(OT_COLOR == poption->type, FALSE);
1153 if (poption->color_vtable->set(poption, color)) {
1154 option_changed(poption);
1155 return TRUE;
1157 return FALSE;
1160 /****************************************************************************
1161 Returns the current value of this video mode option.
1162 ****************************************************************************/
1163 struct video_mode option_video_mode_get(const struct option *poption)
1165 fc_assert_ret_val(NULL != poption, video_mode_construct(-1, -1));
1166 fc_assert_ret_val(OT_VIDEO_MODE == poption->type,
1167 video_mode_construct(-1, -1));
1169 return poption->video_mode_vtable->get(poption);
1172 /****************************************************************************
1173 Returns the default value of this video mode option.
1174 ****************************************************************************/
1175 struct video_mode option_video_mode_def(const struct option *poption)
1177 fc_assert_ret_val(NULL != poption, video_mode_construct(-1, -1));
1178 fc_assert_ret_val(OT_VIDEO_MODE == poption->type,
1179 video_mode_construct(-1, -1));
1181 return poption->video_mode_vtable->def(poption);
1184 /****************************************************************************
1185 Sets the value of this video mode option. Returns TRUE if the value
1186 changed.
1187 ****************************************************************************/
1188 bool option_video_mode_set(struct option *poption, struct video_mode mode)
1190 fc_assert_ret_val(NULL != poption, FALSE);
1191 fc_assert_ret_val(OT_VIDEO_MODE == poption->type, FALSE);
1193 if (poption->video_mode_vtable->set(poption, mode)) {
1194 option_changed(poption);
1195 return TRUE;
1197 return FALSE;
1201 /****************************************************************************
1202 Client option set.
1203 ****************************************************************************/
1204 static struct option *client_optset_option_by_number(int id);
1205 static struct option *client_optset_option_first(void);
1206 static int client_optset_category_number(void);
1207 static const char *client_optset_category_name(int category);
1209 static struct option_set client_optset_static = {
1210 .option_by_number = client_optset_option_by_number,
1211 .option_first = client_optset_option_first,
1212 .category_number = client_optset_category_number,
1213 .category_name = client_optset_category_name
1215 const struct option_set *client_optset = &client_optset_static;
1217 struct copt_val_name {
1218 const char *support; /* Untranslated long support name, used
1219 * for saving. */
1220 const char *pretty; /* Translated, used to display to the
1221 * users. */
1224 /****************************************************************************
1225 Virtuals tables for the client options.
1226 ****************************************************************************/
1227 static int client_option_number(const struct option *poption);
1228 static const char *client_option_name(const struct option *poption);
1229 static const char *client_option_description(const struct option *poption);
1230 static const char *client_option_help_text(const struct option *poption);
1231 static int client_option_category(const struct option *poption);
1232 static bool client_option_is_changeable(const struct option *poption);
1233 static struct option *client_option_next(const struct option *poption);
1234 static void client_option_adjust_defaults(void);
1236 static const struct option_common_vtable client_option_common_vtable = {
1237 .number = client_option_number,
1238 .name = client_option_name,
1239 .description = client_option_description,
1240 .help_text = client_option_help_text,
1241 .category = client_option_category,
1242 .is_changeable = client_option_is_changeable,
1243 .next = client_option_next
1246 static bool client_option_bool_get(const struct option *poption);
1247 static bool client_option_bool_def(const struct option *poption);
1248 static bool client_option_bool_set(struct option *poption, bool val);
1250 static const struct option_bool_vtable client_option_bool_vtable = {
1251 .get = client_option_bool_get,
1252 .def = client_option_bool_def,
1253 .set = client_option_bool_set
1256 static int client_option_int_get(const struct option *poption);
1257 static int client_option_int_def(const struct option *poption);
1258 static int client_option_int_min(const struct option *poption);
1259 static int client_option_int_max(const struct option *poption);
1260 static bool client_option_int_set(struct option *poption, int val);
1262 static const struct option_int_vtable client_option_int_vtable = {
1263 .get = client_option_int_get,
1264 .def = client_option_int_def,
1265 .minimum = client_option_int_min,
1266 .maximum = client_option_int_max,
1267 .set = client_option_int_set
1270 static const char *client_option_str_get(const struct option *poption);
1271 static const char *client_option_str_def(const struct option *poption);
1272 static const struct strvec *
1273 client_option_str_values(const struct option *poption);
1274 static bool client_option_str_set(struct option *poption, const char *str);
1276 static const struct option_str_vtable client_option_str_vtable = {
1277 .get = client_option_str_get,
1278 .def = client_option_str_def,
1279 .values = client_option_str_values,
1280 .set = client_option_str_set
1283 static int client_option_enum_get(const struct option *poption);
1284 static int client_option_enum_def(const struct option *poption);
1285 static const struct strvec *
1286 client_option_enum_pretty_names(const struct option *poption);
1287 static bool client_option_enum_set(struct option *poption, int val);
1289 static const struct option_enum_vtable client_option_enum_vtable = {
1290 .get = client_option_enum_get,
1291 .def = client_option_enum_def,
1292 .values = client_option_enum_pretty_names,
1293 .set = client_option_enum_set,
1294 .cmp = fc_strcasecmp
1297 #if 0 /* There's no bitwise options currently */
1298 static unsigned client_option_bitwise_get(const struct option *poption);
1299 static unsigned client_option_bitwise_def(const struct option *poption);
1300 static const struct strvec *
1301 client_option_bitwise_pretty_names(const struct option *poption);
1302 static bool client_option_bitwise_set(struct option *poption, unsigned val);
1304 static const struct option_bitwise_vtable client_option_bitwise_vtable = {
1305 .get = client_option_bitwise_get,
1306 .def = client_option_bitwise_def,
1307 .values = client_option_bitwise_pretty_names,
1308 .set = client_option_bitwise_set
1310 #endif /* 0 */
1312 static const char *client_option_font_get(const struct option *poption);
1313 static const char *client_option_font_def(const struct option *poption);
1314 static const char *client_option_font_target(const struct option *poption);
1315 static bool client_option_font_set(struct option *poption, const char *font);
1317 static const struct option_font_vtable client_option_font_vtable = {
1318 .get = client_option_font_get,
1319 .def = client_option_font_def,
1320 .target = client_option_font_target,
1321 .set = client_option_font_set
1324 static struct ft_color client_option_color_get(const struct option *poption);
1325 static struct ft_color client_option_color_def(const struct option *poption);
1326 static bool client_option_color_set(struct option *poption,
1327 struct ft_color color);
1329 static const struct option_color_vtable client_option_color_vtable = {
1330 .get = client_option_color_get,
1331 .def = client_option_color_def,
1332 .set = client_option_color_set
1335 static struct video_mode
1336 client_option_video_mode_get(const struct option *poption);
1337 static struct video_mode
1338 client_option_video_mode_def(const struct option *poption);
1339 static bool client_option_video_mode_set(struct option *poption,
1340 struct video_mode mode);
1342 static const struct option_video_mode_vtable client_option_video_mode_vtable = {
1343 .get = client_option_video_mode_get,
1344 .def = client_option_video_mode_def,
1345 .set = client_option_video_mode_set
1348 enum client_option_category {
1349 COC_GRAPHICS,
1350 COC_OVERVIEW,
1351 COC_SOUND,
1352 COC_INTERFACE,
1353 COC_MAPIMG,
1354 COC_NETWORK,
1355 COC_FONT,
1356 COC_MAX
1359 /****************************************************************************
1360 Derived class client option, inherinting of base class option.
1361 ****************************************************************************/
1362 struct client_option {
1363 struct option base_option; /* Base structure, must be the first! */
1365 const char *name; /* Short name - used as an identifier */
1366 const char *description; /* One-line description */
1367 const char *help_text; /* Paragraph-length help text */
1368 enum client_option_category category;
1369 enum gui_type specific; /* GUI_STUB for common options. */
1371 union {
1372 /* OT_BOOLEAN type option. */
1373 struct {
1374 bool *const pvalue;
1375 const bool def;
1376 } boolean;
1377 /* OT_INTEGER type option. */
1378 struct {
1379 int *const pvalue;
1380 const int def, min, max;
1381 } integer;
1382 /* OT_STRING type option. */
1383 struct {
1384 char *const pvalue;
1385 const size_t size;
1386 const char *const def;
1388 * A function to return a string vector of possible string values,
1389 * or NULL for none.
1391 const struct strvec *(*const val_accessor) (const struct option *);
1392 } string;
1393 /* OT_ENUM type option. */
1394 struct {
1395 int *const pvalue;
1396 const int def;
1397 struct strvec *support_names, *pretty_names; /* untranslated */
1398 const struct copt_val_name * (*const name_accessor) (int value);
1399 } enumerator;
1400 /* OT_BITWISE type option. */
1401 struct {
1402 unsigned *const pvalue;
1403 const unsigned def;
1404 struct strvec *support_names, *pretty_names; /* untranslated */
1405 const struct copt_val_name * (*const name_accessor) (int value);
1406 } bitwise;
1407 /* OT_FONT type option. */
1408 struct {
1409 char *const pvalue;
1410 const size_t size;
1411 const char *const def;
1412 const char *const target;
1413 } font;
1414 /* OT_COLOR type option. */
1415 struct {
1416 struct ft_color *const pvalue;
1417 const struct ft_color def;
1418 } color;
1419 /* OT_VIDEO_MODE type option. */
1420 struct {
1421 struct video_mode *const pvalue;
1422 const struct video_mode def;
1423 } video_mode;
1427 #define CLIENT_OPTION(poption) ((struct client_option *) (poption))
1430 * Generate a client option of type OT_BOOLEAN.
1432 * oname: The option data. Note it is used as name to be loaded or saved.
1433 * So, you shouldn't change the name of this variable in any case.
1434 * odesc: A short description of the client option. Should be used with the
1435 * N_() macro.
1436 * ohelp: The help text for the client option. Should be used with the N_()
1437 * macro.
1438 * ocat: The client_option_class of this client option.
1439 * ospec: A gui_type enumerator which determin for what particular client
1440 * gui this option is for. Sets to GUI_STUB for common options.
1441 * odef: The default value of this client option (FALSE or TRUE).
1442 * ocb: A callback function of type void (*)(struct option *) called when
1443 * the option changed.
1445 #define GEN_BOOL_OPTION(oname, odesc, ohelp, ocat, ospec, odef, ocb) \
1447 .base_option = OPTION_BOOL_INIT(&client_optset_static, \
1448 client_option_common_vtable, \
1449 client_option_bool_vtable, ocb), \
1450 .name = #oname, \
1451 .description = odesc, \
1452 .help_text = ohelp, \
1453 .category = ocat, \
1454 .specific = ospec, \
1455 INIT_BRACE_BEGIN \
1456 .boolean = { \
1457 .pvalue = &gui_options.oname, \
1458 .def = odef, \
1460 INIT_BRACE_END \
1464 * Generate a client option of type OT_INTEGER.
1466 * oname: The option data. Note it is used as name to be loaded or saved.
1467 * So, you shouldn't change the name of this variable in any case.
1468 * odesc: A short description of the client option. Should be used with the
1469 * N_() macro.
1470 * ohelp: The help text for the client option. Should be used with the N_()
1471 * macro.
1472 * ocat: The client_option_class of this client option.
1473 * ospec: A gui_type enumerator which determin for what particular client
1474 * gui this option is for. Sets to GUI_STUB for common options.
1475 * odef: The default value of this client option.
1476 * omin: The minimal value of this client option.
1477 * omax: The maximal value of this client option.
1478 * ocb: A callback function of type void (*)(struct option *) called when
1479 * the option changed.
1481 #define GEN_INT_OPTION(oname, odesc, ohelp, ocat, ospec, odef, omin, omax, ocb) \
1483 .base_option = OPTION_INT_INIT(&client_optset_static, \
1484 client_option_common_vtable, \
1485 client_option_int_vtable, ocb), \
1486 .name = #oname, \
1487 .description = odesc, \
1488 .help_text = ohelp, \
1489 .category = ocat, \
1490 .specific = ospec, \
1491 INIT_BRACE_BEGIN \
1492 .integer = { \
1493 .pvalue = &gui_options.oname, \
1494 .def = odef, \
1495 .min = omin, \
1496 .max = omax \
1498 INIT_BRACE_END \
1502 * Generate a client option of type OT_STRING.
1504 * oname: The option data. Note it is used as name to be loaded or saved.
1505 * So, you shouldn't change the name of this variable in any case.
1506 * Be sure to pass the array variable and not a pointer to it because
1507 * the size is calculated with sizeof().
1508 * odesc: A short description of the client option. Should be used with the
1509 * N_() macro.
1510 * ohelp: The help text for the client option. Should be used with the N_()
1511 * macro.
1512 * ocat: The client_option_class of this client option.
1513 * ospec: A gui_type enumerator which determines for what particular client
1514 * gui this option is for. Set to GUI_STUB for common options.
1515 * odef: The default string for this client option.
1516 * ocb: A callback function of type void (*)(struct option *) called when
1517 * the option changed.
1519 #define GEN_STR_OPTION(oname, odesc, ohelp, ocat, ospec, odef, ocb, cbd) \
1521 .base_option = OPTION_STR_INIT(&client_optset_static, \
1522 client_option_common_vtable, \
1523 client_option_str_vtable, ocb, cbd), \
1524 .name = #oname, \
1525 .description = odesc, \
1526 .help_text = ohelp, \
1527 .category = ocat, \
1528 .specific = ospec, \
1529 INIT_BRACE_BEGIN \
1530 .string = { \
1531 .pvalue = gui_options.oname, \
1532 .size = sizeof(gui_options.oname), \
1533 .def = odef, \
1534 .val_accessor = NULL \
1536 INIT_BRACE_END \
1540 * Generate a client option of type OT_STRING with a string accessor
1541 * function.
1543 * oname: The option data. Note it is used as name to be loaded or saved.
1544 * So, you shouldn't change the name of this variable in any case.
1545 * Be sure to pass the array variable and not a pointer to it because
1546 * the size is calculated with sizeof().
1547 * odesc: A short description of the client option. Should be used with the
1548 * N_() macro.
1549 * ohelp: The help text for the client option. Should be used with the N_()
1550 * macro.
1551 * ocat: The client_option_class of this client option.
1552 * ospec: A gui_type enumerator which determin for what particular client
1553 * gui this option is for. Sets to GUI_STUB for common options.
1554 * odef: The default string for this client option.
1555 * oacc: The string accessor where to find the allowed values of type
1556 * 'const struct strvec * (*) (void)'.
1557 * ocb: A callback function of type void (*)(struct option *) called when
1558 * the option changed.
1560 #define GEN_STR_LIST_OPTION(oname, odesc, ohelp, ocat, ospec, odef, oacc, ocb, cbd) \
1562 .base_option = OPTION_STR_INIT(&client_optset_static, \
1563 client_option_common_vtable, \
1564 client_option_str_vtable, ocb, cbd), \
1565 .name = #oname, \
1566 .description = odesc, \
1567 .help_text = ohelp, \
1568 .category = ocat, \
1569 .specific = ospec, \
1570 INIT_BRACE_BEGIN \
1571 .string = { \
1572 .pvalue = gui_options.oname, \
1573 .size = sizeof(gui_options.oname), \
1574 .def = odef, \
1575 .val_accessor = oacc \
1577 INIT_BRACE_END \
1581 * Generate a client option of type OT_ENUM.
1583 * oname: The option data. Note it is used as name to be loaded or saved.
1584 * So, you shouldn't change the name of this variable in any case.
1585 * odesc: A short description of the client option. Should be used with the
1586 * N_() macro.
1587 * ohelp: The help text for the client option. Should be used with the N_()
1588 * macro.
1589 * ocat: The client_option_class of this client option.
1590 * ospec: A gui_type enumerator which determin for what particular client
1591 * gui this option is for. Sets to GUI_STUB for common options.
1592 * odef: The default value for this client option.
1593 * oacc: The name accessor of type 'const struct copt_val_name * (*) (int)'.
1594 * ocb: A callback function of type void (*) (struct option *) called when
1595 * the option changed.
1597 #define GEN_ENUM_OPTION(oname, odesc, ohelp, ocat, ospec, odef, oacc, ocb) \
1599 .base_option = OPTION_ENUM_INIT(&client_optset_static, \
1600 client_option_common_vtable, \
1601 client_option_enum_vtable, ocb), \
1602 .name = #oname, \
1603 .description = odesc, \
1604 .help_text = ohelp, \
1605 .category = ocat, \
1606 .specific = ospec, \
1607 INIT_BRACE_BEGIN \
1608 .enumerator = { \
1609 .pvalue = (int *) &gui_options.oname, \
1610 .def = odef, \
1611 .support_names = NULL, /* Set in options_init(). */ \
1612 .pretty_names = NULL, \
1613 .name_accessor = oacc \
1615 INIT_BRACE_END \
1619 * Generate a client option of type OT_BITWISE.
1621 * oname: The option data. Note it is used as name to be loaded or saved.
1622 * So, you shouldn't change the name of this variable in any case.
1623 * odesc: A short description of the client option. Should be used with the
1624 * N_() macro.
1625 * ohelp: The help text for the client option. Should be used with the N_()
1626 * macro.
1627 * ocat: The client_option_class of this client option.
1628 * ospec: A gui_type enumerator which determin for what particular client
1629 * gui this option is for. Sets to GUI_STUB for common options.
1630 * odef: The default value for this client option.
1631 * oacc: The name accessor of type 'const struct copt_val_name * (*) (int)'.
1632 * ocb: A callback function of type void (*) (struct option *) called when
1633 * the option changed.
1635 #define GEN_BITWISE_OPTION(oname, odesc, ohelp, ocat, ospec, odef, oacc, \
1636 ocb) \
1638 .base_option = OPTION_BITWISE_INIT(&client_optset_static, \
1639 client_option_common_vtable, \
1640 client_option_bitwise_vtable, ocb), \
1641 .name = #oname, \
1642 .description = odesc, \
1643 .help_text = ohelp, \
1644 .category = ocat, \
1645 .specific = ospec, \
1646 INIT_BRACE_BEGIN \
1647 .bitwise = { \
1648 .pvalue = &gui_options.oname, \
1649 .def = odef, \
1650 .support_names = NULL, /* Set in options_init(). */ \
1651 .pretty_names = NULL, \
1652 .name_accessor = oacc \
1654 INIT_BRACE_END \
1658 * Generate a client option of type OT_FONT.
1660 * oname: The option data. Note it is used as name to be loaded or saved.
1661 * So, you shouldn't change the name of this variable in any case.
1662 * Be sure to pass the array variable and not a pointer to it because
1663 * the size is calculated with sizeof().
1664 * otgt: The target widget style.
1665 * odesc: A short description of the client option. Should be used with the
1666 * N_() macro.
1667 * ohelp: The help text for the client option. Should be used with the N_()
1668 * macro.
1669 * ocat: The client_option_class of this client option.
1670 * ospec: A gui_type enumerator which determin for what particular client
1671 * gui this option is for. Sets to GUI_STUB for common options.
1672 * odef: The default string for this client option.
1673 * ocb: A callback function of type void (*)(struct option *) called when
1674 * the option changed.
1676 #define GEN_FONT_OPTION(oname, otgt, odesc, ohelp, ocat, ospec, odef, ocb) \
1678 .base_option = OPTION_FONT_INIT(&client_optset_static, \
1679 client_option_common_vtable, \
1680 client_option_font_vtable, ocb), \
1681 .name = #oname, \
1682 .description = odesc, \
1683 .help_text = ohelp, \
1684 .category = ocat, \
1685 .specific = ospec, \
1686 INIT_BRACE_BEGIN \
1687 .font = { \
1688 .pvalue = gui_options.oname, \
1689 .size = sizeof(gui_options.oname), \
1690 .def = odef, \
1691 .target = otgt, \
1693 INIT_BRACE_END \
1697 * Generate a client option of type OT_COLOR.
1699 * oname: The option data. Note it is used as name to be loaded or saved.
1700 * So, you shouldn't change the name of this variable in any case.
1701 * odesc: A short description of the client option. Should be used with the
1702 * N_() macro.
1703 * ohelp: The help text for the client option. Should be used with the N_()
1704 * macro.
1705 * ocat: The client_option_class of this client option.
1706 * ospec: A gui_type enumerator which determin for what particular client
1707 * gui this option is for. Sets to GUI_STUB for common options.
1708 * odef_fg, odef_bg: The default values for this client option.
1709 * ocb: A callback function of type void (*)(struct option *) called when
1710 * the option changed.
1712 #define GEN_COLOR_OPTION(oname, odesc, ohelp, ocat, ospec, odef_fg, \
1713 odef_bg, ocb) \
1715 .base_option = OPTION_COLOR_INIT(&client_optset_static, \
1716 client_option_common_vtable, \
1717 client_option_color_vtable, ocb), \
1718 .name = #oname, \
1719 .description = odesc, \
1720 .help_text = ohelp, \
1721 .category = ocat, \
1722 .specific = ospec, \
1723 INIT_BRACE_BEGIN \
1724 .color = { \
1725 .pvalue = &gui_options.oname, \
1726 .def = FT_COLOR(odef_fg, odef_bg) \
1728 INIT_BRACE_END \
1732 * Generate a client option of type OT_VIDEO_MODE.
1734 * oname: The option data. Note it is used as name to be loaded or saved.
1735 * So, you shouldn't change the name of this variable in any case.
1736 * odesc: A short description of the client option. Should be used with the
1737 * N_() macro.
1738 * ohelp: The help text for the client option. Should be used with the N_()
1739 * macro.
1740 * ocat: The client_option_class of this client option.
1741 * ospec: A gui_type enumerator which determin for what particular client
1742 * gui this option is for. Sets to GUI_STUB for common options.
1743 * odef_width, odef_height: The default values for this client option.
1744 * ocb: A callback function of type void (*)(struct option *) called when
1745 * the option changed.
1747 #define GEN_VIDEO_OPTION(oname, odesc, ohelp, ocat, ospec, odef_width, \
1748 odef_height, ocb) \
1750 .base_option = OPTION_VIDEO_MODE_INIT(&client_optset_static, \
1751 client_option_common_vtable, \
1752 client_option_video_mode_vtable, \
1753 ocb), \
1754 .name = #oname, \
1755 .description = odesc, \
1756 .help_text = ohelp, \
1757 .category = ocat, \
1758 .specific = ospec, \
1759 INIT_BRACE_BEGIN \
1760 .video_mode = { \
1761 .pvalue = &gui_options.oname, \
1762 .def = VIDEO_MODE(odef_width, odef_height) \
1764 INIT_BRACE_END \
1767 /****************************************************************************
1768 Enumerator name accessors.
1769 ****************************************************************************/
1771 /****************************************************************************
1772 GTK message/chat layout setting names accessor.
1773 ****************************************************************************/
1774 static const struct copt_val_name
1775 *gui_gtk_message_chat_location_name(int value)
1777 /* Order must match enum GUI_GTK_MSGCHAT_* */
1778 static const struct copt_val_name names[] = {
1779 /* TRANS: enum value for 'gui_gtk2/gtk3_message_chat_location' */
1780 { "SPLIT", N_("Split") },
1781 /* TRANS: enum value for 'gui_gtk2/gtk3_message_chat_location' */
1782 { "SEPARATE", N_("Separate") },
1783 /* TRANS: enum value for 'gui_gtk2/gtk3_message_chat_location' */
1784 { "MERGED", N_("Merged") }
1787 return (0 <= value && value < ARRAY_SIZE(names)
1788 ? names + value : NULL);
1791 /****************************************************************************
1792 Popup tech help setting names accessor.
1793 ****************************************************************************/
1794 static const struct copt_val_name
1795 *gui_popup_tech_help_name(int value)
1797 /* Order must match enum GUI_POPUP_TECH_HELP_* */
1798 static const struct copt_val_name names[] = {
1799 /* TRANS: enum value for 'gui_popup_tech_help' */
1800 { "ENABLED", N_("Enabled") },
1801 /* TRANS: enum value for 'gui_popup_tech_help' */
1802 { "DISABLED", N_("Disabled") },
1803 /* TRANS: enum value for 'gui_popup_tech_help' */
1804 { "RULESET", N_("Ruleset") }
1807 return (0 <= value && value < ARRAY_SIZE(names)
1808 ? names + value : NULL);
1811 /* Some changed callbacks. */
1812 static void reqtree_show_icons_callback(struct option *poption);
1813 static void view_option_changed_callback(struct option *poption);
1814 static void voteinfo_bar_callback(struct option *poption);
1815 static void font_changed_callback(struct option *poption);
1816 static void mapimg_changed_callback(struct option *poption);
1817 static void game_music_enable_callback(struct option *poption);
1818 static void menu_music_enable_callback(struct option *poption);
1820 static struct client_option client_options[] = {
1821 GEN_STR_OPTION(default_user_name,
1822 N_("Login name"),
1823 N_("This is the default login username that will be used "
1824 "in the connection dialogs or with the -a command-line "
1825 "parameter."),
1826 COC_NETWORK, GUI_STUB, NULL, NULL, 0),
1827 GEN_BOOL_OPTION(use_prev_server, N_("Default to previously used server"),
1828 N_("Automatically update \"Server\" and \"Server port\" "
1829 "options to match your latest connection, so by "
1830 "default you connect to the same server you used "
1831 "on the previous run. You should enable "
1832 "saving options on exit too, so that the automatic "
1833 "updates to the options get saved too."),
1834 COC_NETWORK, GUI_STUB, NULL, NULL),
1835 GEN_STR_OPTION(default_server_host,
1836 N_("Server"),
1837 N_("This is the default server hostname that will be used "
1838 "in the connection dialogs or with the -a command-line "
1839 "parameter."),
1840 COC_NETWORK, GUI_STUB, "localhost", NULL, 0),
1841 GEN_INT_OPTION(default_server_port,
1842 N_("Server port"),
1843 N_("This is the default server port that will be used "
1844 "in the connection dialogs or with the -a command-line "
1845 "parameter."),
1846 COC_NETWORK, GUI_STUB, DEFAULT_SOCK_PORT, 0, 65535, NULL),
1847 GEN_STR_OPTION(default_metaserver,
1848 N_("Metaserver"),
1849 N_("The metaserver is a host that the client contacts to "
1850 "find out about games on the internet. Don't change "
1851 "this from its default value unless you know what "
1852 "you're doing."),
1853 COC_NETWORK, GUI_STUB, DEFAULT_METASERVER_OPTION, NULL, 0),
1854 GEN_BOOL_OPTION(heartbeat_enabled, N_("Send heartbeat messages to server"),
1855 N_("Regularly send empty heartbeat message to the server "
1856 "to make sure that the connection is still up. This "
1857 "can be useful if the client otherwise may sit for a "
1858 "long time with no data being sent or received at all."),
1859 COC_NETWORK, GUI_STUB, NULL, NULL),
1860 GEN_STR_LIST_OPTION(default_sound_set_name,
1861 N_("Soundset"),
1862 N_("This is the soundset that will be used. Changing "
1863 "this is the same as using the -S command-line "
1864 "parameter."),
1865 COC_SOUND, GUI_STUB, "stdsounds", get_soundset_list, NULL, 0),
1866 GEN_STR_LIST_OPTION(default_music_set_name,
1867 N_("Musicset"),
1868 N_("This is the musicset that will be used. Changing "
1869 "this is the same as using the -m command-line "
1870 "parameter."),
1871 COC_SOUND, GUI_STUB, "stdmusic",
1872 get_musicset_list, musicspec_reread_callback, 0),
1873 GEN_STR_LIST_OPTION(default_sound_plugin_name,
1874 N_("Sound plugin"),
1875 N_("If you have a problem with sound, try changing "
1876 "the sound plugin. The new plugin won't take "
1877 "effect until you restart Freeciv. Changing this "
1878 "is the same as using the -P command-line option."),
1879 COC_SOUND, GUI_STUB, NULL, get_soundplugin_list, NULL, 0),
1880 GEN_STR_OPTION(default_chat_logfile,
1881 N_("The chat log file"),
1882 N_("The name of the chat log file."),
1883 COC_INTERFACE, GUI_STUB, GUI_DEFAULT_CHAT_LOGFILE, NULL, 0),
1884 /* gui_gtk2/3_default_theme_name and gui_sdl/2_default_theme_name are
1885 * different settings to avoid client crash after loading the
1886 * style for the other gui. Keeps 4 different options! */
1887 GEN_STR_LIST_OPTION(gui_gtk2_default_theme_name, N_("Theme"),
1888 N_("By changing this option you change the "
1889 "active theme."),
1890 COC_GRAPHICS, GUI_GTK2, FC_GTK2_DEFAULT_THEME_NAME,
1891 get_themes_list, theme_reread_callback, 0),
1892 GEN_STR_LIST_OPTION(gui_gtk3_default_theme_name, N_("Theme"),
1893 N_("By changing this option you change the "
1894 "active theme."),
1895 COC_GRAPHICS, GUI_GTK3, FC_GTK3_DEFAULT_THEME_NAME,
1896 get_themes_list, theme_reread_callback, 0),
1897 GEN_STR_LIST_OPTION(gui_gtk3_22_default_theme_name, N_("Theme"),
1898 N_("By changing this option you change the "
1899 "active theme."),
1900 COC_GRAPHICS, GUI_GTK3_22, FC_GTK3_22_DEFAULT_THEME_NAME,
1901 get_themes_list, theme_reread_callback, 0),
1902 GEN_STR_LIST_OPTION(gui_sdl_default_theme_name, N_("Theme"),
1903 N_("By changing this option you change the "
1904 "active theme."),
1905 COC_GRAPHICS, GUI_SDL, FC_SDL_DEFAULT_THEME_NAME,
1906 get_themes_list, theme_reread_callback, 0),
1907 GEN_STR_LIST_OPTION(gui_sdl2_default_theme_name, N_("Theme"),
1908 N_("By changing this option you change the "
1909 "active theme."),
1910 COC_GRAPHICS, GUI_SDL2, FC_SDL2_DEFAULT_THEME_NAME,
1911 get_themes_list, theme_reread_callback, 0),
1912 GEN_STR_LIST_OPTION(gui_qt_default_theme_name, N_("Theme"),
1913 N_("By changing this option you change the "
1914 "active theme."),
1915 COC_GRAPHICS, GUI_QT, FC_QT_DEFAULT_THEME_NAME,
1916 get_themes_list, theme_reread_callback, 0),
1918 /* It's important to give empty string instead of NULL as as default
1919 * value. For NULL value it would default to assigning first value
1920 * from the tileset list returned by get_tileset_list() as default
1921 * tileset. We don't want default tileset assigned at all here, but
1922 * leave it to tilespec code that can handle tileset priority. */
1923 GEN_STR_LIST_OPTION(default_tileset_overhead_name, N_("Tileset (Overhead)"),
1924 N_("Select the tileset used with Overhead maps. "
1925 "This may change currently active tileset, if "
1926 "you are playing on such a map, in which "
1927 "case this is the same as using the -t "
1928 "command-line parameter."),
1929 COC_GRAPHICS, GUI_STUB, "",
1930 get_tileset_list, tilespec_reread_callback, 0),
1931 GEN_STR_LIST_OPTION(default_tileset_iso_name, N_("Tileset (Isometric)"),
1932 N_("Select the tileset used with Isometric maps. "
1933 "This may change currently active tileset, if "
1934 "you are playing on such a map, in which "
1935 "case this is the same as using the -t "
1936 "command-line parameter."),
1937 COC_GRAPHICS, GUI_STUB, "",
1938 get_tileset_list, tilespec_reread_callback, TF_ISO),
1939 GEN_STR_LIST_OPTION(default_tileset_hex_name, N_("Tileset (Hex)"),
1940 N_("Select the tileset used with Hex maps. "
1941 "This may change currently active tileset, if "
1942 "you are playing on such a map, in which "
1943 "case this is the same as using the -t "
1944 "command-line parameter."),
1945 COC_GRAPHICS, GUI_STUB, "",
1946 get_tileset_list, tilespec_reread_callback, TF_HEX),
1947 GEN_STR_LIST_OPTION(default_tileset_isohex_name, N_("Tileset (Isometric Hex)"),
1948 N_("Select the tileset used with Isometric Hex maps. "
1949 "This may change currently active tileset, if "
1950 "you are playing on such a map, in which "
1951 "case this is the same as using the -t "
1952 "command-line parameter."),
1953 COC_GRAPHICS, GUI_STUB, "",
1954 get_tileset_list, tilespec_reread_callback, TF_ISO | TF_HEX),
1956 GEN_BOOL_OPTION(draw_city_outlines, N_("Draw city outlines"),
1957 N_("Setting this option will draw a line at the city "
1958 "workable limit."),
1959 COC_GRAPHICS, GUI_STUB, TRUE,
1960 view_option_changed_callback),
1961 GEN_BOOL_OPTION(draw_city_output, N_("Draw city output"),
1962 N_("Setting this option will draw city output for every "
1963 "citizen."),
1964 COC_GRAPHICS, GUI_STUB, FALSE,
1965 view_option_changed_callback),
1966 GEN_BOOL_OPTION(draw_map_grid, N_("Draw the map grid"),
1967 N_("Setting this option will draw a grid over the map."),
1968 COC_GRAPHICS, GUI_STUB, FALSE,
1969 view_option_changed_callback),
1970 GEN_BOOL_OPTION(draw_full_citybar, N_("Draw the city bar"),
1971 N_("Setting this option will display a 'city bar' "
1972 "containing useful information beneath each city. "
1973 "Disabling this option will display only the city's "
1974 "name and, optionally, production."),
1975 COC_GRAPHICS, GUI_STUB,
1976 TRUE, view_option_changed_callback),
1977 GEN_BOOL_OPTION(draw_city_names, N_("Draw the city names"),
1978 N_("Setting this option will draw the names of the cities "
1979 "on the map."),
1980 COC_GRAPHICS, GUI_STUB, TRUE,
1981 view_option_changed_callback),
1982 GEN_BOOL_OPTION(draw_city_growth, N_("Draw the city growth"),
1983 N_("Setting this option will draw in how many turns the "
1984 "cities will grow or shrink."),
1985 COC_GRAPHICS, GUI_STUB, TRUE,
1986 view_option_changed_callback),
1987 GEN_BOOL_OPTION(draw_city_productions, N_("Draw the city productions"),
1988 N_("Setting this option will draw what the cities are "
1989 "currently building on the map."),
1990 COC_GRAPHICS, GUI_STUB, TRUE,
1991 view_option_changed_callback),
1992 GEN_BOOL_OPTION(draw_city_buycost, N_("Draw the city buy costs"),
1993 N_("Setting this option will draw how much gold is "
1994 "needed to buy the production of the cities."),
1995 COC_GRAPHICS, GUI_STUB, FALSE,
1996 view_option_changed_callback),
1997 GEN_BOOL_OPTION(draw_city_trade_routes, N_("Draw the city trade routes"),
1998 N_("Setting this option will draw trade route lines "
1999 "between cities which have trade routes."),
2000 COC_GRAPHICS, GUI_STUB, FALSE,
2001 view_option_changed_callback),
2002 GEN_BOOL_OPTION(draw_terrain, N_("Draw the terrain"),
2003 N_("Setting this option will draw the terrain."),
2004 COC_GRAPHICS, GUI_STUB, TRUE,
2005 view_option_changed_callback),
2006 GEN_BOOL_OPTION(draw_coastline, N_("Draw the coast line"),
2007 N_("Setting this option will draw a line to separate the "
2008 "land from the ocean."),
2009 COC_GRAPHICS, GUI_STUB, FALSE,
2010 view_option_changed_callback),
2011 GEN_BOOL_OPTION(draw_roads_rails, N_("Draw the roads and the railroads"),
2012 N_("Setting this option will draw the roads and the "
2013 "railroads on the map."),
2014 COC_GRAPHICS, GUI_STUB, TRUE,
2015 view_option_changed_callback),
2016 GEN_BOOL_OPTION(draw_irrigation, N_("Draw the irrigation"),
2017 N_("Setting this option will draw the irrigation systems "
2018 "on the map."),
2019 COC_GRAPHICS, GUI_STUB, TRUE,
2020 view_option_changed_callback),
2021 GEN_BOOL_OPTION(draw_mines, N_("Draw the mines"),
2022 N_("Setting this option will draw the mines on the map."),
2023 COC_GRAPHICS, GUI_STUB, TRUE,
2024 view_option_changed_callback),
2025 GEN_BOOL_OPTION(draw_fortress_airbase, N_("Draw the bases"),
2026 N_("Setting this option will draw the bases on the map."),
2027 COC_GRAPHICS, GUI_STUB, TRUE,
2028 view_option_changed_callback),
2029 GEN_BOOL_OPTION(draw_specials, N_("Draw the resources"),
2030 N_("Setting this option will draw the resources on the "
2031 "map."),
2032 COC_GRAPHICS, GUI_STUB, TRUE,
2033 view_option_changed_callback),
2034 GEN_BOOL_OPTION(draw_huts, N_("Draw the huts"),
2035 N_("Setting this option will draw the huts on the "
2036 "map."),
2037 COC_GRAPHICS, GUI_STUB, TRUE,
2038 view_option_changed_callback),
2039 GEN_BOOL_OPTION(draw_pollution, N_("Draw the pollution/nuclear fallout"),
2040 N_("Setting this option will draw pollution and "
2041 "nuclear fallout on the map."),
2042 COC_GRAPHICS, GUI_STUB, TRUE,
2043 view_option_changed_callback),
2044 GEN_BOOL_OPTION(draw_cities, N_("Draw the cities"),
2045 N_("Setting this option will draw the cities on the map."),
2046 COC_GRAPHICS, GUI_STUB, TRUE,
2047 view_option_changed_callback),
2048 GEN_BOOL_OPTION(draw_units, N_("Draw the units"),
2049 N_("Setting this option will draw the units on the map."),
2050 COC_GRAPHICS, GUI_STUB, TRUE,
2051 view_option_changed_callback),
2052 GEN_BOOL_OPTION(solid_color_behind_units,
2053 N_("Solid unit background color"),
2054 N_("Setting this option will cause units on the map "
2055 "view to be drawn with a solid background color "
2056 "instead of the flag backdrop."),
2057 COC_GRAPHICS, GUI_STUB,
2058 FALSE, view_option_changed_callback),
2059 GEN_BOOL_OPTION(draw_unit_shields, N_("Draw shield graphics for units"),
2060 N_("Setting this option will draw a shield icon "
2061 "as the flags on units. If unset, the full flag will "
2062 "be drawn."),
2063 COC_GRAPHICS, GUI_STUB, TRUE, view_option_changed_callback),
2064 GEN_BOOL_OPTION(draw_focus_unit, N_("Draw the units in focus"),
2065 N_("Setting this option will cause the currently focused "
2066 "unit(s) to always be drawn, even if units are not "
2067 "otherwise being drawn (for instance if 'Draw the units' "
2068 "is unset)."),
2069 COC_GRAPHICS, GUI_STUB, FALSE,
2070 view_option_changed_callback),
2071 GEN_BOOL_OPTION(draw_fog_of_war, N_("Draw the fog of war"),
2072 N_("Setting this option will draw the fog of war."),
2073 COC_GRAPHICS, GUI_STUB, TRUE,
2074 view_option_changed_callback),
2075 GEN_BOOL_OPTION(draw_borders, N_("Draw the borders"),
2076 N_("Setting this option will draw the national borders."),
2077 COC_GRAPHICS, GUI_STUB, TRUE,
2078 view_option_changed_callback),
2079 GEN_BOOL_OPTION(draw_native, N_("Draw whether tiles are native to "
2080 "selected unit"),
2081 N_("Setting this option will highlight tiles that the "
2082 "currently selected unit cannot enter unaided due to "
2083 "non-native terrain. (If multiple units are selected, "
2084 "only tiles that all of them can enter are indicated.)"),
2085 COC_GRAPHICS, GUI_STUB, FALSE,
2086 view_option_changed_callback),
2087 GEN_BOOL_OPTION(player_dlg_show_dead_players,
2088 N_("Show dead players in Nations report"),
2089 N_("This option controls whether defeated nations are "
2090 "shown on the Nations report page."),
2091 COC_GRAPHICS, GUI_STUB, TRUE,
2092 view_option_changed_callback),
2093 GEN_BOOL_OPTION(sound_bell_at_new_turn, N_("Sound bell at new turn"),
2094 N_("Set this option to have a \"bell\" event be generated "
2095 "at the start of a new turn. You can control the "
2096 "behavior of the \"bell\" event by editing the message "
2097 "options."),
2098 COC_SOUND, GUI_STUB, FALSE, NULL),
2099 GEN_INT_OPTION(smooth_move_unit_msec,
2100 N_("Unit movement animation time (milliseconds)"),
2101 N_("This option controls how long unit \"animation\" takes "
2102 "when a unit moves on the map view. Set it to 0 to "
2103 "disable animation entirely."),
2104 COC_GRAPHICS, GUI_STUB, 30, 0, 2000, NULL),
2105 GEN_INT_OPTION(smooth_center_slide_msec,
2106 N_("Mapview recentering time (milliseconds)"),
2107 N_("When the map view is recentered, it will slide "
2108 "smoothly over the map to its new position. This "
2109 "option controls how long this slide lasts. Set it to "
2110 "0 to disable mapview sliding entirely."),
2111 COC_GRAPHICS, GUI_STUB, 200, 0, 5000, NULL),
2112 GEN_INT_OPTION(smooth_combat_step_msec,
2113 N_("Combat animation step time (milliseconds)"),
2114 N_("This option controls the speed of combat animation "
2115 "between units on the mapview. Set it to 0 to disable "
2116 "animation entirely."),
2117 COC_GRAPHICS, GUI_STUB, 10, 0, 100, NULL),
2118 GEN_BOOL_OPTION(reqtree_show_icons,
2119 N_("Show icons in the technology tree"),
2120 N_("Setting this option will display icons "
2121 "on the technology tree diagram. Turning "
2122 "this option off makes the technology tree "
2123 "more compact."),
2124 COC_GRAPHICS, GUI_STUB, TRUE, reqtree_show_icons_callback),
2125 GEN_BOOL_OPTION(reqtree_curved_lines,
2126 N_("Use curved lines in the technology tree"),
2127 N_("Setting this option make the technology tree "
2128 "diagram use curved lines to show technology "
2129 "relations. Turning this option off causes "
2130 "the lines to be drawn straight."),
2131 COC_GRAPHICS, GUI_STUB, FALSE,
2132 reqtree_show_icons_callback),
2133 GEN_COLOR_OPTION(highlight_our_names,
2134 N_("Color to highlight your player/user name"),
2135 N_("If set, your player and user name in the new chat "
2136 "messages will be highlighted using this color as "
2137 "background. If not set, it will just not highlight "
2138 "anything."),
2139 COC_GRAPHICS, GUI_STUB, "#000000", "#FFFF00", NULL),
2140 GEN_BOOL_OPTION(ai_manual_turn_done, N_("Manual Turn Done in AI mode"),
2141 N_("Disable this option if you do not want to "
2142 "press the Turn Done button manually when watching "
2143 "an AI player."),
2144 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2145 GEN_BOOL_OPTION(auto_center_on_unit, N_("Auto center on units"),
2146 N_("Set this option to have the active unit centered "
2147 "automatically when the unit focus changes."),
2148 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2149 GEN_BOOL_OPTION(auto_center_on_automated, N_("Show automated units"),
2150 N_("Disable this option if you do not want to see "
2151 "automated units autocentered and animated"),
2152 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2153 GEN_BOOL_OPTION(auto_center_on_combat, N_("Auto center on combat"),
2154 N_("Set this option to have any combat be centered "
2155 "automatically. Disabling this will speed up the time "
2156 "between turns but may cause you to miss combat "
2157 "entirely."),
2158 COC_INTERFACE, GUI_STUB, FALSE, NULL),
2159 GEN_BOOL_OPTION(auto_center_each_turn, N_("Auto center on new turn"),
2160 N_("Set this option to have the client automatically "
2161 "recenter the map on a suitable location at the "
2162 "start of each turn."),
2163 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2164 GEN_BOOL_OPTION(wakeup_focus, N_("Focus on awakened units"),
2165 N_("Set this option to have newly awoken units be "
2166 "focused automatically."),
2167 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2168 GEN_BOOL_OPTION(keyboardless_goto, N_("Keyboardless goto"),
2169 N_("If this option is set then a goto may be initiated "
2170 "by left-clicking and then holding down the mouse "
2171 "button while dragging the mouse onto a different "
2172 "tile."),
2173 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2174 GEN_BOOL_OPTION(goto_into_unknown, N_("Allow goto into the unknown"),
2175 N_("Setting this option will make the game consider "
2176 "moving into unknown tiles. If not, then goto routes "
2177 "will detour around or be blocked by unknown tiles."),
2178 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2179 GEN_BOOL_OPTION(center_when_popup_city, N_("Center map when popup city"),
2180 N_("Setting this option makes the mapview center on a "
2181 "city when its city dialog is popped up."),
2182 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2183 GEN_BOOL_OPTION(concise_city_production, N_("Concise city production"),
2184 N_("Set this option to make the city production (as shown "
2185 "in the city dialog) to be more compact."),
2186 COC_INTERFACE, GUI_STUB, FALSE, NULL),
2187 GEN_BOOL_OPTION(auto_turn_done, N_("End turn when done moving"),
2188 N_("Setting this option makes your turn end automatically "
2189 "when all your units are done moving."),
2190 COC_INTERFACE, GUI_STUB, FALSE, NULL),
2191 GEN_BOOL_OPTION(ask_city_name, N_("Prompt for city names"),
2192 N_("Disabling this option will make the names of newly "
2193 "founded cities be chosen automatically by the server."),
2194 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2195 GEN_BOOL_OPTION(popup_new_cities, N_("Pop up city dialog for new cities"),
2196 N_("Setting this option will pop up a newly-founded "
2197 "city's city dialog automatically."),
2198 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2199 GEN_BOOL_OPTION(popup_actor_arrival, N_("Pop up caravan and spy actions"),
2200 N_("If this option is enabled, when a unit arrives at "
2201 "a city where it can perform an action like "
2202 "establishing a trade route, helping build a wonder, or "
2203 "establishing an embassy, a window will pop up asking "
2204 "which action should be performed. "
2205 "Disabling this option means you will have to do the "
2206 "action manually by pressing either 'r' (for a trade "
2207 "route), 'b' (for building a wonder) or 'd' (for a "
2208 "spy action) when the unit is in the city."),
2209 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2210 GEN_BOOL_OPTION(enable_cursor_changes, N_("Enable cursor changing"),
2211 N_("This option controls whether the client should "
2212 "try to change the mouse cursor depending on what "
2213 "is being pointed at, as well as to indicate "
2214 "changes in the client or server state."),
2215 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2216 GEN_BOOL_OPTION(separate_unit_selection, N_("Select cities before units"),
2217 N_("If this option is enabled, when both cities and "
2218 "units are present in the selection rectangle, only "
2219 "cities will be selected. See the help on Controls."),
2220 COC_INTERFACE, GUI_STUB, FALSE, NULL),
2221 GEN_BOOL_OPTION(unit_selection_clears_orders,
2222 N_("Clear unit orders on selection"),
2223 N_("Enabling this option will cause unit orders to be "
2224 "cleared as soon as one or more units are selected. If "
2225 "this option is disabled, busy units will not stop "
2226 "their current activity when selected. Giving them "
2227 "new orders will clear their current ones; pressing "
2228 "<space> once will clear their orders and leave them "
2229 "selected, and pressing <space> a second time will "
2230 "dismiss them."),
2231 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2232 GEN_BOOL_OPTION(voteinfo_bar_use, N_("Enable vote bar"),
2233 N_("If this option is turned on, the vote bar will be "
2234 "displayed to show vote information."),
2235 COC_GRAPHICS, GUI_STUB, TRUE, voteinfo_bar_callback),
2236 GEN_BOOL_OPTION(voteinfo_bar_always_show,
2237 N_("Always display the vote bar"),
2238 N_("If this option is turned on, the vote bar will never "
2239 "be hidden, even if there is no running vote."),
2240 COC_GRAPHICS, GUI_STUB, FALSE, voteinfo_bar_callback),
2241 GEN_BOOL_OPTION(voteinfo_bar_hide_when_not_player,
2242 N_("Do not show vote bar if not a player"),
2243 N_("If this option is enabled, the client won't show the "
2244 "vote bar if you are not a player."),
2245 COC_GRAPHICS, GUI_STUB, FALSE, voteinfo_bar_callback),
2246 GEN_BOOL_OPTION(voteinfo_bar_new_at_front, N_("Set new votes at front"),
2247 N_("If this option is enabled, then new votes will go "
2248 "to the front of the vote list."),
2249 COC_GRAPHICS, GUI_STUB, FALSE, voteinfo_bar_callback),
2250 GEN_BOOL_OPTION(autoaccept_tileset_suggestion,
2251 N_("Autoaccept tileset suggestions"),
2252 N_("If this option is enabled, any tileset suggested by "
2253 "the ruleset is automatically used; otherwise you "
2254 "are prompted to change tileset."),
2255 COC_GRAPHICS, GUI_STUB, FALSE, NULL),
2257 GEN_BOOL_OPTION(sound_enable_effects,
2258 N_("Enable sound effects"),
2259 N_("Play sound effects, assuming there's suitable "
2260 "sound plugin and soundset with the sounds."),
2261 COC_SOUND, GUI_STUB, TRUE, NULL),
2262 GEN_BOOL_OPTION(sound_enable_game_music,
2263 N_("Enable in-game music"),
2264 N_("Play music during the game, assuming there's suitable "
2265 "sound plugin and musicset with in-game tracks."),
2266 COC_SOUND, GUI_STUB, TRUE, game_music_enable_callback),
2267 GEN_BOOL_OPTION(sound_enable_menu_music,
2268 N_("Enable menu music"),
2269 N_("Play music while not in actual game, "
2270 "assuming there's suitable "
2271 "sound plugin and musicset with menu music tracks."),
2272 COC_SOUND, GUI_STUB, TRUE, menu_music_enable_callback),
2273 GEN_BOOL_OPTION(autoaccept_soundset_suggestion,
2274 N_("Autoaccept soundset suggestions"),
2275 N_("If this option is enabled, any soundset suggested by "
2276 "the ruleset is automatically used."),
2277 COC_SOUND, GUI_STUB, FALSE, NULL),
2278 GEN_BOOL_OPTION(autoaccept_musicset_suggestion,
2279 N_("Autoaccept musicset suggestions"),
2280 N_("If this option is enabled, any musicset suggested by "
2281 "the ruleset is automatically used."),
2282 COC_SOUND, GUI_STUB, FALSE, NULL),
2284 GEN_BOOL_OPTION(overview.layers[OLAYER_BACKGROUND],
2285 N_("Background layer"),
2286 N_("The background layer of the overview shows just "
2287 "ocean and land."),
2288 COC_OVERVIEW, GUI_STUB, TRUE, NULL),
2289 GEN_BOOL_OPTION(overview.layers[OLAYER_RELIEF],
2290 N_("Terrain relief map layer"),
2291 N_("The relief layer shows all terrains on the map."),
2292 COC_OVERVIEW, GUI_STUB, FALSE, overview_redraw_callback),
2293 GEN_BOOL_OPTION(overview.layers[OLAYER_BORDERS],
2294 N_("Borders layer"),
2295 N_("The borders layer of the overview shows which tiles "
2296 "are owned by each player."),
2297 COC_OVERVIEW, GUI_STUB, FALSE, overview_redraw_callback),
2298 GEN_BOOL_OPTION(overview.layers[OLAYER_BORDERS_ON_OCEAN],
2299 N_("Borders layer on ocean tiles"),
2300 N_("The borders layer of the overview are drawn on "
2301 "ocean tiles as well (this may look ugly with many "
2302 "islands). This option is only of interest if you "
2303 "have set the option \"Borders layer\" already."),
2304 COC_OVERVIEW, GUI_STUB, TRUE, overview_redraw_callback),
2305 GEN_BOOL_OPTION(overview.layers[OLAYER_UNITS],
2306 N_("Units layer"),
2307 N_("Enabling this will draw units on the overview."),
2308 COC_OVERVIEW, GUI_STUB, TRUE, overview_redraw_callback),
2309 GEN_BOOL_OPTION(overview.layers[OLAYER_CITIES],
2310 N_("Cities layer"),
2311 N_("Enabling this will draw cities on the overview."),
2312 COC_OVERVIEW, GUI_STUB, TRUE, overview_redraw_callback),
2313 GEN_BOOL_OPTION(overview.fog,
2314 N_("Overview fog of war"),
2315 N_("Enabling this will show fog of war on the "
2316 "overview."),
2317 COC_OVERVIEW, GUI_STUB, TRUE, overview_redraw_callback),
2319 /* options for map images */
2320 GEN_STR_LIST_OPTION(mapimg_format,
2321 N_("Image format"),
2322 N_("The image toolkit and file format used for "
2323 "map images."),
2324 COC_MAPIMG, GUI_STUB, NULL, get_mapimg_format_list,
2325 NULL, 0),
2326 GEN_INT_OPTION(mapimg_zoom,
2327 N_("Zoom factor for map images"),
2328 N_("The magnification used for map images."),
2329 COC_MAPIMG, GUI_STUB, 2, 1, 5, mapimg_changed_callback),
2330 GEN_BOOL_OPTION(mapimg_layer[MAPIMG_LAYER_AREA],
2331 N_("Show area within borders"),
2332 N_("If set, the territory of each nation is shown "
2333 "on the saved image."),
2334 COC_MAPIMG, GUI_STUB, FALSE, mapimg_changed_callback),
2335 GEN_BOOL_OPTION(mapimg_layer[MAPIMG_LAYER_BORDERS],
2336 N_("Show borders"),
2337 N_("If set, the border of each nation is shown on the "
2338 "saved image."),
2339 COC_MAPIMG, GUI_STUB, TRUE, mapimg_changed_callback),
2340 GEN_BOOL_OPTION(mapimg_layer[MAPIMG_LAYER_CITIES],
2341 N_("Show cities"),
2342 N_("If set, cities are shown on the saved image."),
2343 COC_MAPIMG, GUI_STUB, TRUE, mapimg_changed_callback),
2344 GEN_BOOL_OPTION(mapimg_layer[MAPIMG_LAYER_FOGOFWAR],
2345 N_("Show fog of war"),
2346 N_("If set, the extent of fog of war is shown on the "
2347 "saved image."),
2348 COC_MAPIMG, GUI_STUB, TRUE, mapimg_changed_callback),
2349 GEN_BOOL_OPTION(mapimg_layer[MAPIMG_LAYER_TERRAIN],
2350 N_("Show full terrain"),
2351 N_("If set, terrain relief is shown with different colors "
2352 "in the saved image; otherwise, only land and water are "
2353 "distinguished."),
2354 COC_MAPIMG, GUI_STUB, TRUE, mapimg_changed_callback),
2355 GEN_BOOL_OPTION(mapimg_layer[MAPIMG_LAYER_UNITS],
2356 N_("Show units"),
2357 N_("If set, units are shown in the saved image."),
2358 COC_MAPIMG, GUI_STUB, TRUE, mapimg_changed_callback),
2359 GEN_STR_OPTION(mapimg_filename,
2360 N_("Map image file name"),
2361 N_("The base part of the filename for saved map images. "
2362 "A string identifying the game turn and map options will "
2363 "be appended."),
2364 COC_MAPIMG, GUI_STUB, GUI_DEFAULT_MAPIMG_FILENAME, NULL, 0),
2366 /* gui-gtk-2.0 client specific options. */
2367 GEN_BOOL_OPTION(gui_gtk2_fullscreen, N_("Fullscreen"),
2368 N_("If this option is set the client will use the "
2369 "whole screen area for drawing."),
2370 COC_INTERFACE, GUI_GTK2, FALSE, NULL),
2371 GEN_BOOL_OPTION(gui_gtk2_map_scrollbars, N_("Show map scrollbars"),
2372 N_("Disable this option to hide the scrollbars on the "
2373 "map view."),
2374 COC_INTERFACE, GUI_GTK2, FALSE, NULL),
2375 GEN_BOOL_OPTION(gui_gtk2_dialogs_on_top, N_("Keep dialogs on top"),
2376 N_("If this option is set then dialog windows will always "
2377 "remain in front of the main Freeciv window. "
2378 "Disabling this has no effect in fullscreen mode."),
2379 COC_INTERFACE, GUI_GTK2, TRUE, NULL),
2380 GEN_BOOL_OPTION(gui_gtk2_show_task_icons, N_("Show worklist task icons"),
2381 N_("Disabling this will turn off the unit and building "
2382 "icons in the worklist dialog and the production "
2383 "tab of the city dialog."),
2384 COC_GRAPHICS, GUI_GTK2, TRUE, NULL),
2385 GEN_BOOL_OPTION(gui_gtk2_enable_tabs, N_("Enable status report tabs"),
2386 N_("If this option is enabled then report dialogs will "
2387 "be shown as separate tabs rather than in popup "
2388 "dialogs."),
2389 COC_INTERFACE, GUI_GTK2, TRUE, NULL),
2390 GEN_BOOL_OPTION(gui_gtk2_better_fog,
2391 N_("Better fog-of-war drawing"),
2392 N_("If this is enabled then a better method is used "
2393 "for drawing fog-of-war. It is not any slower but "
2394 "will consume about twice as much memory."),
2395 COC_GRAPHICS, GUI_GTK2,
2396 TRUE, view_option_changed_callback),
2397 GEN_BOOL_OPTION(gui_gtk2_show_chat_message_time,
2398 N_("Show time for each chat message"),
2399 N_("If this option is enabled then all chat messages "
2400 "will be prefixed by a time string of the form "
2401 "[hour:minute:second]."),
2402 COC_INTERFACE, GUI_GTK2, FALSE, NULL),
2403 GEN_BOOL_OPTION(gui_gtk2_new_messages_go_to_top,
2404 N_("New message events go to top of list"),
2405 N_("If this option is enabled, new events in the "
2406 "message window will appear at the top of the list, "
2407 "rather than being appended at the bottom."),
2408 COC_INTERFACE, GUI_GTK2, FALSE, NULL),
2409 GEN_BOOL_OPTION(gui_gtk2_show_message_window_buttons,
2410 N_("Show extra message window buttons"),
2411 N_("If this option is enabled, there will be two "
2412 "buttons displayed in the message window for "
2413 "inspecting a city and going to a location. If this "
2414 "option is disabled, these buttons will not appear "
2415 "(you can still double-click with the left mouse "
2416 "button or right-click on a row to inspect or goto "
2417 "respectively). This option will only take effect "
2418 "once the message window is closed and reopened."),
2419 COC_INTERFACE, GUI_GTK2, TRUE, NULL),
2420 GEN_BOOL_OPTION(gui_gtk2_metaserver_tab_first,
2421 N_("Metaserver tab first in network page"),
2422 N_("If this option is enabled, the metaserver tab will "
2423 "be the first notebook tab in the network page. This "
2424 "option requires a restart in order to take effect."),
2425 COC_NETWORK, GUI_GTK2, FALSE, NULL),
2426 GEN_BOOL_OPTION(gui_gtk2_allied_chat_only,
2427 N_("Plain chat messages are sent to allies only"),
2428 N_("If this option is enabled, then plain messages "
2429 "typed into the chat entry while the game is "
2430 "running will only be sent to your allies. "
2431 "Otherwise plain messages will be sent as "
2432 "public chat messages. To send a public chat "
2433 "message with this option enabled, prefix the "
2434 "message with a single colon ':'. This option "
2435 "can also be set using a toggle button beside "
2436 "the chat entry (only visible in multiplayer "
2437 "games)."),
2438 COC_INTERFACE, GUI_GTK2, FALSE, NULL),
2439 GEN_ENUM_OPTION(gui_gtk2_message_chat_location,
2440 N_("Messages and Chat reports location"),
2441 /* TRANS: The strings used in the UI for 'Split' etc are
2442 * tagged 'gui_gtk2/gtk3_message_chat_location' */
2443 N_("Controls where the Messages and Chat reports "
2444 "appear relative to the main view containing the map.\n"
2445 "'Split' allows all three to be seen simultaneously, "
2446 "which is best for multiplayer, but requires a large "
2447 "window to be usable.\n"
2448 "'Separate' puts Messages and Chat in a notebook "
2449 "separate from the main view, so that one of them "
2450 "can always be seen alongside the main view.\n"
2451 "'Merged' makes the Messages and Chat reports into "
2452 "tabs alongside the map and other reports; this "
2453 "allows a larger map view on small screens.\n"
2454 "This option requires a restart in order to take "
2455 "effect."), COC_INTERFACE, GUI_GTK2,
2456 GUI_GTK_MSGCHAT_MERGED /* Ignored! See options_load(). */,
2457 gui_gtk_message_chat_location_name, NULL),
2458 GEN_BOOL_OPTION(gui_gtk2_small_display_layout,
2459 N_("Arrange widgets for small displays"),
2460 N_("If this option is enabled, widgets in the main "
2461 "window will be arranged so that they take up the "
2462 "least amount of total screen space. Specifically, "
2463 "the left panel containing the overview, player "
2464 "status, and the unit information box will be "
2465 "extended over the entire left side of the window. "
2466 "This option requires a restart in order to take "
2467 "effect."), COC_INTERFACE, GUI_GTK2, TRUE, NULL),
2468 GEN_BOOL_OPTION(gui_gtk2_mouse_over_map_focus,
2469 N_("Mouse over the map widget selects it automatically"),
2470 N_("If this option is enabled, then the map will be "
2471 "focused when the mouse hovers over it."),
2472 COC_INTERFACE, GUI_GTK2, FALSE, NULL),
2473 GEN_BOOL_OPTION(gui_gtk2_chatline_autocompletion,
2474 N_("Player or user name autocompletion"),
2475 N_("If this option is turned on, the tabulation key "
2476 "will be used in the chatline to complete the word you "
2477 "are typing with the name of a player or a user."),
2478 COC_INTERFACE, GUI_GTK2, TRUE, NULL),
2479 GEN_INT_OPTION(gui_gtk2_citydlg_xsize,
2480 N_("Width of the city dialog"),
2481 N_("This value is only used if the width of the city "
2482 "dialog is saved."),
2483 COC_INTERFACE, GUI_GTK2, GUI_GTK2_CITYDLG_DEFAULT_XSIZE,
2484 GUI_GTK2_CITYDLG_MIN_XSIZE, GUI_GTK2_CITYDLG_MAX_XSIZE,
2485 NULL),
2486 GEN_INT_OPTION(gui_gtk2_citydlg_ysize,
2487 N_("Height of the city dialog"),
2488 N_("This value is only used if the height of the city "
2489 "dialog is saved."),
2490 COC_INTERFACE, GUI_GTK2, GUI_GTK2_CITYDLG_DEFAULT_YSIZE,
2491 GUI_GTK2_CITYDLG_MIN_YSIZE, GUI_GTK2_CITYDLG_MAX_YSIZE,
2492 NULL),
2493 GEN_ENUM_OPTION(gui_gtk2_popup_tech_help,
2494 N_("Popup tech help when gained"),
2495 N_("Controls if tech help should be opened when "
2496 "new tech has been gained.\n"
2497 "'Ruleset' means that behavior suggested by "
2498 "current ruleset is used."), COC_INTERFACE, GUI_GTK2,
2499 GUI_POPUP_TECH_HELP_RULESET,
2500 gui_popup_tech_help_name, NULL),
2501 GEN_FONT_OPTION(gui_gtk2_font_city_label, "city_label",
2502 N_("City Label"),
2503 N_("This font is used to display the city labels on city "
2504 "dialogs."),
2505 COC_FONT, GUI_GTK2,
2506 "Monospace 8", font_changed_callback),
2507 GEN_FONT_OPTION(gui_gtk2_font_notify_label, "notify_label",
2508 N_("Notify Label"),
2509 N_("This font is used to display server reports such "
2510 "as the demographic report or historian publications."),
2511 COC_FONT, GUI_GTK2,
2512 "Monospace Bold 9", font_changed_callback),
2513 GEN_FONT_OPTION(gui_gtk2_font_spaceship_label, "spaceship_label",
2514 N_("Spaceship Label"),
2515 N_("This font is used to display the spaceship widgets."),
2516 COC_FONT, GUI_GTK2,
2517 "Monospace 8", font_changed_callback),
2518 GEN_FONT_OPTION(gui_gtk2_font_help_label, "help_label",
2519 N_("Help Label"),
2520 N_("This font is used to display the help headers in the "
2521 "help window."),
2522 COC_FONT, GUI_GTK2,
2523 "Sans Bold 10", font_changed_callback),
2524 GEN_FONT_OPTION(gui_gtk2_font_help_link, "help_link",
2525 N_("Help Link"),
2526 N_("This font is used to display the help links in the "
2527 "help window."),
2528 COC_FONT, GUI_GTK2,
2529 "Sans 9", font_changed_callback),
2530 GEN_FONT_OPTION(gui_gtk2_font_help_text, "help_text",
2531 N_("Help Text"),
2532 N_("This font is used to display the help body text in "
2533 "the help window."),
2534 COC_FONT, GUI_GTK2,
2535 "Monospace 8", font_changed_callback),
2536 GEN_FONT_OPTION(gui_gtk2_font_chatline, "chatline",
2537 N_("Chatline Area"),
2538 N_("This font is used to display the text in the "
2539 "chatline area."),
2540 COC_FONT, GUI_GTK2,
2541 "Monospace 8", font_changed_callback),
2542 GEN_FONT_OPTION(gui_gtk2_font_beta_label, "beta_label",
2543 N_("Beta Label"),
2544 N_("This font is used to display the beta label."),
2545 COC_FONT, GUI_GTK2,
2546 "Sans Italic 10", font_changed_callback),
2547 GEN_FONT_OPTION(gui_gtk2_font_small, "small_font",
2548 N_("Small Font"),
2549 N_("This font is used for any small font request. For "
2550 "example, it is used for display the building lists "
2551 "in the city dialog, the Economy report or the Units "
2552 "report."),
2553 COC_FONT, GUI_GTK2,
2554 "Sans 9", NULL),
2555 GEN_FONT_OPTION(gui_gtk2_font_comment_label, "comment_label",
2556 N_("Comment Label"),
2557 N_("This font is used to display comment labels, such as "
2558 "in the governor page of the city dialogs."),
2559 COC_FONT, GUI_GTK2,
2560 "Sans Italic 9", font_changed_callback),
2561 GEN_FONT_OPTION(gui_gtk2_font_city_names, "city_names",
2562 N_("City Names"),
2563 N_("This font is used to the display the city names "
2564 "on the map."),
2565 COC_FONT, GUI_GTK2,
2566 "Sans Bold 10", NULL),
2567 GEN_FONT_OPTION(gui_gtk2_font_city_productions, "city_productions",
2568 N_("City Productions"),
2569 N_("This font is used to the display the city production "
2570 "names on the map."),
2571 COC_FONT, GUI_GTK2,
2572 "Serif 10", NULL),
2573 GEN_FONT_OPTION(gui_gtk2_font_reqtree_text, "reqtree_text",
2574 N_("Requirement Tree"),
2575 N_("This font is used to the display the requirement tree "
2576 "in the Research report."),
2577 COC_FONT, GUI_GTK2,
2578 "Serif 10", NULL),
2580 /* gui-gtk-3.0 client specific options. */
2581 GEN_BOOL_OPTION(gui_gtk3_fullscreen, N_("Fullscreen"),
2582 N_("If this option is set the client will use the "
2583 "whole screen area for drawing."),
2584 COC_INTERFACE, GUI_GTK3, FALSE, NULL),
2585 GEN_BOOL_OPTION(gui_gtk3_map_scrollbars, N_("Show map scrollbars"),
2586 N_("Disable this option to hide the scrollbars on the "
2587 "map view."),
2588 COC_INTERFACE, GUI_GTK3, FALSE, NULL),
2589 GEN_BOOL_OPTION(gui_gtk3_dialogs_on_top, N_("Keep dialogs on top"),
2590 N_("If this option is set then dialog windows will always "
2591 "remain in front of the main Freeciv window. "
2592 "Disabling this has no effect in fullscreen mode."),
2593 COC_INTERFACE, GUI_GTK3, TRUE, NULL),
2594 GEN_BOOL_OPTION(gui_gtk3_show_task_icons, N_("Show worklist task icons"),
2595 N_("Disabling this will turn off the unit and building "
2596 "icons in the worklist dialog and the production "
2597 "tab of the city dialog."),
2598 COC_GRAPHICS, GUI_GTK3, TRUE, NULL),
2599 GEN_BOOL_OPTION(gui_gtk3_enable_tabs, N_("Enable status report tabs"),
2600 N_("If this option is enabled then report dialogs will "
2601 "be shown as separate tabs rather than in popup "
2602 "dialogs."),
2603 COC_INTERFACE, GUI_GTK3, TRUE, NULL),
2604 GEN_BOOL_OPTION(gui_gtk3_show_chat_message_time,
2605 N_("Show time for each chat message"),
2606 N_("If this option is enabled then all chat messages "
2607 "will be prefixed by a time string of the form "
2608 "[hour:minute:second]."),
2609 COC_INTERFACE, GUI_GTK3, FALSE, NULL),
2610 GEN_BOOL_OPTION(gui_gtk3_new_messages_go_to_top,
2611 N_("New message events go to top of list"),
2612 N_("If this option is enabled, new events in the "
2613 "message window will appear at the top of the list, "
2614 "rather than being appended at the bottom."),
2615 COC_INTERFACE, GUI_GTK3, FALSE, NULL),
2616 GEN_BOOL_OPTION(gui_gtk3_show_message_window_buttons,
2617 N_("Show extra message window buttons"),
2618 N_("If this option is enabled, there will be two "
2619 "buttons displayed in the message window for "
2620 "inspecting a city and going to a location. If this "
2621 "option is disabled, these buttons will not appear "
2622 "(you can still double-click with the left mouse "
2623 "button or right-click on a row to inspect or goto "
2624 "respectively). This option will only take effect "
2625 "once the message window is closed and reopened."),
2626 COC_INTERFACE, GUI_GTK3, TRUE, NULL),
2627 GEN_BOOL_OPTION(gui_gtk3_metaserver_tab_first,
2628 N_("Metaserver tab first in network page"),
2629 N_("If this option is enabled, the metaserver tab will "
2630 "be the first notebook tab in the network page. This "
2631 "option requires a restart in order to take effect."),
2632 COC_NETWORK, GUI_GTK3, FALSE, NULL),
2633 GEN_BOOL_OPTION(gui_gtk3_allied_chat_only,
2634 N_("Plain chat messages are sent to allies only"),
2635 N_("If this option is enabled, then plain messages "
2636 "typed into the chat entry while the game is "
2637 "running will only be sent to your allies. "
2638 "Otherwise plain messages will be sent as "
2639 "public chat messages. To send a public chat "
2640 "message with this option enabled, prefix the "
2641 "message with a single colon ':'. This option "
2642 "can also be set using a toggle button beside "
2643 "the chat entry (only visible in multiplayer "
2644 "games)."),
2645 COC_INTERFACE, GUI_GTK3, FALSE, NULL),
2646 GEN_ENUM_OPTION(gui_gtk3_message_chat_location,
2647 N_("Messages and Chat reports location"),
2648 /* TRANS: The strings used in the UI for 'Split' etc are
2649 * tagged 'gui_gtk2/gtk3_message_chat_location' */
2650 N_("Controls where the Messages and Chat reports "
2651 "appear relative to the main view containing the map.\n"
2652 "'Split' allows all three to be seen simultaneously, "
2653 "which is best for multiplayer, but requires a large "
2654 "window to be usable.\n"
2655 "'Separate' puts Messages and Chat in a notebook "
2656 "separate from the main view, so that one of them "
2657 "can always be seen alongside the main view.\n"
2658 "'Merged' makes the Messages and Chat reports into "
2659 "tabs alongside the map and other reports; this "
2660 "allows a larger map view on small screens.\n"
2661 "This option requires a restart in order to take "
2662 "effect."), COC_INTERFACE, GUI_GTK3,
2663 GUI_GTK_MSGCHAT_MERGED /* Ignored! See options_load(). */,
2664 gui_gtk_message_chat_location_name, NULL),
2665 GEN_BOOL_OPTION(gui_gtk3_small_display_layout,
2666 N_("Arrange widgets for small displays"),
2667 N_("If this option is enabled, widgets in the main "
2668 "window will be arranged so that they take up the "
2669 "least amount of total screen space. Specifically, "
2670 "the left panel containing the overview, player "
2671 "status, and the unit information box will be "
2672 "extended over the entire left side of the window. "
2673 "This option requires a restart in order to take "
2674 "effect."), COC_INTERFACE, GUI_GTK3, TRUE, NULL),
2675 GEN_BOOL_OPTION(gui_gtk3_mouse_over_map_focus,
2676 N_("Mouse over the map widget selects it automatically"),
2677 N_("If this option is enabled, then the map will be "
2678 "focused when the mouse hovers over it."),
2679 COC_INTERFACE, GUI_GTK3, FALSE, NULL),
2680 GEN_BOOL_OPTION(gui_gtk3_chatline_autocompletion,
2681 N_("Player or user name autocompletion"),
2682 N_("If this option is turned on, the tabulation key "
2683 "will be used in the chatline to complete the word you "
2684 "are typing with the name of a player or a user."),
2685 COC_INTERFACE, GUI_GTK3, TRUE, NULL),
2686 GEN_INT_OPTION(gui_gtk3_citydlg_xsize,
2687 N_("Width of the city dialog"),
2688 N_("This value is only used if the width of the city "
2689 "dialog is saved."),
2690 COC_INTERFACE, GUI_GTK3, GUI_GTK3_CITYDLG_DEFAULT_XSIZE,
2691 GUI_GTK3_CITYDLG_MIN_XSIZE, GUI_GTK3_CITYDLG_MAX_XSIZE,
2692 NULL),
2693 GEN_INT_OPTION(gui_gtk3_citydlg_ysize,
2694 N_("Height of the city dialog"),
2695 N_("This value is only used if the height of the city "
2696 "dialog is saved."),
2697 COC_INTERFACE, GUI_GTK3, GUI_GTK3_CITYDLG_DEFAULT_YSIZE,
2698 GUI_GTK3_CITYDLG_MIN_YSIZE, GUI_GTK3_CITYDLG_MAX_YSIZE,
2699 NULL),
2700 GEN_ENUM_OPTION(gui_gtk3_popup_tech_help,
2701 N_("Popup tech help when gained"),
2702 N_("Controls if tech help should be opened when "
2703 "new tech has been gained.\n"
2704 "'Ruleset' means that behavior suggested by "
2705 "current ruleset is used."), COC_INTERFACE, GUI_GTK3,
2706 GUI_POPUP_TECH_HELP_RULESET,
2707 gui_popup_tech_help_name, NULL),
2708 GEN_INT_OPTION(gui_gtk3_governor_range_min,
2709 N_("Minimum surplus for a governor"),
2710 N_("The lower limit of the range for requesting surpluses "
2711 "from the governor."),
2712 COC_INTERFACE, GUI_GTK3, GUI_GTK3_GOV_RANGE_MIN_DEFAULT,
2713 GUI_GTK3_GOV_RANGE_MIN_MIN, GUI_GTK3_GOV_RANGE_MIN_MAX,
2714 NULL),
2715 GEN_INT_OPTION(gui_gtk3_governor_range_max,
2716 N_("Maximum surplus for a governor"),
2717 N_("The higher limit of the range for requesting surpluses "
2718 "from the governor."),
2719 COC_INTERFACE, GUI_GTK3, GUI_GTK3_GOV_RANGE_MAX_DEFAULT,
2720 GUI_GTK3_GOV_RANGE_MAX_MIN, GUI_GTK3_GOV_RANGE_MAX_MAX,
2721 NULL),
2722 GEN_FONT_OPTION(gui_gtk3_font_city_label, "city_label",
2723 N_("City Label"),
2724 N_("This font is used to display the city labels on city "
2725 "dialogs."),
2726 COC_FONT, GUI_GTK3,
2727 "Monospace 8", font_changed_callback),
2728 GEN_FONT_OPTION(gui_gtk3_font_notify_label, "notify_label",
2729 N_("Notify Label"),
2730 N_("This font is used to display server reports such "
2731 "as the demographic report or historian publications."),
2732 COC_FONT, GUI_GTK3,
2733 "Monospace Bold 9", font_changed_callback),
2734 GEN_FONT_OPTION(gui_gtk3_font_spaceship_label, "spaceship_label",
2735 N_("Spaceship Label"),
2736 N_("This font is used to display the spaceship widgets."),
2737 COC_FONT, GUI_GTK3,
2738 "Monospace 8", font_changed_callback),
2739 GEN_FONT_OPTION(gui_gtk3_font_help_label, "help_label",
2740 N_("Help Label"),
2741 N_("This font is used to display the help headers in the "
2742 "help window."),
2743 COC_FONT, GUI_GTK3,
2744 "Sans Bold 10", font_changed_callback),
2745 GEN_FONT_OPTION(gui_gtk3_font_help_link, "help_link",
2746 N_("Help Link"),
2747 N_("This font is used to display the help links in the "
2748 "help window."),
2749 COC_FONT, GUI_GTK3,
2750 "Sans 9", font_changed_callback),
2751 GEN_FONT_OPTION(gui_gtk3_font_help_text, "help_text",
2752 N_("Help Text"),
2753 N_("This font is used to display the help body text in "
2754 "the help window."),
2755 COC_FONT, GUI_GTK3,
2756 "Monospace 8", font_changed_callback),
2757 GEN_FONT_OPTION(gui_gtk3_font_chatline, "chatline",
2758 N_("Chatline Area"),
2759 N_("This font is used to display the text in the "
2760 "chatline area."),
2761 COC_FONT, GUI_GTK3,
2762 "Monospace 8", font_changed_callback),
2763 GEN_FONT_OPTION(gui_gtk3_font_beta_label, "beta_label",
2764 N_("Beta Label"),
2765 N_("This font is used to display the beta label."),
2766 COC_FONT, GUI_GTK3,
2767 "Sans Italic 10", font_changed_callback),
2768 GEN_FONT_OPTION(gui_gtk3_font_small, "small_font",
2769 N_("Small Font"),
2770 N_("This font is used for any small font request. For "
2771 "example, it is used for display the building lists "
2772 "in the city dialog, the Economy report or the Units "
2773 "report."),
2774 COC_FONT, GUI_GTK3,
2775 "Sans 9", NULL),
2776 GEN_FONT_OPTION(gui_gtk3_font_comment_label, "comment_label",
2777 N_("Comment Label"),
2778 N_("This font is used to display comment labels, such as "
2779 "in the governor page of the city dialogs."),
2780 COC_FONT, GUI_GTK3,
2781 "Sans Italic 9", font_changed_callback),
2782 GEN_FONT_OPTION(gui_gtk3_font_city_names, "city_names",
2783 N_("City Names"),
2784 N_("This font is used to the display the city names "
2785 "on the map."),
2786 COC_FONT, GUI_GTK3,
2787 "Sans Bold 10", NULL),
2788 GEN_FONT_OPTION(gui_gtk3_font_city_productions, "city_productions",
2789 N_("City Productions"),
2790 N_("This font is used to the display the city production "
2791 "names on the map."),
2792 COC_FONT, GUI_GTK3,
2793 "Serif 10", NULL),
2794 GEN_FONT_OPTION(gui_gtk3_font_reqtree_text, "reqtree_text",
2795 N_("Requirement Tree"),
2796 N_("This font is used to the display the requirement tree "
2797 "in the Research report."),
2798 COC_FONT, GUI_GTK3,
2799 "Serif 10", NULL),
2801 /* gui-gtk-3.22 client specific options. */
2802 GEN_BOOL_OPTION(gui_gtk3_22_fullscreen, N_("Fullscreen"),
2803 N_("If this option is set the client will use the "
2804 "whole screen area for drawing."),
2805 COC_INTERFACE, GUI_GTK3_22, FALSE, NULL),
2806 GEN_BOOL_OPTION(gui_gtk3_22_map_scrollbars, N_("Show map scrollbars"),
2807 N_("Disable this option to hide the scrollbars on the "
2808 "map view."),
2809 COC_INTERFACE, GUI_GTK3_22, FALSE, NULL),
2810 GEN_BOOL_OPTION(gui_gtk3_22_dialogs_on_top, N_("Keep dialogs on top"),
2811 N_("If this option is set then dialog windows will always "
2812 "remain in front of the main Freeciv window. "
2813 "Disabling this has no effect in fullscreen mode."),
2814 COC_INTERFACE, GUI_GTK3_22, TRUE, NULL),
2815 GEN_BOOL_OPTION(gui_gtk3_22_show_task_icons, N_("Show worklist task icons"),
2816 N_("Disabling this will turn off the unit and building "
2817 "icons in the worklist dialog and the production "
2818 "tab of the city dialog."),
2819 COC_GRAPHICS, GUI_GTK3_22, TRUE, NULL),
2820 GEN_BOOL_OPTION(gui_gtk3_22_enable_tabs, N_("Enable status report tabs"),
2821 N_("If this option is enabled then report dialogs will "
2822 "be shown as separate tabs rather than in popup "
2823 "dialogs."),
2824 COC_INTERFACE, GUI_GTK3_22, TRUE, NULL),
2825 GEN_BOOL_OPTION(gui_gtk3_22_show_chat_message_time,
2826 N_("Show time for each chat message"),
2827 N_("If this option is enabled then all chat messages "
2828 "will be prefixed by a time string of the form "
2829 "[hour:minute:second]."),
2830 COC_INTERFACE, GUI_GTK3_22, FALSE, NULL),
2831 GEN_BOOL_OPTION(gui_gtk3_22_new_messages_go_to_top,
2832 N_("New message events go to top of list"),
2833 N_("If this option is enabled, new events in the "
2834 "message window will appear at the top of the list, "
2835 "rather than being appended at the bottom."),
2836 COC_INTERFACE, GUI_GTK3_22, FALSE, NULL),
2837 GEN_BOOL_OPTION(gui_gtk3_22_show_message_window_buttons,
2838 N_("Show extra message window buttons"),
2839 N_("If this option is enabled, there will be two "
2840 "buttons displayed in the message window for "
2841 "inspecting a city and going to a location. If this "
2842 "option is disabled, these buttons will not appear "
2843 "(you can still double-click with the left mouse "
2844 "button or right-click on a row to inspect or goto "
2845 "respectively). This option will only take effect "
2846 "once the message window is closed and reopened."),
2847 COC_INTERFACE, GUI_GTK3_22, TRUE, NULL),
2848 GEN_BOOL_OPTION(gui_gtk3_22_metaserver_tab_first,
2849 N_("Metaserver tab first in network page"),
2850 N_("If this option is enabled, the metaserver tab will "
2851 "be the first notebook tab in the network page. This "
2852 "option requires a restart in order to take effect."),
2853 COC_NETWORK, GUI_GTK3_22, FALSE, NULL),
2854 GEN_BOOL_OPTION(gui_gtk3_22_allied_chat_only,
2855 N_("Plain chat messages are sent to allies only"),
2856 N_("If this option is enabled, then plain messages "
2857 "typed into the chat entry while the game is "
2858 "running will only be sent to your allies. "
2859 "Otherwise plain messages will be sent as "
2860 "public chat messages. To send a public chat "
2861 "message with this option enabled, prefix the "
2862 "message with a single colon ':'. This option "
2863 "can also be set using a toggle button beside "
2864 "the chat entry (only visible in multiplayer "
2865 "games)."),
2866 COC_INTERFACE, GUI_GTK3_22, FALSE, NULL),
2867 GEN_ENUM_OPTION(gui_gtk3_22_message_chat_location,
2868 N_("Messages and Chat reports location"),
2869 /* TRANS: The strings used in the UI for 'Split' etc are
2870 * tagged 'gui_gtk2/gtk3_message_chat_location' */
2871 N_("Controls where the Messages and Chat reports "
2872 "appear relative to the main view containing the map.\n"
2873 "'Split' allows all three to be seen simultaneously, "
2874 "which is best for multiplayer, but requires a large "
2875 "window to be usable.\n"
2876 "'Separate' puts Messages and Chat in a notebook "
2877 "separate from the main view, so that one of them "
2878 "can always be seen alongside the main view.\n"
2879 "'Merged' makes the Messages and Chat reports into "
2880 "tabs alongside the map and other reports; this "
2881 "allows a larger map view on small screens.\n"
2882 "This option requires a restart in order to take "
2883 "effect."), COC_INTERFACE, GUI_GTK3_22,
2884 GUI_GTK_MSGCHAT_MERGED /* Ignored! See options_load(). */,
2885 gui_gtk_message_chat_location_name, NULL),
2886 GEN_BOOL_OPTION(gui_gtk3_22_small_display_layout,
2887 N_("Arrange widgets for small displays"),
2888 N_("If this option is enabled, widgets in the main "
2889 "window will be arranged so that they take up the "
2890 "least amount of total screen space. Specifically, "
2891 "the left panel containing the overview, player "
2892 "status, and the unit information box will be "
2893 "extended over the entire left side of the window. "
2894 "This option requires a restart in order to take "
2895 "effect."), COC_INTERFACE, GUI_GTK3_22, TRUE, NULL),
2896 GEN_BOOL_OPTION(gui_gtk3_22_mouse_over_map_focus,
2897 N_("Mouse over the map widget selects it automatically"),
2898 N_("If this option is enabled, then the map will be "
2899 "focused when the mouse hovers over it."),
2900 COC_INTERFACE, GUI_GTK3_22, FALSE, NULL),
2901 GEN_BOOL_OPTION(gui_gtk3_22_chatline_autocompletion,
2902 N_("Player or user name autocompletion"),
2903 N_("If this option is turned on, the tabulation key "
2904 "will be used in the chatline to complete the word you "
2905 "are typing with the name of a player or a user."),
2906 COC_INTERFACE, GUI_GTK3_22, TRUE, NULL),
2907 GEN_INT_OPTION(gui_gtk3_22_citydlg_xsize,
2908 N_("Width of the city dialog"),
2909 N_("This value is only used if the width of the city "
2910 "dialog is saved."),
2911 COC_INTERFACE, GUI_GTK3_22, GUI_GTK3_22_CITYDLG_DEFAULT_XSIZE,
2912 GUI_GTK3_22_CITYDLG_MIN_XSIZE, GUI_GTK3_22_CITYDLG_MAX_XSIZE,
2913 NULL),
2914 GEN_INT_OPTION(gui_gtk3_22_citydlg_ysize,
2915 N_("Height of the city dialog"),
2916 N_("This value is only used if the height of the city "
2917 "dialog is saved."),
2918 COC_INTERFACE, GUI_GTK3_22, GUI_GTK3_22_CITYDLG_DEFAULT_YSIZE,
2919 GUI_GTK3_22_CITYDLG_MIN_YSIZE, GUI_GTK3_22_CITYDLG_MAX_YSIZE,
2920 NULL),
2921 GEN_ENUM_OPTION(gui_gtk3_22_popup_tech_help,
2922 N_("Popup tech help when gained"),
2923 N_("Controls if tech help should be opened when "
2924 "new tech has been gained.\n"
2925 "'Ruleset' means that behavior suggested by "
2926 "current ruleset is used."), COC_INTERFACE, GUI_GTK3_22,
2927 GUI_POPUP_TECH_HELP_RULESET,
2928 gui_popup_tech_help_name, NULL),
2929 GEN_INT_OPTION(gui_gtk3_22_governor_range_min,
2930 N_("Minimum surplus for a governor"),
2931 N_("The lower limit of the range for requesting surpluses "
2932 "from the governor."),
2933 COC_INTERFACE, GUI_GTK3_22, GUI_GTK3_22_GOV_RANGE_MIN_DEFAULT,
2934 GUI_GTK3_22_GOV_RANGE_MIN_MIN, GUI_GTK3_22_GOV_RANGE_MIN_MAX,
2935 NULL),
2936 GEN_INT_OPTION(gui_gtk3_22_governor_range_max,
2937 N_("Maximum surplus for a governor"),
2938 N_("The higher limit of the range for requesting surpluses "
2939 "from the governor."),
2940 COC_INTERFACE, GUI_GTK3_22, GUI_GTK3_22_GOV_RANGE_MAX_DEFAULT,
2941 GUI_GTK3_22_GOV_RANGE_MAX_MIN, GUI_GTK3_22_GOV_RANGE_MAX_MAX,
2942 NULL),
2943 GEN_FONT_OPTION(gui_gtk3_22_font_city_label, "city_label",
2944 N_("City Label"),
2945 N_("This font is used to display the city labels on city "
2946 "dialogs."),
2947 COC_FONT, GUI_GTK3_22,
2948 "Monospace 8", font_changed_callback),
2949 GEN_FONT_OPTION(gui_gtk3_22_font_notify_label, "notify_label",
2950 N_("Notify Label"),
2951 N_("This font is used to display server reports such "
2952 "as the demographic report or historian publications."),
2953 COC_FONT, GUI_GTK3_22,
2954 "Monospace Bold 9", font_changed_callback),
2955 GEN_FONT_OPTION(gui_gtk3_22_font_spaceship_label, "spaceship_label",
2956 N_("Spaceship Label"),
2957 N_("This font is used to display the spaceship widgets."),
2958 COC_FONT, GUI_GTK3_22,
2959 "Monospace 8", font_changed_callback),
2960 GEN_FONT_OPTION(gui_gtk3_22_font_help_label, "help_label",
2961 N_("Help Label"),
2962 N_("This font is used to display the help headers in the "
2963 "help window."),
2964 COC_FONT, GUI_GTK3_22,
2965 "Sans Bold 10", font_changed_callback),
2966 GEN_FONT_OPTION(gui_gtk3_22_font_help_link, "help_link",
2967 N_("Help Link"),
2968 N_("This font is used to display the help links in the "
2969 "help window."),
2970 COC_FONT, GUI_GTK3_22,
2971 "Sans 9", font_changed_callback),
2972 GEN_FONT_OPTION(gui_gtk3_22_font_help_text, "help_text",
2973 N_("Help Text"),
2974 N_("This font is used to display the help body text in "
2975 "the help window."),
2976 COC_FONT, GUI_GTK3_22,
2977 "Monospace 8", font_changed_callback),
2978 GEN_FONT_OPTION(gui_gtk3_22_font_chatline, "chatline",
2979 N_("Chatline Area"),
2980 N_("This font is used to display the text in the "
2981 "chatline area."),
2982 COC_FONT, GUI_GTK3_22,
2983 "Monospace 8", font_changed_callback),
2984 GEN_FONT_OPTION(gui_gtk3_22_font_beta_label, "beta_label",
2985 N_("Beta Label"),
2986 N_("This font is used to display the beta label."),
2987 COC_FONT, GUI_GTK3_22,
2988 "Sans Italic 10", font_changed_callback),
2989 GEN_FONT_OPTION(gui_gtk3_22_font_small, "small_font",
2990 N_("Small Font"),
2991 N_("This font is used for any small font request. For "
2992 "example, it is used for display the building lists "
2993 "in the city dialog, the Economy report or the Units "
2994 "report."),
2995 COC_FONT, GUI_GTK3_22,
2996 "Sans 9", NULL),
2997 GEN_FONT_OPTION(gui_gtk3_22_font_comment_label, "comment_label",
2998 N_("Comment Label"),
2999 N_("This font is used to display comment labels, such as "
3000 "in the governor page of the city dialogs."),
3001 COC_FONT, GUI_GTK3_22,
3002 "Sans Italic 9", font_changed_callback),
3003 GEN_FONT_OPTION(gui_gtk3_22_font_city_names, "city_names",
3004 N_("City Names"),
3005 N_("This font is used to the display the city names "
3006 "on the map."),
3007 COC_FONT, GUI_GTK3_22,
3008 "Sans Bold 10", NULL),
3009 GEN_FONT_OPTION(gui_gtk3_22_font_city_productions, "city_productions",
3010 N_("City Productions"),
3011 N_("This font is used to the display the city production "
3012 "names on the map."),
3013 COC_FONT, GUI_GTK3_22,
3014 "Serif 10", NULL),
3015 GEN_FONT_OPTION(gui_gtk3_22_font_reqtree_text, "reqtree_text",
3016 N_("Requirement Tree"),
3017 N_("This font is used to the display the requirement tree "
3018 "in the Research report."),
3019 COC_FONT, GUI_GTK3_22,
3020 "Serif 10", NULL),
3022 /* gui-sdl client specific options. */
3023 GEN_BOOL_OPTION(gui_sdl_fullscreen, N_("Fullscreen"),
3024 N_("If this option is set the client will use the "
3025 "whole screen area for drawing."),
3026 COC_INTERFACE, GUI_SDL, FALSE, NULL),
3027 GEN_VIDEO_OPTION(gui_sdl_screen, N_("Screen resolution"),
3028 N_("This option controls the resolution of the "
3029 "selected screen."),
3030 COC_INTERFACE, GUI_SDL, 640, 480, NULL),
3031 GEN_BOOL_OPTION(gui_sdl_do_cursor_animation, N_("Do cursor animation"),
3032 N_("If this option is disabled, the cursor will "
3033 "always be displayed as static."),
3034 COC_INTERFACE, GUI_SDL, TRUE, NULL),
3035 GEN_BOOL_OPTION(gui_sdl_use_color_cursors, N_("Use color cursors"),
3036 N_("If this option is disabled, the cursor will "
3037 "always be displayed in black and white."),
3038 COC_INTERFACE, GUI_SDL, TRUE, NULL),
3040 /* gui-sdl2 client specific options. */
3041 GEN_BOOL_OPTION(gui_sdl2_fullscreen, N_("Fullscreen"),
3042 N_("If this option is set the client will use the "
3043 "whole screen area for drawing."),
3044 COC_INTERFACE, GUI_SDL2, FALSE, NULL),
3045 GEN_VIDEO_OPTION(gui_sdl2_screen, N_("Screen resolution"),
3046 N_("This option controls the resolution of the "
3047 "selected screen."),
3048 COC_INTERFACE, GUI_SDL2, 640, 480, NULL),
3049 GEN_BOOL_OPTION(gui_sdl2_swrenderer, N_("Use software rendering"),
3050 N_("Usually hardware rendering is used when possible. "
3051 "With this option set, software rendering is always used."),
3052 COC_GRAPHICS, GUI_SDL2, FALSE, NULL),
3053 GEN_BOOL_OPTION(gui_sdl2_do_cursor_animation, N_("Do cursor animation"),
3054 N_("If this option is disabled, the cursor will "
3055 "always be displayed as static."),
3056 COC_INTERFACE, GUI_SDL2, TRUE, NULL),
3057 GEN_BOOL_OPTION(gui_sdl2_use_color_cursors, N_("Use color cursors"),
3058 N_("If this option is disabled, the cursor will "
3059 "always be displayed in black and white."),
3060 COC_INTERFACE, GUI_SDL2, TRUE, NULL),
3062 /* gui-qt client specific options. */
3063 GEN_BOOL_OPTION(gui_qt_fullscreen, N_("Fullscreen"),
3064 N_("If this option is set the client will use the "
3065 "whole screen area for drawing."),
3066 COC_INTERFACE, GUI_QT, FALSE, NULL),
3067 GEN_BOOL_OPTION(gui_qt_show_titlebar, N_("Show titlebar"),
3068 N_("If this option is set the client will show a titlebar. "
3069 "If disabled, then no titlebar will be shown, and "
3070 "minimize/maximize/etc buttons will be placed on the "
3071 "menu bar."),
3072 COC_INTERFACE, GUI_QT, TRUE, NULL),
3073 GEN_FONT_OPTION(gui_qt_font_city_label, "city_label",
3074 N_("City Label"),
3075 N_("This font is used to display the city labels on city "
3076 "dialogs."),
3077 COC_FONT, GUI_QT,
3078 "Monospace,8,-1,5,50,0,0,0,0,0", font_changed_callback),
3079 GEN_FONT_OPTION(gui_qt_font_default, "default_font",
3080 N_("Default font"),
3081 N_("This is default font"),
3082 COC_FONT, GUI_QT,
3083 "Sans Serif,10,-1,5,75,0,0,0,0,0", font_changed_callback),
3084 GEN_FONT_OPTION(gui_qt_font_notify_label, "notify_label",
3085 N_("Notify Label"),
3086 N_("This font is used to display server reports such "
3087 "as the demographic report or historian publications."),
3088 COC_FONT, GUI_QT,
3089 "Monospace,9,-1,5,75,0,0,0,0,0", font_changed_callback),
3090 GEN_FONT_OPTION(gui_qt_font_spaceship_label, "spaceship_label",
3091 N_("Spaceship Label"),
3092 N_("This font is used to display the spaceship widgets."),
3093 COC_FONT, GUI_QT,
3094 "Monospace,8,-1,5,50,0,0,0,0,0", font_changed_callback),
3095 GEN_FONT_OPTION(gui_qt_font_help_label, "help_label",
3096 N_("Help Label"),
3097 N_("This font is used to display the help labels in the "
3098 "help window."),
3099 COC_FONT, GUI_QT,
3100 "Sans Serif,9,-1,5,50,0,0,0,0,0", font_changed_callback),
3101 GEN_FONT_OPTION(gui_qt_font_help_link, "help_link",
3102 N_("Help Link"),
3103 N_("This font is used to display the help links in the "
3104 "help window."),
3105 COC_FONT, GUI_QT,
3106 "Sans Serif,9,-1,5,50,0,0,0,0,0", font_changed_callback),
3107 GEN_FONT_OPTION(gui_qt_font_help_text, "help_text",
3108 N_("Help Text"),
3109 N_("This font is used to display the help body text in "
3110 "the help window."),
3111 COC_FONT, GUI_QT,
3112 "Monospace,8,-1,5,50,0,0,0,0,0", font_changed_callback),
3113 GEN_FONT_OPTION(gui_qt_font_help_title, "help_title",
3114 N_("Help Title"),
3115 N_("This font is used to display the help title in "
3116 "the help window."),
3117 COC_FONT, GUI_QT,
3118 "Sans Serif,10,-1,5,75,0,0,0,0,0", font_changed_callback),
3119 GEN_FONT_OPTION(gui_qt_font_chatline, "chatline",
3120 N_("Chatline Area"),
3121 N_("This font is used to display the text in the "
3122 "chatline area."),
3123 COC_FONT, GUI_QT,
3124 "Monospace,8,-1,5,50,0,0,0,0,0", font_changed_callback),
3125 GEN_FONT_OPTION(gui_qt_font_beta_label, "beta_label",
3126 N_("Beta Label"),
3127 N_("This font is used to display the beta label."),
3128 COC_FONT, GUI_QT,
3129 "Sans Serif,10,-1,5,50,1,0,0,0,0", font_changed_callback),
3130 GEN_FONT_OPTION(gui_qt_font_small, "small_font",
3131 N_("Small Font"),
3132 N_("This font is used for any small font request. For "
3133 "example, it is used for display the building lists "
3134 "in the city dialog, the Economy report or the Units "
3135 "report."),
3136 COC_FONT, GUI_QT,
3137 "Sans Serif,9,-1,5,50,0,0,0,0,0", font_changed_callback),
3138 GEN_FONT_OPTION(gui_qt_font_comment_label, "comment_label",
3139 N_("Comment Label"),
3140 N_("This font is used to display comment labels, such as "
3141 "in the governor page of the city dialogs."),
3142 COC_FONT, GUI_QT,
3143 "Sans Serif,9,-1,5,50,1,0,0,0,0", font_changed_callback),
3144 GEN_FONT_OPTION(gui_qt_font_city_names, "city_names",
3145 N_("City Names"),
3146 N_("This font is used to the display the city names "
3147 "on the map."),
3148 COC_FONT, GUI_QT,
3149 "Sans Serif,10,-1,5,75,0,0,0,0,0", font_changed_callback),
3150 GEN_FONT_OPTION(gui_qt_font_city_productions, "city_productions",
3151 N_("City Productions"),
3152 N_("This font is used to the display the city production "
3153 "names on the map."),
3154 COC_FONT, GUI_QT,
3155 "Sans Serif,10,-1,5,50,1,0,0,0,0", font_changed_callback),
3156 GEN_FONT_OPTION(gui_qt_font_reqtree_text, "reqtree_text",
3157 N_("Requirement Tree"),
3158 N_("This font is used to the display the requirement tree "
3159 "in the Research report."),
3160 COC_FONT, GUI_QT,
3161 "Sans Serif,10,-1,5,50,1,0,0,0,0", font_changed_callback),
3162 GEN_BOOL_OPTION(gui_qt_show_preview, N_("Show savegame information"),
3163 N_("If this option is set the client will show "
3164 "information and map preview about current savegame "),
3165 COC_GRAPHICS, GUI_QT, TRUE, NULL),
3166 GEN_BOOL_OPTION(gui_qt_sidebar_left, N_("Sidebar position"),
3167 N_("If this option is set sidebar will be on left, "
3168 "otherwise it will on right side of map"),
3169 COC_INTERFACE, GUI_QT, TRUE, NULL),
3170 GEN_STR_OPTION(gui_qt_wakeup_text,
3171 N_("Wake up sequence"),
3172 N_("String which will trigger sound in pregame page, "
3173 "%1 stands for nick"),
3174 COC_INTERFACE, GUI_QT, "Wake up %1", NULL, 0)
3177 static const int client_options_num = ARRAY_SIZE(client_options);
3179 /* Iteration loop, including invalid options for the current gui type. */
3180 #define client_options_iterate_all(poption) \
3182 const struct client_option *const poption##_max = \
3183 client_options + client_options_num; \
3184 struct client_option *client_##poption = client_options; \
3185 struct option *poption; \
3186 for (; client_##poption < poption##_max; client_##poption++) { \
3187 poption = OPTION(client_##poption);
3189 #define client_options_iterate_all_end \
3194 /****************************************************************************
3195 Returns the next valid option pointer for the current gui type.
3196 ****************************************************************************/
3197 static struct client_option *
3198 client_option_next_valid(struct client_option *poption)
3200 const struct client_option *const max =
3201 client_options + client_options_num;
3202 const enum gui_type our_type = get_gui_type();
3204 while (poption < max
3205 && poption->specific != GUI_STUB
3206 && poption->specific != our_type) {
3207 poption++;
3210 return (poption < max ? poption : NULL);
3213 /****************************************************************************
3214 Returns the option corresponding to this id.
3215 ****************************************************************************/
3216 static struct option *client_optset_option_by_number(int id)
3218 if (0 > id || id > client_options_num) {
3219 return NULL;
3221 return OPTION(client_options + id);
3224 /****************************************************************************
3225 Returns the first valid option pointer for the current gui type.
3226 ****************************************************************************/
3227 static struct option *client_optset_option_first(void)
3229 return OPTION(client_option_next_valid(client_options));
3232 /****************************************************************************
3233 Returns the number of client option categories.
3234 ****************************************************************************/
3235 static int client_optset_category_number(void)
3237 return COC_MAX;
3240 /****************************************************************************
3241 Returns the name (translated) of the option class.
3242 ****************************************************************************/
3243 static const char *client_optset_category_name(int category)
3245 switch (category) {
3246 case COC_GRAPHICS:
3247 return _("Graphics");
3248 case COC_OVERVIEW:
3249 /* TRANS: Options section for overview map (mini-map) */
3250 return Q_("?map:Overview");
3251 case COC_SOUND:
3252 return _("Sound");
3253 case COC_INTERFACE:
3254 return _("Interface");
3255 case COC_MAPIMG:
3256 return _("Map Image");
3257 case COC_NETWORK:
3258 return _("Network");
3259 case COC_FONT:
3260 return _("Font");
3261 case COC_MAX:
3262 break;
3265 log_error("%s: invalid option category number %d.",
3266 __FUNCTION__, category);
3267 return NULL;
3270 /***************************************************************************
3271 Returns the number of this client option.
3272 ****************************************************************************/
3273 static int client_option_number(const struct option *poption)
3275 return CLIENT_OPTION(poption) - client_options;
3278 /****************************************************************************
3279 Returns the name of this client option.
3280 ****************************************************************************/
3281 static const char *client_option_name(const struct option *poption)
3283 return CLIENT_OPTION(poption)->name;
3286 /****************************************************************************
3287 Returns the description of this client option.
3288 ****************************************************************************/
3289 static const char *client_option_description(const struct option *poption)
3291 return _(CLIENT_OPTION(poption)->description);
3294 /****************************************************************************
3295 Returns the help text for this client option.
3296 ****************************************************************************/
3297 static const char *client_option_help_text(const struct option *poption)
3299 return _(CLIENT_OPTION(poption)->help_text);
3302 /****************************************************************************
3303 Returns the category of this client option.
3304 ****************************************************************************/
3305 static int client_option_category(const struct option *poption)
3307 return CLIENT_OPTION(poption)->category;
3310 /****************************************************************************
3311 Returns TRUE if this client option can be modified.
3312 ****************************************************************************/
3313 static bool client_option_is_changeable(const struct option *poption)
3315 return TRUE;
3318 /****************************************************************************
3319 Returns the next valid option pointer for the current gui type.
3320 ****************************************************************************/
3321 static struct option *client_option_next(const struct option *poption)
3323 return OPTION(client_option_next_valid(CLIENT_OPTION(poption) + 1));
3326 /****************************************************************************
3327 Returns the value of this client option of type OT_BOOLEAN.
3328 ****************************************************************************/
3329 static bool client_option_bool_get(const struct option *poption)
3331 return *(CLIENT_OPTION(poption)->boolean.pvalue);
3334 /****************************************************************************
3335 Returns the default value of this client option of type OT_BOOLEAN.
3336 ****************************************************************************/
3337 static bool client_option_bool_def(const struct option *poption)
3339 return CLIENT_OPTION(poption)->boolean.def;
3342 /****************************************************************************
3343 Set the value of this client option of type OT_BOOLEAN. Returns TRUE if
3344 the value changed.
3345 ****************************************************************************/
3346 static bool client_option_bool_set(struct option *poption, bool val)
3348 struct client_option *pcoption = CLIENT_OPTION(poption);
3350 if (*pcoption->boolean.pvalue == val) {
3351 return FALSE;
3354 *pcoption->boolean.pvalue = val;
3355 return TRUE;
3358 /****************************************************************************
3359 Returns the value of this client option of type OT_INTEGER.
3360 ****************************************************************************/
3361 static int client_option_int_get(const struct option *poption)
3363 return *(CLIENT_OPTION(poption)->integer.pvalue);
3366 /****************************************************************************
3367 Returns the default value of this client option of type OT_INTEGER.
3368 ****************************************************************************/
3369 static int client_option_int_def(const struct option *poption)
3371 return CLIENT_OPTION(poption)->integer.def;
3374 /****************************************************************************
3375 Returns the minimal value for this client option of type OT_INTEGER.
3376 ****************************************************************************/
3377 static int client_option_int_min(const struct option *poption)
3379 return CLIENT_OPTION(poption)->integer.min;
3382 /****************************************************************************
3383 Returns the maximal value for this client option of type OT_INTEGER.
3384 ****************************************************************************/
3385 static int client_option_int_max(const struct option *poption)
3387 return CLIENT_OPTION(poption)->integer.max;
3390 /****************************************************************************
3391 Set the value of this client option of type OT_INTEGER. Returns TRUE if
3392 the value changed.
3393 ****************************************************************************/
3394 static bool client_option_int_set(struct option *poption, int val)
3396 struct client_option *pcoption = CLIENT_OPTION(poption);
3398 if (val < pcoption->integer.min
3399 || val > pcoption->integer.max
3400 || *pcoption->integer.pvalue == val) {
3401 return FALSE;
3404 *pcoption->integer.pvalue = val;
3405 return TRUE;
3408 /****************************************************************************
3409 Returns the value of this client option of type OT_STRING.
3410 ****************************************************************************/
3411 static const char *client_option_str_get(const struct option *poption)
3413 return CLIENT_OPTION(poption)->string.pvalue;
3416 /****************************************************************************
3417 Returns the default value of this client option of type OT_STRING.
3418 ****************************************************************************/
3419 static const char *client_option_str_def(const struct option *poption)
3421 return CLIENT_OPTION(poption)->string.def;
3424 /****************************************************************************
3425 Returns the possible string values of this client option of type
3426 OT_STRING.
3427 ****************************************************************************/
3428 static const struct strvec *
3429 client_option_str_values(const struct option *poption)
3431 return (CLIENT_OPTION(poption)->string.val_accessor
3432 ? CLIENT_OPTION(poption)->string.val_accessor(poption) : NULL);
3435 /****************************************************************************
3436 Set the value of this client option of type OT_STRING. Returns TRUE if
3437 the value changed.
3438 ****************************************************************************/
3439 static bool client_option_str_set(struct option *poption, const char *str)
3441 struct client_option *pcoption = CLIENT_OPTION(poption);
3443 if (strlen(str) >= pcoption->string.size
3444 || 0 == strcmp(pcoption->string.pvalue, str)) {
3445 return FALSE;
3448 fc_strlcpy(pcoption->string.pvalue, str, pcoption->string.size);
3449 return TRUE;
3452 /****************************************************************************
3453 Returns the current value of this client option of type OT_ENUM.
3454 ****************************************************************************/
3455 static int client_option_enum_get(const struct option *poption)
3457 return *(CLIENT_OPTION(poption)->enumerator.pvalue);
3460 /****************************************************************************
3461 Returns the default value of this client option of type OT_ENUM.
3462 ****************************************************************************/
3463 static int client_option_enum_def(const struct option *poption)
3465 return CLIENT_OPTION(poption)->enumerator.def;
3468 /****************************************************************************
3469 Returns the possible values of this client option of type OT_ENUM, as
3470 user-visible (translatable but not translated) strings.
3471 ****************************************************************************/
3472 static const struct strvec *
3473 client_option_enum_pretty_names(const struct option *poption)
3475 return CLIENT_OPTION(poption)->enumerator.pretty_names;
3478 /****************************************************************************
3479 Set the value of this client option of type OT_ENUM. Returns TRUE if
3480 the value changed.
3481 ****************************************************************************/
3482 static bool client_option_enum_set(struct option *poption, int val)
3484 struct client_option *pcoption = CLIENT_OPTION(poption);
3486 if (*pcoption->enumerator.pvalue == val
3487 || 0 > val
3488 || val >= strvec_size(pcoption->enumerator.support_names)) {
3489 return FALSE;
3492 *pcoption->enumerator.pvalue = val;
3493 return TRUE;
3496 /****************************************************************************
3497 Returns the "support" name of the value for this client option of type
3498 OT_ENUM (a string suitable for saving in a file).
3499 The prototype must match the 'secfile_enum_name_data_fn_t' type.
3500 ****************************************************************************/
3501 static const char *client_option_enum_secfile_str(secfile_data_t data,
3502 int val)
3504 const struct strvec *names = CLIENT_OPTION(data)->enumerator.support_names;
3506 return (0 <= val && val < strvec_size(names)
3507 ? strvec_get(names, val) : NULL);
3510 #if 0 /* There's no bitwise options currently */
3511 /****************************************************************************
3512 Returns the current value of this client option of type OT_BITWISE.
3513 ****************************************************************************/
3514 static unsigned client_option_bitwise_get(const struct option *poption)
3516 return *(CLIENT_OPTION(poption)->bitwise.pvalue);
3519 /****************************************************************************
3520 Returns the default value of this client option of type OT_BITWISE.
3521 ****************************************************************************/
3522 static unsigned client_option_bitwise_def(const struct option *poption)
3524 return CLIENT_OPTION(poption)->bitwise.def;
3527 /****************************************************************************
3528 Returns the possible values of this client option of type OT_BITWISE, as
3529 user-visible (translatable but not translated) strings.
3530 ****************************************************************************/
3531 static const struct strvec *
3532 client_option_bitwise_pretty_names(const struct option *poption)
3534 return CLIENT_OPTION(poption)->bitwise.pretty_names;
3537 /****************************************************************************
3538 Set the value of this client option of type OT_BITWISE. Returns TRUE if
3539 the value changed.
3540 ****************************************************************************/
3541 static bool client_option_bitwise_set(struct option *poption, unsigned val)
3543 struct client_option *pcoption = CLIENT_OPTION(poption);
3545 if (*pcoption->bitwise.pvalue == val) {
3546 return FALSE;
3549 *pcoption->bitwise.pvalue = val;
3550 return TRUE;
3552 #endif /* 0 */
3554 /****************************************************************************
3555 Returns the "support" name of a single value for this client option of type
3556 OT_BITWISE (a string suitable for saving in a file).
3557 The prototype must match the 'secfile_enum_name_data_fn_t' type.
3558 ****************************************************************************/
3559 static const char *client_option_bitwise_secfile_str(secfile_data_t data,
3560 int val)
3562 const struct strvec *names = CLIENT_OPTION(data)->bitwise.support_names;
3564 return (0 <= val && val < strvec_size(names)
3565 ? strvec_get(names, val) : NULL);
3568 /****************************************************************************
3569 Returns the value of this client option of type OT_FONT.
3570 ****************************************************************************/
3571 static const char *client_option_font_get(const struct option *poption)
3573 return CLIENT_OPTION(poption)->font.pvalue;
3576 /****************************************************************************
3577 Returns the default value of this client option of type OT_FONT.
3578 ****************************************************************************/
3579 static const char *client_option_font_def(const struct option *poption)
3581 return CLIENT_OPTION(poption)->font.def;
3584 /****************************************************************************
3585 Returns the target style name of this client option of type OT_FONT.
3586 ****************************************************************************/
3587 static const char *client_option_font_target(const struct option *poption)
3589 return CLIENT_OPTION(poption)->font.target;
3592 /****************************************************************************
3593 Set the value of this client option of type OT_FONT. Returns TRUE if
3594 the value changed.
3595 ****************************************************************************/
3596 static bool client_option_font_set(struct option *poption, const char *font)
3598 struct client_option *pcoption = CLIENT_OPTION(poption);
3600 if (strlen(font) >= pcoption->font.size
3601 || 0 == strcmp(pcoption->font.pvalue, font)) {
3602 return FALSE;
3605 fc_strlcpy(pcoption->font.pvalue, font, pcoption->font.size);
3606 return TRUE;
3609 /****************************************************************************
3610 Returns the value of this client option of type OT_COLOR.
3611 ****************************************************************************/
3612 static struct ft_color client_option_color_get(const struct option *poption)
3614 return *CLIENT_OPTION(poption)->color.pvalue;
3617 /****************************************************************************
3618 Returns the default value of this client option of type OT_COLOR.
3619 ****************************************************************************/
3620 static struct ft_color client_option_color_def(const struct option *poption)
3622 return CLIENT_OPTION(poption)->color.def;
3625 /****************************************************************************
3626 Set the value of this client option of type OT_COLOR. Returns TRUE if
3627 the value changed.
3628 ****************************************************************************/
3629 static bool client_option_color_set(struct option *poption,
3630 struct ft_color color)
3632 struct ft_color *pcolor = CLIENT_OPTION(poption)->color.pvalue;
3633 bool changed = FALSE;
3635 #define color_set(color_tgt, color) \
3636 if (NULL == color_tgt) { \
3637 if (NULL != color) { \
3638 color_tgt = fc_strdup(color); \
3639 changed = TRUE; \
3641 } else { \
3642 if (NULL == color) { \
3643 free((void *) color_tgt); \
3644 color_tgt = NULL; \
3645 changed = TRUE; \
3646 } else if (0 != strcmp(color_tgt, color)) { \
3647 free((void *) color_tgt); \
3648 color_tgt = fc_strdup(color); \
3649 changed = TRUE; \
3653 color_set(pcolor->foreground, color.foreground);
3654 color_set(pcolor->background, color.background);
3656 #undef color_set
3658 return changed;
3661 /****************************************************************************
3662 Returns the value of this client option of type OT_VIDEO_MODE.
3663 ****************************************************************************/
3664 static struct video_mode
3665 client_option_video_mode_get(const struct option *poption)
3667 return *CLIENT_OPTION(poption)->video_mode.pvalue;
3670 /****************************************************************************
3671 Returns the default value of this client option of type OT_VIDEO_MODE.
3672 ****************************************************************************/
3673 static struct video_mode
3674 client_option_video_mode_def(const struct option *poption)
3676 return CLIENT_OPTION(poption)->video_mode.def;
3679 /****************************************************************************
3680 Set the value of this client option of type OT_VIDEO_MODE. Returns TRUE
3681 if the value changed.
3682 ****************************************************************************/
3683 static bool client_option_video_mode_set(struct option *poption,
3684 struct video_mode mode)
3686 struct client_option *pcoption = CLIENT_OPTION(poption);
3688 if (0 == memcmp(&mode, pcoption->video_mode.pvalue,
3689 sizeof(struct video_mode))) {
3690 return FALSE;
3693 *pcoption->video_mode.pvalue = mode;
3694 return TRUE;
3697 /****************************************************************************
3698 Load the option from a file. Returns TRUE if the option changed.
3699 ****************************************************************************/
3700 static bool client_option_load(struct option *poption,
3701 struct section_file *sf)
3703 fc_assert_ret_val(NULL != poption, FALSE);
3704 fc_assert_ret_val(NULL != sf, FALSE);
3706 switch (option_type(poption)) {
3707 case OT_BOOLEAN:
3709 bool value;
3711 return (secfile_lookup_bool(sf, &value, "client.%s",
3712 option_name(poption))
3713 && option_bool_set(poption, value));
3715 case OT_INTEGER:
3717 int value;
3719 return (secfile_lookup_int(sf, &value, "client.%s",
3720 option_name(poption))
3721 && option_int_set(poption, value));
3723 case OT_STRING:
3725 const char *string;
3727 return ((string = secfile_lookup_str(sf, "client.%s",
3728 option_name(poption)))
3729 && option_str_set(poption, string));
3731 case OT_ENUM:
3733 int value;
3735 return (secfile_lookup_enum_data(sf, &value, FALSE,
3736 client_option_enum_secfile_str,
3737 poption, "client.%s",
3738 option_name(poption))
3739 && option_enum_set_int(poption, value));
3741 case OT_BITWISE:
3743 int value;
3745 return (secfile_lookup_enum_data(sf, &value, TRUE,
3746 client_option_bitwise_secfile_str,
3747 poption, "client.%s",
3748 option_name(poption))
3749 && option_bitwise_set(poption, value));
3751 case OT_FONT:
3753 const char *string;
3755 return ((string = secfile_lookup_str(sf, "client.%s",
3756 option_name(poption)))
3757 && option_font_set(poption, string));
3759 case OT_COLOR:
3761 struct ft_color color;
3763 return ((color.foreground =
3764 secfile_lookup_str(sf, "client.%s.foreground",
3765 option_name(poption)))
3766 && (color.background =
3767 secfile_lookup_str(sf, "client.%s.background",
3768 option_name(poption)))
3769 && option_color_set(poption, color));
3771 case OT_VIDEO_MODE:
3773 struct video_mode mode;
3775 return (secfile_lookup_int(sf, &mode.width, "client.%s.width",
3776 option_name(poption))
3777 && secfile_lookup_int(sf, &mode.height, "client.%s.height",
3778 option_name(poption))
3779 && option_video_mode_set(poption, mode));
3782 return FALSE;
3785 /****************************************************************************
3786 Save the option to a file.
3787 ****************************************************************************/
3788 static void client_option_save(struct option *poption,
3789 struct section_file *sf)
3791 fc_assert_ret(NULL != poption);
3792 fc_assert_ret(NULL != sf);
3794 switch (option_type(poption)) {
3795 case OT_BOOLEAN:
3796 secfile_insert_bool(sf, option_bool_get(poption),
3797 "client.%s", option_name(poption));
3798 break;
3799 case OT_INTEGER:
3800 secfile_insert_int(sf, option_int_get(poption),
3801 "client.%s", option_name(poption));
3802 break;
3803 case OT_STRING:
3804 secfile_insert_str(sf, option_str_get(poption),
3805 "client.%s", option_name(poption));
3806 break;
3807 case OT_ENUM:
3808 secfile_insert_enum_data(sf, option_enum_get_int(poption), FALSE,
3809 client_option_enum_secfile_str, poption,
3810 "client.%s", option_name(poption));
3811 break;
3812 case OT_BITWISE:
3813 secfile_insert_enum_data(sf, option_bitwise_get(poption), TRUE,
3814 client_option_bitwise_secfile_str, poption,
3815 "client.%s", option_name(poption));
3816 break;
3817 case OT_FONT:
3818 secfile_insert_str(sf, option_font_get(poption),
3819 "client.%s", option_name(poption));
3820 break;
3821 case OT_COLOR:
3823 struct ft_color color = option_color_get(poption);
3825 secfile_insert_str(sf, color.foreground, "client.%s.foreground",
3826 option_name(poption));
3827 secfile_insert_str(sf, color.background, "client.%s.background",
3828 option_name(poption));
3830 break;
3831 case OT_VIDEO_MODE:
3833 struct video_mode mode = option_video_mode_get(poption);
3835 secfile_insert_int(sf, mode.width, "client.%s.width",
3836 option_name(poption));
3837 secfile_insert_int(sf, mode.height, "client.%s.height",
3838 option_name(poption));
3840 break;
3845 /****************************************************************************
3846 Server options variables.
3847 ****************************************************************************/
3848 static char **server_options_categories = NULL;
3849 static struct server_option *server_options = NULL;
3851 static int server_options_categories_num = 0;
3852 static int server_options_num = 0;
3855 /****************************************************************************
3856 Server option set.
3857 ****************************************************************************/
3858 static struct option *server_optset_option_by_number(int id);
3859 static struct option *server_optset_option_first(void);
3860 static int server_optset_category_number(void);
3861 static const char *server_optset_category_name(int category);
3863 static struct option_set server_optset_static = {
3864 .option_by_number = server_optset_option_by_number,
3865 .option_first = server_optset_option_first,
3866 .category_number = server_optset_category_number,
3867 .category_name = server_optset_category_name
3869 const struct option_set *server_optset = &server_optset_static;
3872 /****************************************************************************
3873 Virtuals tables for the client options.
3874 ****************************************************************************/
3875 static int server_option_number(const struct option *poption);
3876 static const char *server_option_name(const struct option *poption);
3877 static const char *server_option_description(const struct option *poption);
3878 static const char *server_option_help_text(const struct option *poption);
3879 static int server_option_category(const struct option *poption);
3880 static bool server_option_is_changeable(const struct option *poption);
3881 static struct option *server_option_next(const struct option *poption);
3883 static const struct option_common_vtable server_option_common_vtable = {
3884 .number = server_option_number,
3885 .name = server_option_name,
3886 .description = server_option_description,
3887 .help_text = server_option_help_text,
3888 .category = server_option_category,
3889 .is_changeable = server_option_is_changeable,
3890 .next = server_option_next
3893 static bool server_option_bool_get(const struct option *poption);
3894 static bool server_option_bool_def(const struct option *poption);
3895 static bool server_option_bool_set(struct option *poption, bool val);
3897 static const struct option_bool_vtable server_option_bool_vtable = {
3898 .get = server_option_bool_get,
3899 .def = server_option_bool_def,
3900 .set = server_option_bool_set
3903 static int server_option_int_get(const struct option *poption);
3904 static int server_option_int_def(const struct option *poption);
3905 static int server_option_int_min(const struct option *poption);
3906 static int server_option_int_max(const struct option *poption);
3907 static bool server_option_int_set(struct option *poption, int val);
3909 static const struct option_int_vtable server_option_int_vtable = {
3910 .get = server_option_int_get,
3911 .def = server_option_int_def,
3912 .minimum = server_option_int_min,
3913 .maximum = server_option_int_max,
3914 .set = server_option_int_set
3917 static const char *server_option_str_get(const struct option *poption);
3918 static const char *server_option_str_def(const struct option *poption);
3919 static const struct strvec *
3920 server_option_str_values(const struct option *poption);
3921 static bool server_option_str_set(struct option *poption, const char *str);
3923 static const struct option_str_vtable server_option_str_vtable = {
3924 .get = server_option_str_get,
3925 .def = server_option_str_def,
3926 .values = server_option_str_values,
3927 .set = server_option_str_set
3930 static int server_option_enum_get(const struct option *poption);
3931 static int server_option_enum_def(const struct option *poption);
3932 static const struct strvec *
3933 server_option_enum_pretty(const struct option *poption);
3934 static bool server_option_enum_set(struct option *poption, int val);
3936 static const struct option_enum_vtable server_option_enum_vtable = {
3937 .get = server_option_enum_get,
3938 .def = server_option_enum_def,
3939 .values = server_option_enum_pretty,
3940 .set = server_option_enum_set,
3941 .cmp = strcmp
3944 static unsigned server_option_bitwise_get(const struct option *poption);
3945 static unsigned server_option_bitwise_def(const struct option *poption);
3946 static const struct strvec *
3947 server_option_bitwise_pretty(const struct option *poption);
3948 static bool server_option_bitwise_set(struct option *poption, unsigned val);
3950 static const struct option_bitwise_vtable server_option_bitwise_vtable = {
3951 .get = server_option_bitwise_get,
3952 .def = server_option_bitwise_def,
3953 .values = server_option_bitwise_pretty,
3954 .set = server_option_bitwise_set
3957 /****************************************************************************
3958 Derived class server option, inheriting from base class option.
3959 ****************************************************************************/
3960 struct server_option {
3961 struct option base_option; /* Base structure, must be the first! */
3963 char *name; /* Short name - used as an identifier */
3964 char *description; /* One-line description */
3965 char *help_text; /* Paragraph-length help text */
3966 unsigned char category;
3967 bool desired_sent;
3968 bool is_changeable;
3969 bool is_visible;
3971 union {
3972 /* OT_BOOLEAN type option. */
3973 struct {
3974 bool value;
3975 bool def;
3976 } boolean;
3977 /* OT_INTEGER type option. */
3978 struct {
3979 int value;
3980 int def, min, max;
3981 } integer;
3982 /* OT_STRING type option. */
3983 struct {
3984 char *value;
3985 char *def;
3986 } string;
3987 /* OT_ENUM type option. */
3988 struct {
3989 int value;
3990 int def;
3991 struct strvec *support_names;
3992 struct strvec *pretty_names; /* untranslated */
3993 } enumerator;
3994 /* OT_BITWISE type option. */
3995 struct {
3996 unsigned value;
3997 unsigned def;
3998 struct strvec *support_names;
3999 struct strvec *pretty_names; /* untranslated */
4000 } bitwise;
4004 #define SERVER_OPTION(poption) ((struct server_option *) (poption))
4006 static void desired_settable_option_send(struct option *poption);
4009 /****************************************************************************
4010 Initialize the server options (not received yet).
4011 ****************************************************************************/
4012 void server_options_init(void)
4014 fc_assert(NULL == server_options_categories);
4015 fc_assert(NULL == server_options);
4016 fc_assert(0 == server_options_categories_num);
4017 fc_assert(0 == server_options_num);
4020 /****************************************************************************
4021 Free one server option.
4022 ****************************************************************************/
4023 static void server_option_free(struct server_option *poption)
4025 switch (poption->base_option.type) {
4026 case OT_STRING:
4027 if (NULL != poption->string.value) {
4028 FC_FREE(poption->string.value);
4030 if (NULL != poption->string.def) {
4031 FC_FREE(poption->string.def);
4033 break;
4035 case OT_ENUM:
4036 if (NULL != poption->enumerator.support_names) {
4037 strvec_destroy(poption->enumerator.support_names);
4038 poption->enumerator.support_names = NULL;
4040 if (NULL != poption->enumerator.pretty_names) {
4041 strvec_destroy(poption->enumerator.pretty_names);
4042 poption->enumerator.pretty_names = NULL;
4044 break;
4046 case OT_BITWISE:
4047 if (NULL != poption->bitwise.support_names) {
4048 strvec_destroy(poption->bitwise.support_names);
4049 poption->bitwise.support_names = NULL;
4051 if (NULL != poption->bitwise.pretty_names) {
4052 strvec_destroy(poption->bitwise.pretty_names);
4053 poption->bitwise.pretty_names = NULL;
4055 break;
4057 case OT_BOOLEAN:
4058 case OT_INTEGER:
4059 case OT_FONT:
4060 case OT_COLOR:
4061 case OT_VIDEO_MODE:
4062 break;
4065 if (NULL != poption->name) {
4066 FC_FREE(poption->name);
4068 if (NULL != poption->description) {
4069 FC_FREE(poption->description);
4071 if (NULL != poption->help_text) {
4072 FC_FREE(poption->help_text);
4076 /****************************************************************************
4077 Free the server options, if already received.
4078 ****************************************************************************/
4079 void server_options_free(void)
4081 int i;
4083 /* Don't keep this dialog open. */
4084 option_dialog_popdown(server_optset);
4086 /* Free the options themselves. */
4087 if (NULL != server_options) {
4088 for (i = 0; i < server_options_num; i++) {
4089 server_option_free(server_options + i);
4091 FC_FREE(server_options);
4092 server_options_num = 0;
4095 /* Free the categories. */
4096 if (NULL != server_options_categories) {
4097 for (i = 0; i < server_options_categories_num; i++) {
4098 if (NULL != server_options_categories[i]) {
4099 FC_FREE(server_options_categories[i]);
4102 FC_FREE(server_options_categories);
4103 server_options_categories_num = 0;
4107 /****************************************************************************
4108 Allocate the server options and categories.
4109 ****************************************************************************/
4110 void handle_server_setting_control
4111 (const struct packet_server_setting_control *packet)
4113 int i;
4115 /* This packet should be received only once. */
4116 fc_assert_ret(NULL == server_options_categories);
4117 fc_assert_ret(NULL == server_options);
4118 fc_assert_ret(0 == server_options_categories_num);
4119 fc_assert_ret(0 == server_options_num);
4121 /* Allocate server option categories. */
4122 if (0 < packet->categories_num) {
4123 server_options_categories_num = packet->categories_num;
4124 server_options_categories =
4125 fc_calloc(server_options_categories_num,
4126 sizeof(*server_options_categories));
4128 for (i = 0; i < server_options_categories_num; i++) {
4129 /* NB: Translate now. */
4130 server_options_categories[i] = fc_strdup(_(packet->category_names[i]));
4134 /* Allocate server options. */
4135 if (0 < packet->settings_num) {
4136 server_options_num = packet->settings_num;
4137 server_options = fc_calloc(server_options_num, sizeof(*server_options));
4141 /****************************************************************************
4142 Receive a server setting info packet.
4143 ****************************************************************************/
4144 void handle_server_setting_const
4145 (const struct packet_server_setting_const *packet)
4147 struct option *poption = server_optset_option_by_number(packet->id);
4148 struct server_option *psoption = SERVER_OPTION(poption);
4150 fc_assert_ret(NULL != poption);
4152 fc_assert(NULL == psoption->name);
4153 psoption->name = fc_strdup(packet->name);
4154 fc_assert(NULL == psoption->description);
4155 /* NB: Translate now. */
4156 psoption->description = fc_strdup(_(packet->short_help));
4157 fc_assert(NULL == psoption->help_text);
4158 /* NB: Translate now. */
4159 psoption->help_text = fc_strdup(_(packet->extra_help));
4160 psoption->category = packet->category;
4163 /****************************************************************************
4164 Common part of handle_server_setting_*() functions. See below.
4165 ****************************************************************************/
4166 #define handle_server_setting_common(psoption, packet) \
4167 psoption->is_changeable = packet->is_changeable; \
4168 if (psoption->is_visible != packet->is_visible) { \
4169 if (psoption->is_visible) { \
4170 need_gui_remove = TRUE; \
4171 } else if (packet->is_visible) { \
4172 need_gui_add = TRUE; \
4174 psoption->is_visible = packet->is_visible; \
4177 if (!psoption->desired_sent \
4178 && psoption->is_visible \
4179 && psoption->is_changeable \
4180 && is_server_running() \
4181 && packet->initial_setting) { \
4182 /* Only send our private settings if we are running \
4183 * on a forked local server, i.e. started by the \
4184 * client with the "Start New Game" button. \
4185 * Do now override settings that are already saved to savegame \
4186 * and now loaded. */ \
4187 desired_settable_option_send(OPTION(poption)); \
4188 psoption->desired_sent = TRUE; \
4191 /* Update the GUI. */ \
4192 if (need_gui_remove) { \
4193 option_gui_remove(poption); \
4194 } else if (need_gui_add) { \
4195 option_gui_add(poption); \
4196 } else { \
4197 option_gui_update(poption); \
4200 /****************************************************************************
4201 Receive a boolean server setting info packet.
4202 ****************************************************************************/
4203 void handle_server_setting_bool
4204 (const struct packet_server_setting_bool *packet)
4206 struct option *poption = server_optset_option_by_number(packet->id);
4207 struct server_option *psoption = SERVER_OPTION(poption);
4208 bool need_gui_remove = FALSE;
4209 bool need_gui_add = FALSE;
4211 fc_assert_ret(NULL != poption);
4213 if (NULL == poption->common_vtable) {
4214 /* Not initialized yet. */
4215 poption->poptset = server_optset;
4216 poption->common_vtable = &server_option_common_vtable;
4217 poption->type = OT_BOOLEAN;
4218 poption->bool_vtable = &server_option_bool_vtable;
4220 fc_assert_ret_msg(OT_BOOLEAN == poption->type,
4221 "Server setting \"%s\" (nb %d) has type %s (%d), "
4222 "expected %s (%d)",
4223 option_name(poption), option_number(poption),
4224 option_type_name(poption->type), poption->type,
4225 option_type_name(OT_BOOLEAN), OT_BOOLEAN);
4227 if (packet->is_visible) {
4228 psoption->boolean.value = packet->val;
4229 psoption->boolean.def = packet->default_val;
4232 handle_server_setting_common(psoption, packet);
4235 /****************************************************************************
4236 Receive a integer server setting info packet.
4237 ****************************************************************************/
4238 void handle_server_setting_int
4239 (const struct packet_server_setting_int *packet)
4241 struct option *poption = server_optset_option_by_number(packet->id);
4242 struct server_option *psoption = SERVER_OPTION(poption);
4243 bool need_gui_remove = FALSE;
4244 bool need_gui_add = FALSE;
4246 fc_assert_ret(NULL != poption);
4248 if (NULL == poption->common_vtable) {
4249 /* Not initialized yet. */
4250 poption->poptset = server_optset;
4251 poption->common_vtable = &server_option_common_vtable;
4252 poption->type = OT_INTEGER;
4253 poption->int_vtable = &server_option_int_vtable;
4255 fc_assert_ret_msg(OT_INTEGER == poption->type,
4256 "Server setting \"%s\" (nb %d) has type %s (%d), "
4257 "expected %s (%d)",
4258 option_name(poption), option_number(poption),
4259 option_type_name(poption->type), poption->type,
4260 option_type_name(OT_INTEGER), OT_INTEGER);
4262 if (packet->is_visible) {
4263 psoption->integer.value = packet->val;
4264 psoption->integer.def = packet->default_val;
4265 psoption->integer.min = packet->min_val;
4266 psoption->integer.max = packet->max_val;
4269 handle_server_setting_common(psoption, packet);
4272 /****************************************************************************
4273 Receive a string server setting info packet.
4274 ****************************************************************************/
4275 void handle_server_setting_str
4276 (const struct packet_server_setting_str *packet)
4278 struct option *poption = server_optset_option_by_number(packet->id);
4279 struct server_option *psoption = SERVER_OPTION(poption);
4280 bool need_gui_remove = FALSE;
4281 bool need_gui_add = FALSE;
4283 fc_assert_ret(NULL != poption);
4285 if (NULL == poption->common_vtable) {
4286 /* Not initialized yet. */
4287 poption->poptset = server_optset;
4288 poption->common_vtable = &server_option_common_vtable;
4289 poption->type = OT_STRING;
4290 poption->str_vtable = &server_option_str_vtable;
4292 fc_assert_ret_msg(OT_STRING == poption->type,
4293 "Server setting \"%s\" (nb %d) has type %s (%d), "
4294 "expected %s (%d)",
4295 option_name(poption), option_number(poption),
4296 option_type_name(poption->type), poption->type,
4297 option_type_name(OT_STRING), OT_STRING);
4299 if (packet->is_visible) {
4300 if (NULL == psoption->string.value) {
4301 psoption->string.value = fc_strdup(packet->val);
4302 } else if (0 != strcmp(packet->val, psoption->string.value)) {
4303 free(psoption->string.value);
4304 psoption->string.value = fc_strdup(packet->val);
4306 if (NULL == psoption->string.def) {
4307 psoption->string.def = fc_strdup(packet->default_val);
4308 } else if (0 != strcmp(packet->default_val, psoption->string.def)) {
4309 free(psoption->string.def);
4310 psoption->string.def = fc_strdup(packet->default_val);
4314 handle_server_setting_common(psoption, packet);
4317 /****************************************************************************
4318 Receive an enumerator server setting info packet.
4319 ****************************************************************************/
4320 void handle_server_setting_enum
4321 (const struct packet_server_setting_enum *packet)
4323 struct option *poption = server_optset_option_by_number(packet->id);
4324 struct server_option *psoption = SERVER_OPTION(poption);
4325 bool need_gui_remove = FALSE;
4326 bool need_gui_add = FALSE;
4328 fc_assert_ret(NULL != poption);
4330 if (NULL == poption->common_vtable) {
4331 /* Not initialized yet. */
4332 poption->poptset = server_optset;
4333 poption->common_vtable = &server_option_common_vtable;
4334 poption->type = OT_ENUM;
4335 poption->enum_vtable = &server_option_enum_vtable;
4337 fc_assert_ret_msg(OT_ENUM == poption->type,
4338 "Server setting \"%s\" (nb %d) has type %s (%d), "
4339 "expected %s (%d)",
4340 option_name(poption), option_number(poption),
4341 option_type_name(poption->type), poption->type,
4342 option_type_name(OT_ENUM), OT_ENUM);
4344 if (packet->is_visible) {
4345 int i;
4347 psoption->enumerator.value = packet->val;
4348 psoption->enumerator.def = packet->default_val;
4350 if (NULL == psoption->enumerator.support_names) {
4351 /* First time we get this packet. */
4352 fc_assert(NULL == psoption->enumerator.pretty_names);
4353 psoption->enumerator.support_names = strvec_new();
4354 strvec_reserve(psoption->enumerator.support_names, packet->values_num);
4355 psoption->enumerator.pretty_names = strvec_new();
4356 strvec_reserve(psoption->enumerator.pretty_names, packet->values_num);
4357 for (i = 0; i < packet->values_num; i++) {
4358 strvec_set(psoption->enumerator.support_names, i,
4359 packet->support_names[i]);
4360 /* Store untranslated string from server. */
4361 strvec_set(psoption->enumerator.pretty_names, i,
4362 packet->pretty_names[i]);
4364 } else if (strvec_size(psoption->enumerator.support_names)
4365 != packet->values_num) {
4366 fc_assert(strvec_size(psoption->enumerator.support_names)
4367 == strvec_size(psoption->enumerator.pretty_names));
4368 /* The number of values have changed, we need to reset the list
4369 * of possible values. */
4370 strvec_reserve(psoption->enumerator.support_names, packet->values_num);
4371 strvec_reserve(psoption->enumerator.pretty_names, packet->values_num);
4372 for (i = 0; i < packet->values_num; i++) {
4373 strvec_set(psoption->enumerator.support_names, i,
4374 packet->support_names[i]);
4375 /* Store untranslated string from server. */
4376 strvec_set(psoption->enumerator.pretty_names, i,
4377 packet->pretty_names[i]);
4379 need_gui_remove = TRUE;
4380 need_gui_add = TRUE;
4381 } else {
4382 /* Check if a value changed, then we need to reset the list
4383 * of possible values. */
4384 const char *str;
4386 for (i = 0; i < packet->values_num; i++) {
4387 str = strvec_get(psoption->enumerator.pretty_names, i);
4388 if (NULL == str || 0 != strcmp(str, packet->pretty_names[i])) {
4389 /* Store untranslated string from server. */
4390 strvec_set(psoption->enumerator.pretty_names, i,
4391 packet->pretty_names[i]);
4392 need_gui_remove = TRUE;
4393 need_gui_add = TRUE;
4395 /* Support names are not visible, we don't need to check if it
4396 * has changed. */
4397 strvec_set(psoption->enumerator.support_names, i,
4398 packet->support_names[i]);
4403 handle_server_setting_common(psoption, packet);
4406 /****************************************************************************
4407 Receive a bitwise server setting info packet.
4408 ****************************************************************************/
4409 void handle_server_setting_bitwise
4410 (const struct packet_server_setting_bitwise *packet)
4412 struct option *poption = server_optset_option_by_number(packet->id);
4413 struct server_option *psoption = SERVER_OPTION(poption);
4414 bool need_gui_remove = FALSE;
4415 bool need_gui_add = FALSE;
4417 fc_assert_ret(NULL != poption);
4419 if (NULL == poption->common_vtable) {
4420 /* Not initialized yet. */
4421 poption->poptset = server_optset;
4422 poption->common_vtable = &server_option_common_vtable;
4423 poption->type = OT_BITWISE;
4424 poption->bitwise_vtable = &server_option_bitwise_vtable;
4426 fc_assert_ret_msg(OT_BITWISE == poption->type,
4427 "Server setting \"%s\" (nb %d) has type %s (%d), "
4428 "expected %s (%d)",
4429 option_name(poption), option_number(poption),
4430 option_type_name(poption->type), poption->type,
4431 option_type_name(OT_BITWISE), OT_BITWISE);
4433 if (packet->is_visible) {
4434 int i;
4436 psoption->bitwise.value = packet->val;
4437 psoption->bitwise.def = packet->default_val;
4439 if (NULL == psoption->bitwise.support_names) {
4440 /* First time we get this packet. */
4441 fc_assert(NULL == psoption->bitwise.pretty_names);
4442 psoption->bitwise.support_names = strvec_new();
4443 strvec_reserve(psoption->bitwise.support_names, packet->bits_num);
4444 psoption->bitwise.pretty_names = strvec_new();
4445 strvec_reserve(psoption->bitwise.pretty_names, packet->bits_num);
4446 for (i = 0; i < packet->bits_num; i++) {
4447 strvec_set(psoption->bitwise.support_names, i,
4448 packet->support_names[i]);
4449 /* Store untranslated string from server. */
4450 strvec_set(psoption->bitwise.pretty_names, i,
4451 packet->pretty_names[i]);
4453 } else if (strvec_size(psoption->bitwise.support_names)
4454 != packet->bits_num) {
4455 fc_assert(strvec_size(psoption->bitwise.support_names)
4456 == strvec_size(psoption->bitwise.pretty_names));
4457 /* The number of values have changed, we need to reset the list
4458 * of possible values. */
4459 strvec_reserve(psoption->bitwise.support_names, packet->bits_num);
4460 strvec_reserve(psoption->bitwise.pretty_names, packet->bits_num);
4461 for (i = 0; i < packet->bits_num; i++) {
4462 strvec_set(psoption->bitwise.support_names, i,
4463 packet->support_names[i]);
4464 /* Store untranslated string from server. */
4465 strvec_set(psoption->bitwise.pretty_names, i,
4466 packet->pretty_names[i]);
4468 need_gui_remove = TRUE;
4469 need_gui_add = TRUE;
4470 } else {
4471 /* Check if a value changed, then we need to reset the list
4472 * of possible values. */
4473 const char *str;
4475 for (i = 0; i < packet->bits_num; i++) {
4476 str = strvec_get(psoption->bitwise.pretty_names, i);
4477 if (NULL == str || 0 != strcmp(str, packet->pretty_names[i])) {
4478 /* Store untranslated string from server. */
4479 strvec_set(psoption->bitwise.pretty_names, i,
4480 packet->pretty_names[i]);
4481 need_gui_remove = TRUE;
4482 need_gui_add = TRUE;
4484 /* Support names are not visible, we don't need to check if it
4485 * has changed. */
4486 strvec_set(psoption->bitwise.support_names, i,
4487 packet->support_names[i]);
4492 handle_server_setting_common(psoption, packet);
4495 /****************************************************************************
4496 Returns the next valid option pointer for the current gui type.
4497 ****************************************************************************/
4498 static struct server_option *
4499 server_option_next_valid(struct server_option *poption)
4501 const struct server_option *const max =
4502 server_options + server_options_num;
4504 while (NULL != poption && poption < max && !poption->is_visible) {
4505 poption++;
4508 return (poption < max ? poption : NULL);
4511 /****************************************************************************
4512 Returns the server option associated to the number
4513 ****************************************************************************/
4514 struct option *server_optset_option_by_number(int id)
4516 if (0 > id || id > server_options_num) {
4517 return NULL;
4519 return OPTION(server_options + id);
4522 /****************************************************************************
4523 Returns the first valid (visible) option pointer.
4524 ****************************************************************************/
4525 struct option *server_optset_option_first(void)
4527 return OPTION(server_option_next_valid(server_options));
4530 /****************************************************************************
4531 Returns the number of server option categories.
4532 ****************************************************************************/
4533 int server_optset_category_number(void)
4535 return server_options_categories_num;
4538 /****************************************************************************
4539 Returns the name (translated) of the server option category.
4540 ****************************************************************************/
4541 const char *server_optset_category_name(int category)
4543 if (0 > category || category >= server_options_categories_num) {
4544 return NULL;
4547 return server_options_categories[category];
4550 /***************************************************************************
4551 Returns the number of this server option.
4552 ****************************************************************************/
4553 static int server_option_number(const struct option *poption)
4555 return SERVER_OPTION(poption) - server_options;
4558 /****************************************************************************
4559 Returns the name of this server option.
4560 ****************************************************************************/
4561 static const char *server_option_name(const struct option *poption)
4563 return SERVER_OPTION(poption)->name;
4566 /****************************************************************************
4567 Returns the (translated) description of this server option.
4568 ****************************************************************************/
4569 static const char *server_option_description(const struct option *poption)
4571 return SERVER_OPTION(poption)->description;
4574 /****************************************************************************
4575 Returns the (translated) help text for this server option.
4576 ****************************************************************************/
4577 static const char *server_option_help_text(const struct option *poption)
4579 return SERVER_OPTION(poption)->help_text;
4582 /****************************************************************************
4583 Returns the category of this server option.
4584 ****************************************************************************/
4585 static int server_option_category(const struct option *poption)
4587 return SERVER_OPTION(poption)->category;
4590 /****************************************************************************
4591 Returns TRUE if this client option can be modified.
4592 ****************************************************************************/
4593 static bool server_option_is_changeable(const struct option *poption)
4595 return SERVER_OPTION(poption)->is_changeable;
4598 /****************************************************************************
4599 Returns the next valid (visible) option pointer.
4600 ****************************************************************************/
4601 static struct option *server_option_next(const struct option *poption)
4603 return OPTION(server_option_next_valid(SERVER_OPTION(poption) + 1));
4606 /****************************************************************************
4607 Returns the value of this server option of type OT_BOOLEAN.
4608 ****************************************************************************/
4609 static bool server_option_bool_get(const struct option *poption)
4611 return SERVER_OPTION(poption)->boolean.value;
4614 /****************************************************************************
4615 Returns the default value of this server option of type OT_BOOLEAN.
4616 ****************************************************************************/
4617 static bool server_option_bool_def(const struct option *poption)
4619 return SERVER_OPTION(poption)->boolean.def;
4622 /****************************************************************************
4623 Set the value of this server option of type OT_BOOLEAN. Returns TRUE if
4624 the value changed.
4625 ****************************************************************************/
4626 static bool server_option_bool_set(struct option *poption, bool val)
4628 struct server_option *psoption = SERVER_OPTION(poption);
4630 if (psoption->boolean.value == val) {
4631 return FALSE;
4634 send_chat_printf("/set %s %s", psoption->name,
4635 val ? "enabled" : "disabled");
4636 return TRUE;
4639 /****************************************************************************
4640 Returns the value of this server option of type OT_INTEGER.
4641 ****************************************************************************/
4642 static int server_option_int_get(const struct option *poption)
4644 return SERVER_OPTION(poption)->integer.value;
4647 /****************************************************************************
4648 Returns the default value of this server option of type OT_INTEGER.
4649 ****************************************************************************/
4650 static int server_option_int_def(const struct option *poption)
4652 return SERVER_OPTION(poption)->integer.def;
4655 /****************************************************************************
4656 Returns the minimal value for this server option of type OT_INTEGER.
4657 ****************************************************************************/
4658 static int server_option_int_min(const struct option *poption)
4660 return SERVER_OPTION(poption)->integer.min;
4663 /****************************************************************************
4664 Returns the maximal value for this server option of type OT_INTEGER.
4665 ****************************************************************************/
4666 static int server_option_int_max(const struct option *poption)
4668 return SERVER_OPTION(poption)->integer.max;
4671 /****************************************************************************
4672 Set the value of this server option of type OT_INTEGER. Returns TRUE if
4673 the value changed.
4674 ****************************************************************************/
4675 static bool server_option_int_set(struct option *poption, int val)
4677 struct server_option *psoption = SERVER_OPTION(poption);
4679 if (val < psoption->integer.min
4680 || val > psoption->integer.max
4681 || psoption->integer.value == val) {
4682 return FALSE;
4685 send_chat_printf("/set %s %d", psoption->name, val);
4686 return TRUE;
4689 /****************************************************************************
4690 Returns the value of this server option of type OT_STRING.
4691 ****************************************************************************/
4692 static const char *server_option_str_get(const struct option *poption)
4694 return SERVER_OPTION(poption)->string.value;
4697 /****************************************************************************
4698 Returns the default value of this server option of type OT_STRING.
4699 ****************************************************************************/
4700 static const char *server_option_str_def(const struct option *poption)
4702 return SERVER_OPTION(poption)->string.def;
4705 /****************************************************************************
4706 Returns the possible string values of this server option of type
4707 OT_STRING.
4708 ****************************************************************************/
4709 static const struct strvec *
4710 server_option_str_values(const struct option *poption)
4712 return NULL;
4715 /****************************************************************************
4716 Set the value of this server option of type OT_STRING. Returns TRUE if
4717 the value changed.
4718 ****************************************************************************/
4719 static bool server_option_str_set(struct option *poption, const char *str)
4721 struct server_option *psoption = SERVER_OPTION(poption);
4723 if (0 == strcmp(psoption->string.value, str)) {
4724 return FALSE;
4727 send_chat_printf("/set %s \"%s\"", psoption->name, str);
4728 return TRUE;
4731 /****************************************************************************
4732 Returns the current value of this server option of type OT_ENUM.
4733 ****************************************************************************/
4734 static int server_option_enum_get(const struct option *poption)
4736 return SERVER_OPTION(poption)->enumerator.value;
4739 /****************************************************************************
4740 Returns the default value of this server option of type OT_ENUM.
4741 ****************************************************************************/
4742 static int server_option_enum_def(const struct option *poption)
4744 return SERVER_OPTION(poption)->enumerator.def;
4747 /****************************************************************************
4748 Returns the user-visible, translatable (but untranslated) "pretty" names
4749 of this server option of type OT_ENUM.
4750 ****************************************************************************/
4751 static const struct strvec *
4752 server_option_enum_pretty(const struct option *poption)
4754 return SERVER_OPTION(poption)->enumerator.pretty_names;
4757 /****************************************************************************
4758 Set the value of this server option of type OT_ENUM. Returns TRUE if
4759 the value changed.
4760 ****************************************************************************/
4761 static bool server_option_enum_set(struct option *poption, int val)
4763 struct server_option *psoption = SERVER_OPTION(poption);
4764 const char *name;
4766 if (val == psoption->enumerator.value
4767 || !(name = strvec_get(psoption->enumerator.support_names, val))) {
4768 return FALSE;
4771 send_chat_printf("/set %s \"%s\"", psoption->name, name);
4772 return TRUE;
4775 /****************************************************************************
4776 Returns the long support names of the values of the server option of type
4777 OT_ENUM.
4778 ****************************************************************************/
4779 static void server_option_enum_support_name(const struct option *poption,
4780 const char **pvalue,
4781 const char **pdefault)
4783 const struct server_option *psoption = SERVER_OPTION(poption);
4784 const struct strvec *values = psoption->enumerator.support_names;
4786 if (NULL != pvalue) {
4787 *pvalue = strvec_get(values, psoption->enumerator.value);
4789 if (NULL != pdefault) {
4790 *pdefault = strvec_get(values, psoption->enumerator.def);
4794 /****************************************************************************
4795 Returns the current value of this server option of type OT_BITWISE.
4796 ****************************************************************************/
4797 static unsigned server_option_bitwise_get(const struct option *poption)
4799 return SERVER_OPTION(poption)->bitwise.value;
4802 /****************************************************************************
4803 Returns the default value of this server option of type OT_BITWISE.
4804 ****************************************************************************/
4805 static unsigned server_option_bitwise_def(const struct option *poption)
4807 return SERVER_OPTION(poption)->bitwise.def;
4810 /****************************************************************************
4811 Returns the user-visible, translatable (but untranslated) "pretty" names
4812 of this server option of type OT_BITWISE.
4813 ****************************************************************************/
4814 static const struct strvec *
4815 server_option_bitwise_pretty(const struct option *poption)
4817 return SERVER_OPTION(poption)->bitwise.pretty_names;
4820 /****************************************************************************
4821 Compute the long support names of a value.
4822 ****************************************************************************/
4823 static void server_option_bitwise_support_base(const struct strvec *values,
4824 unsigned val,
4825 char *buf, size_t buf_len)
4827 int bit;
4829 buf[0] = '\0';
4830 for (bit = 0; bit < strvec_size(values); bit++) {
4831 if ((1 << bit) & val) {
4832 if ('\0' != buf[0]) {
4833 fc_strlcat(buf, "|", buf_len);
4835 fc_strlcat(buf, strvec_get(values, bit), buf_len);
4840 /****************************************************************************
4841 Set the value of this server option of type OT_BITWISE. Returns TRUE if
4842 the value changed.
4843 ****************************************************************************/
4844 static bool server_option_bitwise_set(struct option *poption, unsigned val)
4846 struct server_option *psoption = SERVER_OPTION(poption);
4847 char name[MAX_LEN_MSG];
4849 if (val == psoption->bitwise.value) {
4850 return FALSE;
4853 server_option_bitwise_support_base(psoption->bitwise.support_names, val,
4854 name, sizeof(name));
4855 send_chat_printf("/set %s \"%s\"", psoption->name, name);
4856 return TRUE;
4859 /****************************************************************************
4860 Compute the long support names of the values of the server option of type
4861 OT_BITWISE.
4862 ****************************************************************************/
4863 static void server_option_bitwise_support_name(const struct option *poption,
4864 char *val_buf, size_t val_len,
4865 char *def_buf, size_t def_len)
4867 const struct server_option *psoption = SERVER_OPTION(poption);
4868 const struct strvec *values = psoption->bitwise.support_names;
4870 if (NULL != val_buf && 0 < val_len) {
4871 server_option_bitwise_support_base(values, psoption->bitwise.value,
4872 val_buf, val_len);
4874 if (NULL != def_buf && 0 < def_len) {
4875 server_option_bitwise_support_base(values, psoption->bitwise.def,
4876 def_buf, def_len);
4881 /** Message Options: **/
4883 int messages_where[E_COUNT];
4886 /****************************************************************
4887 These could be a static table initialisation, except
4888 its easier to do it this way.
4889 *****************************************************************/
4890 static void message_options_init(void)
4892 int none[] = {
4893 E_IMP_BUY, E_IMP_SOLD, E_UNIT_BUY,
4894 E_UNIT_LOST_ATT, E_UNIT_WIN_ATT, E_GAME_START,
4895 E_CITY_BUILD, E_NEXT_YEAR,
4896 E_CITY_PRODUCTION_CHANGED,
4897 E_CITY_MAY_SOON_GROW, E_WORKLIST, E_AI_DEBUG
4899 int out_only[] = {
4900 E_NATION_SELECTED, E_CHAT_MSG, E_CHAT_ERROR, E_CONNECTION,
4901 E_LOG_ERROR, E_SETTING, E_VOTE_NEW, E_VOTE_RESOLVED, E_VOTE_ABORTED
4903 int all[] = {
4904 E_LOG_FATAL, E_SCRIPT, E_DEPRECATION_WARNING
4906 int i;
4908 for (i = 0; i <= event_type_max(); i++) {
4909 /* Include possible undefined values. */
4910 messages_where[i] = MW_MESSAGES;
4912 for (i = 0; i < ARRAY_SIZE(none); i++) {
4913 messages_where[none[i]] = 0;
4915 for (i = 0; i < ARRAY_SIZE(out_only); i++) {
4916 messages_where[out_only[i]] = MW_OUTPUT;
4918 for (i = 0; i < ARRAY_SIZE(all); i++) {
4919 messages_where[all[i]] = MW_MESSAGES | MW_POPUP;
4922 events_init();
4925 /****************************************************************
4926 Free resources allocated for message options system
4927 *****************************************************************/
4928 static void message_options_free(void)
4930 events_free();
4933 /****************************************************************
4934 Load the message options; use the function defined by
4935 specnum.h (see also events.h).
4936 *****************************************************************/
4937 static void message_options_load(struct section_file *file,
4938 const char *prefix)
4940 enum event_type event;
4941 int i, num_events;
4942 const char *p;
4944 if (!secfile_lookup_int(file, &num_events, "messages.count")) {
4945 /* version < 2.2 */
4946 /* Order of the events in 2.1. */
4947 const enum event_type old_events[] = {
4948 E_CITY_CANTBUILD, E_CITY_LOST, E_CITY_LOVE, E_CITY_DISORDER,
4949 E_CITY_FAMINE, E_CITY_FAMINE_FEARED, E_CITY_GROWTH,
4950 E_CITY_MAY_SOON_GROW, E_CITY_AQUEDUCT, E_CITY_AQ_BUILDING,
4951 E_CITY_NORMAL, E_CITY_NUKED, E_CITY_CMA_RELEASE, E_CITY_GRAN_THROTTLE,
4952 E_CITY_TRANSFER, E_CITY_BUILD, E_CITY_PRODUCTION_CHANGED,
4953 E_WORKLIST, E_UPRISING, E_CIVIL_WAR, E_ANARCHY, E_FIRST_CONTACT,
4954 E_NEW_GOVERNMENT, E_LOW_ON_FUNDS, E_POLLUTION, E_REVOLT_DONE,
4955 E_REVOLT_START, E_SPACESHIP, E_MY_DIPLOMAT_BRIBE,
4956 E_DIPLOMATIC_INCIDENT, E_MY_DIPLOMAT_ESCAPE, E_MY_DIPLOMAT_EMBASSY,
4957 E_MY_DIPLOMAT_FAILED, E_MY_DIPLOMAT_INCITE, E_MY_DIPLOMAT_POISON,
4958 E_MY_DIPLOMAT_SABOTAGE, E_MY_DIPLOMAT_THEFT, E_ENEMY_DIPLOMAT_BRIBE,
4959 E_ENEMY_DIPLOMAT_EMBASSY, E_ENEMY_DIPLOMAT_FAILED,
4960 E_ENEMY_DIPLOMAT_INCITE, E_ENEMY_DIPLOMAT_POISON,
4961 E_ENEMY_DIPLOMAT_SABOTAGE, E_ENEMY_DIPLOMAT_THEFT,
4962 E_CARAVAN_ACTION, E_SCRIPT, E_BROADCAST_REPORT, E_GAME_END,
4963 E_GAME_START, E_NATION_SELECTED, E_DESTROYED, E_REPORT, E_TURN_BELL,
4964 E_NEXT_YEAR, E_GLOBAL_ECO, E_NUKE, E_HUT_BARB, E_HUT_CITY, E_HUT_GOLD,
4965 E_HUT_BARB_KILLED, E_HUT_MERC, E_HUT_SETTLER, E_HUT_TECH,
4966 E_HUT_BARB_CITY_NEAR, E_IMP_BUY, E_IMP_BUILD, E_IMP_AUCTIONED,
4967 E_IMP_AUTO, E_IMP_SOLD, E_TECH_GAIN, E_TECH_LEARNED, E_TREATY_ALLIANCE,
4968 E_TREATY_BROKEN, E_TREATY_CEASEFIRE, E_TREATY_PEACE,
4969 E_TREATY_SHARED_VISION, E_UNIT_LOST_ATT, E_UNIT_WIN_ATT, E_UNIT_BUY,
4970 E_UNIT_BUILT, E_UNIT_LOST_DEF, E_UNIT_WIN, E_UNIT_BECAME_VET,
4971 E_UNIT_UPGRADED, E_UNIT_RELOCATED, E_UNIT_ORDERS, E_WONDER_BUILD,
4972 E_WONDER_OBSOLETE, E_WONDER_STARTED, E_WONDER_STOPPED,
4973 E_WONDER_WILL_BE_BUILT, E_DIPLOMACY, E_TREATY_EMBASSY,
4974 E_BAD_COMMAND, E_SETTING, E_CHAT_MSG, E_MESSAGE_WALL, E_CHAT_ERROR,
4975 E_CONNECTION, E_AI_DEBUG
4977 const size_t old_events_num = ARRAY_SIZE(old_events);
4979 for (i = 0; i < old_events_num; i++) {
4980 messages_where[old_events[i]] =
4981 secfile_lookup_int_default(file, messages_where[old_events[i]],
4982 "%s.message_where_%02d", prefix, i);
4984 return;
4987 for (i = 0; i < num_events; i++) {
4988 p = secfile_lookup_str(file, "messages.event%d.name", i);
4989 if (NULL == p) {
4990 log_error("Corruption in file %s: %s",
4991 secfile_name(file), secfile_error());
4992 continue;
4994 event = event_type_by_name(p, strcmp);
4995 if (!event_type_is_valid(event)) {
4996 log_error("Event not supported: %s", p);
4997 continue;
5000 if (!secfile_lookup_int(file, &messages_where[event],
5001 "messages.event%d.where", i)) {
5002 log_error("Corruption in file %s: %s",
5003 secfile_name(file), secfile_error());
5008 /****************************************************************
5009 Save the message options; use the function defined by
5010 specnum.h (see also events.h).
5011 *****************************************************************/
5012 static void message_options_save(struct section_file *file,
5013 const char *prefix)
5015 enum event_type event;
5016 int i = 0;
5018 for (event = event_type_begin(); event != event_type_end();
5019 event = event_type_next(event)) {
5020 secfile_insert_str(file, event_type_name(event),
5021 "messages.event%d.name", i);
5022 secfile_insert_int(file, messages_where[i],
5023 "messages.event%d.where", i);
5024 i++;
5027 secfile_insert_int(file, i, "messages.count");
5031 /****************************************************************
5032 Does heavy lifting for looking up a preset.
5033 *****************************************************************/
5034 static void load_cma_preset(struct section_file *file, int i)
5036 struct cm_parameter parameter;
5037 const char *name =
5038 secfile_lookup_str_default(file, "preset",
5039 "cma.preset%d.name", i);
5041 output_type_iterate(o) {
5042 parameter.minimal_surplus[o] =
5043 secfile_lookup_int_default(file, 0, "cma.preset%d.minsurp%d", i, o);
5044 parameter.factor[o] =
5045 secfile_lookup_int_default(file, 0, "cma.preset%d.factor%d", i, o);
5046 } output_type_iterate_end;
5047 parameter.require_happy =
5048 secfile_lookup_bool_default(file, FALSE, "cma.preset%d.reqhappy", i);
5049 parameter.happy_factor =
5050 secfile_lookup_int_default(file, 0, "cma.preset%d.happyfactor", i);
5051 parameter.allow_disorder = FALSE;
5052 parameter.allow_specialists = TRUE;
5054 cmafec_preset_add(name, &parameter);
5057 /****************************************************************
5058 Does heavy lifting for inserting a preset.
5059 *****************************************************************/
5060 static void save_cma_preset(struct section_file *file, int i)
5062 const struct cm_parameter *const pparam = cmafec_preset_get_parameter(i);
5063 char *name = cmafec_preset_get_descr(i);
5065 secfile_insert_str(file, name, "cma.preset%d.name", i);
5067 output_type_iterate(o) {
5068 secfile_insert_int(file, pparam->minimal_surplus[o],
5069 "cma.preset%d.minsurp%d", i, o);
5070 secfile_insert_int(file, pparam->factor[o],
5071 "cma.preset%d.factor%d", i, o);
5072 } output_type_iterate_end;
5073 secfile_insert_bool(file, pparam->require_happy,
5074 "cma.preset%d.reqhappy", i);
5075 secfile_insert_int(file, pparam->happy_factor,
5076 "cma.preset%d.happyfactor", i);
5079 /****************************************************************
5080 Insert all cma presets.
5081 *****************************************************************/
5082 static void save_cma_presets(struct section_file *file)
5084 int i;
5086 secfile_insert_int_comment(file, cmafec_preset_num(),
5087 _("If you add a preset by hand,"
5088 " also update \"number_of_presets\""),
5089 "cma.number_of_presets");
5090 for (i = 0; i < cmafec_preset_num(); i++) {
5091 save_cma_preset(file, i);
5095 /* Old rc file name. */
5096 #define OLD_OPTION_FILE_NAME ".civclientrc"
5097 /* New rc file name. */
5098 #define MID_OPTION_FILE_NAME ".freeciv-client-rc-%d.%d"
5099 #define NEW_OPTION_FILE_NAME "freeciv-client-rc-%d.%d"
5100 #if MINOR_VERSION >= 90
5101 #define MAJOR_NEW_OPTION_FILE_NAME (MAJOR_VERSION + 1)
5102 #define MINOR_NEW_OPTION_FILE_NAME 0
5103 #else /* MINOR_VERSION < 90 */
5104 #define MAJOR_NEW_OPTION_FILE_NAME MAJOR_VERSION
5105 #if IS_DEVEL_VERSION && ! IS_FREEZE_VERSION
5106 #define MINOR_NEW_OPTION_FILE_NAME (MINOR_VERSION + 1)
5107 #else
5108 #define MINOR_NEW_OPTION_FILE_NAME MINOR_VERSION
5109 #endif /* IS_DEVEL_VERSION */
5110 #endif /* MINOR_VERSION >= 90 */
5111 /* The first version the new option name appeared (2.6). */
5112 #define FIRST_MAJOR_NEW_OPTION_FILE_NAME 2
5113 #define FIRST_MINOR_NEW_OPTION_FILE_NAME 6
5114 /* The first version the mid option name appeared (2.2). */
5115 #define FIRST_MAJOR_MID_OPTION_FILE_NAME 2
5116 #define FIRST_MINOR_MID_OPTION_FILE_NAME 2
5117 /* The first version the new boolean values appeared (2.3). */
5118 #define FIRST_MAJOR_NEW_BOOLEAN 2
5119 #define FIRST_MINOR_NEW_BOOLEAN 3
5120 /****************************************************************
5121 Returns pointer to static memory containing name of the current
5122 option file. Usually used for saving.
5123 Ie, based on FREECIV_OPT env var, and home dir. (or a
5124 OPTION_FILE_NAME define defined in fc_config.h)
5125 Or NULL if problem.
5126 *****************************************************************/
5127 static const char *get_current_option_file_name(void)
5129 static char name_buffer[256];
5130 const char *name;
5132 name = getenv("FREECIV_OPT");
5134 if (name) {
5135 sz_strlcpy(name_buffer, name);
5136 } else {
5137 #ifdef OPTION_FILE_NAME
5138 fc_strlcpy(name_buffer, OPTION_FILE_NAME, sizeof(name_buffer));
5139 #else
5140 name = user_home_dir();
5141 if (!name) {
5142 log_error(_("Cannot find your home directory"));
5143 return NULL;
5145 fc_snprintf(name_buffer, sizeof(name_buffer),
5146 "%s" DIR_SEPARATOR ".freeciv" DIR_SEPARATOR NEW_OPTION_FILE_NAME,
5147 name, MAJOR_NEW_OPTION_FILE_NAME, MINOR_NEW_OPTION_FILE_NAME);
5148 #endif /* OPTION_FILE_NAME */
5150 log_verbose("settings file is %s", name_buffer);
5151 return name_buffer;
5154 /****************************************************************************
5155 Check the last option file we saved. Usually used to load. Ie, based on
5156 FREECIV_OPT env var, and home dir. (or a OPTION_FILE_NAME define defined
5157 in fc_config.h), or NULL if not found.
5159 Set in allow_digital_boolean if we should look for old boolean values
5160 (saved as 0 and 1), so if the rc file version is older than 2.3.0.
5161 ****************************************************************************/
5162 static const char *get_last_option_file_name(bool *allow_digital_boolean)
5164 static char name_buffer[256];
5165 const char *name;
5166 static int last_minors[] = {
5167 0, /* There was no 0.x releases */
5168 14, /* 1.14 */
5169 6 /* 2.6 */
5172 FC_STATIC_ASSERT(MAJOR_VERSION < sizeof(last_minors) / sizeof(int), missing_last_minor);
5174 *allow_digital_boolean = FALSE;
5175 name = getenv("FREECIV_OPT");
5176 if (name) {
5177 sz_strlcpy(name_buffer, name);
5178 } else {
5179 #ifdef OPTION_FILE_NAME
5180 fc_strlcpy(name_buffer, OPTION_FILE_NAME, sizeof(name_buffer));
5181 #else
5182 int major, minor;
5183 struct stat buf;
5185 name = user_home_dir();
5186 if (!name) {
5187 log_error(_("Cannot find your home directory"));
5188 return NULL;
5190 for (major = MAJOR_NEW_OPTION_FILE_NAME,
5191 minor = MINOR_NEW_OPTION_FILE_NAME;
5192 major >= FIRST_MAJOR_NEW_OPTION_FILE_NAME; major--) {
5193 for (; (major == FIRST_MAJOR_NEW_OPTION_FILE_NAME
5194 ? minor >= FIRST_MINOR_NEW_OPTION_FILE_NAME
5195 : minor >= 0); minor--) {
5196 fc_snprintf(name_buffer, sizeof(name_buffer),
5197 "%s" DIR_SEPARATOR ".freeciv" DIR_SEPARATOR NEW_OPTION_FILE_NAME,
5198 name, major, minor);
5199 if (0 == fc_stat(name_buffer, &buf)) {
5200 if (MAJOR_NEW_OPTION_FILE_NAME != major
5201 || MINOR_NEW_OPTION_FILE_NAME != minor) {
5202 log_normal(_("Didn't find '%s' option file, "
5203 "loading from '%s' instead."),
5204 get_current_option_file_name() + strlen(name) + 1,
5205 name_buffer + strlen(name) + 1);
5208 return name_buffer;
5211 minor = last_minors[major - 1];
5214 /* minor having max value of FIRST_MINOR_NEW_OPTION_FILE_NAME
5215 * works since MID versioning scheme was used within major version 2
5216 * only (2.2 - 2.6) so the last minor is bigger than any earlier minor. */
5217 for (major = FIRST_MAJOR_MID_OPTION_FILE_NAME,
5218 minor = FIRST_MINOR_NEW_OPTION_FILE_NAME ;
5219 minor >= FIRST_MINOR_MID_OPTION_FILE_NAME ;
5220 minor--) {
5221 fc_snprintf(name_buffer, sizeof(name_buffer),
5222 "%s" DIR_SEPARATOR MID_OPTION_FILE_NAME, name, major, minor);
5223 if (0 == fc_stat(name_buffer, &buf)) {
5224 log_normal(_("Didn't find '%s' option file, "
5225 "loading from '%s' instead."),
5226 get_current_option_file_name() + strlen(name) + 1,
5227 name_buffer + strlen(name) + 1);
5229 if (FIRST_MINOR_NEW_BOOLEAN > minor) {
5230 *allow_digital_boolean = TRUE;
5232 return name_buffer;
5236 /* Try with the old one. */
5237 fc_snprintf(name_buffer, sizeof(name_buffer),
5238 "%s" DIR_SEPARATOR OLD_OPTION_FILE_NAME, name);
5239 if (0 == fc_stat(name_buffer, &buf)) {
5240 log_normal(_("Didn't find '%s' option file, "
5241 "loading from '%s' instead."),
5242 get_current_option_file_name() + strlen(name) + 1,
5243 OLD_OPTION_FILE_NAME);
5244 *allow_digital_boolean = TRUE;
5245 return name_buffer;
5246 } else {
5247 return NULL;
5249 #endif /* OPTION_FILE_NAME */
5251 log_verbose("settings file is %s", name_buffer);
5252 return name_buffer;
5254 #undef OLD_OPTION_FILE_NAME
5255 #undef MID_OPTION_FILE_NAME
5256 #undef NEW_OPTION_FILE_NAME
5257 #undef FIRST_MAJOR_NEW_OPTION_FILE_NAME
5258 #undef FIRST_MINOR_NEW_OPTION_FILE_NAME
5259 #undef FIRST_MAJOR_MID_OPTION_FILE_NAME
5260 #undef FIRST_MINOR_MID_OPTION_FILE_NAME
5261 #undef FIRST_MINOR_NEW_BOOLEAN
5264 /****************************************************************************
5265 Desired settable options.
5266 ****************************************************************************/
5267 #define SPECHASH_TAG settable_options
5268 #define SPECHASH_ASTR_KEY_TYPE
5269 #define SPECHASH_ASTR_DATA_TYPE
5270 #include "spechash.h"
5271 #define settable_options_hash_iterate(hash, name, value) \
5272 TYPED_HASH_ITERATE(const char *, const char *, hash, name, value)
5273 #define settable_options_hash_iterate_end HASH_ITERATE_END
5275 static struct settable_options_hash *settable_options_hash = NULL;
5277 /**************************************************************************
5278 Load the server options.
5279 **************************************************************************/
5280 static void settable_options_load(struct section_file *sf)
5282 char buf[64];
5283 const struct section *psection;
5284 const struct entry_list *entries;
5285 const char *string;
5286 bool bval;
5287 int ival;
5289 fc_assert_ret(NULL != settable_options_hash);
5291 settable_options_hash_clear(settable_options_hash);
5293 psection = secfile_section_by_name(sf, "server");
5294 if (NULL == psection) {
5295 /* Does not exist! */
5296 return;
5299 entries = section_entries(psection);
5300 entry_list_iterate(entries, pentry) {
5301 string = NULL;
5302 switch (entry_type(pentry)) {
5303 case ENTRY_BOOL:
5304 if (entry_bool_get(pentry, &bval)) {
5305 fc_strlcpy(buf, bval ? "enabled" : "disabled", sizeof(buf));
5306 string = buf;
5308 break;
5310 case ENTRY_INT:
5311 if (entry_int_get(pentry, &ival)) {
5312 fc_snprintf(buf, sizeof(buf), "%d", ival);
5313 string = buf;
5315 break;
5317 case ENTRY_STR:
5318 (void) entry_str_get(pentry, &string);
5319 break;
5321 case ENTRY_FLOAT:
5322 case ENTRY_FILEREFERENCE:
5323 /* Not supported yet */
5324 break;
5327 if (NULL == string) {
5328 log_error("Entry type variant of \"%s.%s\" is not supported.",
5329 section_name(psection), entry_name(pentry));
5330 continue;
5333 settable_options_hash_insert(settable_options_hash, entry_name(pentry),
5334 string);
5335 } entry_list_iterate_end;
5338 /****************************************************************
5339 Save the desired server options.
5340 *****************************************************************/
5341 static void settable_options_save(struct section_file *sf)
5343 fc_assert_ret(NULL != settable_options_hash);
5345 settable_options_hash_iterate(settable_options_hash, name, value) {
5346 if (!fc_strcasecmp(name, "gameseed") || !fc_strcasecmp(name, "mapseed")) {
5347 /* Do not save mapseed or gameseed. */
5348 continue;
5350 if (!fc_strcasecmp(name, "topology")) {
5351 /* client_start_server() sets topology based on tileset. Don't store
5352 * its choice. The tileset is already stored. Storing topology leads
5353 * to all sort of breakage:
5354 * - it breaks ruleset default topology.
5355 * - it interacts badly with tileset ruleset change, ruleset tileset
5356 * change and topology tileset change.
5357 * - its value is probably based on what tileset was loaded when
5358 * client_start_server() decided to set topology, not on player
5359 * choice.
5361 continue;
5363 secfile_insert_str(sf, value, "server.%s", name);
5364 } settable_options_hash_iterate_end;
5367 /****************************************************************************
5368 Update the desired settable options hash table from the current
5369 setting configuration.
5370 ****************************************************************************/
5371 void desired_settable_options_update(void)
5373 char val_buf[1024], def_buf[1024];
5374 const char *value, *def_val;
5376 fc_assert_ret(NULL != settable_options_hash);
5378 options_iterate(server_optset, poption) {
5379 value = NULL;
5380 def_val = NULL;
5381 switch (option_type(poption)) {
5382 case OT_BOOLEAN:
5383 fc_strlcpy(val_buf, option_bool_get(poption) ? "enabled" : "disabled",
5384 sizeof(val_buf));
5385 value = val_buf;
5386 fc_strlcpy(def_buf, option_bool_def(poption) ? "enabled" : "disabled",
5387 sizeof(def_buf));
5388 def_val = def_buf;
5389 break;
5390 case OT_INTEGER:
5391 fc_snprintf(val_buf, sizeof(val_buf), "%d", option_int_get(poption));
5392 value = val_buf;
5393 fc_snprintf(def_buf, sizeof(def_buf), "%d", option_int_def(poption));
5394 def_val = def_buf;
5395 break;
5396 case OT_STRING:
5397 value = option_str_get(poption);
5398 def_val = option_str_def(poption);
5399 break;
5400 case OT_ENUM:
5401 server_option_enum_support_name(poption, &value, &def_val);
5402 break;
5403 case OT_BITWISE:
5404 server_option_bitwise_support_name(poption, val_buf, sizeof(val_buf),
5405 def_buf, sizeof(def_buf));
5406 value = val_buf;
5407 def_val = def_buf;
5408 break;
5409 case OT_FONT:
5410 case OT_COLOR:
5411 case OT_VIDEO_MODE:
5412 break;
5415 if (NULL == value || NULL == def_val) {
5416 log_error("Option type %s (%d) not supported for '%s'.",
5417 option_type_name(option_type(poption)), option_type(poption),
5418 option_name(poption));
5419 continue;
5422 if (0 == strcmp(value, def_val)) {
5423 /* Not set, using default... */
5424 settable_options_hash_remove(settable_options_hash,
5425 option_name(poption));
5426 } else {
5427 /* Really desired. */
5428 settable_options_hash_replace(settable_options_hash,
5429 option_name(poption), value);
5431 } options_iterate_end;
5434 /****************************************************************
5435 Update a desired settable option in the hash table from a value
5436 which can be different of the current consiguration.
5437 *****************************************************************/
5438 void desired_settable_option_update(const char *op_name,
5439 const char *op_value,
5440 bool allow_replace)
5442 fc_assert_ret(NULL != settable_options_hash);
5444 if (allow_replace) {
5445 settable_options_hash_replace(settable_options_hash, op_name, op_value);
5446 } else {
5447 settable_options_hash_insert(settable_options_hash, op_name, op_value);
5451 /****************************************************************************
5452 Convert old integer to new values (Freeciv 2.2.x to Freeciv 2.3.x).
5453 Very ugly hack. TODO: Remove this later.
5454 ****************************************************************************/
5455 static bool settable_option_upgrade_value(const struct option *poption,
5456 int old_value,
5457 char *buf, size_t buf_len)
5459 const char *name = option_name(poption);
5461 #define SETTING_CASE(ARG_name, ...) \
5462 if (0 == strcmp(ARG_name, name)) { \
5463 static const char *values[] = { __VA_ARGS__ }; \
5464 if (0 <= old_value && old_value < ARRAY_SIZE(values) \
5465 && NULL != values[old_value]) { \
5466 fc_strlcpy(buf, values[old_value], buf_len); \
5467 return TRUE; \
5468 } else { \
5469 return FALSE; \
5473 SETTING_CASE("topology", "", "WRAPX", "WRAPY", "WRAPX|WRAPY", "ISO",
5474 "WRAPX|ISO", "WRAPY|ISO", "WRAPX|WRAPY|ISO", "HEX",
5475 "WRAPX|HEX", "WRAPY|HEX", "WRAPX|WRAPY|HEX", "ISO|HEX",
5476 "WRAPX|ISO|HEX", "WRAPY|ISO|HEX", "WRAPX|WRAPY|ISO|HEX");
5477 SETTING_CASE("generator", NULL, "RANDOM", "FRACTAL", "ISLAND");
5478 SETTING_CASE("startpos", "DEFAULT", "SINGLE", "2or3", "ALL", "VARIABLE");
5479 SETTING_CASE("borders", "DISABLED", "ENABLED", "SEE_INSIDE", "EXPAND");
5480 SETTING_CASE("diplomacy", "ALL", "HUMAN", "AI", "TEAM", "DISABLED");
5481 SETTING_CASE("citynames", "NO_RESTRICTIONS", "PLAYER_UNIQUE",
5482 "GLOBAL_UNIQUE", "NO_STEALING");
5483 SETTING_CASE("barbarians", "DISABLED", "HUTS_ONLY", "NORMAL", "FREQUENT",
5484 "HORDES");
5485 SETTING_CASE("phasemode", "ALL", "PLAYER", "TEAM");
5486 SETTING_CASE("compresstype", "PLAIN", "LIBZ", "BZIP2");
5488 #undef SETTING_CASE
5489 return FALSE;
5492 /****************************************************************************
5493 Send the desired server options to the server.
5494 ****************************************************************************/
5495 static void desired_settable_option_send(struct option *poption)
5497 char *desired;
5498 int value;
5500 fc_assert_ret(NULL != settable_options_hash);
5502 if (!settable_options_hash_lookup(settable_options_hash,
5503 option_name(poption), &desired)) {
5504 /* No change explicitly desired. */
5505 return;
5508 switch (option_type(poption)) {
5509 case OT_BOOLEAN:
5510 if ((0 == fc_strcasecmp("enabled", desired)
5511 || (str_to_int(desired, &value) && 1 == value))
5512 && !option_bool_get(poption)) {
5513 send_chat_printf("/set %s enabled", option_name(poption));
5514 } else if ((0 == fc_strcasecmp("disabled", desired)
5515 || (str_to_int(desired, &value) && 0 == value))
5516 && option_bool_get(poption)) {
5517 send_chat_printf("/set %s disabled", option_name(poption));
5519 return;
5520 case OT_INTEGER:
5521 if (str_to_int(desired, &value) && value != option_int_get(poption)) {
5522 send_chat_printf("/set %s %d", option_name(poption), value);
5524 return;
5525 case OT_STRING:
5526 if (0 != strcmp(desired, option_str_get(poption))) {
5527 send_chat_printf("/set %s \"%s\"", option_name(poption), desired);
5529 return;
5530 case OT_ENUM:
5532 char desired_buf[256];
5533 const char *value_str;
5535 /* Handle old values. */
5536 if (str_to_int(desired, &value)
5537 && settable_option_upgrade_value(poption, value, desired_buf,
5538 sizeof(desired_buf))) {
5539 desired = desired_buf;
5542 server_option_enum_support_name(poption, &value_str, NULL);
5543 if (0 != strcmp(desired, value_str)) {
5544 send_chat_printf("/set %s \"%s\"", option_name(poption), desired);
5547 return;
5548 case OT_BITWISE:
5550 char desired_buf[256], value_buf[256];
5552 /* Handle old values. */
5553 if (str_to_int(desired, &value)
5554 && settable_option_upgrade_value(poption, value, desired_buf,
5555 sizeof(desired_buf))) {
5556 desired = desired_buf;
5559 server_option_bitwise_support_name(poption, value_buf,
5560 sizeof(value_buf), NULL, 0);
5561 if (0 != strcmp(desired, value_buf)) {
5562 send_chat_printf("/set %s \"%s\"", option_name(poption), desired);
5565 return;
5566 case OT_FONT:
5567 case OT_COLOR:
5568 case OT_VIDEO_MODE:
5569 break;
5572 log_error("Option type %s (%d) not supported for '%s'.",
5573 option_type_name(option_type(poption)), option_type(poption),
5574 option_name(poption));
5578 /****************************************************************************
5579 City and player report dialog options.
5580 ****************************************************************************/
5581 #define SPECHASH_TAG dialog_options
5582 #define SPECHASH_ASTR_KEY_TYPE
5583 #define SPECHASH_IDATA_TYPE bool
5584 #define SPECHASH_UDATA_TO_IDATA FC_INT_TO_PTR
5585 #define SPECHASH_IDATA_TO_UDATA FC_PTR_TO_INT
5586 #include "spechash.h"
5587 #define dialog_options_hash_iterate(hash, column, visible) \
5588 TYPED_HASH_ITERATE(const char *, intptr_t, hash, column, visible)
5589 #define dialog_options_hash_iterate_end HASH_ITERATE_END
5591 static struct dialog_options_hash *dialog_options_hash = NULL;
5593 /****************************************************************************
5594 Load the city and player report dialog options.
5595 ****************************************************************************/
5596 static void options_dialogs_load(struct section_file *sf)
5598 const struct entry_list *entries;
5599 const char *prefixes[] = { "player_dlg_", "city_report_", NULL };
5600 const char **prefix;
5601 bool visible;
5603 fc_assert_ret(NULL != dialog_options_hash);
5605 entries = section_entries(secfile_section_by_name(sf, "client"));
5607 if (NULL != entries) {
5608 entry_list_iterate(entries, pentry) {
5609 for (prefix = prefixes; NULL != *prefix; prefix++) {
5610 if (0 == strncmp(*prefix, entry_name(pentry), strlen(*prefix))
5611 && secfile_lookup_bool(sf, &visible, "client.%s",
5612 entry_name(pentry))) {
5613 dialog_options_hash_replace(dialog_options_hash,
5614 entry_name(pentry), visible);
5615 break;
5618 } entry_list_iterate_end;
5622 /****************************************************************************
5623 Save the city and player report dialog options.
5624 ****************************************************************************/
5625 static void options_dialogs_save(struct section_file *sf)
5627 fc_assert_ret(NULL != dialog_options_hash);
5629 options_dialogs_update();
5630 dialog_options_hash_iterate(dialog_options_hash, column, visible) {
5631 secfile_insert_bool(sf, visible, "client.%s", column);
5632 } dialog_options_hash_iterate_end;
5635 /****************************************************************
5636 This set the city and player report dialog options to the
5637 current ones. It's called when the client goes to
5638 C_S_DISCONNECTED state.
5639 *****************************************************************/
5640 void options_dialogs_update(void)
5642 char buf[64];
5643 int i;
5645 fc_assert_ret(NULL != dialog_options_hash);
5647 /* Player report dialog options. */
5648 for (i = 1; i < num_player_dlg_columns; i++) {
5649 fc_snprintf(buf, sizeof(buf), "player_dlg_%s",
5650 player_dlg_columns[i].tagname);
5651 dialog_options_hash_replace(dialog_options_hash, buf,
5652 player_dlg_columns[i].show);
5655 /* City report dialog options. */
5656 for (i = 0; i < num_city_report_spec(); i++) {
5657 fc_snprintf(buf, sizeof(buf), "city_report_%s",
5658 city_report_spec_tagname(i));
5659 dialog_options_hash_replace(dialog_options_hash, buf,
5660 *city_report_spec_show_ptr(i));
5664 /****************************************************************
5665 This set the city and player report dialog options. It's called
5666 when the client goes to C_S_RUNNING state.
5667 *****************************************************************/
5668 void options_dialogs_set(void)
5670 char buf[64];
5671 bool visible;
5672 int i;
5674 fc_assert_ret(NULL != dialog_options_hash);
5676 /* Player report dialog options. */
5677 for (i = 1; i < num_player_dlg_columns; i++) {
5678 fc_snprintf(buf, sizeof(buf), "player_dlg_%s",
5679 player_dlg_columns[i].tagname);
5680 if (dialog_options_hash_lookup(dialog_options_hash, buf, &visible)) {
5681 player_dlg_columns[i].show = visible;
5685 /* City report dialog options. */
5686 for (i = 0; i < num_city_report_spec(); i++) {
5687 fc_snprintf(buf, sizeof(buf), "city_report_%s",
5688 city_report_spec_tagname(i));
5689 if (dialog_options_hash_lookup(dialog_options_hash, buf, &visible)) {
5690 *city_report_spec_show_ptr(i) = visible;
5696 /****************************************************************
5697 Load from the rc file any options that are not ruleset specific.
5698 It is called after ui_init(), yet before ui_main().
5699 Unfortunately, this means that some clients cannot display.
5700 Instead, use log_*().
5701 *****************************************************************/
5702 void options_load(void)
5704 struct section_file *sf;
5705 bool allow_digital_boolean;
5706 int i, num;
5707 const char *name;
5708 const char *const prefix = "client";
5709 const char *str;
5711 name = get_last_option_file_name(&allow_digital_boolean);
5712 if (!name) {
5713 log_normal(_("Didn't find the option file. Creating a new one."));
5714 client_option_adjust_defaults();
5715 options_fully_initialized = TRUE;
5716 create_default_cma_presets();
5717 gui_options.first_boot = TRUE;
5718 return;
5720 if (!(sf = secfile_load(name, TRUE))) {
5721 log_debug("Error loading option file '%s':\n%s", name, secfile_error());
5722 /* try to create the rc file */
5723 sf = secfile_new(TRUE);
5724 secfile_insert_str(sf, VERSION_STRING, "client.version");
5726 create_default_cma_presets();
5727 save_cma_presets(sf);
5729 /* FIXME: need better messages */
5730 if (!secfile_save(sf, name, 0, FZ_PLAIN)) {
5731 log_error(_("Save failed, cannot write to file %s"), name);
5732 } else {
5733 log_normal(_("Saved settings to file %s"), name);
5735 secfile_destroy(sf);
5736 options_fully_initialized = TRUE;
5737 return;
5739 secfile_allow_digital_boolean(sf, allow_digital_boolean);
5741 /* a "secret" option for the lazy. TODO: make this saveable */
5742 sz_strlcpy(password,
5743 secfile_lookup_str_default(sf, "", "%s.password", prefix));
5745 gui_options.save_options_on_exit =
5746 secfile_lookup_bool_default(sf, gui_options.save_options_on_exit,
5747 "%s.save_options_on_exit", prefix);
5748 gui_options.migrate_fullscreen =
5749 secfile_lookup_bool_default(sf, gui_options.migrate_fullscreen,
5750 "%s.fullscreen_mode", prefix);
5752 /* Settings migrations */
5753 gui_options.gui_gtk3_22_migrated_from_gtk3 =
5754 secfile_lookup_bool_default(sf, gui_options.gui_gtk3_22_migrated_from_gtk3,
5755 "%s.migration_gtk3_22_from_gtk3", prefix);
5756 gui_options.gui_gtk3_migrated_from_gtk2 =
5757 secfile_lookup_bool_default(sf, gui_options.gui_gtk3_migrated_from_gtk2,
5758 "%s.migration_gtk3_from_gtk2", prefix);
5759 gui_options.gui_sdl2_migrated_from_sdl =
5760 secfile_lookup_bool_default(sf, gui_options.gui_sdl2_migrated_from_sdl,
5761 "%s.migration_sdl2_from_sdl", prefix);
5762 gui_options.gui_gtk2_migrated_from_2_5 =
5763 secfile_lookup_bool_default(sf, gui_options.gui_gtk3_migrated_from_2_5,
5764 "%s.migration_gtk2_from_2_5", prefix);
5765 gui_options.gui_gtk3_migrated_from_2_5 =
5766 secfile_lookup_bool_default(sf, gui_options.gui_gtk2_migrated_from_2_5,
5767 "%s.migration_gtk3_from_2_5", prefix);
5768 gui_options.gui_qt_migrated_from_2_5 =
5769 secfile_lookup_bool_default(sf, gui_options.gui_qt_migrated_from_2_5,
5770 "%s.migration_qt_from_2_5", prefix);
5772 /* These are not gui-enabled yet */
5773 gui_options.zoom_set =
5774 secfile_lookup_bool_default(sf, FALSE, "%s.zoom_set", prefix);
5775 gui_options.zoom_default_level =
5776 secfile_lookup_float_default(sf, 1.0,
5777 "%s.zoom_default_level", prefix);
5779 str = secfile_lookup_str_default(sf, NULL, "client.default_tileset_name");
5780 if (str != NULL) {
5781 strncpy(gui_options.default_tileset_name, str,
5782 sizeof(gui_options.default_tileset_name));
5785 /* Backwards compatibility for removed options replaced by entirely "new"
5786 * options. The equivalent "new" option will override these, if set. */
5788 /* Removed in 2.3 */
5789 /* Note: this overrides the previously specified default for
5790 * gui_gtk2_message_chat_location */
5791 /* gtk3 client never had the old form of this option. The overridden
5792 * gui_gtk2_ value will be propagated to gui_gtk3_ later by
5793 * migrate_options_from_gtk2() if necessary. */
5794 if (secfile_lookup_bool_default(sf, FALSE,
5795 "%s.gui_gtk2_merge_notebooks", prefix)) {
5796 gui_options.gui_gtk2_message_chat_location = GUI_GTK_MSGCHAT_MERGED;
5797 } else if (secfile_lookup_bool_default(sf, FALSE,
5798 "%s.gui_gtk2_split_bottom_notebook",
5799 prefix)) {
5800 gui_options.gui_gtk2_message_chat_location = GUI_GTK_MSGCHAT_SPLIT;
5801 } else {
5802 gui_options.gui_gtk2_message_chat_location = GUI_GTK_MSGCHAT_SEPARATE;
5805 /* Renamed in 2.6 */
5806 gui_options.popup_actor_arrival = secfile_lookup_bool_default(sf, TRUE,
5807 "%s.popup_caravan_arrival", prefix);
5809 /* Load all the regular options */
5810 client_options_iterate_all(poption) {
5811 client_option_load(poption, sf);
5812 } client_options_iterate_all_end;
5814 /* More backwards compatibility, for removed options that had been
5815 * folded into then-existing options. Here, the backwards-compatibility
5816 * behaviour overrides the "destination" option. */
5818 /* Removed in 2.4 */
5819 if (!secfile_lookup_bool_default(sf, TRUE,
5820 "%s.do_combat_animation", prefix)) {
5821 gui_options.smooth_combat_step_msec = 0;
5824 message_options_load(sf, prefix);
5825 options_dialogs_load(sf);
5827 /* Load cma presets. If cma.number_of_presets doesn't exist, don't load
5828 * any, the order here should be reversed to keep the order the same */
5829 if (secfile_lookup_int(sf, &num, "cma.number_of_presets")) {
5830 for (i = num - 1; i >= 0; i--) {
5831 load_cma_preset(sf, i);
5833 } else {
5834 create_default_cma_presets();
5837 settable_options_load(sf);
5838 global_worklists_load(sf);
5840 secfile_destroy(sf);
5841 options_fully_initialized = TRUE;
5844 /**************************************************************************
5845 Write messages from option saving to the output window.
5846 **************************************************************************/
5847 static void option_save_output_window_callback(enum log_level lvl,
5848 const char *msg, ...)
5850 va_list args;
5852 va_start(args, msg);
5853 output_window_vprintf(ftc_client, msg, args);
5854 va_end(args);
5857 /**************************************************************************
5858 Save all options.
5859 **************************************************************************/
5860 void options_save(option_save_log_callback log_cb)
5862 struct section_file *sf;
5863 const char *name = get_current_option_file_name();
5864 char dir_name[2048];
5865 int i;
5867 if (log_cb == NULL) {
5868 /* Default callback */
5869 log_cb = option_save_output_window_callback;
5872 if (!name) {
5873 log_cb(LOG_ERROR, _("Save failed, cannot find a filename."));
5874 return;
5877 sf = secfile_new(TRUE);
5878 secfile_insert_str(sf, VERSION_STRING, "client.version");
5880 secfile_insert_bool(sf, gui_options.save_options_on_exit,
5881 "client.save_options_on_exit");
5882 secfile_insert_bool_comment(sf, gui_options.migrate_fullscreen,
5883 "deprecated", "client.fullscreen_mode");
5885 /* Migrations */
5886 secfile_insert_bool(sf, gui_options.gui_gtk3_22_migrated_from_gtk3,
5887 "client.migration_gtk3_22_from_gtk3");
5888 secfile_insert_bool(sf, gui_options.gui_gtk3_migrated_from_gtk2,
5889 "client.migration_gtk3_from_gtk2");
5890 secfile_insert_bool(sf, gui_options.gui_sdl2_migrated_from_sdl,
5891 "client.migration_sdl2_from_sdl");
5892 secfile_insert_bool(sf, gui_options.gui_gtk2_migrated_from_2_5,
5893 "client.migration_gtk2_from_2_5");
5894 secfile_insert_bool(sf, gui_options.gui_gtk3_migrated_from_2_5,
5895 "client.migration_gtk3_from_2_5");
5896 secfile_insert_bool(sf, gui_options.gui_qt_migrated_from_2_5,
5897 "client.migration_qt_from_2_5");
5899 /* gui-enabled options */
5900 client_options_iterate_all(poption) {
5901 client_option_save(poption, sf);
5902 } client_options_iterate_all_end;
5904 /* These are not gui-enabled yet. */
5905 secfile_insert_bool(sf, gui_options.zoom_set, "client.zoom_set");
5906 secfile_insert_float(sf, gui_options.zoom_default_level,
5907 "client.zoom_default_level");
5909 if (gui_options.default_tileset_name[0] != '\0') {
5910 secfile_insert_str(sf, gui_options.default_tileset_name,
5911 "client.default_tileset_name");
5914 message_options_save(sf, "client");
5915 options_dialogs_save(sf);
5917 /* server settings */
5918 save_cma_presets(sf);
5919 settable_options_save(sf);
5921 /* insert global worklists */
5922 global_worklists_save(sf);
5924 /* Directory name */
5925 strncpy(dir_name, name, sizeof(dir_name));
5926 for (i = strlen(dir_name) - 1 ; dir_name[i] != DIR_SEPARATOR_CHAR && i >= 0; i--) {
5927 /* Nothing */
5929 if (i > 0) {
5930 dir_name[i] = '\0';
5931 make_dir(dir_name);
5934 /* save to disk */
5935 if (!secfile_save(sf, name, 0, FZ_PLAIN)) {
5936 log_cb(LOG_ERROR, _("Save failed, cannot write to file %s"), name);
5937 } else {
5938 log_cb(LOG_VERBOSE, _("Saved settings to file %s"), name);
5940 secfile_destroy(sf);
5944 /**************************************************************************
5945 Initialize lists of names for a client option.
5946 **************************************************************************/
5947 static void options_init_names(const struct copt_val_name *(*acc)(int),
5948 struct strvec **support, struct strvec **pretty)
5950 int val;
5951 const struct copt_val_name *name;
5952 fc_assert_ret(NULL != acc);
5953 *support = strvec_new();
5954 *pretty = strvec_new();
5955 for (val=0; (name = acc(val)); val++) {
5956 strvec_append(*support, name->support);
5957 strvec_append(*pretty, name->pretty);
5961 /**************************************************************************
5962 Initialize the option module.
5963 **************************************************************************/
5964 void options_init(void)
5966 message_options_init();
5967 options_extra_init();
5968 global_worklists_init();
5970 settable_options_hash = settable_options_hash_new();
5971 dialog_options_hash = dialog_options_hash_new();
5973 client_options_iterate_all(poption) {
5974 struct client_option *pcoption = CLIENT_OPTION(poption);
5976 switch (option_type(poption)) {
5977 case OT_INTEGER:
5978 if (option_int_def(poption) < option_int_min(poption)
5979 || option_int_def(poption) > option_int_max(poption)) {
5980 int new_default = MAX(MIN(option_int_def(poption),
5981 option_int_max(poption)),
5982 option_int_min(poption));
5984 log_error("option %s has default value of %d, which is "
5985 "out of its range [%d; %d], changing to %d.",
5986 option_name(poption), option_int_def(poption),
5987 option_int_min(poption), option_int_max(poption),
5988 new_default);
5989 *((int *) &(pcoption->integer.def)) = new_default;
5991 break;
5993 case OT_STRING:
5994 if (gui_options.default_user_name == option_str_get(poption)) {
5995 /* Hack to get a default value. */
5996 *((const char **) &(pcoption->string.def)) =
5997 fc_strdup(gui_options.default_user_name);
6000 if (NULL == option_str_def(poption)) {
6001 const struct strvec *values = option_str_values(poption);
6003 if (NULL == values || strvec_size(values) == 0) {
6004 log_error("Invalid NULL default string for option %s.",
6005 option_name(poption));
6006 } else {
6007 *((const char **) &(pcoption->string.def)) =
6008 strvec_get(values, 0);
6011 break;
6013 case OT_ENUM:
6014 fc_assert(NULL == pcoption->enumerator.support_names);
6015 fc_assert(NULL == pcoption->enumerator.pretty_names);
6016 options_init_names(pcoption->enumerator.name_accessor,
6017 &pcoption->enumerator.support_names,
6018 &pcoption->enumerator.pretty_names);
6019 fc_assert(NULL != pcoption->enumerator.support_names);
6020 fc_assert(NULL != pcoption->enumerator.pretty_names);
6021 break;
6023 case OT_BITWISE:
6024 fc_assert(NULL == pcoption->bitwise.support_names);
6025 fc_assert(NULL == pcoption->bitwise.pretty_names);
6026 options_init_names(pcoption->bitwise.name_accessor,
6027 &pcoption->bitwise.support_names,
6028 &pcoption->bitwise.pretty_names);
6029 fc_assert(NULL != pcoption->bitwise.support_names);
6030 fc_assert(NULL != pcoption->bitwise.pretty_names);
6031 break;
6033 case OT_COLOR:
6035 /* Duplicate the string pointers. */
6036 struct ft_color *pcolor = pcoption->color.pvalue;
6038 if (NULL != pcolor->foreground) {
6039 pcolor->foreground = fc_strdup(pcolor->foreground);
6041 if (NULL != pcolor->background) {
6042 pcolor->background = fc_strdup(pcolor->background);
6046 case OT_BOOLEAN:
6047 case OT_FONT:
6048 case OT_VIDEO_MODE:
6049 break;
6052 /* Set to default. */
6053 option_reset(poption);
6054 } client_options_iterate_all_end;
6057 /**************************************************************************
6058 Free the option module.
6059 **************************************************************************/
6060 void options_free(void)
6062 client_options_iterate_all(poption) {
6063 struct client_option *pcoption = CLIENT_OPTION(poption);
6065 switch (option_type(poption)) {
6066 case OT_ENUM:
6067 fc_assert_action(NULL != pcoption->enumerator.support_names, break);
6068 strvec_destroy(pcoption->enumerator.support_names);
6069 pcoption->enumerator.support_names = NULL;
6070 fc_assert_action(NULL != pcoption->enumerator.pretty_names, break);
6071 strvec_destroy(pcoption->enumerator.pretty_names);
6072 pcoption->enumerator.pretty_names = NULL;
6073 break;
6075 case OT_BITWISE:
6076 fc_assert_action(NULL != pcoption->bitwise.support_names, break);
6077 strvec_destroy(pcoption->bitwise.support_names);
6078 pcoption->bitwise.support_names = NULL;
6079 fc_assert_action(NULL != pcoption->bitwise.pretty_names, break);
6080 strvec_destroy(pcoption->bitwise.pretty_names);
6081 pcoption->bitwise.pretty_names = NULL;
6082 break;
6084 case OT_BOOLEAN:
6085 case OT_INTEGER:
6086 case OT_STRING:
6087 case OT_FONT:
6088 case OT_COLOR:
6089 case OT_VIDEO_MODE:
6090 break;
6092 } client_options_iterate_all_end;
6094 if (NULL != settable_options_hash) {
6095 settable_options_hash_destroy(settable_options_hash);
6096 settable_options_hash = NULL;
6099 if (NULL != dialog_options_hash) {
6100 dialog_options_hash_destroy(dialog_options_hash);
6101 dialog_options_hash = NULL;
6104 message_options_free();
6105 global_worklists_free();
6108 /****************************************************************************
6109 Callback when the reqtree show icons option is changed. The tree is
6110 recalculated.
6111 ****************************************************************************/
6112 static void reqtree_show_icons_callback(struct option *poption)
6114 science_report_dialog_redraw();
6117 /****************************************************************************
6118 Callback for when any view option is changed.
6119 ****************************************************************************/
6120 static void view_option_changed_callback(struct option *poption)
6122 menus_init();
6123 update_map_canvas_visible();
6126 /****************************************************************************
6127 Callback for when any voteinfo bar option is changed.
6128 ****************************************************************************/
6129 static void voteinfo_bar_callback(struct option *poption)
6131 voteinfo_gui_update();
6134 /****************************************************************************
6135 Callback for font options.
6136 ****************************************************************************/
6137 static void font_changed_callback(struct option *poption)
6139 fc_assert_ret(OT_FONT == option_type(OPTION(poption)));
6140 gui_update_font(option_font_target(poption), option_font_get(poption));
6143 /****************************************************************************
6144 Callback for mapimg options.
6145 ****************************************************************************/
6146 static void mapimg_changed_callback(struct option *poption)
6148 if (!mapimg_client_define()) {
6149 bool success;
6151 log_normal("Error setting the value for %s (%s). Restoring the default "
6152 "value.", option_name(poption), mapimg_error());
6154 /* Reset the value to the default value. */
6155 success = option_reset(poption);
6156 fc_assert_msg(success == TRUE,
6157 "Failed to reset the option \"%s\".",
6158 option_name(poption));
6159 success = mapimg_client_define();
6160 fc_assert_msg(success == TRUE,
6161 "Failed to restore mapimg definition for option \"%s\".",
6162 option_name(poption));
6166 /****************************************************************************
6167 Callback for music enabling option.
6168 ****************************************************************************/
6169 static void game_music_enable_callback(struct option *poption)
6171 if (client_state() == C_S_RUNNING) {
6172 if (gui_options.sound_enable_game_music) {
6173 start_style_music();
6174 } else {
6175 stop_style_music();
6180 /****************************************************************************
6181 Callback for music enabling option.
6182 ****************************************************************************/
6183 static void menu_music_enable_callback(struct option *poption)
6185 if (client_state() != C_S_RUNNING) {
6186 if (gui_options.sound_enable_menu_music) {
6187 start_menu_music("music_menu", NULL);
6188 } else {
6189 stop_menu_music();
6194 /****************************************************************************
6195 Make dynamic adjustments to first-launch default options.
6196 ****************************************************************************/
6197 static void client_option_adjust_defaults(void)
6199 adjust_default_options();
6202 /****************************************************************************
6203 Convert a video mode to string. Returns TRUE on success.
6204 ****************************************************************************/
6205 bool video_mode_to_string(char *buf, size_t buf_len, struct video_mode *mode)
6207 return (2 < fc_snprintf(buf, buf_len, "%dx%d", mode->width, mode->height));
6210 /****************************************************************************
6211 Convert a string to video mode. Returns TRUE on success.
6212 ****************************************************************************/
6213 bool string_to_video_mode(const char *buf, struct video_mode *mode)
6215 return (2 == sscanf(buf, "%dx%d", &mode->width, &mode->height));
6218 /****************************************************************************
6219 Option framework wrapper for mapimg_get_format_list()
6220 ****************************************************************************/
6221 static const struct strvec *get_mapimg_format_list(const struct option *poption)
6223 return mapimg_get_format_list();
6226 /****************************************************************************
6227 What is the user defined tileset for the given topology
6228 ****************************************************************************/
6229 const char *tileset_name_for_topology(int topology_id)
6231 const char *tsn = NULL;
6233 switch (topology_id & (TF_ISO | TF_HEX)) {
6234 case 0:
6235 tsn = gui_options.default_tileset_overhead_name;
6236 break;
6237 case TF_ISO:
6238 tsn = gui_options.default_tileset_iso_name;
6239 break;
6240 case TF_HEX:
6241 tsn = gui_options.default_tileset_hex_name;
6242 break;
6243 case TF_ISO | TF_HEX:
6244 tsn = gui_options.default_tileset_isohex_name;
6245 break;
6248 if (tsn == NULL) {
6249 tsn = gui_options.default_tileset_name;
6252 return tsn;
6255 /****************************************************************************
6256 Set given tileset as the default for suitable topology
6257 ****************************************************************************/
6258 void option_set_default_ts(struct tileset *t)
6260 const char *optname = "<not set>";
6261 struct option *opt;
6263 switch (tileset_topo_index(t)) {
6264 case TS_TOPO_OVERHEAD:
6265 /* Overhead */
6266 optname = "default_tileset_overhead_name";
6267 break;
6268 case TS_TOPO_ISO:
6269 /* Iso */
6270 optname = "default_tileset_iso_name";
6271 break;
6272 case TS_TOPO_HEX:
6273 /* Hex */
6274 optname = "default_tileset_hex_name";
6275 break;
6276 case TS_TOPO_ISOHEX:
6277 /* Isohex */
6278 optname = "default_tileset_isohex_name";
6279 break;
6282 opt = optset_option_by_name(client_optset, optname);
6284 if (opt == NULL) {
6285 log_error("Unknown option name \"%s\" in option_set_default_ts()", optname);
6286 return;
6289 /* Do not call option_str_set() since we don't want option changed callback
6290 * to reload this tileset. */
6291 opt->str_vtable->set(opt, tileset_basename(t));
6292 option_gui_update(opt);
6295 /****************************************************************************
6296 Does topology-specific tileset option lack value?
6297 ****************************************************************************/
6298 static bool is_ts_option_unset(const char *optname)
6300 struct option *opt;
6301 const char *val;
6303 opt = optset_option_by_name(client_optset, optname);
6305 if (opt == NULL) {
6306 return TRUE;
6309 val = opt->str_vtable->get(opt);
6311 if (val == NULL || val[0] == '\0') {
6312 return TRUE;
6315 return FALSE;
6318 /****************************************************************************
6319 Fill default tilesets for topology-specific settings.
6320 ****************************************************************************/
6321 void fill_topo_ts_default(void)
6323 if (is_ts_option_unset("default_tileset_overhead_name")) {
6324 log_debug("Setting tileset for overhead topology.");
6325 tilespec_try_read(NULL, FALSE, 0, FALSE);
6327 if (is_ts_option_unset("default_tileset_iso_name")) {
6328 log_debug("Setting tileset for iso topology.");
6329 tilespec_try_read(NULL, FALSE, TF_ISO, FALSE);
6331 if (is_ts_option_unset("default_tileset_hex_name")) {
6332 log_debug("Setting tileset for hex topology.");
6333 tilespec_try_read(NULL, FALSE, TF_HEX, FALSE);
6335 if (is_ts_option_unset("default_tileset_isohex_name")) {
6336 log_debug("Setting tileset for isohex topology.");
6337 tilespec_try_read(NULL, FALSE, TF_ISO | TF_HEX, FALSE);