webperimental: killstack decides stack protects.
[freeciv.git] / client / options.c
blobdf75a6bb808d8b1c5f1541a6ab138e8f6cc2cc09
1 /***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12 ***********************************************************************/
14 #ifdef HAVE_CONFIG_H
15 #include <fc_config.h>
16 #endif
18 #include <stdarg.h>
19 #include <string.h>
20 #include <sys/stat.h>
21 #include <sys/types.h>
23 /* utility */
24 #include "fcintl.h"
25 #include "ioz.h"
26 #include "log.h"
27 #include "mem.h"
28 #include "registry.h"
29 #include "shared.h"
30 #include "string_vector.h"
31 #include "support.h"
33 /* common */
34 #include "events.h"
35 #include "version.h"
37 /* client/agents */
38 #include "cma_fec.h"
40 /* client/include */
41 #include "chatline_g.h"
42 #include "dialogs_g.h"
43 #include "gui_main_g.h"
44 #include "menu_g.h"
45 #include "optiondlg_g.h"
46 #include "repodlgs_g.h"
47 #include "voteinfo_bar_g.h"
49 /* client */
50 #include "audio.h"
51 #include "cityrepdata.h"
52 #include "client_main.h"
53 #include "climisc.h"
54 #include "connectdlg_common.h"
55 #include "global_worklist.h"
56 #include "mapctrl_common.h"
57 #include "mapview_common.h"
58 #include "music.h"
59 #include "overview_common.h"
60 #include "packhand_gen.h"
61 #include "plrdlg_common.h"
62 #include "repodlgs_common.h"
63 #include "servers.h"
64 #include "themes_common.h"
65 #include "tilespec.h"
67 #include "options.h"
70 struct client_options gui_options = {
71 /** Defaults for options normally on command line **/
73 .default_user_name = "\0",
74 .default_server_host = "localhost",
75 .default_server_port = DEFAULT_SOCK_PORT,
76 .default_metaserver = DEFAULT_METASERVER_OPTION,
77 .default_tileset_overhead_name = "\0",
78 .default_tileset_iso_name = "\0",
79 .default_tileset_hex_name = "\0",
80 .default_tileset_isohex_name = "\0",
81 .default_sound_set_name = "stdsounds",
82 .default_music_set_name = "stdmusic",
83 .default_sound_plugin_name = "\0",
84 .default_chat_logfile = GUI_DEFAULT_CHAT_LOGFILE,
86 .save_options_on_exit = TRUE,
88 .use_prev_server = FALSE,
89 .heartbeat_enabled = FALSE,
91 /** Migrations **/
92 .first_boot = FALSE,
93 .default_tileset_name = "\0",
94 .gui_gtk3_migrated_from_gtk2 = FALSE,
95 .gui_gtk3_22_migrated_from_gtk3 = FALSE,
96 .gui_gtk4_migrated_from_gtk3_22 = FALSE,
97 .gui_sdl2_migrated_from_sdl = FALSE,
98 .gui_gtk2_migrated_from_2_5 = FALSE,
99 .gui_gtk3_migrated_from_2_5 = FALSE,
100 .gui_qt_migrated_from_2_5 = FALSE,
102 .migrate_fullscreen = FALSE,
104 /** Local Options: **/
106 .solid_color_behind_units = FALSE,
107 .sound_bell_at_new_turn = FALSE,
108 .smooth_move_unit_msec = 30,
109 .smooth_center_slide_msec = 200,
110 .smooth_combat_step_msec = 10,
111 .ai_manual_turn_done = TRUE,
112 .auto_center_on_unit = TRUE,
113 .auto_center_on_automated = TRUE,
114 .auto_center_on_combat = FALSE,
115 .auto_center_each_turn = TRUE,
116 .wakeup_focus = TRUE,
117 .goto_into_unknown = TRUE,
118 .center_when_popup_city = TRUE,
119 .show_previous_turn_messages = TRUE,
120 .concise_city_production = FALSE,
121 .auto_turn_done = FALSE,
122 .meta_accelerators = TRUE,
123 .ask_city_name = TRUE,
124 .popup_new_cities = TRUE,
125 .popup_actor_arrival = TRUE,
126 .popup_attack_actions = TRUE,
127 .keyboardless_goto = TRUE,
128 .enable_cursor_changes = TRUE,
129 .separate_unit_selection = FALSE,
130 .unit_selection_clears_orders = TRUE,
131 .highlight_our_names = FT_COLOR("#000000", "#FFFF00"),
133 .voteinfo_bar_use = TRUE,
134 .voteinfo_bar_always_show = FALSE,
135 .voteinfo_bar_hide_when_not_player = FALSE,
136 .voteinfo_bar_new_at_front = FALSE,
138 .autoaccept_tileset_suggestion = FALSE,
139 .autoaccept_soundset_suggestion = FALSE,
140 .autoaccept_musicset_suggestion = FALSE,
142 .sound_enable_effects = TRUE,
143 .sound_enable_menu_music = TRUE,
144 .sound_enable_game_music = TRUE,
146 /* This option is currently set by the client - not by the user. */
147 .update_city_text_in_refresh_tile = TRUE,
149 .draw_city_outlines = TRUE,
150 .draw_city_output = FALSE,
151 .draw_map_grid = FALSE,
152 .draw_city_names = TRUE,
153 .draw_city_growth = TRUE,
154 .draw_city_productions = TRUE,
155 .draw_city_buycost = FALSE,
156 .draw_city_trade_routes = FALSE,
157 .draw_terrain = TRUE,
158 .draw_coastline = FALSE,
159 .draw_roads_rails = TRUE,
160 .draw_irrigation = TRUE,
161 .draw_mines = TRUE,
162 .draw_fortress_airbase = TRUE,
163 .draw_specials = TRUE,
164 .draw_huts = TRUE,
165 .draw_pollution = TRUE,
166 .draw_cities = TRUE,
167 .draw_units = TRUE,
168 .draw_focus_unit = FALSE,
169 .draw_fog_of_war = TRUE,
170 .draw_borders = TRUE,
171 .draw_native = FALSE,
172 .draw_full_citybar = TRUE,
173 .draw_unit_shields = TRUE,
174 .player_dlg_show_dead_players = TRUE,
175 .reqtree_show_icons = TRUE,
176 .reqtree_curved_lines = FALSE,
178 /* options for map images */
179 /* .mapimg_format, */
180 .mapimg_zoom = 2,
181 /* See the definition of MAPIMG_LAYER in mapimg.h. */
182 .mapimg_layer = {
183 FALSE, /* a - MAPIMG_LAYER_AREA */
184 TRUE, /* b - MAPIMG_LAYER_BORDERS */
185 TRUE, /* c - MAPIMG_LAYER_CITIES */
186 TRUE, /* f - MAPIMG_LAYER_FOGOFWAR */
187 TRUE, /* k - MAPIMG_LAYER_KNOWLEDGE */
188 TRUE, /* t - MAPIMG_LAYER_TERRAIN */
189 TRUE /* u - MAPIMG_LAYER_UNITS */
191 /* .mapimg_filename, */
193 .zoom_set = FALSE,
194 .zoom_default_level = 1.0,
196 /* gui-gtk-2.0 client specific options. */
197 .gui_gtk2_default_theme_name = FC_GTK2_DEFAULT_THEME_NAME,
198 .gui_gtk2_fullscreen = FALSE,
199 .gui_gtk2_map_scrollbars = FALSE,
200 .gui_gtk2_dialogs_on_top = TRUE,
201 .gui_gtk2_show_task_icons = TRUE,
202 .gui_gtk2_enable_tabs = TRUE,
203 .gui_gtk2_better_fog = TRUE,
204 .gui_gtk2_show_chat_message_time = FALSE,
205 .gui_gtk2_new_messages_go_to_top = FALSE,
206 .gui_gtk2_show_message_window_buttons = TRUE,
207 .gui_gtk2_metaserver_tab_first = FALSE,
208 .gui_gtk2_allied_chat_only = FALSE,
209 .gui_gtk2_message_chat_location = GUI_GTK_MSGCHAT_MERGED,
210 .gui_gtk2_small_display_layout = TRUE,
211 .gui_gtk2_mouse_over_map_focus = FALSE,
212 .gui_gtk2_chatline_autocompletion = TRUE,
213 .gui_gtk2_citydlg_xsize = GUI_GTK2_CITYDLG_DEFAULT_XSIZE,
214 .gui_gtk2_citydlg_ysize = GUI_GTK2_CITYDLG_DEFAULT_YSIZE,
215 .gui_gtk2_popup_tech_help = GUI_POPUP_TECH_HELP_RULESET,
216 .gui_gtk2_font_city_label = "Monospace 8",
217 .gui_gtk2_font_notify_label = "Monospace Bold 9",
218 .gui_gtk2_font_spaceship_label = "Monospace 8",
219 .gui_gtk2_font_help_label = "Sans Bold 10",
220 .gui_gtk2_font_help_link = "Sans 9",
221 .gui_gtk2_font_help_text = "Monospace 8",
222 .gui_gtk2_font_chatline = "Monospace 8",
223 .gui_gtk2_font_beta_label = "Sans Italic 10",
224 .gui_gtk2_font_small = "Sans 9",
225 .gui_gtk2_font_comment_label = "Sans Italic 9",
226 .gui_gtk2_font_city_names = "Sans Bold 10",
227 .gui_gtk2_font_city_productions = "Serif 10",
228 .gui_gtk2_font_reqtree_text = "Serif 10",
230 /* gui-gtk-3.0 client specific options. */
231 .gui_gtk3_default_theme_name = FC_GTK3_DEFAULT_THEME_NAME,
232 .gui_gtk3_fullscreen = FALSE,
233 .gui_gtk3_map_scrollbars = FALSE,
234 .gui_gtk3_dialogs_on_top = TRUE,
235 .gui_gtk3_show_task_icons = TRUE,
236 .gui_gtk3_enable_tabs = TRUE,
237 .gui_gtk3_show_chat_message_time = FALSE,
238 .gui_gtk3_new_messages_go_to_top = FALSE,
239 .gui_gtk3_show_message_window_buttons = TRUE,
240 .gui_gtk3_metaserver_tab_first = FALSE,
241 .gui_gtk3_allied_chat_only = FALSE,
242 .gui_gtk3_message_chat_location = GUI_GTK_MSGCHAT_MERGED,
243 .gui_gtk3_small_display_layout = TRUE,
244 .gui_gtk3_mouse_over_map_focus = FALSE,
245 .gui_gtk3_chatline_autocompletion = TRUE,
246 .gui_gtk3_citydlg_xsize = GUI_GTK3_CITYDLG_DEFAULT_XSIZE,
247 .gui_gtk3_citydlg_ysize = GUI_GTK3_CITYDLG_DEFAULT_YSIZE,
248 .gui_gtk3_popup_tech_help = GUI_POPUP_TECH_HELP_RULESET,
249 .gui_gtk3_governor_range_min = -20,
250 .gui_gtk3_governor_range_max = 20,
251 .gui_gtk3_font_city_label = "Monospace 8",
252 .gui_gtk3_font_notify_label = "Monospace Bold 9",
253 .gui_gtk3_font_spaceship_label = "Monospace 8",
254 .gui_gtk3_font_help_label = "Sans Bold 10",
255 .gui_gtk3_font_help_link = "Sans 9",
256 .gui_gtk3_font_help_text = "Monospace 8",
257 .gui_gtk3_font_chatline = "Monospace 8",
258 .gui_gtk3_font_beta_label = "Sans Italic 10",
259 .gui_gtk3_font_small = "Sans 9",
260 .gui_gtk3_font_comment_label = "Sans Italic 9",
261 .gui_gtk3_font_city_names = "Sans Bold 10",
262 .gui_gtk3_font_city_productions = "Serif 10",
263 .gui_gtk3_font_reqtree_text = "Serif 10",
265 /* gui-gtk-3.22 client specific options. */
266 .gui_gtk3_22_default_theme_name = FC_GTK3_22_DEFAULT_THEME_NAME,
267 .gui_gtk3_22_fullscreen = FALSE,
268 .gui_gtk3_22_map_scrollbars = FALSE,
269 .gui_gtk3_22_dialogs_on_top = TRUE,
270 .gui_gtk3_22_show_task_icons = TRUE,
271 .gui_gtk3_22_enable_tabs = TRUE,
272 .gui_gtk3_22_show_chat_message_time = FALSE,
273 .gui_gtk3_22_new_messages_go_to_top = FALSE,
274 .gui_gtk3_22_show_message_window_buttons = TRUE,
275 .gui_gtk3_22_metaserver_tab_first = FALSE,
276 .gui_gtk3_22_allied_chat_only = FALSE,
277 .gui_gtk3_22_message_chat_location = GUI_GTK_MSGCHAT_MERGED,
278 .gui_gtk3_22_small_display_layout = TRUE,
279 .gui_gtk3_22_mouse_over_map_focus = FALSE,
280 .gui_gtk3_22_chatline_autocompletion = TRUE,
281 .gui_gtk3_22_citydlg_xsize = GUI_GTK3_22_CITYDLG_DEFAULT_XSIZE,
282 .gui_gtk3_22_citydlg_ysize = GUI_GTK3_22_CITYDLG_DEFAULT_YSIZE,
283 .gui_gtk3_22_popup_tech_help = GUI_POPUP_TECH_HELP_RULESET,
284 .gui_gtk3_22_governor_range_min = -20,
285 .gui_gtk3_22_governor_range_max = 20,
286 .gui_gtk3_22_font_city_label = "Monospace 8",
287 .gui_gtk3_22_font_notify_label = "Monospace Bold 9",
288 .gui_gtk3_22_font_spaceship_label = "Monospace 8",
289 .gui_gtk3_22_font_help_label = "Sans Bold 10",
290 .gui_gtk3_22_font_help_link = "Sans 9",
291 .gui_gtk3_22_font_help_text = "Monospace 8",
292 .gui_gtk3_22_font_chatline = "Monospace 8",
293 .gui_gtk3_22_font_beta_label = "Sans Italic 10",
294 .gui_gtk3_22_font_small = "Sans 9",
295 .gui_gtk3_22_font_comment_label = "Sans Italic 9",
296 .gui_gtk3_22_font_city_names = "Sans Bold 10",
297 .gui_gtk3_22_font_city_productions = "Serif 10",
298 .gui_gtk3_22_font_reqtree_text = "Serif 10",
300 /* gui-gtk-3.x client specific options. */
301 .gui_gtk4_default_theme_name = FC_GTK4_DEFAULT_THEME_NAME,
302 .gui_gtk4_fullscreen = FALSE,
303 .gui_gtk4_map_scrollbars = FALSE,
304 .gui_gtk4_dialogs_on_top = TRUE,
305 .gui_gtk4_show_task_icons = TRUE,
306 .gui_gtk4_enable_tabs = TRUE,
307 .gui_gtk4_show_chat_message_time = FALSE,
308 .gui_gtk4_new_messages_go_to_top = FALSE,
309 .gui_gtk4_show_message_window_buttons = TRUE,
310 .gui_gtk4_metaserver_tab_first = FALSE,
311 .gui_gtk4_allied_chat_only = FALSE,
312 .gui_gtk4_message_chat_location = GUI_GTK_MSGCHAT_MERGED,
313 .gui_gtk4_small_display_layout = TRUE,
314 .gui_gtk4_mouse_over_map_focus = FALSE,
315 .gui_gtk4_chatline_autocompletion = TRUE,
316 .gui_gtk4_citydlg_xsize = GUI_GTK4_CITYDLG_DEFAULT_XSIZE,
317 .gui_gtk4_citydlg_ysize = GUI_GTK4_CITYDLG_DEFAULT_YSIZE,
318 .gui_gtk4_popup_tech_help = GUI_POPUP_TECH_HELP_RULESET,
319 .gui_gtk4_governor_range_min = -20,
320 .gui_gtk4_governor_range_max = 20,
321 .gui_gtk4_font_city_label = "Monospace 8",
322 .gui_gtk4_font_notify_label = "Monospace Bold 9",
323 .gui_gtk4_font_spaceship_label = "Monospace 8",
324 .gui_gtk4_font_help_label = "Sans Bold 10",
325 .gui_gtk4_font_help_link = "Sans 9",
326 .gui_gtk4_font_help_text = "Monospace 8",
327 .gui_gtk4_font_chatline = "Monospace 8",
328 .gui_gtk4_font_beta_label = "Sans Italic 10",
329 .gui_gtk4_font_small = "Sans 9",
330 .gui_gtk4_font_comment_label = "Sans Italic 9",
331 .gui_gtk4_font_city_names = "Sans Bold 10",
332 .gui_gtk4_font_city_productions = "Serif 10",
333 .gui_gtk4_font_reqtree_text = "Serif 10",
335 /* gui-sdl client specific options. */
336 .gui_sdl_fullscreen = FALSE,
337 .gui_sdl_screen = VIDEO_MODE(640, 480),
338 .gui_sdl_do_cursor_animation = TRUE,
339 .gui_sdl_use_color_cursors = TRUE,
341 /* gui-sdl2 client specific options. */
342 .gui_sdl2_default_theme_name = FC_SDL2_DEFAULT_THEME_NAME,
343 .gui_sdl2_fullscreen = FALSE,
344 .gui_sdl2_screen = VIDEO_MODE(640, 480),
345 .gui_sdl2_swrenderer = FALSE,
346 .gui_sdl2_do_cursor_animation = TRUE,
347 .gui_sdl2_use_color_cursors = TRUE,
349 /* gui-qt client specific options. */
350 .gui_qt_fullscreen = FALSE,
351 .gui_qt_show_preview = TRUE,
352 .gui_qt_sidebar_left = TRUE,
353 .gui_qt_default_theme_name = FC_QT_DEFAULT_THEME_NAME,
354 .gui_qt_font_city_label = "Monospace,8,-1,5,50,0,0,0,0,0",
355 .gui_qt_font_default = "Sans Serif,10,-1,5,75,0,0,0,0,0",
356 .gui_qt_font_notify_label = "Monospace,8,-1,5,75,0,0,0,0,0",
357 .gui_qt_font_spaceship_label = "Monospace,8,-1,5,50,0,0,0,0,0",
358 .gui_qt_font_help_label = "Sans Serif,9,-1,5,50,0,0,0,0,0",
359 .gui_qt_font_help_link = "Sans Serif,9,-1,5,50,0,0,0,0,0",
360 .gui_qt_font_help_text = "Monospace,8,-1,5,50,0,0,0,0,0",
361 .gui_qt_font_help_title = "Sans Serif,10,-1,5,75,0,0,0,0,0",
362 .gui_qt_font_chatline = "Monospace,8,-1,5,50,0,0,0,0,0",
363 .gui_qt_font_beta_label = "Sans Serif,10,-1,5,50,1,0,0,0,0",
364 .gui_qt_font_small = "Sans Serif,9,-1,5,50,0,0,0,0,0",
365 .gui_qt_font_comment_label = "Sans Serif,9,-1,5,50,1,0,0,0,0",
366 .gui_qt_font_city_names = "Sans Serif,10,-1,5,75,0,0,0,0,0",
367 .gui_qt_font_city_productions = "Sans Serif,10,-1,5,50,1,0,0,0,0",
368 .gui_qt_font_reqtree_text = "Sans Serif,10,-1,5,50,1,0,0,0,0",
369 .gui_qt_show_titlebar = TRUE,
370 .gui_qt_wakeup_text = "Wake up %1"
373 /* Set to TRUE after the first call to options_init(), to avoid the usage
374 * of non-initialized datas when calling the changed callback. */
375 static bool options_fully_initialized = FALSE;
377 static const struct strvec *get_mapimg_format_list(const struct option *poption);
379 /****************************************************************************
380 Option set structure.
381 ****************************************************************************/
382 struct option_set {
383 struct option * (*option_by_number) (int);
384 struct option * (*option_first) (void);
386 int (*category_number) (void);
387 const char * (*category_name) (int);
390 /****************************************************************************
391 Returns the option corresponding of the number in this option set.
392 ****************************************************************************/
393 struct option *optset_option_by_number(const struct option_set *poptset,
394 int id)
396 fc_assert_ret_val(NULL != poptset, NULL);
398 return poptset->option_by_number(id);
401 /****************************************************************************
402 Returns the option corresponding of the name in this option set.
403 ****************************************************************************/
404 struct option *optset_option_by_name(const struct option_set *poptset,
405 const char *name)
407 fc_assert_ret_val(NULL != poptset, NULL);
409 options_iterate(poptset, poption) {
410 if (0 == strcmp(option_name(poption), name)) {
411 return poption;
413 } options_iterate_end;
414 return NULL;
417 /****************************************************************************
418 Returns the first option of this option set.
419 ****************************************************************************/
420 struct option *optset_option_first(const struct option_set *poptset)
422 fc_assert_ret_val(NULL != poptset, NULL);
424 return poptset->option_first();
427 /****************************************************************************
428 Returns the number of categories of this option set.
429 ****************************************************************************/
430 int optset_category_number(const struct option_set *poptset)
432 fc_assert_ret_val(NULL != poptset, 0);
434 return poptset->category_number();
437 /****************************************************************************
438 Returns the name (translated) of the category of this option set.
439 ****************************************************************************/
440 const char *optset_category_name(const struct option_set *poptset,
441 int category)
443 fc_assert_ret_val(NULL != poptset, NULL);
445 return poptset->category_name(category);
449 /****************************************************************************
450 The base class for options.
451 ****************************************************************************/
452 struct option {
453 /* A link to the option set. */
454 const struct option_set *poptset;
455 /* Type of the option. */
456 enum option_type type;
458 /* Common accessors. */
459 const struct option_common_vtable {
460 int (*number) (const struct option *);
461 const char * (*name) (const struct option *);
462 const char * (*description) (const struct option *);
463 const char * (*help_text) (const struct option *);
464 int (*category) (const struct option *);
465 bool (*is_changeable) (const struct option *);
466 struct option * (*next) (const struct option *);
467 } *common_vtable;
468 /* Specific typed accessors. */
469 union {
470 /* Specific boolean accessors (OT_BOOLEAN == type). */
471 const struct option_bool_vtable {
472 bool (*get) (const struct option *);
473 bool (*def) (const struct option *);
474 bool (*set) (struct option *, bool);
475 } *bool_vtable;
476 /* Specific integer accessors (OT_INTEGER == type). */
477 const struct option_int_vtable {
478 int (*get) (const struct option *);
479 int (*def) (const struct option *);
480 int (*minimum) (const struct option *);
481 int (*maximum) (const struct option *);
482 bool (*set) (struct option *, int);
483 } *int_vtable;
484 /* Specific string accessors (OT_STRING == type). */
485 const struct option_str_vtable {
486 const char * (*get) (const struct option *);
487 const char * (*def) (const struct option *);
488 const struct strvec * (*values) (const struct option *);
489 bool (*set) (struct option *, const char *);
490 } *str_vtable;
491 /* Specific enum accessors (OT_ENUM == type). */
492 const struct option_enum_vtable {
493 int (*get) (const struct option *);
494 int (*def) (const struct option *);
495 const struct strvec * (*values) (const struct option *);
496 bool (*set) (struct option *, int);
497 int (*cmp) (const char *, const char *);
498 } *enum_vtable;
499 /* Specific bitwise accessors (OT_BITWISE == type). */
500 const struct option_bitwise_vtable {
501 unsigned (*get) (const struct option *);
502 unsigned (*def) (const struct option *);
503 const struct strvec * (*values) (const struct option *);
504 bool (*set) (struct option *, unsigned);
505 } *bitwise_vtable;
506 /* Specific font accessors (OT_FONT == type). */
507 const struct option_font_vtable {
508 const char * (*get) (const struct option *);
509 const char * (*def) (const struct option *);
510 const char * (*target) (const struct option *);
511 bool (*set) (struct option *, const char *);
512 } *font_vtable;
513 /* Specific color accessors (OT_COLOR == type). */
514 const struct option_color_vtable {
515 struct ft_color (*get) (const struct option *);
516 struct ft_color (*def) (const struct option *);
517 bool (*set) (struct option *, struct ft_color);
518 } *color_vtable;
519 /* Specific video mode accessors (OT_VIDEO_MODE == type). */
520 const struct option_video_mode_vtable {
521 struct video_mode (*get) (const struct option *);
522 struct video_mode (*def) (const struct option *);
523 bool (*set) (struct option *, struct video_mode);
524 } *video_mode_vtable;
527 /* Called after the value changed. */
528 void (*changed_callback) (struct option *option);
530 int callback_data;
532 /* Volatile. */
533 void *gui_data;
536 #define OPTION(poption) ((struct option *) (poption))
538 #define OPTION_INIT(optset, spec_type, spec_table_var, common_table, \
539 spec_table, changed_cb, cb_data) { \
540 .poptset = optset, \
541 .type = spec_type, \
542 .common_vtable = &common_table, \
543 INIT_BRACE_BEGIN \
544 .spec_table_var = &spec_table \
545 INIT_BRACE_END, \
546 .changed_callback = changed_cb, \
547 .callback_data = cb_data, \
548 .gui_data = NULL \
550 #define OPTION_BOOL_INIT(optset, common_table, bool_table, changed_cb) \
551 OPTION_INIT(optset, OT_BOOLEAN, bool_vtable, common_table, bool_table, \
552 changed_cb, 0)
553 #define OPTION_INT_INIT(optset, common_table, int_table, changed_cb) \
554 OPTION_INIT(optset, OT_INTEGER, int_vtable, common_table, int_table, \
555 changed_cb, 0)
556 #define OPTION_STR_INIT(optset, common_table, str_table, changed_cb, cb_data) \
557 OPTION_INIT(optset, OT_STRING, str_vtable, common_table, str_table, \
558 changed_cb, cb_data)
559 #define OPTION_ENUM_INIT(optset, common_table, enum_table, changed_cb) \
560 OPTION_INIT(optset, OT_ENUM, enum_vtable, common_table, enum_table, \
561 changed_cb, 0)
562 #define OPTION_BITWISE_INIT(optset, common_table, bitwise_table, \
563 changed_cb) \
564 OPTION_INIT(optset, OT_BITWISE, bitwise_vtable, common_table, \
565 bitwise_table, changed_cb, 0)
566 #define OPTION_FONT_INIT(optset, common_table, font_table, changed_cb) \
567 OPTION_INIT(optset, OT_FONT, font_vtable, common_table, font_table, \
568 changed_cb, 0)
569 #define OPTION_COLOR_INIT(optset, common_table, color_table, changed_cb) \
570 OPTION_INIT(optset, OT_COLOR, color_vtable, common_table, color_table, \
571 changed_cb, 0)
572 #define OPTION_VIDEO_MODE_INIT(optset, common_table, video_mode_table, \
573 changed_cb) \
574 OPTION_INIT(optset, OT_VIDEO_MODE, video_mode_vtable, common_table, \
575 video_mode_table, changed_cb, 0)
578 /****************************************************************************
579 Returns the option set owner of this option.
580 ****************************************************************************/
581 const struct option_set *option_optset(const struct option *poption)
583 fc_assert_ret_val(NULL != poption, NULL);
585 return poption->poptset;
588 /****************************************************************************
589 Returns the number of the option.
590 ****************************************************************************/
591 int option_number(const struct option *poption)
593 fc_assert_ret_val(NULL != poption, -1);
595 return poption->common_vtable->number(poption);
598 /****************************************************************************
599 Returns the name of the option.
600 ****************************************************************************/
601 const char *option_name(const struct option *poption)
603 fc_assert_ret_val(NULL != poption, NULL);
605 return poption->common_vtable->name(poption);
608 /****************************************************************************
609 Returns the description (translated) of the option.
610 ****************************************************************************/
611 const char *option_description(const struct option *poption)
613 fc_assert_ret_val(NULL != poption, NULL);
615 return poption->common_vtable->description(poption);
618 /****************************************************************************
619 Returns the help text (translated) of the option.
620 ****************************************************************************/
621 const char *option_help_text(const struct option *poption)
623 fc_assert_ret_val(NULL != poption, NULL);
625 return poption->common_vtable->help_text(poption);
628 /****************************************************************************
629 Returns the type of the option.
630 ****************************************************************************/
631 enum option_type option_type(const struct option *poption)
633 fc_assert_ret_val(NULL != poption, -1);
635 return poption->type;
638 /****************************************************************************
639 Returns the category of the option.
640 ****************************************************************************/
641 int option_category(const struct option *poption)
643 fc_assert_ret_val(NULL != poption, -1);
645 return poption->common_vtable->category(poption);
648 /****************************************************************************
649 Returns the name (tranlated) of the category of the option.
650 ****************************************************************************/
651 const char *option_category_name(const struct option *poption)
653 fc_assert_ret_val(NULL != poption, NULL);
655 return optset_category_name(poption->poptset,
656 poption->common_vtable->category(poption));
659 /****************************************************************************
660 Returns TRUE if this option can be modified.
661 ****************************************************************************/
662 bool option_is_changeable(const struct option *poption)
664 fc_assert_ret_val(NULL != poption, FALSE);
666 return poption->common_vtable->is_changeable(poption);
669 /****************************************************************************
670 Returns the next option or NULL if this is the last.
671 ****************************************************************************/
672 struct option *option_next(const struct option *poption)
674 fc_assert_ret_val(NULL != poption, NULL);
676 return poption->common_vtable->next(poption);
679 /****************************************************************************
680 Set the option to its default value. Returns TRUE if the option changed.
681 ****************************************************************************/
682 bool option_reset(struct option *poption)
684 fc_assert_ret_val(NULL != poption, FALSE);
686 switch (option_type(poption)) {
687 case OT_BOOLEAN:
688 return option_bool_set(poption, option_bool_def(poption));
689 case OT_INTEGER:
690 return option_int_set(poption, option_int_def(poption));
691 case OT_STRING:
692 return option_str_set(poption, option_str_def(poption));
693 case OT_ENUM:
694 return option_enum_set_int(poption, option_enum_def_int(poption));
695 case OT_BITWISE:
696 return option_bitwise_set(poption, option_bitwise_def(poption));
697 case OT_FONT:
698 return option_font_set(poption, option_font_def(poption));
699 case OT_COLOR:
700 return option_color_set(poption, option_color_def(poption));
701 case OT_VIDEO_MODE:
702 return option_video_mode_set(poption, option_video_mode_def(poption));
704 return FALSE;
707 /****************************************************************************
708 Set the function to call every time this option changes. Can be NULL.
709 ****************************************************************************/
710 void option_set_changed_callback(struct option *poption,
711 void (*callback) (struct option *))
713 fc_assert_ret(NULL != poption);
715 poption->changed_callback = callback;
718 /****************************************************************************
719 Force to use the option changed callback.
720 ****************************************************************************/
721 void option_changed(struct option *poption)
723 fc_assert_ret(NULL != poption);
725 if (!options_fully_initialized) {
726 /* Prevent to use non-initialized datas. */
727 return;
730 if (poption->changed_callback) {
731 poption->changed_callback(poption);
734 option_gui_update(poption);
737 /****************************************************************************
738 Set the gui data for this option.
739 ****************************************************************************/
740 void option_set_gui_data(struct option *poption, void *data)
742 fc_assert_ret(NULL != poption);
744 poption->gui_data = data;
747 /****************************************************************************
748 Returns the gui data of this option.
749 ****************************************************************************/
750 void *option_get_gui_data(const struct option *poption)
752 fc_assert_ret_val(NULL != poption, NULL);
754 return poption->gui_data;
757 /****************************************************************************
758 Returns the callback data of this option.
759 ****************************************************************************/
760 int option_get_cb_data(const struct option *poption)
762 fc_assert_ret_val(NULL != poption, 0);
764 return poption->callback_data;
767 /****************************************************************************
768 Returns the current value of this boolean option.
769 ****************************************************************************/
770 bool option_bool_get(const struct option *poption)
772 fc_assert_ret_val(NULL != poption, FALSE);
773 fc_assert_ret_val(OT_BOOLEAN == poption->type, FALSE);
775 return poption->bool_vtable->get(poption);
778 /****************************************************************************
779 Returns the default value of this boolean option.
780 ****************************************************************************/
781 bool option_bool_def(const struct option *poption)
783 fc_assert_ret_val(NULL != poption, FALSE);
784 fc_assert_ret_val(OT_BOOLEAN == poption->type, FALSE);
786 return poption->bool_vtable->def(poption);
789 /****************************************************************************
790 Sets the value of this boolean option. Returns TRUE if the value changed.
791 ****************************************************************************/
792 bool option_bool_set(struct option *poption, bool val)
794 fc_assert_ret_val(NULL != poption, FALSE);
795 fc_assert_ret_val(OT_BOOLEAN == poption->type, FALSE);
797 if (poption->bool_vtable->set(poption, val)) {
798 option_changed(poption);
799 return TRUE;
801 return FALSE;
804 /****************************************************************************
805 Returns the current value of this integer option.
806 ****************************************************************************/
807 int option_int_get(const struct option *poption)
809 fc_assert_ret_val(NULL != poption, 0);
810 fc_assert_ret_val(OT_INTEGER == poption->type, 0);
812 return poption->int_vtable->get(poption);
815 /****************************************************************************
816 Returns the default value of this integer option.
817 ****************************************************************************/
818 int option_int_def(const struct option *poption)
820 fc_assert_ret_val(NULL != poption, 0);
821 fc_assert_ret_val(OT_INTEGER == poption->type, 0);
823 return poption->int_vtable->def(poption);
826 /****************************************************************************
827 Returns the minimal value of this integer option.
828 ****************************************************************************/
829 int option_int_min(const struct option *poption)
831 fc_assert_ret_val(NULL != poption, 0);
832 fc_assert_ret_val(OT_INTEGER == poption->type, 0);
834 return poption->int_vtable->minimum(poption);
837 /****************************************************************************
838 Returns the maximal value of this integer option.
839 ****************************************************************************/
840 int option_int_max(const struct option *poption)
842 fc_assert_ret_val(NULL != poption, 0);
843 fc_assert_ret_val(OT_INTEGER == poption->type, 0);
845 return poption->int_vtable->maximum(poption);
848 /****************************************************************************
849 Sets the value of this integer option. Returns TRUE if the value changed.
850 ****************************************************************************/
851 bool option_int_set(struct option *poption, int val)
853 fc_assert_ret_val(NULL != poption, FALSE);
854 fc_assert_ret_val(OT_INTEGER == poption->type, FALSE);
856 if (poption->int_vtable->set(poption, val)) {
857 option_changed(poption);
858 return TRUE;
860 return FALSE;
863 /****************************************************************************
864 Returns the current value of this string option.
865 ****************************************************************************/
866 const char *option_str_get(const struct option *poption)
868 fc_assert_ret_val(NULL != poption, NULL);
869 fc_assert_ret_val(OT_STRING == poption->type, NULL);
871 return poption->str_vtable->get(poption);
874 /****************************************************************************
875 Returns the default value of this string option.
876 ****************************************************************************/
877 const char *option_str_def(const struct option *poption)
879 fc_assert_ret_val(NULL != poption, NULL);
880 fc_assert_ret_val(OT_STRING == poption->type, NULL);
882 return poption->str_vtable->def(poption);
885 /****************************************************************************
886 Returns the possible string values of this string option.
887 ****************************************************************************/
888 const struct strvec *option_str_values(const struct option *poption)
890 fc_assert_ret_val(NULL != poption, NULL);
891 fc_assert_ret_val(OT_STRING == poption->type, NULL);
893 return poption->str_vtable->values(poption);
896 /****************************************************************************
897 Sets the value of this string option. Returns TRUE if the value changed.
898 ****************************************************************************/
899 bool option_str_set(struct option *poption, const char *str)
901 fc_assert_ret_val(NULL != poption, FALSE);
902 fc_assert_ret_val(OT_STRING == poption->type, FALSE);
903 fc_assert_ret_val(NULL != str, FALSE);
905 if (poption->str_vtable->set(poption, str)) {
906 option_changed(poption);
907 return TRUE;
909 return FALSE;
912 /****************************************************************************
913 Returns the value corresponding to the user-visible (translatable but not
914 translated) string. Returns -1 if not matched.
915 ****************************************************************************/
916 int option_enum_str_to_int(const struct option *poption, const char *str)
918 const struct strvec *values;
919 int val;
921 fc_assert_ret_val(NULL != poption, -1);
922 fc_assert_ret_val(OT_ENUM == poption->type, -1);
923 values = poption->enum_vtable->values(poption);
924 fc_assert_ret_val(NULL != values, -1);
926 for (val = 0; val < strvec_size(values); val++) {
927 if (0 == poption->enum_vtable->cmp(strvec_get(values, val), str)) {
928 return val;
931 return -1;
934 /****************************************************************************
935 Returns the user-visible (translatable but not translated) string
936 corresponding to the value. Returns NULL on error.
937 ****************************************************************************/
938 const char *option_enum_int_to_str(const struct option *poption, int val)
940 const struct strvec *values;
942 fc_assert_ret_val(NULL != poption, NULL);
943 fc_assert_ret_val(OT_ENUM == poption->type, NULL);
944 values = poption->enum_vtable->values(poption);
945 fc_assert_ret_val(NULL != values, NULL);
947 return strvec_get(values, val);
950 /****************************************************************************
951 Returns the current value of this enum option (as an integer).
952 ****************************************************************************/
953 int option_enum_get_int(const struct option *poption)
955 fc_assert_ret_val(NULL != poption, -1);
956 fc_assert_ret_val(OT_ENUM == poption->type, -1);
958 return poption->enum_vtable->get(poption);
961 /****************************************************************************
962 Returns the current value of this enum option as a user-visible
963 (translatable but not translated) string.
964 ****************************************************************************/
965 const char *option_enum_get_str(const struct option *poption)
967 fc_assert_ret_val(NULL != poption, NULL);
968 fc_assert_ret_val(OT_ENUM == poption->type, NULL);
970 return strvec_get(poption->enum_vtable->values(poption),
971 poption->enum_vtable->get(poption));
974 /****************************************************************************
975 Returns the default value of this enum option (as an integer).
976 ****************************************************************************/
977 int option_enum_def_int(const struct option *poption)
979 fc_assert_ret_val(NULL != poption, -1);
980 fc_assert_ret_val(OT_ENUM == poption->type, -1);
982 return poption->enum_vtable->def(poption);
985 /****************************************************************************
986 Returns the default value of this enum option as a user-visible
987 (translatable but not translated) string.
988 ****************************************************************************/
989 const char *option_enum_def_str(const struct option *poption)
991 fc_assert_ret_val(NULL != poption, NULL);
992 fc_assert_ret_val(OT_ENUM == poption->type, NULL);
994 return strvec_get(poption->enum_vtable->values(poption),
995 poption->enum_vtable->def(poption));
998 /****************************************************************************
999 Returns the possible string values of this enum option, as user-visible
1000 (translatable but not translated) strings.
1001 ****************************************************************************/
1002 const struct strvec *option_enum_values(const struct option *poption)
1004 fc_assert_ret_val(NULL != poption, NULL);
1005 fc_assert_ret_val(OT_ENUM == poption->type, NULL);
1007 return poption->enum_vtable->values(poption);
1010 /****************************************************************************
1011 Sets the value of this enum option. Returns TRUE if the value changed.
1012 ****************************************************************************/
1013 bool option_enum_set_int(struct option *poption, int val)
1015 fc_assert_ret_val(NULL != poption, FALSE);
1016 fc_assert_ret_val(OT_ENUM == poption->type, FALSE);
1018 if (poption->enum_vtable->set(poption, val)) {
1019 option_changed(poption);
1020 return TRUE;
1022 return FALSE;
1025 /****************************************************************************
1026 Sets the value of this enum option from a string, which is matched as a
1027 user-visible (translatable but not translated) string. Returns TRUE if the
1028 value changed.
1029 ****************************************************************************/
1030 bool option_enum_set_str(struct option *poption, const char *str)
1032 fc_assert_ret_val(NULL != poption, FALSE);
1033 fc_assert_ret_val(OT_ENUM == poption->type, FALSE);
1034 fc_assert_ret_val(NULL != str, FALSE);
1036 if (poption->enum_vtable->set(poption,
1037 option_enum_str_to_int(poption, str))) {
1038 option_changed(poption);
1039 return TRUE;
1041 return FALSE;
1044 /****************************************************************************
1045 Returns the current value of this bitwise option.
1046 ****************************************************************************/
1047 unsigned option_bitwise_get(const struct option *poption)
1049 fc_assert_ret_val(NULL != poption, 0);
1050 fc_assert_ret_val(OT_BITWISE == poption->type, 0);
1052 return poption->bitwise_vtable->get(poption);
1055 /****************************************************************************
1056 Returns the default value of this bitwise option.
1057 ****************************************************************************/
1058 unsigned option_bitwise_def(const struct option *poption)
1060 fc_assert_ret_val(NULL != poption, 0);
1061 fc_assert_ret_val(OT_BITWISE == poption->type, 0);
1063 return poption->bitwise_vtable->def(poption);
1066 /****************************************************************************
1067 Returns the mask of this bitwise option.
1068 ****************************************************************************/
1069 unsigned option_bitwise_mask(const struct option *poption)
1071 const struct strvec *values;
1073 fc_assert_ret_val(NULL != poption, 0);
1074 fc_assert_ret_val(OT_BITWISE == poption->type, 0);
1076 values = poption->bitwise_vtable->values(poption);
1077 fc_assert_ret_val(NULL != values, 0);
1079 return (1 << strvec_size(values)) - 1;
1082 /****************************************************************************
1083 Returns a vector of strings describing every bit of this option, as
1084 user-visible (translatable but not translated) strings.
1085 ****************************************************************************/
1086 const struct strvec *option_bitwise_values(const struct option *poption)
1088 fc_assert_ret_val(NULL != poption, NULL);
1089 fc_assert_ret_val(OT_BITWISE == poption->type, NULL);
1091 return poption->bitwise_vtable->values(poption);
1094 /****************************************************************************
1095 Sets the value of this bitwise option. Returns TRUE if the value changed.
1096 ****************************************************************************/
1097 bool option_bitwise_set(struct option *poption, unsigned val)
1099 fc_assert_ret_val(NULL != poption, FALSE);
1100 fc_assert_ret_val(OT_BITWISE == poption->type, FALSE);
1102 if (0 != (val & ~option_bitwise_mask(poption))
1103 || !poption->bitwise_vtable->set(poption, val)) {
1104 return FALSE;
1107 option_changed(poption);
1108 return TRUE;
1111 /****************************************************************************
1112 Returns the current value of this font option.
1113 ****************************************************************************/
1114 const char *option_font_get(const struct option *poption)
1116 fc_assert_ret_val(NULL != poption, NULL);
1117 fc_assert_ret_val(OT_FONT == poption->type, NULL);
1119 return poption->font_vtable->get(poption);
1122 /****************************************************************************
1123 Returns the default value of this font option.
1124 ****************************************************************************/
1125 const char *option_font_def(const struct option *poption)
1127 fc_assert_ret_val(NULL != poption, NULL);
1128 fc_assert_ret_val(OT_FONT == poption->type, NULL);
1130 return poption->font_vtable->def(poption);
1133 /****************************************************************************
1134 Returns the target style name of this font option.
1135 ****************************************************************************/
1136 const char *option_font_target(const struct option *poption)
1138 fc_assert_ret_val(NULL != poption, NULL);
1139 fc_assert_ret_val(OT_FONT == poption->type, NULL);
1141 return poption->font_vtable->target(poption);
1144 /****************************************************************************
1145 Sets the value of this font option. Returns TRUE if the value changed.
1146 ****************************************************************************/
1147 bool option_font_set(struct option *poption, const char *font)
1149 fc_assert_ret_val(NULL != poption, FALSE);
1150 fc_assert_ret_val(OT_FONT == poption->type, FALSE);
1151 fc_assert_ret_val(NULL != font, FALSE);
1153 if (poption->font_vtable->set(poption, font)) {
1154 option_changed(poption);
1155 return TRUE;
1157 return FALSE;
1160 /****************************************************************************
1161 Returns the current value of this color option.
1162 ****************************************************************************/
1163 struct ft_color option_color_get(const struct option *poption)
1165 fc_assert_ret_val(NULL != poption, ft_color_construct(NULL, NULL));
1166 fc_assert_ret_val(OT_COLOR == poption->type, ft_color_construct(NULL, NULL));
1168 return poption->color_vtable->get(poption);
1171 /****************************************************************************
1172 Returns the default value of this color option.
1173 ****************************************************************************/
1174 struct ft_color option_color_def(const struct option *poption)
1176 fc_assert_ret_val(NULL != poption, ft_color_construct(NULL, NULL));
1177 fc_assert_ret_val(OT_COLOR == poption->type, ft_color_construct(NULL, NULL));
1179 return poption->color_vtable->def(poption);
1182 /****************************************************************************
1183 Sets the value of this color option. Returns TRUE if the value
1184 changed.
1185 ****************************************************************************/
1186 bool option_color_set(struct option *poption, struct ft_color color)
1188 fc_assert_ret_val(NULL != poption, FALSE);
1189 fc_assert_ret_val(OT_COLOR == poption->type, FALSE);
1191 if (poption->color_vtable->set(poption, color)) {
1192 option_changed(poption);
1193 return TRUE;
1195 return FALSE;
1198 /****************************************************************************
1199 Returns the current value of this video mode option.
1200 ****************************************************************************/
1201 struct video_mode option_video_mode_get(const struct option *poption)
1203 fc_assert_ret_val(NULL != poption, video_mode_construct(-1, -1));
1204 fc_assert_ret_val(OT_VIDEO_MODE == poption->type,
1205 video_mode_construct(-1, -1));
1207 return poption->video_mode_vtable->get(poption);
1210 /****************************************************************************
1211 Returns the default value of this video mode option.
1212 ****************************************************************************/
1213 struct video_mode option_video_mode_def(const struct option *poption)
1215 fc_assert_ret_val(NULL != poption, video_mode_construct(-1, -1));
1216 fc_assert_ret_val(OT_VIDEO_MODE == poption->type,
1217 video_mode_construct(-1, -1));
1219 return poption->video_mode_vtable->def(poption);
1222 /****************************************************************************
1223 Sets the value of this video mode option. Returns TRUE if the value
1224 changed.
1225 ****************************************************************************/
1226 bool option_video_mode_set(struct option *poption, struct video_mode mode)
1228 fc_assert_ret_val(NULL != poption, FALSE);
1229 fc_assert_ret_val(OT_VIDEO_MODE == poption->type, FALSE);
1231 if (poption->video_mode_vtable->set(poption, mode)) {
1232 option_changed(poption);
1233 return TRUE;
1235 return FALSE;
1239 /****************************************************************************
1240 Client option set.
1241 ****************************************************************************/
1242 static struct option *client_optset_option_by_number(int id);
1243 static struct option *client_optset_option_first(void);
1244 static int client_optset_category_number(void);
1245 static const char *client_optset_category_name(int category);
1247 static struct option_set client_optset_static = {
1248 .option_by_number = client_optset_option_by_number,
1249 .option_first = client_optset_option_first,
1250 .category_number = client_optset_category_number,
1251 .category_name = client_optset_category_name
1253 const struct option_set *client_optset = &client_optset_static;
1255 struct copt_val_name {
1256 const char *support; /* Untranslated long support name, used
1257 * for saving. */
1258 const char *pretty; /* Translated, used to display to the
1259 * users. */
1262 /****************************************************************************
1263 Virtuals tables for the client options.
1264 ****************************************************************************/
1265 static int client_option_number(const struct option *poption);
1266 static const char *client_option_name(const struct option *poption);
1267 static const char *client_option_description(const struct option *poption);
1268 static const char *client_option_help_text(const struct option *poption);
1269 static int client_option_category(const struct option *poption);
1270 static bool client_option_is_changeable(const struct option *poption);
1271 static struct option *client_option_next(const struct option *poption);
1272 static void client_option_adjust_defaults(void);
1274 static const struct option_common_vtable client_option_common_vtable = {
1275 .number = client_option_number,
1276 .name = client_option_name,
1277 .description = client_option_description,
1278 .help_text = client_option_help_text,
1279 .category = client_option_category,
1280 .is_changeable = client_option_is_changeable,
1281 .next = client_option_next
1284 static bool client_option_bool_get(const struct option *poption);
1285 static bool client_option_bool_def(const struct option *poption);
1286 static bool client_option_bool_set(struct option *poption, bool val);
1288 static const struct option_bool_vtable client_option_bool_vtable = {
1289 .get = client_option_bool_get,
1290 .def = client_option_bool_def,
1291 .set = client_option_bool_set
1294 static int client_option_int_get(const struct option *poption);
1295 static int client_option_int_def(const struct option *poption);
1296 static int client_option_int_min(const struct option *poption);
1297 static int client_option_int_max(const struct option *poption);
1298 static bool client_option_int_set(struct option *poption, int val);
1300 static const struct option_int_vtable client_option_int_vtable = {
1301 .get = client_option_int_get,
1302 .def = client_option_int_def,
1303 .minimum = client_option_int_min,
1304 .maximum = client_option_int_max,
1305 .set = client_option_int_set
1308 static const char *client_option_str_get(const struct option *poption);
1309 static const char *client_option_str_def(const struct option *poption);
1310 static const struct strvec *
1311 client_option_str_values(const struct option *poption);
1312 static bool client_option_str_set(struct option *poption, const char *str);
1314 static const struct option_str_vtable client_option_str_vtable = {
1315 .get = client_option_str_get,
1316 .def = client_option_str_def,
1317 .values = client_option_str_values,
1318 .set = client_option_str_set
1321 static int client_option_enum_get(const struct option *poption);
1322 static int client_option_enum_def(const struct option *poption);
1323 static const struct strvec *
1324 client_option_enum_pretty_names(const struct option *poption);
1325 static bool client_option_enum_set(struct option *poption, int val);
1327 static const struct option_enum_vtable client_option_enum_vtable = {
1328 .get = client_option_enum_get,
1329 .def = client_option_enum_def,
1330 .values = client_option_enum_pretty_names,
1331 .set = client_option_enum_set,
1332 .cmp = fc_strcasecmp
1335 #if 0 /* There's no bitwise options currently */
1336 static unsigned client_option_bitwise_get(const struct option *poption);
1337 static unsigned client_option_bitwise_def(const struct option *poption);
1338 static const struct strvec *
1339 client_option_bitwise_pretty_names(const struct option *poption);
1340 static bool client_option_bitwise_set(struct option *poption, unsigned val);
1342 static const struct option_bitwise_vtable client_option_bitwise_vtable = {
1343 .get = client_option_bitwise_get,
1344 .def = client_option_bitwise_def,
1345 .values = client_option_bitwise_pretty_names,
1346 .set = client_option_bitwise_set
1348 #endif /* 0 */
1350 static const char *client_option_font_get(const struct option *poption);
1351 static const char *client_option_font_def(const struct option *poption);
1352 static const char *client_option_font_target(const struct option *poption);
1353 static bool client_option_font_set(struct option *poption, const char *font);
1355 static const struct option_font_vtable client_option_font_vtable = {
1356 .get = client_option_font_get,
1357 .def = client_option_font_def,
1358 .target = client_option_font_target,
1359 .set = client_option_font_set
1362 static struct ft_color client_option_color_get(const struct option *poption);
1363 static struct ft_color client_option_color_def(const struct option *poption);
1364 static bool client_option_color_set(struct option *poption,
1365 struct ft_color color);
1367 static const struct option_color_vtable client_option_color_vtable = {
1368 .get = client_option_color_get,
1369 .def = client_option_color_def,
1370 .set = client_option_color_set
1373 static struct video_mode
1374 client_option_video_mode_get(const struct option *poption);
1375 static struct video_mode
1376 client_option_video_mode_def(const struct option *poption);
1377 static bool client_option_video_mode_set(struct option *poption,
1378 struct video_mode mode);
1380 static const struct option_video_mode_vtable client_option_video_mode_vtable = {
1381 .get = client_option_video_mode_get,
1382 .def = client_option_video_mode_def,
1383 .set = client_option_video_mode_set
1386 enum client_option_category {
1387 COC_GRAPHICS,
1388 COC_OVERVIEW,
1389 COC_SOUND,
1390 COC_INTERFACE,
1391 COC_MAPIMG,
1392 COC_NETWORK,
1393 COC_FONT,
1394 COC_MAX
1397 /****************************************************************************
1398 Derived class client option, inherinting of base class option.
1399 ****************************************************************************/
1400 struct client_option {
1401 struct option base_option; /* Base structure, must be the first! */
1403 const char *name; /* Short name - used as an identifier */
1404 const char *description; /* One-line description */
1405 const char *help_text; /* Paragraph-length help text */
1406 enum client_option_category category;
1407 enum gui_type specific; /* GUI_STUB for common options. */
1409 union {
1410 /* OT_BOOLEAN type option. */
1411 struct {
1412 bool *const pvalue;
1413 const bool def;
1414 } boolean;
1415 /* OT_INTEGER type option. */
1416 struct {
1417 int *const pvalue;
1418 const int def, min, max;
1419 } integer;
1420 /* OT_STRING type option. */
1421 struct {
1422 char *const pvalue;
1423 const size_t size;
1424 const char *const def;
1426 * A function to return a string vector of possible string values,
1427 * or NULL for none.
1429 const struct strvec *(*const val_accessor) (const struct option *);
1430 } string;
1431 /* OT_ENUM type option. */
1432 struct {
1433 int *const pvalue;
1434 const int def;
1435 struct strvec *support_names, *pretty_names; /* untranslated */
1436 const struct copt_val_name * (*const name_accessor) (int value);
1437 } enumerator;
1438 /* OT_BITWISE type option. */
1439 struct {
1440 unsigned *const pvalue;
1441 const unsigned def;
1442 struct strvec *support_names, *pretty_names; /* untranslated */
1443 const struct copt_val_name * (*const name_accessor) (int value);
1444 } bitwise;
1445 /* OT_FONT type option. */
1446 struct {
1447 char *const pvalue;
1448 const size_t size;
1449 const char *const def;
1450 const char *const target;
1451 } font;
1452 /* OT_COLOR type option. */
1453 struct {
1454 struct ft_color *const pvalue;
1455 const struct ft_color def;
1456 } color;
1457 /* OT_VIDEO_MODE type option. */
1458 struct {
1459 struct video_mode *const pvalue;
1460 const struct video_mode def;
1461 } video_mode;
1465 #define CLIENT_OPTION(poption) ((struct client_option *) (poption))
1468 * Generate a client option of type OT_BOOLEAN.
1470 * oname: The option data. Note it is used as name to be loaded or saved.
1471 * So, you shouldn't change the name of this variable in any case.
1472 * odesc: A short description of the client option. Should be used with the
1473 * N_() macro.
1474 * ohelp: The help text for the client option. Should be used with the N_()
1475 * macro.
1476 * ocat: The client_option_class of this client option.
1477 * ospec: A gui_type enumerator which determin for what particular client
1478 * gui this option is for. Sets to GUI_STUB for common options.
1479 * odef: The default value of this client option (FALSE or TRUE).
1480 * ocb: A callback function of type void (*)(struct option *) called when
1481 * the option changed.
1483 #define GEN_BOOL_OPTION(oname, odesc, ohelp, ocat, ospec, odef, ocb) \
1485 .base_option = OPTION_BOOL_INIT(&client_optset_static, \
1486 client_option_common_vtable, \
1487 client_option_bool_vtable, ocb), \
1488 .name = #oname, \
1489 .description = odesc, \
1490 .help_text = ohelp, \
1491 .category = ocat, \
1492 .specific = ospec, \
1493 INIT_BRACE_BEGIN \
1494 .boolean = { \
1495 .pvalue = &gui_options.oname, \
1496 .def = odef, \
1498 INIT_BRACE_END \
1502 * Generate a client option of type OT_INTEGER.
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 * odesc: A short description of the client option. Should be used with the
1507 * N_() macro.
1508 * ohelp: The help text for the client option. Should be used with the N_()
1509 * macro.
1510 * ocat: The client_option_class of this client option.
1511 * ospec: A gui_type enumerator which determin for what particular client
1512 * gui this option is for. Sets to GUI_STUB for common options.
1513 * odef: The default value of this client option.
1514 * omin: The minimal value of this client option.
1515 * omax: The maximal value of this client option.
1516 * ocb: A callback function of type void (*)(struct option *) called when
1517 * the option changed.
1519 #define GEN_INT_OPTION(oname, odesc, ohelp, ocat, ospec, odef, omin, omax, ocb) \
1521 .base_option = OPTION_INT_INIT(&client_optset_static, \
1522 client_option_common_vtable, \
1523 client_option_int_vtable, ocb), \
1524 .name = #oname, \
1525 .description = odesc, \
1526 .help_text = ohelp, \
1527 .category = ocat, \
1528 .specific = ospec, \
1529 INIT_BRACE_BEGIN \
1530 .integer = { \
1531 .pvalue = &gui_options.oname, \
1532 .def = odef, \
1533 .min = omin, \
1534 .max = omax \
1536 INIT_BRACE_END \
1540 * Generate a client option of type OT_STRING.
1542 * oname: The option data. Note it is used as name to be loaded or saved.
1543 * So, you shouldn't change the name of this variable in any case.
1544 * Be sure to pass the array variable and not a pointer to it because
1545 * the size is calculated with sizeof().
1546 * odesc: A short description of the client option. Should be used with the
1547 * N_() macro.
1548 * ohelp: The help text for the client option. Should be used with the N_()
1549 * macro.
1550 * ocat: The client_option_class of this client option.
1551 * ospec: A gui_type enumerator which determines for what particular client
1552 * gui this option is for. Set to GUI_STUB for common options.
1553 * odef: The default string for this client option.
1554 * ocb: A callback function of type void (*)(struct option *) called when
1555 * the option changed.
1557 #define GEN_STR_OPTION(oname, odesc, ohelp, ocat, ospec, odef, ocb, cbd) \
1559 .base_option = OPTION_STR_INIT(&client_optset_static, \
1560 client_option_common_vtable, \
1561 client_option_str_vtable, ocb, cbd), \
1562 .name = #oname, \
1563 .description = odesc, \
1564 .help_text = ohelp, \
1565 .category = ocat, \
1566 .specific = ospec, \
1567 INIT_BRACE_BEGIN \
1568 .string = { \
1569 .pvalue = gui_options.oname, \
1570 .size = sizeof(gui_options.oname), \
1571 .def = odef, \
1572 .val_accessor = NULL \
1574 INIT_BRACE_END \
1578 * Generate a client option of type OT_STRING with a string accessor
1579 * function.
1581 * oname: The option data. Note it is used as name to be loaded or saved.
1582 * So, you shouldn't change the name of this variable in any case.
1583 * Be sure to pass the array variable and not a pointer to it because
1584 * the size is calculated with sizeof().
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 string for this client option.
1593 * oacc: The string accessor where to find the allowed values of type
1594 * 'const struct strvec * (*) (void)'.
1595 * ocb: A callback function of type void (*)(struct option *) called when
1596 * the option changed.
1598 #define GEN_STR_LIST_OPTION(oname, odesc, ohelp, ocat, ospec, odef, oacc, ocb, cbd) \
1600 .base_option = OPTION_STR_INIT(&client_optset_static, \
1601 client_option_common_vtable, \
1602 client_option_str_vtable, ocb, cbd), \
1603 .name = #oname, \
1604 .description = odesc, \
1605 .help_text = ohelp, \
1606 .category = ocat, \
1607 .specific = ospec, \
1608 INIT_BRACE_BEGIN \
1609 .string = { \
1610 .pvalue = gui_options.oname, \
1611 .size = sizeof(gui_options.oname), \
1612 .def = odef, \
1613 .val_accessor = oacc \
1615 INIT_BRACE_END \
1619 * Generate a client option of type OT_ENUM.
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_ENUM_OPTION(oname, odesc, ohelp, ocat, ospec, odef, oacc, ocb) \
1637 .base_option = OPTION_ENUM_INIT(&client_optset_static, \
1638 client_option_common_vtable, \
1639 client_option_enum_vtable, ocb), \
1640 .name = #oname, \
1641 .description = odesc, \
1642 .help_text = ohelp, \
1643 .category = ocat, \
1644 .specific = ospec, \
1645 INIT_BRACE_BEGIN \
1646 .enumerator = { \
1647 .pvalue = (int *) &gui_options.oname, \
1648 .def = odef, \
1649 .support_names = NULL, /* Set in options_init(). */ \
1650 .pretty_names = NULL, \
1651 .name_accessor = oacc \
1653 INIT_BRACE_END \
1657 * Generate a client option of type OT_BITWISE.
1659 * oname: The option data. Note it is used as name to be loaded or saved.
1660 * So, you shouldn't change the name of this variable in any case.
1661 * odesc: A short description of the client option. Should be used with the
1662 * N_() macro.
1663 * ohelp: The help text for the client option. Should be used with the N_()
1664 * macro.
1665 * ocat: The client_option_class of this client option.
1666 * ospec: A gui_type enumerator which determin for what particular client
1667 * gui this option is for. Sets to GUI_STUB for common options.
1668 * odef: The default value for this client option.
1669 * oacc: The name accessor of type 'const struct copt_val_name * (*) (int)'.
1670 * ocb: A callback function of type void (*) (struct option *) called when
1671 * the option changed.
1673 #define GEN_BITWISE_OPTION(oname, odesc, ohelp, ocat, ospec, odef, oacc, \
1674 ocb) \
1676 .base_option = OPTION_BITWISE_INIT(&client_optset_static, \
1677 client_option_common_vtable, \
1678 client_option_bitwise_vtable, ocb), \
1679 .name = #oname, \
1680 .description = odesc, \
1681 .help_text = ohelp, \
1682 .category = ocat, \
1683 .specific = ospec, \
1684 INIT_BRACE_BEGIN \
1685 .bitwise = { \
1686 .pvalue = &gui_options.oname, \
1687 .def = odef, \
1688 .support_names = NULL, /* Set in options_init(). */ \
1689 .pretty_names = NULL, \
1690 .name_accessor = oacc \
1692 INIT_BRACE_END \
1696 * Generate a client option of type OT_FONT.
1698 * oname: The option data. Note it is used as name to be loaded or saved.
1699 * So, you shouldn't change the name of this variable in any case.
1700 * Be sure to pass the array variable and not a pointer to it because
1701 * the size is calculated with sizeof().
1702 * otgt: The target widget style.
1703 * odesc: A short description of the client option. Should be used with the
1704 * N_() macro.
1705 * ohelp: The help text for the client option. Should be used with the N_()
1706 * macro.
1707 * ocat: The client_option_class of this client option.
1708 * ospec: A gui_type enumerator which determin for what particular client
1709 * gui this option is for. Sets to GUI_STUB for common options.
1710 * odef: The default string for this client option.
1711 * ocb: A callback function of type void (*)(struct option *) called when
1712 * the option changed.
1714 #define GEN_FONT_OPTION(oname, otgt, odesc, ohelp, ocat, ospec, odef, ocb) \
1716 .base_option = OPTION_FONT_INIT(&client_optset_static, \
1717 client_option_common_vtable, \
1718 client_option_font_vtable, ocb), \
1719 .name = #oname, \
1720 .description = odesc, \
1721 .help_text = ohelp, \
1722 .category = ocat, \
1723 .specific = ospec, \
1724 INIT_BRACE_BEGIN \
1725 .font = { \
1726 .pvalue = gui_options.oname, \
1727 .size = sizeof(gui_options.oname), \
1728 .def = odef, \
1729 .target = otgt, \
1731 INIT_BRACE_END \
1735 * Generate a client option of type OT_COLOR.
1737 * oname: The option data. Note it is used as name to be loaded or saved.
1738 * So, you shouldn't change the name of this variable in any case.
1739 * odesc: A short description of the client option. Should be used with the
1740 * N_() macro.
1741 * ohelp: The help text for the client option. Should be used with the N_()
1742 * macro.
1743 * ocat: The client_option_class of this client option.
1744 * ospec: A gui_type enumerator which determin for what particular client
1745 * gui this option is for. Sets to GUI_STUB for common options.
1746 * odef_fg, odef_bg: The default values for this client option.
1747 * ocb: A callback function of type void (*)(struct option *) called when
1748 * the option changed.
1750 #define GEN_COLOR_OPTION(oname, odesc, ohelp, ocat, ospec, odef_fg, \
1751 odef_bg, ocb) \
1753 .base_option = OPTION_COLOR_INIT(&client_optset_static, \
1754 client_option_common_vtable, \
1755 client_option_color_vtable, ocb), \
1756 .name = #oname, \
1757 .description = odesc, \
1758 .help_text = ohelp, \
1759 .category = ocat, \
1760 .specific = ospec, \
1761 INIT_BRACE_BEGIN \
1762 .color = { \
1763 .pvalue = &gui_options.oname, \
1764 .def = FT_COLOR(odef_fg, odef_bg) \
1766 INIT_BRACE_END \
1770 * Generate a client option of type OT_VIDEO_MODE.
1772 * oname: The option data. Note it is used as name to be loaded or saved.
1773 * So, you shouldn't change the name of this variable in any case.
1774 * odesc: A short description of the client option. Should be used with the
1775 * N_() macro.
1776 * ohelp: The help text for the client option. Should be used with the N_()
1777 * macro.
1778 * ocat: The client_option_class of this client option.
1779 * ospec: A gui_type enumerator which determin for what particular client
1780 * gui this option is for. Sets to GUI_STUB for common options.
1781 * odef_width, odef_height: The default values for this client option.
1782 * ocb: A callback function of type void (*)(struct option *) called when
1783 * the option changed.
1785 #define GEN_VIDEO_OPTION(oname, odesc, ohelp, ocat, ospec, odef_width, \
1786 odef_height, ocb) \
1788 .base_option = OPTION_VIDEO_MODE_INIT(&client_optset_static, \
1789 client_option_common_vtable, \
1790 client_option_video_mode_vtable, \
1791 ocb), \
1792 .name = #oname, \
1793 .description = odesc, \
1794 .help_text = ohelp, \
1795 .category = ocat, \
1796 .specific = ospec, \
1797 INIT_BRACE_BEGIN \
1798 .video_mode = { \
1799 .pvalue = &gui_options.oname, \
1800 .def = VIDEO_MODE(odef_width, odef_height) \
1802 INIT_BRACE_END \
1805 /****************************************************************************
1806 Enumerator name accessors.
1807 ****************************************************************************/
1809 /****************************************************************************
1810 GTK message/chat layout setting names accessor.
1811 ****************************************************************************/
1812 static const struct copt_val_name
1813 *gui_gtk_message_chat_location_name(int value)
1815 /* Order must match enum GUI_GTK_MSGCHAT_* */
1816 static const struct copt_val_name names[] = {
1817 /* TRANS: enum value for 'gui_gtk2/gtk3/gtk3x_message_chat_location' */
1818 { "SPLIT", N_("Split") },
1819 /* TRANS: enum value for 'gui_gtk2/gtk3/gtk3x_message_chat_location' */
1820 { "SEPARATE", N_("Separate") },
1821 /* TRANS: enum value for 'gui_gtk2/gtk3/gtk3x_message_chat_location' */
1822 { "MERGED", N_("Merged") }
1825 return (0 <= value && value < ARRAY_SIZE(names)
1826 ? names + value : NULL);
1829 /****************************************************************************
1830 Popup tech help setting names accessor.
1831 ****************************************************************************/
1832 static const struct copt_val_name
1833 *gui_popup_tech_help_name(int value)
1835 /* Order must match enum GUI_POPUP_TECH_HELP_* */
1836 static const struct copt_val_name names[] = {
1837 /* TRANS: enum value for 'gui_popup_tech_help' */
1838 { "ENABLED", N_("Enabled") },
1839 /* TRANS: enum value for 'gui_popup_tech_help' */
1840 { "DISABLED", N_("Disabled") },
1841 /* TRANS: enum value for 'gui_popup_tech_help' */
1842 { "RULESET", N_("Ruleset") }
1845 return (0 <= value && value < ARRAY_SIZE(names)
1846 ? names + value : NULL);
1849 /* Some changed callbacks. */
1850 static void reqtree_show_icons_callback(struct option *poption);
1851 static void view_option_changed_callback(struct option *poption);
1852 static void manual_turn_done_callback(struct option *poption);
1853 static void voteinfo_bar_callback(struct option *poption);
1854 static void font_changed_callback(struct option *poption);
1855 static void mapimg_changed_callback(struct option *poption);
1856 static void game_music_enable_callback(struct option *poption);
1857 static void menu_music_enable_callback(struct option *poption);
1859 static struct client_option client_options[] = {
1860 GEN_STR_OPTION(default_user_name,
1861 N_("Login name"),
1862 N_("This is the default login username that will be used "
1863 "in the connection dialogs or with the -a command-line "
1864 "parameter."),
1865 COC_NETWORK, GUI_STUB, NULL, NULL, 0),
1866 GEN_BOOL_OPTION(use_prev_server, N_("Default to previously used server"),
1867 N_("Automatically update \"Server\" and \"Server port\" "
1868 "options to match your latest connection, so by "
1869 "default you connect to the same server you used "
1870 "on the previous run. You should enable "
1871 "saving options on exit too, so that the automatic "
1872 "updates to the options get saved too."),
1873 COC_NETWORK, GUI_STUB, NULL, NULL),
1874 GEN_STR_OPTION(default_server_host,
1875 N_("Server"),
1876 N_("This is the default server hostname that will be used "
1877 "in the connection dialogs or with the -a command-line "
1878 "parameter."),
1879 COC_NETWORK, GUI_STUB, "localhost", NULL, 0),
1880 GEN_INT_OPTION(default_server_port,
1881 N_("Server port"),
1882 N_("This is the default server port that will be used "
1883 "in the connection dialogs or with the -a command-line "
1884 "parameter."),
1885 COC_NETWORK, GUI_STUB, DEFAULT_SOCK_PORT, 0, 65535, NULL),
1886 GEN_STR_OPTION(default_metaserver,
1887 N_("Metaserver"),
1888 N_("The metaserver is a host that the client contacts to "
1889 "find out about games on the internet. Don't change "
1890 "this from its default value unless you know what "
1891 "you're doing."),
1892 COC_NETWORK, GUI_STUB, DEFAULT_METASERVER_OPTION, NULL, 0),
1893 GEN_BOOL_OPTION(heartbeat_enabled, N_("Send heartbeat messages to server"),
1894 N_("Regularly send empty heartbeat message to the server "
1895 "to make sure that the connection is still up. This "
1896 "can be useful if the client otherwise may sit for a "
1897 "long time with no data being sent or received at all."),
1898 COC_NETWORK, GUI_STUB, NULL, NULL),
1899 GEN_STR_LIST_OPTION(default_sound_set_name,
1900 N_("Soundset"),
1901 N_("This is the soundset that will be used. Changing "
1902 "this is the same as using the -S command-line "
1903 "parameter."),
1904 COC_SOUND, GUI_STUB, "stdsounds", get_soundset_list, NULL, 0),
1905 GEN_STR_LIST_OPTION(default_music_set_name,
1906 N_("Musicset"),
1907 N_("This is the musicset that will be used. Changing "
1908 "this is the same as using the -m command-line "
1909 "parameter."),
1910 COC_SOUND, GUI_STUB, "stdmusic", get_musicset_list, musicspec_reread_callback, 0),
1911 GEN_STR_LIST_OPTION(default_sound_plugin_name,
1912 N_("Sound plugin"),
1913 N_("If you have a problem with sound, try changing "
1914 "the sound plugin. The new plugin won't take "
1915 "effect until you restart Freeciv. Changing this "
1916 "is the same as using the -P command-line option."),
1917 COC_SOUND, GUI_STUB, NULL, get_soundplugin_list, NULL, 0),
1918 GEN_STR_OPTION(default_chat_logfile,
1919 N_("The chat log file"),
1920 N_("The name of the chat log file."),
1921 COC_INTERFACE, GUI_STUB, GUI_DEFAULT_CHAT_LOGFILE, NULL, 0),
1922 /* gui_gtk3/4_default_theme_name and gui_sdl2_default_theme_name are
1923 * different settings to avoid client crash after loading the
1924 * style for the other gui. Keeps 5 different options! */
1925 GEN_STR_LIST_OPTION(gui_gtk3_default_theme_name, N_("Theme"),
1926 N_("By changing this option you change the "
1927 "active theme."),
1928 COC_GRAPHICS, GUI_GTK3, FC_GTK3_DEFAULT_THEME_NAME,
1929 get_themes_list, theme_reread_callback, 0),
1930 GEN_STR_LIST_OPTION(gui_gtk3_22_default_theme_name, N_("Theme"),
1931 N_("By changing this option you change the "
1932 "active theme."),
1933 COC_GRAPHICS, GUI_GTK3_22, FC_GTK3_22_DEFAULT_THEME_NAME,
1934 get_themes_list, theme_reread_callback, 0),
1935 GEN_STR_LIST_OPTION(gui_gtk4_default_theme_name, N_("Theme"),
1936 N_("By changing this option you change the "
1937 "active theme."),
1938 COC_GRAPHICS, GUI_GTK3x, FC_GTK4_DEFAULT_THEME_NAME,
1939 get_themes_list, theme_reread_callback, 0),
1940 GEN_STR_LIST_OPTION(gui_sdl2_default_theme_name, N_("Theme"),
1941 N_("By changing this option you change the "
1942 "active theme."),
1943 COC_GRAPHICS, GUI_SDL2, FC_SDL2_DEFAULT_THEME_NAME,
1944 get_themes_list, theme_reread_callback, 0),
1945 GEN_STR_LIST_OPTION(gui_qt_default_theme_name, N_("Theme"),
1946 N_("By changing this option you change the "
1947 "active theme."),
1948 COC_GRAPHICS, GUI_QT, FC_QT_DEFAULT_THEME_NAME,
1949 get_themes_list, theme_reread_callback, 0),
1951 /* It's important to give empty string instead of NULL as as default
1952 * value. For NULL value it would default to assigning first value
1953 * from the tileset list returned by get_tileset_list() as default
1954 * tileset. We don't want default tileset assigned at all here, but
1955 * leave it to tilespec code that can handle tileset priority. */
1956 GEN_STR_LIST_OPTION(default_tileset_overhead_name, N_("Tileset (Overhead)"),
1957 N_("Select the tileset used with Overhead maps. "
1958 "This may change currently active tileset, if "
1959 "you are playing on such a map, in which "
1960 "case this is the same as using the -t "
1961 "command-line parameter."),
1962 COC_GRAPHICS, GUI_STUB, "",
1963 get_tileset_list, tilespec_reread_callback, 0),
1964 GEN_STR_LIST_OPTION(default_tileset_iso_name, N_("Tileset (Isometric)"),
1965 N_("Select the tileset used with Isometric maps. "
1966 "This may change currently active tileset, if "
1967 "you are playing on such a map, in which "
1968 "case this is the same as using the -t "
1969 "command-line parameter."),
1970 COC_GRAPHICS, GUI_STUB, "",
1971 get_tileset_list, tilespec_reread_callback, TF_ISO),
1972 GEN_STR_LIST_OPTION(default_tileset_hex_name, N_("Tileset (Hex)"),
1973 N_("Select the tileset used with Hex maps. "
1974 "This may change currently active tileset, if "
1975 "you are playing on such a map, in which "
1976 "case this is the same as using the -t "
1977 "command-line parameter."),
1978 COC_GRAPHICS, GUI_STUB, "",
1979 get_tileset_list, tilespec_reread_callback, TF_HEX),
1980 GEN_STR_LIST_OPTION(default_tileset_isohex_name, N_("Tileset (Isometric Hex)"),
1981 N_("Select the tileset used with Isometric Hex maps. "
1982 "This may change currently active tileset, if "
1983 "you are playing on such a map, in which "
1984 "case this is the same as using the -t "
1985 "command-line parameter."),
1986 COC_GRAPHICS, GUI_STUB, "",
1987 get_tileset_list, tilespec_reread_callback, TF_ISO | TF_HEX),
1989 GEN_BOOL_OPTION(draw_city_outlines, N_("Draw city outlines"),
1990 N_("Setting this option will draw a line at the city "
1991 "workable limit."),
1992 COC_GRAPHICS, GUI_STUB, TRUE,
1993 view_option_changed_callback),
1994 GEN_BOOL_OPTION(draw_city_output, N_("Draw city output"),
1995 N_("Setting this option will draw city output for every "
1996 "citizen."),
1997 COC_GRAPHICS, GUI_STUB, FALSE,
1998 view_option_changed_callback),
1999 GEN_BOOL_OPTION(draw_map_grid, N_("Draw the map grid"),
2000 N_("Setting this option will draw a grid over the map."),
2001 COC_GRAPHICS, GUI_STUB, FALSE,
2002 view_option_changed_callback),
2003 GEN_BOOL_OPTION(draw_full_citybar, N_("Draw the city bar"),
2004 N_("Setting this option will display a 'city bar' "
2005 "containing useful information beneath each city. "
2006 "Disabling this option will display only the city's "
2007 "name and, optionally, production."),
2008 COC_GRAPHICS, GUI_STUB,
2009 TRUE, view_option_changed_callback),
2010 GEN_BOOL_OPTION(draw_city_names, N_("Draw the city names"),
2011 N_("Setting this option will draw the names of the cities "
2012 "on the map."),
2013 COC_GRAPHICS, GUI_STUB, TRUE,
2014 view_option_changed_callback),
2015 GEN_BOOL_OPTION(draw_city_growth, N_("Draw the city growth"),
2016 N_("Setting this option will draw in how many turns the "
2017 "cities will grow or shrink."),
2018 COC_GRAPHICS, GUI_STUB, TRUE,
2019 view_option_changed_callback),
2020 GEN_BOOL_OPTION(draw_city_productions, N_("Draw the city productions"),
2021 N_("Setting this option will draw what the cities are "
2022 "currently building on the map."),
2023 COC_GRAPHICS, GUI_STUB, TRUE,
2024 view_option_changed_callback),
2025 GEN_BOOL_OPTION(draw_city_buycost, N_("Draw the city buy costs"),
2026 N_("Setting this option will draw how much gold is "
2027 "needed to buy the production of the cities."),
2028 COC_GRAPHICS, GUI_STUB, FALSE,
2029 view_option_changed_callback),
2030 GEN_BOOL_OPTION(draw_city_trade_routes, N_("Draw the city trade routes"),
2031 N_("Setting this option will draw trade route lines "
2032 "between cities which have trade routes."),
2033 COC_GRAPHICS, GUI_STUB, FALSE,
2034 view_option_changed_callback),
2035 GEN_BOOL_OPTION(draw_terrain, N_("Draw the terrain"),
2036 N_("Setting this option will draw the terrain."),
2037 COC_GRAPHICS, GUI_STUB, TRUE,
2038 view_option_changed_callback),
2039 GEN_BOOL_OPTION(draw_coastline, N_("Draw the coast line"),
2040 N_("Setting this option will draw a line to separate the "
2041 "land from the ocean."),
2042 COC_GRAPHICS, GUI_STUB, FALSE,
2043 view_option_changed_callback),
2044 GEN_BOOL_OPTION(draw_roads_rails, N_("Draw the roads and the railroads"),
2045 N_("Setting this option will draw the roads and the "
2046 "railroads on the map."),
2047 COC_GRAPHICS, GUI_STUB, TRUE,
2048 view_option_changed_callback),
2049 GEN_BOOL_OPTION(draw_irrigation, N_("Draw the irrigation"),
2050 N_("Setting this option will draw the irrigation systems "
2051 "on the map."),
2052 COC_GRAPHICS, GUI_STUB, TRUE,
2053 view_option_changed_callback),
2054 GEN_BOOL_OPTION(draw_mines, N_("Draw the mines"),
2055 N_("Setting this option will draw the mines on the map."),
2056 COC_GRAPHICS, GUI_STUB, TRUE,
2057 view_option_changed_callback),
2058 GEN_BOOL_OPTION(draw_fortress_airbase, N_("Draw the bases"),
2059 N_("Setting this option will draw the bases on the map."),
2060 COC_GRAPHICS, GUI_STUB, TRUE,
2061 view_option_changed_callback),
2062 GEN_BOOL_OPTION(draw_specials, N_("Draw the resources"),
2063 N_("Setting this option will draw the resources on the "
2064 "map."),
2065 COC_GRAPHICS, GUI_STUB, TRUE,
2066 view_option_changed_callback),
2067 GEN_BOOL_OPTION(draw_huts, N_("Draw the huts"),
2068 N_("Setting this option will draw the huts on the "
2069 "map."),
2070 COC_GRAPHICS, GUI_STUB, TRUE,
2071 view_option_changed_callback),
2072 GEN_BOOL_OPTION(draw_pollution, N_("Draw the pollution/nuclear fallout"),
2073 N_("Setting this option will draw pollution and "
2074 "nuclear fallout on the map."),
2075 COC_GRAPHICS, GUI_STUB, TRUE,
2076 view_option_changed_callback),
2077 GEN_BOOL_OPTION(draw_cities, N_("Draw the cities"),
2078 N_("Setting this option will draw the cities on the map."),
2079 COC_GRAPHICS, GUI_STUB, TRUE,
2080 view_option_changed_callback),
2081 GEN_BOOL_OPTION(draw_units, N_("Draw the units"),
2082 N_("Setting this option will draw the units on the map."),
2083 COC_GRAPHICS, GUI_STUB, TRUE,
2084 view_option_changed_callback),
2085 GEN_BOOL_OPTION(solid_color_behind_units,
2086 N_("Solid unit background color"),
2087 N_("Setting this option will cause units on the map "
2088 "view to be drawn with a solid background color "
2089 "instead of the flag backdrop."),
2090 COC_GRAPHICS, GUI_STUB,
2091 FALSE, view_option_changed_callback),
2092 GEN_BOOL_OPTION(draw_unit_shields, N_("Draw shield graphics for units"),
2093 N_("Setting this option will draw a shield icon "
2094 "as the flags on units. If unset, the full flag will "
2095 "be drawn."),
2096 COC_GRAPHICS, GUI_STUB, TRUE, view_option_changed_callback),
2097 GEN_BOOL_OPTION(draw_focus_unit, N_("Draw the units in focus"),
2098 N_("Setting this option will cause the currently focused "
2099 "unit(s) to always be drawn, even if units are not "
2100 "otherwise being drawn (for instance if 'Draw the units' "
2101 "is unset)."),
2102 COC_GRAPHICS, GUI_STUB, FALSE,
2103 view_option_changed_callback),
2104 GEN_BOOL_OPTION(draw_fog_of_war, N_("Draw the fog of war"),
2105 N_("Setting this option will draw the fog of war."),
2106 COC_GRAPHICS, GUI_STUB, TRUE,
2107 view_option_changed_callback),
2108 GEN_BOOL_OPTION(draw_borders, N_("Draw the borders"),
2109 N_("Setting this option will draw the national borders."),
2110 COC_GRAPHICS, GUI_STUB, TRUE,
2111 view_option_changed_callback),
2112 GEN_BOOL_OPTION(draw_native, N_("Draw whether tiles are native to "
2113 "selected unit"),
2114 N_("Setting this option will highlight tiles that the "
2115 "currently selected unit cannot enter unaided due to "
2116 "non-native terrain. (If multiple units are selected, "
2117 "only tiles that all of them can enter are indicated.)"),
2118 COC_GRAPHICS, GUI_STUB, FALSE,
2119 view_option_changed_callback),
2120 GEN_BOOL_OPTION(player_dlg_show_dead_players,
2121 N_("Show dead players in Nations report"),
2122 N_("This option controls whether defeated nations are "
2123 "shown on the Nations report page."),
2124 COC_GRAPHICS, GUI_STUB, TRUE,
2125 view_option_changed_callback),
2126 GEN_BOOL_OPTION(sound_bell_at_new_turn, N_("Sound bell at new turn"),
2127 N_("Set this option to have a \"bell\" event be generated "
2128 "at the start of a new turn. You can control the "
2129 "behavior of the \"bell\" event by editing the message "
2130 "options."),
2131 COC_SOUND, GUI_STUB, FALSE, NULL),
2132 GEN_INT_OPTION(smooth_move_unit_msec,
2133 N_("Unit movement animation time (milliseconds)"),
2134 N_("This option controls how long unit \"animation\" takes "
2135 "when a unit moves on the map view. Set it to 0 to "
2136 "disable animation entirely."),
2137 COC_GRAPHICS, GUI_STUB, 30, 0, 2000, NULL),
2138 GEN_INT_OPTION(smooth_center_slide_msec,
2139 N_("Mapview recentering time (milliseconds)"),
2140 N_("When the map view is recentered, it will slide "
2141 "smoothly over the map to its new position. This "
2142 "option controls how long this slide lasts. Set it to "
2143 "0 to disable mapview sliding entirely."),
2144 COC_GRAPHICS, GUI_STUB, 200, 0, 5000, NULL),
2145 GEN_INT_OPTION(smooth_combat_step_msec,
2146 N_("Combat animation step time (milliseconds)"),
2147 N_("This option controls the speed of combat animation "
2148 "between units on the mapview. Set it to 0 to disable "
2149 "animation entirely."),
2150 COC_GRAPHICS, GUI_STUB, 10, 0, 100, NULL),
2151 GEN_BOOL_OPTION(reqtree_show_icons,
2152 N_("Show icons in the technology tree"),
2153 N_("Setting this option will display icons "
2154 "on the technology tree diagram. Turning "
2155 "this option off makes the technology tree "
2156 "more compact."),
2157 COC_GRAPHICS, GUI_STUB, TRUE, reqtree_show_icons_callback),
2158 GEN_BOOL_OPTION(reqtree_curved_lines,
2159 N_("Use curved lines in the technology tree"),
2160 N_("Setting this option make the technology tree "
2161 "diagram use curved lines to show technology "
2162 "relations. Turning this option off causes "
2163 "the lines to be drawn straight."),
2164 COC_GRAPHICS, GUI_STUB, FALSE,
2165 reqtree_show_icons_callback),
2166 GEN_COLOR_OPTION(highlight_our_names,
2167 N_("Color to highlight your player/user name"),
2168 N_("If set, your player and user name in the new chat "
2169 "messages will be highlighted using this color as "
2170 "background. If not set, it will just not highlight "
2171 "anything."),
2172 COC_GRAPHICS, GUI_STUB, "#000000", "#FFFF00", NULL),
2173 GEN_BOOL_OPTION(ai_manual_turn_done, N_("Manual Turn Done in AI mode"),
2174 N_("Disable this option if you do not want to "
2175 "press the Turn Done button manually when watching "
2176 "an AI player."),
2177 COC_INTERFACE, GUI_STUB, TRUE, manual_turn_done_callback),
2178 GEN_BOOL_OPTION(auto_center_on_unit, N_("Auto center on units"),
2179 N_("Set this option to have the active unit centered "
2180 "automatically when the unit focus changes."),
2181 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2182 GEN_BOOL_OPTION(auto_center_on_automated, N_("Show automated units"),
2183 N_("Disable this option if you do not want to see "
2184 "automated units autocentered and animated"),
2185 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2186 GEN_BOOL_OPTION(auto_center_on_combat, N_("Auto center on combat"),
2187 N_("Set this option to have any combat be centered "
2188 "automatically. Disabling this will speed up the time "
2189 "between turns but may cause you to miss combat "
2190 "entirely."),
2191 COC_INTERFACE, GUI_STUB, FALSE, NULL),
2192 GEN_BOOL_OPTION(auto_center_each_turn, N_("Auto center on new turn"),
2193 N_("Set this option to have the client automatically "
2194 "recenter the map on a suitable location at the "
2195 "start of each turn."),
2196 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2197 GEN_BOOL_OPTION(wakeup_focus, N_("Focus on awakened units"),
2198 N_("Set this option to have newly awoken units be "
2199 "focused automatically."),
2200 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2201 GEN_BOOL_OPTION(keyboardless_goto, N_("Keyboardless goto"),
2202 N_("If this option is set then a goto may be initiated "
2203 "by left-clicking and then holding down the mouse "
2204 "button while dragging the mouse onto a different "
2205 "tile."),
2206 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2207 GEN_BOOL_OPTION(goto_into_unknown, N_("Allow goto into the unknown"),
2208 N_("Setting this option will make the game consider "
2209 "moving into unknown tiles. If not, then goto routes "
2210 "will detour around or be blocked by unknown tiles."),
2211 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2212 GEN_BOOL_OPTION(center_when_popup_city, N_("Center map when popup city"),
2213 N_("Setting this option makes the mapview center on a "
2214 "city when its city dialog is popped up."),
2215 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2216 GEN_BOOL_OPTION(show_previous_turn_messages, N_("Show messages from previous turn"),
2217 N_("Message Window shows messages also from previous turn. "
2218 "This makes sure you don't miss messages received in the end of "
2219 "the turn, just before the window gets cleared."),
2220 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2221 GEN_BOOL_OPTION(concise_city_production, N_("Concise city production"),
2222 N_("Set this option to make the city production (as shown "
2223 "in the city dialog) to be more compact."),
2224 COC_INTERFACE, GUI_STUB, FALSE, NULL),
2225 GEN_BOOL_OPTION(auto_turn_done, N_("End turn when done moving"),
2226 N_("Setting this option makes your turn end automatically "
2227 "when all your units are done moving."),
2228 COC_INTERFACE, GUI_STUB, FALSE, NULL),
2229 GEN_BOOL_OPTION(ask_city_name, N_("Prompt for city names"),
2230 N_("Disabling this option will make the names of newly "
2231 "founded cities be chosen automatically by the server."),
2232 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2233 GEN_BOOL_OPTION(popup_new_cities, N_("Pop up city dialog for new cities"),
2234 N_("Setting this option will pop up a newly-founded "
2235 "city's city dialog automatically."),
2236 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2237 GEN_BOOL_OPTION(popup_actor_arrival, N_("Pop up caravan and spy actions"),
2238 N_("If this option is enabled, when a unit arrives at "
2239 "a city where it can perform an action like "
2240 "establishing a trade route, helping build a wonder, or "
2241 "establishing an embassy, a window will pop up asking "
2242 "which action should be performed. "
2243 "Disabling this option means you will have to do the "
2244 "action manually by pressing either 'r' (for a trade "
2245 "route), 'b' (for building a wonder) or 'd' (for a "
2246 "spy action) when the unit is in the city."),
2247 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2248 GEN_BOOL_OPTION(popup_attack_actions, N_("Pop up attack questions"),
2249 N_("If this option is enabled, when a unit arrives at a "
2250 "target it can attack, a window will pop up asking "
2251 "which action should be performed even if an attack "
2252 "action is legal and no other interesting action are. "
2253 "This allows you to change you mind or to select an "
2254 "uninteresting action."),
2255 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2256 GEN_BOOL_OPTION(enable_cursor_changes, N_("Enable cursor changing"),
2257 N_("This option controls whether the client should "
2258 "try to change the mouse cursor depending on what "
2259 "is being pointed at, as well as to indicate "
2260 "changes in the client or server state."),
2261 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2262 GEN_BOOL_OPTION(separate_unit_selection, N_("Select cities before units"),
2263 N_("If this option is enabled, when both cities and "
2264 "units are present in the selection rectangle, only "
2265 "cities will be selected. See the help on Controls."),
2266 COC_INTERFACE, GUI_STUB, FALSE, NULL),
2267 GEN_BOOL_OPTION(unit_selection_clears_orders,
2268 N_("Clear unit orders on selection"),
2269 N_("Enabling this option will cause unit orders to be "
2270 "cleared as soon as one or more units are selected. If "
2271 "this option is disabled, busy units will not stop "
2272 "their current activity when selected. Giving them "
2273 "new orders will clear their current ones; pressing "
2274 "<space> once will clear their orders and leave them "
2275 "selected, and pressing <space> a second time will "
2276 "dismiss them."),
2277 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2278 GEN_BOOL_OPTION(voteinfo_bar_use, N_("Enable vote bar"),
2279 N_("If this option is turned on, the vote bar will be "
2280 "displayed to show vote information."),
2281 COC_GRAPHICS, GUI_STUB, TRUE, voteinfo_bar_callback),
2282 GEN_BOOL_OPTION(voteinfo_bar_always_show,
2283 N_("Always display the vote bar"),
2284 N_("If this option is turned on, the vote bar will never "
2285 "be hidden, even if there is no running vote."),
2286 COC_GRAPHICS, GUI_STUB, FALSE, voteinfo_bar_callback),
2287 GEN_BOOL_OPTION(voteinfo_bar_hide_when_not_player,
2288 N_("Do not show vote bar if not a player"),
2289 N_("If this option is enabled, the client won't show the "
2290 "vote bar if you are not a player."),
2291 COC_GRAPHICS, GUI_STUB, FALSE, voteinfo_bar_callback),
2292 GEN_BOOL_OPTION(voteinfo_bar_new_at_front, N_("Set new votes at front"),
2293 N_("If this option is enabled, then new votes will go "
2294 "to the front of the vote list."),
2295 COC_GRAPHICS, GUI_STUB, FALSE, voteinfo_bar_callback),
2296 GEN_BOOL_OPTION(autoaccept_tileset_suggestion,
2297 N_("Autoaccept tileset suggestions"),
2298 N_("If this option is enabled, any tileset suggested by "
2299 "the ruleset is automatically used; otherwise you "
2300 "are prompted to change tileset."),
2301 COC_GRAPHICS, GUI_STUB, FALSE, NULL),
2303 GEN_BOOL_OPTION(sound_enable_effects,
2304 N_("Enable sound effects"),
2305 N_("Play sound effects, assuming there's suitable "
2306 "sound plugin and soundset with the sounds."),
2307 COC_SOUND, GUI_STUB, TRUE, NULL),
2308 GEN_BOOL_OPTION(sound_enable_game_music,
2309 N_("Enable in-game music"),
2310 N_("Play music during the game, assuming there's suitable "
2311 "sound plugin and musicset with in-game tracks."),
2312 COC_SOUND, GUI_STUB, TRUE, game_music_enable_callback),
2313 GEN_BOOL_OPTION(sound_enable_menu_music,
2314 N_("Enable menu music"),
2315 N_("Play music while not in actual game, "
2316 "assuming there's suitable "
2317 "sound plugin and musicset with menu music tracks."),
2318 COC_SOUND, GUI_STUB, TRUE, menu_music_enable_callback),
2319 GEN_BOOL_OPTION(autoaccept_soundset_suggestion,
2320 N_("Autoaccept soundset suggestions"),
2321 N_("If this option is enabled, any soundset suggested by "
2322 "the ruleset is automatically used."),
2323 COC_SOUND, GUI_STUB, FALSE, NULL),
2324 GEN_BOOL_OPTION(autoaccept_musicset_suggestion,
2325 N_("Autoaccept musicset suggestions"),
2326 N_("If this option is enabled, any musicset suggested by "
2327 "the ruleset is automatically used."),
2328 COC_SOUND, GUI_STUB, FALSE, NULL),
2330 GEN_BOOL_OPTION(overview.layers[OLAYER_BACKGROUND],
2331 N_("Background layer"),
2332 N_("The background layer of the overview shows just "
2333 "ocean and land."),
2334 COC_OVERVIEW, GUI_STUB, TRUE, NULL),
2335 GEN_BOOL_OPTION(overview.layers[OLAYER_RELIEF],
2336 N_("Terrain relief map layer"),
2337 N_("The relief layer shows all terrains on the map."),
2338 COC_OVERVIEW, GUI_STUB, FALSE, overview_redraw_callback),
2339 GEN_BOOL_OPTION(overview.layers[OLAYER_BORDERS],
2340 N_("Borders layer"),
2341 N_("The borders layer of the overview shows which tiles "
2342 "are owned by each player."),
2343 COC_OVERVIEW, GUI_STUB, FALSE, overview_redraw_callback),
2344 GEN_BOOL_OPTION(overview.layers[OLAYER_BORDERS_ON_OCEAN],
2345 N_("Borders layer on ocean tiles"),
2346 N_("The borders layer of the overview are drawn on "
2347 "ocean tiles as well (this may look ugly with many "
2348 "islands). This option is only of interest if you "
2349 "have set the option \"Borders layer\" already."),
2350 COC_OVERVIEW, GUI_STUB, TRUE, overview_redraw_callback),
2351 GEN_BOOL_OPTION(overview.layers[OLAYER_UNITS],
2352 N_("Units layer"),
2353 N_("Enabling this will draw units on the overview."),
2354 COC_OVERVIEW, GUI_STUB, TRUE, overview_redraw_callback),
2355 GEN_BOOL_OPTION(overview.layers[OLAYER_CITIES],
2356 N_("Cities layer"),
2357 N_("Enabling this will draw cities on the overview."),
2358 COC_OVERVIEW, GUI_STUB, TRUE, overview_redraw_callback),
2359 GEN_BOOL_OPTION(overview.fog,
2360 N_("Overview fog of war"),
2361 N_("Enabling this will show fog of war on the "
2362 "overview."),
2363 COC_OVERVIEW, GUI_STUB, TRUE, overview_redraw_callback),
2365 /* options for map images */
2366 GEN_STR_LIST_OPTION(mapimg_format,
2367 N_("Image format"),
2368 N_("The image toolkit and file format used for "
2369 "map images."),
2370 COC_MAPIMG, GUI_STUB, NULL, get_mapimg_format_list,
2371 NULL, 0),
2372 GEN_INT_OPTION(mapimg_zoom,
2373 N_("Zoom factor for map images"),
2374 N_("The magnification used for map images."),
2375 COC_MAPIMG, GUI_STUB, 2, 1, 5, mapimg_changed_callback),
2376 GEN_BOOL_OPTION(mapimg_layer[MAPIMG_LAYER_AREA],
2377 N_("Show area within borders"),
2378 N_("If set, the territory of each nation is shown "
2379 "on the saved image."),
2380 COC_MAPIMG, GUI_STUB, FALSE, mapimg_changed_callback),
2381 GEN_BOOL_OPTION(mapimg_layer[MAPIMG_LAYER_BORDERS],
2382 N_("Show borders"),
2383 N_("If set, the border of each nation is shown on the "
2384 "saved image."),
2385 COC_MAPIMG, GUI_STUB, TRUE, mapimg_changed_callback),
2386 GEN_BOOL_OPTION(mapimg_layer[MAPIMG_LAYER_CITIES],
2387 N_("Show cities"),
2388 N_("If set, cities are shown on the saved image."),
2389 COC_MAPIMG, GUI_STUB, TRUE, mapimg_changed_callback),
2390 GEN_BOOL_OPTION(mapimg_layer[MAPIMG_LAYER_FOGOFWAR],
2391 N_("Show fog of war"),
2392 N_("If set, the extent of fog of war is shown on the "
2393 "saved image."),
2394 COC_MAPIMG, GUI_STUB, TRUE, mapimg_changed_callback),
2395 GEN_BOOL_OPTION(mapimg_layer[MAPIMG_LAYER_TERRAIN],
2396 N_("Show full terrain"),
2397 N_("If set, terrain relief is shown with different colors "
2398 "in the saved image; otherwise, only land and water are "
2399 "distinguished."),
2400 COC_MAPIMG, GUI_STUB, TRUE, mapimg_changed_callback),
2401 GEN_BOOL_OPTION(mapimg_layer[MAPIMG_LAYER_UNITS],
2402 N_("Show units"),
2403 N_("If set, units are shown in the saved image."),
2404 COC_MAPIMG, GUI_STUB, TRUE, mapimg_changed_callback),
2405 GEN_STR_OPTION(mapimg_filename,
2406 N_("Map image file name"),
2407 N_("The base part of the filename for saved map images. "
2408 "A string identifying the game turn and map options will "
2409 "be appended."),
2410 COC_MAPIMG, GUI_STUB, GUI_DEFAULT_MAPIMG_FILENAME, NULL, 0),
2412 /* gui-gtk-2.0 client specific options.
2413 * These are still kept just so users can migrate them to gtk3-client */
2414 GEN_BOOL_OPTION(gui_gtk2_fullscreen, NULL, NULL,
2415 COC_INTERFACE, GUI_GTK2, FALSE, NULL),
2416 GEN_BOOL_OPTION(gui_gtk2_map_scrollbars, NULL, NULL,
2417 COC_INTERFACE, GUI_GTK2, FALSE, NULL),
2418 GEN_BOOL_OPTION(gui_gtk2_dialogs_on_top, NULL, NULL,
2419 COC_INTERFACE, GUI_GTK2, TRUE, NULL),
2420 GEN_BOOL_OPTION(gui_gtk2_show_task_icons, NULL, NULL,
2421 COC_GRAPHICS, GUI_GTK2, TRUE, NULL),
2422 GEN_BOOL_OPTION(gui_gtk2_enable_tabs, NULL, NULL,
2423 COC_INTERFACE, GUI_GTK2, TRUE, NULL),
2424 GEN_BOOL_OPTION(gui_gtk2_better_fog, NULL, NULL,
2425 COC_GRAPHICS, GUI_GTK2,
2426 TRUE, view_option_changed_callback),
2427 GEN_BOOL_OPTION(gui_gtk2_show_chat_message_time, NULL, NULL,
2428 COC_INTERFACE, GUI_GTK2, FALSE, NULL),
2429 GEN_BOOL_OPTION(gui_gtk2_new_messages_go_to_top, NULL, NULL,
2430 COC_INTERFACE, GUI_GTK2, FALSE, NULL),
2431 GEN_BOOL_OPTION(gui_gtk2_show_message_window_buttons, NULL, NULL,
2432 COC_INTERFACE, GUI_GTK2, TRUE, NULL),
2433 GEN_BOOL_OPTION(gui_gtk2_metaserver_tab_first, NULL, NULL,
2434 COC_NETWORK, GUI_GTK2, FALSE, NULL),
2435 GEN_BOOL_OPTION(gui_gtk2_allied_chat_only, NULL, NULL,
2436 COC_INTERFACE, GUI_GTK2, FALSE, NULL),
2437 GEN_ENUM_OPTION(gui_gtk2_message_chat_location, NULL, NULL,
2438 COC_INTERFACE, GUI_GTK2,
2439 GUI_GTK_MSGCHAT_MERGED /* Ignored! See options_load(). */,
2440 gui_gtk_message_chat_location_name, NULL),
2441 GEN_BOOL_OPTION(gui_gtk2_small_display_layout, NULL, NULL,
2442 COC_INTERFACE, GUI_GTK2, TRUE, NULL),
2443 GEN_BOOL_OPTION(gui_gtk2_mouse_over_map_focus, NULL, NULL,
2444 COC_INTERFACE, GUI_GTK2, FALSE, NULL),
2445 GEN_BOOL_OPTION(gui_gtk2_chatline_autocompletion, NULL, NULL,
2446 COC_INTERFACE, GUI_GTK2, TRUE, NULL),
2447 GEN_INT_OPTION(gui_gtk2_citydlg_xsize, NULL, NULL,
2448 COC_INTERFACE, GUI_GTK2, GUI_GTK2_CITYDLG_DEFAULT_XSIZE,
2449 GUI_GTK2_CITYDLG_MIN_XSIZE, GUI_GTK2_CITYDLG_MAX_XSIZE,
2450 NULL),
2451 GEN_INT_OPTION(gui_gtk2_citydlg_ysize, NULL, NULL,
2452 COC_INTERFACE, GUI_GTK2, GUI_GTK2_CITYDLG_DEFAULT_YSIZE,
2453 GUI_GTK2_CITYDLG_MIN_YSIZE, GUI_GTK2_CITYDLG_MAX_YSIZE,
2454 NULL),
2455 GEN_ENUM_OPTION(gui_gtk2_popup_tech_help, NULL, NULL,
2456 COC_INTERFACE, GUI_GTK2,
2457 GUI_POPUP_TECH_HELP_RULESET,
2458 gui_popup_tech_help_name, NULL),
2459 GEN_FONT_OPTION(gui_gtk2_font_city_label, "city_label",
2460 NULL, NULL,
2461 COC_FONT, GUI_GTK2,
2462 "Monospace 8", font_changed_callback),
2463 GEN_FONT_OPTION(gui_gtk2_font_notify_label, "notify_label",
2464 NULL, NULL,
2465 COC_FONT, GUI_GTK2,
2466 "Monospace Bold 9", font_changed_callback),
2467 GEN_FONT_OPTION(gui_gtk2_font_spaceship_label, "spaceship_label",
2468 NULL, NULL,
2469 COC_FONT, GUI_GTK2,
2470 "Monospace 8", font_changed_callback),
2471 GEN_FONT_OPTION(gui_gtk2_font_help_label, "help_label",
2472 NULL, NULL,
2473 COC_FONT, GUI_GTK2,
2474 "Sans Bold 10", font_changed_callback),
2475 GEN_FONT_OPTION(gui_gtk2_font_help_link, "help_link",
2476 NULL, NULL,
2477 COC_FONT, GUI_GTK2,
2478 "Sans 9", font_changed_callback),
2479 GEN_FONT_OPTION(gui_gtk2_font_help_text, "help_text",
2480 NULL, NULL,
2481 COC_FONT, GUI_GTK2,
2482 "Monospace 8", font_changed_callback),
2483 GEN_FONT_OPTION(gui_gtk2_font_chatline, "chatline",
2484 NULL, NULL,
2485 COC_FONT, GUI_GTK2,
2486 "Monospace 8", font_changed_callback),
2487 GEN_FONT_OPTION(gui_gtk2_font_beta_label, "beta_label",
2488 NULL, NULL,
2489 COC_FONT, GUI_GTK2,
2490 "Sans Italic 10", font_changed_callback),
2491 GEN_FONT_OPTION(gui_gtk2_font_small, "small_font",
2492 NULL, NULL,
2493 COC_FONT, GUI_GTK2,
2494 "Sans 9", NULL),
2495 GEN_FONT_OPTION(gui_gtk2_font_comment_label, "comment_label",
2496 NULL, NULL,
2497 COC_FONT, GUI_GTK2,
2498 "Sans Italic 9", font_changed_callback),
2499 GEN_FONT_OPTION(gui_gtk2_font_city_names, "city_names",
2500 NULL, NULL,
2501 COC_FONT, GUI_GTK2,
2502 "Sans Bold 10", NULL),
2503 GEN_FONT_OPTION(gui_gtk2_font_city_productions, "city_productions",
2504 NULL, NULL,
2505 COC_FONT, GUI_GTK2,
2506 "Serif 10", NULL),
2507 GEN_FONT_OPTION(gui_gtk2_font_reqtree_text, "reqtree_text",
2508 NULL, NULL,
2509 COC_FONT, GUI_GTK2,
2510 "Serif 10", NULL),
2512 /* gui-gtk-3.0 client specific options. */
2513 GEN_BOOL_OPTION(gui_gtk3_fullscreen, N_("Fullscreen"),
2514 N_("If this option is set the client will use the "
2515 "whole screen area for drawing."),
2516 COC_INTERFACE, GUI_GTK3, FALSE, NULL),
2517 GEN_BOOL_OPTION(gui_gtk3_map_scrollbars, N_("Show map scrollbars"),
2518 N_("Disable this option to hide the scrollbars on the "
2519 "map view."),
2520 COC_INTERFACE, GUI_GTK3, FALSE, NULL),
2521 GEN_BOOL_OPTION(gui_gtk3_dialogs_on_top, N_("Keep dialogs on top"),
2522 N_("If this option is set then dialog windows will always "
2523 "remain in front of the main Freeciv window. "
2524 "Disabling this has no effect in fullscreen mode."),
2525 COC_INTERFACE, GUI_GTK3, TRUE, NULL),
2526 GEN_BOOL_OPTION(gui_gtk3_show_task_icons, N_("Show worklist task icons"),
2527 N_("Disabling this will turn off the unit and building "
2528 "icons in the worklist dialog and the production "
2529 "tab of the city dialog."),
2530 COC_GRAPHICS, GUI_GTK3, TRUE, NULL),
2531 GEN_BOOL_OPTION(gui_gtk3_enable_tabs, N_("Enable status report tabs"),
2532 N_("If this option is enabled then report dialogs will "
2533 "be shown as separate tabs rather than in popup "
2534 "dialogs."),
2535 COC_INTERFACE, GUI_GTK3, TRUE, NULL),
2536 GEN_BOOL_OPTION(gui_gtk3_show_chat_message_time,
2537 N_("Show time for each chat message"),
2538 N_("If this option is enabled then all chat messages "
2539 "will be prefixed by a time string of the form "
2540 "[hour:minute:second]."),
2541 COC_INTERFACE, GUI_GTK3, FALSE, NULL),
2542 GEN_BOOL_OPTION(gui_gtk3_new_messages_go_to_top,
2543 N_("New message events go to top of list"),
2544 N_("If this option is enabled, new events in the "
2545 "message window will appear at the top of the list, "
2546 "rather than being appended at the bottom."),
2547 COC_INTERFACE, GUI_GTK3, FALSE, NULL),
2548 GEN_BOOL_OPTION(gui_gtk3_show_message_window_buttons,
2549 N_("Show extra message window buttons"),
2550 N_("If this option is enabled, there will be two "
2551 "buttons displayed in the message window for "
2552 "inspecting a city and going to a location. If this "
2553 "option is disabled, these buttons will not appear "
2554 "(you can still double-click with the left mouse "
2555 "button or right-click on a row to inspect or goto "
2556 "respectively). This option will only take effect "
2557 "once the message window is closed and reopened."),
2558 COC_INTERFACE, GUI_GTK3, TRUE, NULL),
2559 GEN_BOOL_OPTION(gui_gtk3_metaserver_tab_first,
2560 N_("Metaserver tab first in network page"),
2561 N_("If this option is enabled, the metaserver tab will "
2562 "be the first notebook tab in the network page. This "
2563 "option requires a restart in order to take effect."),
2564 COC_NETWORK, GUI_GTK3, FALSE, NULL),
2565 GEN_BOOL_OPTION(gui_gtk3_allied_chat_only,
2566 N_("Plain chat messages are sent to allies only"),
2567 N_("If this option is enabled, then plain messages "
2568 "typed into the chat entry while the game is "
2569 "running will only be sent to your allies. "
2570 "Otherwise plain messages will be sent as "
2571 "public chat messages. To send a public chat "
2572 "message with this option enabled, prefix the "
2573 "message with a single colon ':'. This option "
2574 "can also be set using a toggle button beside "
2575 "the chat entry (only visible in multiplayer "
2576 "games)."),
2577 COC_INTERFACE, GUI_GTK3, FALSE, NULL),
2578 GEN_ENUM_OPTION(gui_gtk3_message_chat_location,
2579 N_("Messages and Chat reports location"),
2580 /* TRANS: The strings used in the UI for 'Split' etc are
2581 * tagged 'gui_gtk2/gtk3/gtk3x_message_chat_location' */
2582 N_("Controls where the Messages and Chat reports "
2583 "appear relative to the main view containing the map.\n"
2584 "'Split' allows all three to be seen simultaneously, "
2585 "which is best for multiplayer, but requires a large "
2586 "window to be usable.\n"
2587 "'Separate' puts Messages and Chat in a notebook "
2588 "separate from the main view, so that one of them "
2589 "can always be seen alongside the main view.\n"
2590 "'Merged' makes the Messages and Chat reports into "
2591 "tabs alongside the map and other reports; this "
2592 "allows a larger map view on small screens.\n"
2593 "This option requires a restart in order to take "
2594 "effect."), COC_INTERFACE, GUI_GTK3,
2595 GUI_GTK_MSGCHAT_MERGED /* Ignored! See options_load(). */,
2596 gui_gtk_message_chat_location_name, NULL),
2597 GEN_BOOL_OPTION(gui_gtk3_small_display_layout,
2598 N_("Arrange widgets for small displays"),
2599 N_("If this option is enabled, widgets in the main "
2600 "window will be arranged so that they take up the "
2601 "least amount of total screen space. Specifically, "
2602 "the left panel containing the overview, player "
2603 "status, and the unit information box will be "
2604 "extended over the entire left side of the window. "
2605 "This option requires a restart in order to take "
2606 "effect."), COC_INTERFACE, GUI_GTK3, TRUE, NULL),
2607 GEN_BOOL_OPTION(gui_gtk3_mouse_over_map_focus,
2608 N_("Mouse over the map widget selects it automatically"),
2609 N_("If this option is enabled, then the map will be "
2610 "focused when the mouse hovers over it."),
2611 COC_INTERFACE, GUI_GTK3, FALSE, NULL),
2612 GEN_BOOL_OPTION(gui_gtk3_chatline_autocompletion,
2613 N_("Player or user name autocompletion"),
2614 N_("If this option is turned on, the tabulation key "
2615 "will be used in the chatline to complete the word you "
2616 "are typing with the name of a player or a user."),
2617 COC_INTERFACE, GUI_GTK3, TRUE, NULL),
2618 GEN_INT_OPTION(gui_gtk3_citydlg_xsize,
2619 N_("Width of the city dialog"),
2620 N_("This value is only used if the width of the city "
2621 "dialog is saved."),
2622 COC_INTERFACE, GUI_GTK3, GUI_GTK3_CITYDLG_DEFAULT_XSIZE,
2623 GUI_GTK3_CITYDLG_MIN_XSIZE, GUI_GTK3_CITYDLG_MAX_XSIZE,
2624 NULL),
2625 GEN_INT_OPTION(gui_gtk3_citydlg_ysize,
2626 N_("Height of the city dialog"),
2627 N_("This value is only used if the height of the city "
2628 "dialog is saved."),
2629 COC_INTERFACE, GUI_GTK3, GUI_GTK3_CITYDLG_DEFAULT_YSIZE,
2630 GUI_GTK3_CITYDLG_MIN_YSIZE, GUI_GTK3_CITYDLG_MAX_YSIZE,
2631 NULL),
2632 GEN_ENUM_OPTION(gui_gtk3_popup_tech_help,
2633 N_("Popup tech help when gained"),
2634 N_("Controls if tech help should be opened when "
2635 "new tech has been gained.\n"
2636 "'Ruleset' means that behavior suggested by "
2637 "current ruleset is used."), COC_INTERFACE, GUI_GTK3,
2638 GUI_POPUP_TECH_HELP_RULESET,
2639 gui_popup_tech_help_name, NULL),
2640 GEN_INT_OPTION(gui_gtk3_governor_range_min,
2641 N_("Minimum surplus for a governor"),
2642 N_("The lower limit of the range for requesting surpluses "
2643 "from the governor."),
2644 COC_INTERFACE, GUI_GTK3, GUI_GTK3_GOV_RANGE_MIN_DEFAULT,
2645 GUI_GTK3_GOV_RANGE_MIN_MIN, GUI_GTK3_GOV_RANGE_MIN_MAX,
2646 NULL),
2647 GEN_INT_OPTION(gui_gtk3_governor_range_max,
2648 N_("Maximum surplus for a governor"),
2649 N_("The higher limit of the range for requesting surpluses "
2650 "from the governor."),
2651 COC_INTERFACE, GUI_GTK3, GUI_GTK3_GOV_RANGE_MAX_DEFAULT,
2652 GUI_GTK3_GOV_RANGE_MAX_MIN, GUI_GTK3_GOV_RANGE_MAX_MAX,
2653 NULL),
2654 GEN_FONT_OPTION(gui_gtk3_font_city_label, "city_label",
2655 N_("City Label"),
2656 N_("This font is used to display the city labels on city "
2657 "dialogs."),
2658 COC_FONT, GUI_GTK3,
2659 "Monospace 8", font_changed_callback),
2660 GEN_FONT_OPTION(gui_gtk3_font_notify_label, "notify_label",
2661 N_("Notify Label"),
2662 N_("This font is used to display server reports such "
2663 "as the demographic report or historian publications."),
2664 COC_FONT, GUI_GTK3,
2665 "Monospace Bold 9", font_changed_callback),
2666 GEN_FONT_OPTION(gui_gtk3_font_spaceship_label, "spaceship_label",
2667 N_("Spaceship Label"),
2668 N_("This font is used to display the spaceship widgets."),
2669 COC_FONT, GUI_GTK3,
2670 "Monospace 8", font_changed_callback),
2671 GEN_FONT_OPTION(gui_gtk3_font_help_label, "help_label",
2672 N_("Help Label"),
2673 N_("This font is used to display the help headers in the "
2674 "help window."),
2675 COC_FONT, GUI_GTK3,
2676 "Sans Bold 10", font_changed_callback),
2677 GEN_FONT_OPTION(gui_gtk3_font_help_link, "help_link",
2678 N_("Help Link"),
2679 N_("This font is used to display the help links in the "
2680 "help window."),
2681 COC_FONT, GUI_GTK3,
2682 "Sans 9", font_changed_callback),
2683 GEN_FONT_OPTION(gui_gtk3_font_help_text, "help_text",
2684 N_("Help Text"),
2685 N_("This font is used to display the help body text in "
2686 "the help window."),
2687 COC_FONT, GUI_GTK3,
2688 "Monospace 8", font_changed_callback),
2689 GEN_FONT_OPTION(gui_gtk3_font_chatline, "chatline",
2690 N_("Chatline Area"),
2691 N_("This font is used to display the text in the "
2692 "chatline area."),
2693 COC_FONT, GUI_GTK3,
2694 "Monospace 8", font_changed_callback),
2695 GEN_FONT_OPTION(gui_gtk3_font_beta_label, "beta_label",
2696 N_("Beta Label"),
2697 N_("This font is used to display the beta label."),
2698 COC_FONT, GUI_GTK3,
2699 "Sans Italic 10", font_changed_callback),
2700 GEN_FONT_OPTION(gui_gtk3_font_small, "small_font",
2701 N_("Small Font"),
2702 N_("This font is used for any small font request. For "
2703 "example, it is used for display the building lists "
2704 "in the city dialog, the Economy report or the Units "
2705 "report."),
2706 COC_FONT, GUI_GTK3,
2707 "Sans 9", NULL),
2708 GEN_FONT_OPTION(gui_gtk3_font_comment_label, "comment_label",
2709 N_("Comment Label"),
2710 N_("This font is used to display comment labels, such as "
2711 "in the governor page of the city dialogs."),
2712 COC_FONT, GUI_GTK3,
2713 "Sans Italic 9", font_changed_callback),
2714 GEN_FONT_OPTION(gui_gtk3_font_city_names, "city_names",
2715 N_("City Names"),
2716 N_("This font is used to the display the city names "
2717 "on the map."),
2718 COC_FONT, GUI_GTK3,
2719 "Sans Bold 10", NULL),
2720 GEN_FONT_OPTION(gui_gtk3_font_city_productions, "city_productions",
2721 N_("City Productions"),
2722 N_("This font is used to the display the city production "
2723 "names on the map."),
2724 COC_FONT, GUI_GTK3,
2725 "Serif 10", NULL),
2726 GEN_FONT_OPTION(gui_gtk3_font_reqtree_text, "reqtree_text",
2727 N_("Requirement Tree"),
2728 N_("This font is used to the display the requirement tree "
2729 "in the Research report."),
2730 COC_FONT, GUI_GTK3,
2731 "Serif 10", NULL),
2733 /* gui-gtk-3.22 client specific options. */
2734 GEN_BOOL_OPTION(gui_gtk3_22_fullscreen, N_("Fullscreen"),
2735 N_("If this option is set the client will use the "
2736 "whole screen area for drawing."),
2737 COC_INTERFACE, GUI_GTK3_22, FALSE, NULL),
2738 GEN_BOOL_OPTION(gui_gtk3_22_map_scrollbars, N_("Show map scrollbars"),
2739 N_("Disable this option to hide the scrollbars on the "
2740 "map view."),
2741 COC_INTERFACE, GUI_GTK3_22, FALSE, NULL),
2742 GEN_BOOL_OPTION(gui_gtk3_22_dialogs_on_top, N_("Keep dialogs on top"),
2743 N_("If this option is set then dialog windows will always "
2744 "remain in front of the main Freeciv window. "
2745 "Disabling this has no effect in fullscreen mode."),
2746 COC_INTERFACE, GUI_GTK3_22, TRUE, NULL),
2747 GEN_BOOL_OPTION(gui_gtk3_22_show_task_icons, N_("Show worklist task icons"),
2748 N_("Disabling this will turn off the unit and building "
2749 "icons in the worklist dialog and the production "
2750 "tab of the city dialog."),
2751 COC_GRAPHICS, GUI_GTK3_22, TRUE, NULL),
2752 GEN_BOOL_OPTION(gui_gtk3_22_enable_tabs, N_("Enable status report tabs"),
2753 N_("If this option is enabled then report dialogs will "
2754 "be shown as separate tabs rather than in popup "
2755 "dialogs."),
2756 COC_INTERFACE, GUI_GTK3_22, TRUE, NULL),
2757 GEN_BOOL_OPTION(gui_gtk3_22_show_chat_message_time,
2758 N_("Show time for each chat message"),
2759 N_("If this option is enabled then all chat messages "
2760 "will be prefixed by a time string of the form "
2761 "[hour:minute:second]."),
2762 COC_INTERFACE, GUI_GTK3_22, FALSE, NULL),
2763 GEN_BOOL_OPTION(gui_gtk3_22_new_messages_go_to_top,
2764 N_("New message events go to top of list"),
2765 N_("If this option is enabled, new events in the "
2766 "message window will appear at the top of the list, "
2767 "rather than being appended at the bottom."),
2768 COC_INTERFACE, GUI_GTK3_22, FALSE, NULL),
2769 GEN_BOOL_OPTION(gui_gtk3_22_show_message_window_buttons,
2770 N_("Show extra message window buttons"),
2771 N_("If this option is enabled, there will be two "
2772 "buttons displayed in the message window for "
2773 "inspecting a city and going to a location. If this "
2774 "option is disabled, these buttons will not appear "
2775 "(you can still double-click with the left mouse "
2776 "button or right-click on a row to inspect or goto "
2777 "respectively). This option will only take effect "
2778 "once the message window is closed and reopened."),
2779 COC_INTERFACE, GUI_GTK3_22, TRUE, NULL),
2780 GEN_BOOL_OPTION(gui_gtk3_22_metaserver_tab_first,
2781 N_("Metaserver tab first in network page"),
2782 N_("If this option is enabled, the metaserver tab will "
2783 "be the first notebook tab in the network page. This "
2784 "option requires a restart in order to take effect."),
2785 COC_NETWORK, GUI_GTK3_22, FALSE, NULL),
2786 GEN_BOOL_OPTION(gui_gtk3_22_allied_chat_only,
2787 N_("Plain chat messages are sent to allies only"),
2788 N_("If this option is enabled, then plain messages "
2789 "typed into the chat entry while the game is "
2790 "running will only be sent to your allies. "
2791 "Otherwise plain messages will be sent as "
2792 "public chat messages. To send a public chat "
2793 "message with this option enabled, prefix the "
2794 "message with a single colon ':'. This option "
2795 "can also be set using a toggle button beside "
2796 "the chat entry (only visible in multiplayer "
2797 "games)."),
2798 COC_INTERFACE, GUI_GTK3_22, FALSE, NULL),
2799 GEN_ENUM_OPTION(gui_gtk3_22_message_chat_location,
2800 N_("Messages and Chat reports location"),
2801 /* TRANS: The strings used in the UI for 'Split' etc are
2802 * tagged 'gui_gtk2/gtk3/gtk3x_message_chat_location' */
2803 N_("Controls where the Messages and Chat reports "
2804 "appear relative to the main view containing the map.\n"
2805 "'Split' allows all three to be seen simultaneously, "
2806 "which is best for multiplayer, but requires a large "
2807 "window to be usable.\n"
2808 "'Separate' puts Messages and Chat in a notebook "
2809 "separate from the main view, so that one of them "
2810 "can always be seen alongside the main view.\n"
2811 "'Merged' makes the Messages and Chat reports into "
2812 "tabs alongside the map and other reports; this "
2813 "allows a larger map view on small screens.\n"
2814 "This option requires a restart in order to take "
2815 "effect."), COC_INTERFACE, GUI_GTK3_22,
2816 GUI_GTK_MSGCHAT_MERGED /* Ignored! See options_load(). */,
2817 gui_gtk_message_chat_location_name, NULL),
2818 GEN_BOOL_OPTION(gui_gtk3_22_small_display_layout,
2819 N_("Arrange widgets for small displays"),
2820 N_("If this option is enabled, widgets in the main "
2821 "window will be arranged so that they take up the "
2822 "least amount of total screen space. Specifically, "
2823 "the left panel containing the overview, player "
2824 "status, and the unit information box will be "
2825 "extended over the entire left side of the window. "
2826 "This option requires a restart in order to take "
2827 "effect."), COC_INTERFACE, GUI_GTK3_22, TRUE, NULL),
2828 GEN_BOOL_OPTION(gui_gtk3_22_mouse_over_map_focus,
2829 N_("Mouse over the map widget selects it automatically"),
2830 N_("If this option is enabled, then the map will be "
2831 "focused when the mouse hovers over it."),
2832 COC_INTERFACE, GUI_GTK3_22, FALSE, NULL),
2833 GEN_BOOL_OPTION(gui_gtk3_22_chatline_autocompletion,
2834 N_("Player or user name autocompletion"),
2835 N_("If this option is turned on, the tabulation key "
2836 "will be used in the chatline to complete the word you "
2837 "are typing with the name of a player or a user."),
2838 COC_INTERFACE, GUI_GTK3_22, TRUE, NULL),
2839 GEN_INT_OPTION(gui_gtk3_22_citydlg_xsize,
2840 N_("Width of the city dialog"),
2841 N_("This value is only used if the width of the city "
2842 "dialog is saved."),
2843 COC_INTERFACE, GUI_GTK3_22, GUI_GTK3_22_CITYDLG_DEFAULT_XSIZE,
2844 GUI_GTK3_22_CITYDLG_MIN_XSIZE, GUI_GTK3_22_CITYDLG_MAX_XSIZE,
2845 NULL),
2846 GEN_INT_OPTION(gui_gtk3_22_citydlg_ysize,
2847 N_("Height of the city dialog"),
2848 N_("This value is only used if the height of the city "
2849 "dialog is saved."),
2850 COC_INTERFACE, GUI_GTK3_22, GUI_GTK3_22_CITYDLG_DEFAULT_YSIZE,
2851 GUI_GTK3_22_CITYDLG_MIN_YSIZE, GUI_GTK3_22_CITYDLG_MAX_YSIZE,
2852 NULL),
2853 GEN_ENUM_OPTION(gui_gtk3_22_popup_tech_help,
2854 N_("Popup tech help when gained"),
2855 N_("Controls if tech help should be opened when "
2856 "new tech has been gained.\n"
2857 "'Ruleset' means that behavior suggested by "
2858 "current ruleset is used."), COC_INTERFACE, GUI_GTK3_22,
2859 GUI_POPUP_TECH_HELP_RULESET,
2860 gui_popup_tech_help_name, NULL),
2861 GEN_INT_OPTION(gui_gtk3_22_governor_range_min,
2862 N_("Minimum surplus for a governor"),
2863 N_("The lower limit of the range for requesting surpluses "
2864 "from the governor."),
2865 COC_INTERFACE, GUI_GTK3_22, GUI_GTK3_22_GOV_RANGE_MIN_DEFAULT,
2866 GUI_GTK3_22_GOV_RANGE_MIN_MIN, GUI_GTK3_22_GOV_RANGE_MIN_MAX,
2867 NULL),
2868 GEN_INT_OPTION(gui_gtk3_22_governor_range_max,
2869 N_("Maximum surplus for a governor"),
2870 N_("The higher limit of the range for requesting surpluses "
2871 "from the governor."),
2872 COC_INTERFACE, GUI_GTK3_22, GUI_GTK3_22_GOV_RANGE_MAX_DEFAULT,
2873 GUI_GTK3_22_GOV_RANGE_MAX_MIN, GUI_GTK3_22_GOV_RANGE_MAX_MAX,
2874 NULL),
2875 GEN_FONT_OPTION(gui_gtk3_22_font_city_label, "city_label",
2876 N_("City Label"),
2877 N_("This font is used to display the city labels on city "
2878 "dialogs."),
2879 COC_FONT, GUI_GTK3_22,
2880 "Monospace 8", font_changed_callback),
2881 GEN_FONT_OPTION(gui_gtk3_22_font_notify_label, "notify_label",
2882 N_("Notify Label"),
2883 N_("This font is used to display server reports such "
2884 "as the demographic report or historian publications."),
2885 COC_FONT, GUI_GTK3_22,
2886 "Monospace Bold 9", font_changed_callback),
2887 GEN_FONT_OPTION(gui_gtk3_22_font_spaceship_label, "spaceship_label",
2888 N_("Spaceship Label"),
2889 N_("This font is used to display the spaceship widgets."),
2890 COC_FONT, GUI_GTK3_22,
2891 "Monospace 8", font_changed_callback),
2892 GEN_FONT_OPTION(gui_gtk3_22_font_help_label, "help_label",
2893 N_("Help Label"),
2894 N_("This font is used to display the help headers in the "
2895 "help window."),
2896 COC_FONT, GUI_GTK3_22,
2897 "Sans Bold 10", font_changed_callback),
2898 GEN_FONT_OPTION(gui_gtk3_22_font_help_link, "help_link",
2899 N_("Help Link"),
2900 N_("This font is used to display the help links in the "
2901 "help window."),
2902 COC_FONT, GUI_GTK3_22,
2903 "Sans 9", font_changed_callback),
2904 GEN_FONT_OPTION(gui_gtk3_22_font_help_text, "help_text",
2905 N_("Help Text"),
2906 N_("This font is used to display the help body text in "
2907 "the help window."),
2908 COC_FONT, GUI_GTK3_22,
2909 "Monospace 8", font_changed_callback),
2910 GEN_FONT_OPTION(gui_gtk3_22_font_chatline, "chatline",
2911 N_("Chatline Area"),
2912 N_("This font is used to display the text in the "
2913 "chatline area."),
2914 COC_FONT, GUI_GTK3_22,
2915 "Monospace 8", font_changed_callback),
2916 GEN_FONT_OPTION(gui_gtk3_22_font_beta_label, "beta_label",
2917 N_("Beta Label"),
2918 N_("This font is used to display the beta label."),
2919 COC_FONT, GUI_GTK3_22,
2920 "Sans Italic 10", font_changed_callback),
2921 GEN_FONT_OPTION(gui_gtk3_22_font_small, "small_font",
2922 N_("Small Font"),
2923 N_("This font is used for any small font request. For "
2924 "example, it is used for display the building lists "
2925 "in the city dialog, the Economy report or the Units "
2926 "report."),
2927 COC_FONT, GUI_GTK3_22,
2928 "Sans 9", NULL),
2929 GEN_FONT_OPTION(gui_gtk3_22_font_comment_label, "comment_label",
2930 N_("Comment Label"),
2931 N_("This font is used to display comment labels, such as "
2932 "in the governor page of the city dialogs."),
2933 COC_FONT, GUI_GTK3_22,
2934 "Sans Italic 9", font_changed_callback),
2935 GEN_FONT_OPTION(gui_gtk3_22_font_city_names, "city_names",
2936 N_("City Names"),
2937 N_("This font is used to the display the city names "
2938 "on the map."),
2939 COC_FONT, GUI_GTK3_22,
2940 "Sans Bold 10", NULL),
2941 GEN_FONT_OPTION(gui_gtk3_22_font_city_productions, "city_productions",
2942 N_("City Productions"),
2943 N_("This font is used to the display the city production "
2944 "names on the map."),
2945 COC_FONT, GUI_GTK3_22,
2946 "Serif 10", NULL),
2947 GEN_FONT_OPTION(gui_gtk3_22_font_reqtree_text, "reqtree_text",
2948 N_("Requirement Tree"),
2949 N_("This font is used to the display the requirement tree "
2950 "in the Research report."),
2951 COC_FONT, GUI_GTK3_22,
2952 "Serif 10", NULL),
2954 /* gui-gtk-3.x client specific options. */
2955 GEN_BOOL_OPTION(gui_gtk4_fullscreen, N_("Fullscreen"),
2956 N_("If this option is set the client will use the "
2957 "whole screen area for drawing."),
2958 COC_INTERFACE, GUI_GTK3x, FALSE, NULL),
2959 GEN_BOOL_OPTION(gui_gtk4_map_scrollbars, N_("Show map scrollbars"),
2960 N_("Disable this option to hide the scrollbars on the "
2961 "map view."),
2962 COC_INTERFACE, GUI_GTK3x, FALSE, NULL),
2963 GEN_BOOL_OPTION(gui_gtk4_dialogs_on_top, N_("Keep dialogs on top"),
2964 N_("If this option is set then dialog windows will always "
2965 "remain in front of the main Freeciv window. "
2966 "Disabling this has no effect in fullscreen mode."),
2967 COC_INTERFACE, GUI_GTK3x, TRUE, NULL),
2968 GEN_BOOL_OPTION(gui_gtk4_show_task_icons, N_("Show worklist task icons"),
2969 N_("Disabling this will turn off the unit and building "
2970 "icons in the worklist dialog and the production "
2971 "tab of the city dialog."),
2972 COC_GRAPHICS, GUI_GTK3x, TRUE, NULL),
2973 GEN_BOOL_OPTION(gui_gtk4_enable_tabs, N_("Enable status report tabs"),
2974 N_("If this option is enabled then report dialogs will "
2975 "be shown as separate tabs rather than in popup "
2976 "dialogs."),
2977 COC_INTERFACE, GUI_GTK3x, TRUE, NULL),
2978 GEN_BOOL_OPTION(gui_gtk4_show_chat_message_time,
2979 N_("Show time for each chat message"),
2980 N_("If this option is enabled then all chat messages "
2981 "will be prefixed by a time string of the form "
2982 "[hour:minute:second]."),
2983 COC_INTERFACE, GUI_GTK3x, FALSE, NULL),
2984 GEN_BOOL_OPTION(gui_gtk4_new_messages_go_to_top,
2985 N_("New message events go to top of list"),
2986 N_("If this option is enabled, new events in the "
2987 "message window will appear at the top of the list, "
2988 "rather than being appended at the bottom."),
2989 COC_INTERFACE, GUI_GTK3x, FALSE, NULL),
2990 GEN_BOOL_OPTION(gui_gtk4_show_message_window_buttons,
2991 N_("Show extra message window buttons"),
2992 N_("If this option is enabled, there will be two "
2993 "buttons displayed in the message window for "
2994 "inspecting a city and going to a location. If this "
2995 "option is disabled, these buttons will not appear "
2996 "(you can still double-click with the left mouse "
2997 "button or right-click on a row to inspect or goto "
2998 "respectively). This option will only take effect "
2999 "once the message window is closed and reopened."),
3000 COC_INTERFACE, GUI_GTK3x, TRUE, NULL),
3001 GEN_BOOL_OPTION(gui_gtk4_metaserver_tab_first,
3002 N_("Metaserver tab first in network page"),
3003 N_("If this option is enabled, the metaserver tab will "
3004 "be the first notebook tab in the network page. This "
3005 "option requires a restart in order to take effect."),
3006 COC_NETWORK, GUI_GTK3x, FALSE, NULL),
3007 GEN_BOOL_OPTION(gui_gtk4_allied_chat_only,
3008 N_("Plain chat messages are sent to allies only"),
3009 N_("If this option is enabled, then plain messages "
3010 "typed into the chat entry while the game is "
3011 "running will only be sent to your allies. "
3012 "Otherwise plain messages will be sent as "
3013 "public chat messages. To send a public chat "
3014 "message with this option enabled, prefix the "
3015 "message with a single colon ':'. This option "
3016 "can also be set using a toggle button beside "
3017 "the chat entry (only visible in multiplayer "
3018 "games)."),
3019 COC_INTERFACE, GUI_GTK3x, FALSE, NULL),
3020 GEN_ENUM_OPTION(gui_gtk4_message_chat_location,
3021 N_("Messages and Chat reports location"),
3022 /* TRANS: The strings used in the UI for 'Split' etc are
3023 * tagged 'gui_gtk2/gtk3/gtk3x_message_chat_location' */
3024 N_("Controls where the Messages and Chat reports "
3025 "appear relative to the main view containing the map.\n"
3026 "'Split' allows all three to be seen simultaneously, "
3027 "which is best for multiplayer, but requires a large "
3028 "window to be usable.\n"
3029 "'Separate' puts Messages and Chat in a notebook "
3030 "separate from the main view, so that one of them "
3031 "can always be seen alongside the main view.\n"
3032 "'Merged' makes the Messages and Chat reports into "
3033 "tabs alongside the map and other reports; this "
3034 "allows a larger map view on small screens.\n"
3035 "This option requires a restart in order to take "
3036 "effect."), COC_INTERFACE, GUI_GTK3x,
3037 GUI_GTK_MSGCHAT_MERGED /* Ignored! See options_load(). */,
3038 gui_gtk_message_chat_location_name, NULL),
3039 GEN_BOOL_OPTION(gui_gtk4_small_display_layout,
3040 N_("Arrange widgets for small displays"),
3041 N_("If this option is enabled, widgets in the main "
3042 "window will be arranged so that they take up the "
3043 "least amount of total screen space. Specifically, "
3044 "the left panel containing the overview, player "
3045 "status, and the unit information box will be "
3046 "extended over the entire left side of the window. "
3047 "This option requires a restart in order to take "
3048 "effect."), COC_INTERFACE, GUI_GTK3x, TRUE, NULL),
3049 GEN_BOOL_OPTION(gui_gtk4_mouse_over_map_focus,
3050 N_("Mouse over the map widget selects it automatically"),
3051 N_("If this option is enabled, then the map will be "
3052 "focused when the mouse hovers over it."),
3053 COC_INTERFACE, GUI_GTK3x, FALSE, NULL),
3054 GEN_BOOL_OPTION(gui_gtk4_chatline_autocompletion,
3055 N_("Player or user name autocompletion"),
3056 N_("If this option is turned on, the tabulation key "
3057 "will be used in the chatline to complete the word you "
3058 "are typing with the name of a player or a user."),
3059 COC_INTERFACE, GUI_GTK3x, TRUE, NULL),
3060 GEN_INT_OPTION(gui_gtk4_citydlg_xsize,
3061 N_("Width of the city dialog"),
3062 N_("This value is only used if the width of the city "
3063 "dialog is saved."),
3064 COC_INTERFACE, GUI_GTK3x, GUI_GTK4_CITYDLG_DEFAULT_XSIZE,
3065 GUI_GTK4_CITYDLG_MIN_XSIZE, GUI_GTK4_CITYDLG_MAX_XSIZE,
3066 NULL),
3067 GEN_INT_OPTION(gui_gtk4_citydlg_ysize,
3068 N_("Height of the city dialog"),
3069 N_("This value is only used if the height of the city "
3070 "dialog is saved."),
3071 COC_INTERFACE, GUI_GTK3x, GUI_GTK4_CITYDLG_DEFAULT_YSIZE,
3072 GUI_GTK4_CITYDLG_MIN_YSIZE, GUI_GTK4_CITYDLG_MAX_YSIZE,
3073 NULL),
3074 GEN_ENUM_OPTION(gui_gtk4_popup_tech_help,
3075 N_("Popup tech help when gained"),
3076 N_("Controls if tech help should be opened when "
3077 "new tech has been gained.\n"
3078 "'Ruleset' means that behavior suggested by "
3079 "current ruleset is used."), COC_INTERFACE, GUI_GTK3x,
3080 GUI_POPUP_TECH_HELP_RULESET,
3081 gui_popup_tech_help_name, NULL),
3082 GEN_INT_OPTION(gui_gtk4_governor_range_min,
3083 N_("Minimum surplus for a governor"),
3084 N_("The lower limit of the range for requesting surpluses "
3085 "from the governor."),
3086 COC_INTERFACE, GUI_GTK3x, GUI_GTK4_GOV_RANGE_MIN_DEFAULT,
3087 GUI_GTK4_GOV_RANGE_MIN_MIN, GUI_GTK4_GOV_RANGE_MIN_MAX,
3088 NULL),
3089 GEN_INT_OPTION(gui_gtk4_governor_range_max,
3090 N_("Maximum surplus for a governor"),
3091 N_("The higher limit of the range for requesting surpluses "
3092 "from the governor."),
3093 COC_INTERFACE, GUI_GTK3x, GUI_GTK4_GOV_RANGE_MAX_DEFAULT,
3094 GUI_GTK4_GOV_RANGE_MAX_MIN, GUI_GTK4_GOV_RANGE_MAX_MAX,
3095 NULL),
3096 GEN_FONT_OPTION(gui_gtk4_font_city_label, "city_label",
3097 N_("City Label"),
3098 N_("This font is used to display the city labels on city "
3099 "dialogs."),
3100 COC_FONT, GUI_GTK3x,
3101 "Monospace 8", font_changed_callback),
3102 GEN_FONT_OPTION(gui_gtk4_font_notify_label, "notify_label",
3103 N_("Notify Label"),
3104 N_("This font is used to display server reports such "
3105 "as the demographic report or historian publications."),
3106 COC_FONT, GUI_GTK3x,
3107 "Monospace Bold 9", font_changed_callback),
3108 GEN_FONT_OPTION(gui_gtk4_font_spaceship_label, "spaceship_label",
3109 N_("Spaceship Label"),
3110 N_("This font is used to display the spaceship widgets."),
3111 COC_FONT, GUI_GTK3x,
3112 "Monospace 8", font_changed_callback),
3113 GEN_FONT_OPTION(gui_gtk4_font_help_label, "help_label",
3114 N_("Help Label"),
3115 N_("This font is used to display the help headers in the "
3116 "help window."),
3117 COC_FONT, GUI_GTK3x,
3118 "Sans Bold 10", font_changed_callback),
3119 GEN_FONT_OPTION(gui_gtk4_font_help_link, "help_link",
3120 N_("Help Link"),
3121 N_("This font is used to display the help links in the "
3122 "help window."),
3123 COC_FONT, GUI_GTK3x,
3124 "Sans 9", font_changed_callback),
3125 GEN_FONT_OPTION(gui_gtk4_font_help_text, "help_text",
3126 N_("Help Text"),
3127 N_("This font is used to display the help body text in "
3128 "the help window."),
3129 COC_FONT, GUI_GTK3x,
3130 "Monospace 8", font_changed_callback),
3131 GEN_FONT_OPTION(gui_gtk4_font_chatline, "chatline",
3132 N_("Chatline Area"),
3133 N_("This font is used to display the text in the "
3134 "chatline area."),
3135 COC_FONT, GUI_GTK3x,
3136 "Monospace 8", font_changed_callback),
3137 GEN_FONT_OPTION(gui_gtk4_font_beta_label, "beta_label",
3138 N_("Beta Label"),
3139 N_("This font is used to display the beta label."),
3140 COC_FONT, GUI_GTK3x,
3141 "Sans Italic 10", font_changed_callback),
3142 GEN_FONT_OPTION(gui_gtk4_font_small, "small_font",
3143 N_("Small Font"),
3144 N_("This font is used for any small font request. For "
3145 "example, it is used for display the building lists "
3146 "in the city dialog, the Economy report or the Units "
3147 "report."),
3148 COC_FONT, GUI_GTK3x,
3149 "Sans 9", NULL),
3150 GEN_FONT_OPTION(gui_gtk4_font_comment_label, "comment_label",
3151 N_("Comment Label"),
3152 N_("This font is used to display comment labels, such as "
3153 "in the governor page of the city dialogs."),
3154 COC_FONT, GUI_GTK3x,
3155 "Sans Italic 9", font_changed_callback),
3156 GEN_FONT_OPTION(gui_gtk4_font_city_names, "city_names",
3157 N_("City Names"),
3158 N_("This font is used to the display the city names "
3159 "on the map."),
3160 COC_FONT, GUI_GTK3x,
3161 "Sans Bold 10", NULL),
3162 GEN_FONT_OPTION(gui_gtk4_font_city_productions, "city_productions",
3163 N_("City Productions"),
3164 N_("This font is used to the display the city production "
3165 "names on the map."),
3166 COC_FONT, GUI_GTK3x,
3167 "Serif 10", NULL),
3168 GEN_FONT_OPTION(gui_gtk4_font_reqtree_text, "reqtree_text",
3169 N_("Requirement Tree"),
3170 N_("This font is used to the display the requirement tree "
3171 "in the Research report."),
3172 COC_FONT, GUI_GTK3x,
3173 "Serif 10", NULL),
3175 /* gui-sdl client specific options.
3176 * These are still kept just so users can migrate them to sdl2-client */
3177 GEN_BOOL_OPTION(gui_sdl_fullscreen, NULL, NULL,
3178 COC_INTERFACE, GUI_SDL, FALSE, NULL),
3179 GEN_VIDEO_OPTION(gui_sdl_screen, NULL, NULL,
3180 COC_INTERFACE, GUI_SDL, 640, 480, NULL),
3181 GEN_BOOL_OPTION(gui_sdl_do_cursor_animation, NULL, NULL,
3182 COC_INTERFACE, GUI_SDL, TRUE, NULL),
3183 GEN_BOOL_OPTION(gui_sdl_use_color_cursors, NULL, NULL,
3184 COC_INTERFACE, GUI_SDL, TRUE, NULL),
3186 /* gui-sdl2 client specific options. */
3187 GEN_BOOL_OPTION(gui_sdl2_fullscreen, N_("Fullscreen"),
3188 N_("If this option is set the client will use the "
3189 "whole screen area for drawing."),
3190 COC_INTERFACE, GUI_SDL2, FALSE, NULL),
3191 GEN_VIDEO_OPTION(gui_sdl2_screen, N_("Screen resolution"),
3192 N_("This option controls the resolution of the "
3193 "selected screen."),
3194 COC_INTERFACE, GUI_SDL2, 640, 480, NULL),
3195 GEN_BOOL_OPTION(gui_sdl2_swrenderer, N_("Use software rendering"),
3196 N_("Usually hardware rendering is used when possible. "
3197 "With this option set, software rendering is always used."),
3198 COC_GRAPHICS, GUI_SDL2, FALSE, NULL),
3199 GEN_BOOL_OPTION(gui_sdl2_do_cursor_animation, N_("Do cursor animation"),
3200 N_("If this option is disabled, the cursor will "
3201 "always be displayed as static."),
3202 COC_INTERFACE, GUI_SDL2, TRUE, NULL),
3203 GEN_BOOL_OPTION(gui_sdl2_use_color_cursors, N_("Use color cursors"),
3204 N_("If this option is disabled, the cursor will "
3205 "always be displayed in black and white."),
3206 COC_INTERFACE, GUI_SDL2, TRUE, NULL),
3208 /* gui-qt client specific options. */
3209 GEN_BOOL_OPTION(gui_qt_fullscreen, N_("Fullscreen"),
3210 N_("If this option is set the client will use the "
3211 "whole screen area for drawing."),
3212 COC_INTERFACE, GUI_QT, FALSE, NULL),
3213 GEN_BOOL_OPTION(gui_qt_show_titlebar, N_("Show titlebar"),
3214 N_("If this option is set the client will show a titlebar. "
3215 "If disabled, then no titlebar will be shown, and "
3216 "minimize/maximize/etc buttons will be placed on the "
3217 "menu bar."),
3218 COC_INTERFACE, GUI_QT, TRUE, NULL),
3219 GEN_FONT_OPTION(gui_qt_font_city_label, "city_label",
3220 N_("City Label"),
3221 N_("This font is used to display the city labels on city "
3222 "dialogs."),
3223 COC_FONT, GUI_QT,
3224 "Monospace,8,-1,5,50,0,0,0,0,0", font_changed_callback),
3225 GEN_FONT_OPTION(gui_qt_font_default, "default_font",
3226 N_("Default font"),
3227 N_("This is default font"),
3228 COC_FONT, GUI_QT,
3229 "Sans Serif,10,-1,5,75,0,0,0,0,0", font_changed_callback),
3230 GEN_FONT_OPTION(gui_qt_font_notify_label, "notify_label",
3231 N_("Notify Label"),
3232 N_("This font is used to display server reports such "
3233 "as the demographic report or historian publications."),
3234 COC_FONT, GUI_QT,
3235 "Monospace,9,-1,5,75,0,0,0,0,0", font_changed_callback),
3236 GEN_FONT_OPTION(gui_qt_font_spaceship_label, "spaceship_label",
3237 N_("Spaceship Label"),
3238 N_("This font is used to display the spaceship widgets."),
3239 COC_FONT, GUI_QT,
3240 "Monospace,8,-1,5,50,0,0,0,0,0", font_changed_callback),
3241 GEN_FONT_OPTION(gui_qt_font_help_label, "help_label",
3242 N_("Help Label"),
3243 N_("This font is used to display the help labels in the "
3244 "help window."),
3245 COC_FONT, GUI_QT,
3246 "Sans Serif,9,-1,5,50,0,0,0,0,0", font_changed_callback),
3247 GEN_FONT_OPTION(gui_qt_font_help_link, "help_link",
3248 N_("Help Link"),
3249 N_("This font is used to display the help links in the "
3250 "help window."),
3251 COC_FONT, GUI_QT,
3252 "Sans Serif,9,-1,5,50,0,0,0,0,0", font_changed_callback),
3253 GEN_FONT_OPTION(gui_qt_font_help_text, "help_text",
3254 N_("Help Text"),
3255 N_("This font is used to display the help body text in "
3256 "the help window."),
3257 COC_FONT, GUI_QT,
3258 "Monospace,8,-1,5,50,0,0,0,0,0", font_changed_callback),
3259 GEN_FONT_OPTION(gui_qt_font_help_title, "help_title",
3260 N_("Help Title"),
3261 N_("This font is used to display the help title in "
3262 "the help window."),
3263 COC_FONT, GUI_QT,
3264 "Sans Serif,10,-1,5,75,0,0,0,0,0", font_changed_callback),
3265 GEN_FONT_OPTION(gui_qt_font_chatline, "chatline",
3266 N_("Chatline Area"),
3267 N_("This font is used to display the text in the "
3268 "chatline area."),
3269 COC_FONT, GUI_QT,
3270 "Monospace,8,-1,5,50,0,0,0,0,0", font_changed_callback),
3271 GEN_FONT_OPTION(gui_qt_font_beta_label, "beta_label",
3272 N_("Beta Label"),
3273 N_("This font is used to display the beta label."),
3274 COC_FONT, GUI_QT,
3275 "Sans Serif,10,-1,5,50,1,0,0,0,0", font_changed_callback),
3276 GEN_FONT_OPTION(gui_qt_font_small, "small_font",
3277 N_("Small Font"),
3278 N_("This font is used for any small font request. For "
3279 "example, it is used for display the building lists "
3280 "in the city dialog, the Economy report or the Units "
3281 "report."),
3282 COC_FONT, GUI_QT,
3283 "Sans Serif,9,-1,5,50,0,0,0,0,0", font_changed_callback),
3284 GEN_FONT_OPTION(gui_qt_font_comment_label, "comment_label",
3285 N_("Comment Label"),
3286 N_("This font is used to display comment labels, such as "
3287 "in the governor page of the city dialogs."),
3288 COC_FONT, GUI_QT,
3289 "Sans Serif,9,-1,5,50,1,0,0,0,0", font_changed_callback),
3290 GEN_FONT_OPTION(gui_qt_font_city_names, "city_names",
3291 N_("City Names"),
3292 N_("This font is used to the display the city names "
3293 "on the map."),
3294 COC_FONT, GUI_QT,
3295 "Sans Serif,10,-1,5,75,0,0,0,0,0", font_changed_callback),
3296 GEN_FONT_OPTION(gui_qt_font_city_productions, "city_productions",
3297 N_("City Productions"),
3298 N_("This font is used to the display the city production "
3299 "names on the map."),
3300 COC_FONT, GUI_QT,
3301 "Sans Serif,10,-1,5,50,1,0,0,0,0", font_changed_callback),
3302 GEN_FONT_OPTION(gui_qt_font_reqtree_text, "reqtree_text",
3303 N_("Requirement Tree"),
3304 N_("This font is used to the display the requirement tree "
3305 "in the Research report."),
3306 COC_FONT, GUI_QT,
3307 "Sans Serif,10,-1,5,50,1,0,0,0,0", font_changed_callback),
3308 GEN_BOOL_OPTION(gui_qt_show_preview, N_("Show savegame information"),
3309 N_("If this option is set the client will show "
3310 "information and map preview about current savegame "),
3311 COC_GRAPHICS, GUI_QT, TRUE, NULL),
3312 GEN_BOOL_OPTION(gui_qt_sidebar_left, N_("Sidebar position"),
3313 N_("If this option is set sidebar will be on left, "
3314 "otherwise it will on right side of map"),
3315 COC_INTERFACE, GUI_QT, TRUE, NULL),
3316 GEN_STR_OPTION(gui_qt_wakeup_text,
3317 N_("Wake up sequence"),
3318 N_("String which will trigger sound in pregame page, "
3319 "%1 stands for nick"),
3320 COC_INTERFACE, GUI_QT, "Wake up %1", NULL, 0)
3323 static const int client_options_num = ARRAY_SIZE(client_options);
3325 /* Iteration loop, including invalid options for the current gui type. */
3326 #define client_options_iterate_all(poption) \
3328 const struct client_option *const poption##_max = \
3329 client_options + client_options_num; \
3330 struct client_option *client_##poption = client_options; \
3331 struct option *poption; \
3332 for (; client_##poption < poption##_max; client_##poption++) { \
3333 poption = OPTION(client_##poption);
3335 #define client_options_iterate_all_end \
3340 /****************************************************************************
3341 Returns the next valid option pointer for the current gui type.
3342 ****************************************************************************/
3343 static struct client_option *
3344 client_option_next_valid(struct client_option *poption)
3346 const struct client_option *const max =
3347 client_options + client_options_num;
3348 const enum gui_type our_type = get_gui_type();
3350 while (poption < max
3351 && poption->specific != GUI_STUB
3352 && poption->specific != our_type) {
3353 poption++;
3356 return (poption < max ? poption : NULL);
3359 /****************************************************************************
3360 Returns the option corresponding to this id.
3361 ****************************************************************************/
3362 static struct option *client_optset_option_by_number(int id)
3364 if (0 > id || id > client_options_num) {
3365 return NULL;
3367 return OPTION(client_options + id);
3370 /****************************************************************************
3371 Returns the first valid option pointer for the current gui type.
3372 ****************************************************************************/
3373 static struct option *client_optset_option_first(void)
3375 return OPTION(client_option_next_valid(client_options));
3378 /****************************************************************************
3379 Returns the number of client option categories.
3380 ****************************************************************************/
3381 static int client_optset_category_number(void)
3383 return COC_MAX;
3386 /****************************************************************************
3387 Returns the name (translated) of the option class.
3388 ****************************************************************************/
3389 static const char *client_optset_category_name(int category)
3391 switch (category) {
3392 case COC_GRAPHICS:
3393 return _("Graphics");
3394 case COC_OVERVIEW:
3395 /* TRANS: Options section for overview map (mini-map) */
3396 return Q_("?map:Overview");
3397 case COC_SOUND:
3398 return _("Sound");
3399 case COC_INTERFACE:
3400 return _("Interface");
3401 case COC_MAPIMG:
3402 return _("Map Image");
3403 case COC_NETWORK:
3404 return _("Network");
3405 case COC_FONT:
3406 return _("Font");
3407 case COC_MAX:
3408 break;
3411 log_error("%s: invalid option category number %d.",
3412 __FUNCTION__, category);
3413 return NULL;
3416 /***************************************************************************
3417 Returns the number of this client option.
3418 ****************************************************************************/
3419 static int client_option_number(const struct option *poption)
3421 return CLIENT_OPTION(poption) - client_options;
3424 /****************************************************************************
3425 Returns the name of this client option.
3426 ****************************************************************************/
3427 static const char *client_option_name(const struct option *poption)
3429 return CLIENT_OPTION(poption)->name;
3432 /****************************************************************************
3433 Returns the description of this client option.
3434 ****************************************************************************/
3435 static const char *client_option_description(const struct option *poption)
3437 return _(CLIENT_OPTION(poption)->description);
3440 /****************************************************************************
3441 Returns the help text for this client option.
3442 ****************************************************************************/
3443 static const char *client_option_help_text(const struct option *poption)
3445 return _(CLIENT_OPTION(poption)->help_text);
3448 /****************************************************************************
3449 Returns the category of this client option.
3450 ****************************************************************************/
3451 static int client_option_category(const struct option *poption)
3453 return CLIENT_OPTION(poption)->category;
3456 /****************************************************************************
3457 Returns TRUE if this client option can be modified.
3458 ****************************************************************************/
3459 static bool client_option_is_changeable(const struct option *poption)
3461 return TRUE;
3464 /****************************************************************************
3465 Returns the next valid option pointer for the current gui type.
3466 ****************************************************************************/
3467 static struct option *client_option_next(const struct option *poption)
3469 return OPTION(client_option_next_valid(CLIENT_OPTION(poption) + 1));
3472 /****************************************************************************
3473 Returns the value of this client option of type OT_BOOLEAN.
3474 ****************************************************************************/
3475 static bool client_option_bool_get(const struct option *poption)
3477 return *(CLIENT_OPTION(poption)->boolean.pvalue);
3480 /****************************************************************************
3481 Returns the default value of this client option of type OT_BOOLEAN.
3482 ****************************************************************************/
3483 static bool client_option_bool_def(const struct option *poption)
3485 return CLIENT_OPTION(poption)->boolean.def;
3488 /****************************************************************************
3489 Set the value of this client option of type OT_BOOLEAN. Returns TRUE if
3490 the value changed.
3491 ****************************************************************************/
3492 static bool client_option_bool_set(struct option *poption, bool val)
3494 struct client_option *pcoption = CLIENT_OPTION(poption);
3496 if (*pcoption->boolean.pvalue == val) {
3497 return FALSE;
3500 *pcoption->boolean.pvalue = val;
3501 return TRUE;
3504 /****************************************************************************
3505 Returns the value of this client option of type OT_INTEGER.
3506 ****************************************************************************/
3507 static int client_option_int_get(const struct option *poption)
3509 return *(CLIENT_OPTION(poption)->integer.pvalue);
3512 /****************************************************************************
3513 Returns the default value of this client option of type OT_INTEGER.
3514 ****************************************************************************/
3515 static int client_option_int_def(const struct option *poption)
3517 return CLIENT_OPTION(poption)->integer.def;
3520 /****************************************************************************
3521 Returns the minimal value for this client option of type OT_INTEGER.
3522 ****************************************************************************/
3523 static int client_option_int_min(const struct option *poption)
3525 return CLIENT_OPTION(poption)->integer.min;
3528 /****************************************************************************
3529 Returns the maximal value for this client option of type OT_INTEGER.
3530 ****************************************************************************/
3531 static int client_option_int_max(const struct option *poption)
3533 return CLIENT_OPTION(poption)->integer.max;
3536 /****************************************************************************
3537 Set the value of this client option of type OT_INTEGER. Returns TRUE if
3538 the value changed.
3539 ****************************************************************************/
3540 static bool client_option_int_set(struct option *poption, int val)
3542 struct client_option *pcoption = CLIENT_OPTION(poption);
3544 if (val < pcoption->integer.min
3545 || val > pcoption->integer.max
3546 || *pcoption->integer.pvalue == val) {
3547 return FALSE;
3550 *pcoption->integer.pvalue = val;
3551 return TRUE;
3554 /****************************************************************************
3555 Returns the value of this client option of type OT_STRING.
3556 ****************************************************************************/
3557 static const char *client_option_str_get(const struct option *poption)
3559 return CLIENT_OPTION(poption)->string.pvalue;
3562 /****************************************************************************
3563 Returns the default value of this client option of type OT_STRING.
3564 ****************************************************************************/
3565 static const char *client_option_str_def(const struct option *poption)
3567 return CLIENT_OPTION(poption)->string.def;
3570 /****************************************************************************
3571 Returns the possible string values of this client option of type
3572 OT_STRING.
3573 ****************************************************************************/
3574 static const struct strvec *
3575 client_option_str_values(const struct option *poption)
3577 return (CLIENT_OPTION(poption)->string.val_accessor
3578 ? CLIENT_OPTION(poption)->string.val_accessor(poption) : NULL);
3581 /****************************************************************************
3582 Set the value of this client option of type OT_STRING. Returns TRUE if
3583 the value changed.
3584 ****************************************************************************/
3585 static bool client_option_str_set(struct option *poption, const char *str)
3587 struct client_option *pcoption = CLIENT_OPTION(poption);
3589 if (strlen(str) >= pcoption->string.size
3590 || 0 == strcmp(pcoption->string.pvalue, str)) {
3591 return FALSE;
3594 fc_strlcpy(pcoption->string.pvalue, str, pcoption->string.size);
3595 return TRUE;
3598 /****************************************************************************
3599 Returns the current value of this client option of type OT_ENUM.
3600 ****************************************************************************/
3601 static int client_option_enum_get(const struct option *poption)
3603 return *(CLIENT_OPTION(poption)->enumerator.pvalue);
3606 /****************************************************************************
3607 Returns the default value of this client option of type OT_ENUM.
3608 ****************************************************************************/
3609 static int client_option_enum_def(const struct option *poption)
3611 return CLIENT_OPTION(poption)->enumerator.def;
3614 /****************************************************************************
3615 Returns the possible values of this client option of type OT_ENUM, as
3616 user-visible (translatable but not translated) strings.
3617 ****************************************************************************/
3618 static const struct strvec *
3619 client_option_enum_pretty_names(const struct option *poption)
3621 return CLIENT_OPTION(poption)->enumerator.pretty_names;
3624 /****************************************************************************
3625 Set the value of this client option of type OT_ENUM. Returns TRUE if
3626 the value changed.
3627 ****************************************************************************/
3628 static bool client_option_enum_set(struct option *poption, int val)
3630 struct client_option *pcoption = CLIENT_OPTION(poption);
3632 if (*pcoption->enumerator.pvalue == val
3633 || 0 > val
3634 || val >= strvec_size(pcoption->enumerator.support_names)) {
3635 return FALSE;
3638 *pcoption->enumerator.pvalue = val;
3639 return TRUE;
3642 /****************************************************************************
3643 Returns the "support" name of the value for this client option of type
3644 OT_ENUM (a string suitable for saving in a file).
3645 The prototype must match the 'secfile_enum_name_data_fn_t' type.
3646 ****************************************************************************/
3647 static const char *client_option_enum_secfile_str(secfile_data_t data,
3648 int val)
3650 const struct strvec *names = CLIENT_OPTION(data)->enumerator.support_names;
3652 return (0 <= val && val < strvec_size(names)
3653 ? strvec_get(names, val) : NULL);
3656 #if 0 /* There's no bitwise options currently */
3657 /****************************************************************************
3658 Returns the current value of this client option of type OT_BITWISE.
3659 ****************************************************************************/
3660 static unsigned client_option_bitwise_get(const struct option *poption)
3662 return *(CLIENT_OPTION(poption)->bitwise.pvalue);
3665 /****************************************************************************
3666 Returns the default value of this client option of type OT_BITWISE.
3667 ****************************************************************************/
3668 static unsigned client_option_bitwise_def(const struct option *poption)
3670 return CLIENT_OPTION(poption)->bitwise.def;
3673 /****************************************************************************
3674 Returns the possible values of this client option of type OT_BITWISE, as
3675 user-visible (translatable but not translated) strings.
3676 ****************************************************************************/
3677 static const struct strvec *
3678 client_option_bitwise_pretty_names(const struct option *poption)
3680 return CLIENT_OPTION(poption)->bitwise.pretty_names;
3683 /****************************************************************************
3684 Set the value of this client option of type OT_BITWISE. Returns TRUE if
3685 the value changed.
3686 ****************************************************************************/
3687 static bool client_option_bitwise_set(struct option *poption, unsigned val)
3689 struct client_option *pcoption = CLIENT_OPTION(poption);
3691 if (*pcoption->bitwise.pvalue == val) {
3692 return FALSE;
3695 *pcoption->bitwise.pvalue = val;
3696 return TRUE;
3698 #endif /* 0 */
3700 /****************************************************************************
3701 Returns the "support" name of a single value for this client option of type
3702 OT_BITWISE (a string suitable for saving in a file).
3703 The prototype must match the 'secfile_enum_name_data_fn_t' type.
3704 ****************************************************************************/
3705 static const char *client_option_bitwise_secfile_str(secfile_data_t data,
3706 int val)
3708 const struct strvec *names = CLIENT_OPTION(data)->bitwise.support_names;
3710 return (0 <= val && val < strvec_size(names)
3711 ? strvec_get(names, val) : NULL);
3714 /****************************************************************************
3715 Returns the value of this client option of type OT_FONT.
3716 ****************************************************************************/
3717 static const char *client_option_font_get(const struct option *poption)
3719 return CLIENT_OPTION(poption)->font.pvalue;
3722 /****************************************************************************
3723 Returns the default value of this client option of type OT_FONT.
3724 ****************************************************************************/
3725 static const char *client_option_font_def(const struct option *poption)
3727 return CLIENT_OPTION(poption)->font.def;
3730 /****************************************************************************
3731 Returns the target style name of this client option of type OT_FONT.
3732 ****************************************************************************/
3733 static const char *client_option_font_target(const struct option *poption)
3735 return CLIENT_OPTION(poption)->font.target;
3738 /****************************************************************************
3739 Set the value of this client option of type OT_FONT. Returns TRUE if
3740 the value changed.
3741 ****************************************************************************/
3742 static bool client_option_font_set(struct option *poption, const char *font)
3744 struct client_option *pcoption = CLIENT_OPTION(poption);
3746 if (strlen(font) >= pcoption->font.size
3747 || 0 == strcmp(pcoption->font.pvalue, font)) {
3748 return FALSE;
3751 fc_strlcpy(pcoption->font.pvalue, font, pcoption->font.size);
3752 return TRUE;
3755 /****************************************************************************
3756 Returns the value of this client option of type OT_COLOR.
3757 ****************************************************************************/
3758 static struct ft_color client_option_color_get(const struct option *poption)
3760 return *CLIENT_OPTION(poption)->color.pvalue;
3763 /****************************************************************************
3764 Returns the default value of this client option of type OT_COLOR.
3765 ****************************************************************************/
3766 static struct ft_color client_option_color_def(const struct option *poption)
3768 return CLIENT_OPTION(poption)->color.def;
3771 /****************************************************************************
3772 Set the value of this client option of type OT_COLOR. Returns TRUE if
3773 the value changed.
3774 ****************************************************************************/
3775 static bool client_option_color_set(struct option *poption,
3776 struct ft_color color)
3778 struct ft_color *pcolor = CLIENT_OPTION(poption)->color.pvalue;
3779 bool changed = FALSE;
3781 #define color_set(color_tgt, color) \
3782 if (NULL == color_tgt) { \
3783 if (NULL != color) { \
3784 color_tgt = fc_strdup(color); \
3785 changed = TRUE; \
3787 } else { \
3788 if (NULL == color) { \
3789 free((void *) color_tgt); \
3790 color_tgt = NULL; \
3791 changed = TRUE; \
3792 } else if (0 != strcmp(color_tgt, color)) { \
3793 free((void *) color_tgt); \
3794 color_tgt = fc_strdup(color); \
3795 changed = TRUE; \
3799 color_set(pcolor->foreground, color.foreground);
3800 color_set(pcolor->background, color.background);
3802 #undef color_set
3804 return changed;
3807 /****************************************************************************
3808 Returns the value of this client option of type OT_VIDEO_MODE.
3809 ****************************************************************************/
3810 static struct video_mode
3811 client_option_video_mode_get(const struct option *poption)
3813 return *CLIENT_OPTION(poption)->video_mode.pvalue;
3816 /****************************************************************************
3817 Returns the default value of this client option of type OT_VIDEO_MODE.
3818 ****************************************************************************/
3819 static struct video_mode
3820 client_option_video_mode_def(const struct option *poption)
3822 return CLIENT_OPTION(poption)->video_mode.def;
3825 /****************************************************************************
3826 Set the value of this client option of type OT_VIDEO_MODE. Returns TRUE
3827 if the value changed.
3828 ****************************************************************************/
3829 static bool client_option_video_mode_set(struct option *poption,
3830 struct video_mode mode)
3832 struct client_option *pcoption = CLIENT_OPTION(poption);
3834 if (0 == memcmp(&mode, pcoption->video_mode.pvalue,
3835 sizeof(struct video_mode))) {
3836 return FALSE;
3839 *pcoption->video_mode.pvalue = mode;
3840 return TRUE;
3843 /****************************************************************************
3844 Load the option from a file. Returns TRUE if the option changed.
3845 ****************************************************************************/
3846 static bool client_option_load(struct option *poption,
3847 struct section_file *sf)
3849 fc_assert_ret_val(NULL != poption, FALSE);
3850 fc_assert_ret_val(NULL != sf, FALSE);
3852 switch (option_type(poption)) {
3853 case OT_BOOLEAN:
3855 bool value;
3857 return (secfile_lookup_bool(sf, &value, "client.%s",
3858 option_name(poption))
3859 && option_bool_set(poption, value));
3861 case OT_INTEGER:
3863 int value;
3865 return (secfile_lookup_int(sf, &value, "client.%s",
3866 option_name(poption))
3867 && option_int_set(poption, value));
3869 case OT_STRING:
3871 const char *string;
3873 return ((string = secfile_lookup_str(sf, "client.%s",
3874 option_name(poption)))
3875 && option_str_set(poption, string));
3877 case OT_ENUM:
3879 int value;
3881 return (secfile_lookup_enum_data(sf, &value, FALSE,
3882 client_option_enum_secfile_str,
3883 poption, "client.%s",
3884 option_name(poption))
3885 && option_enum_set_int(poption, value));
3887 case OT_BITWISE:
3889 int value;
3891 return (secfile_lookup_enum_data(sf, &value, TRUE,
3892 client_option_bitwise_secfile_str,
3893 poption, "client.%s",
3894 option_name(poption))
3895 && option_bitwise_set(poption, value));
3897 case OT_FONT:
3899 const char *string;
3901 return ((string = secfile_lookup_str(sf, "client.%s",
3902 option_name(poption)))
3903 && option_font_set(poption, string));
3905 case OT_COLOR:
3907 struct ft_color color;
3909 return ((color.foreground =
3910 secfile_lookup_str(sf, "client.%s.foreground",
3911 option_name(poption)))
3912 && (color.background =
3913 secfile_lookup_str(sf, "client.%s.background",
3914 option_name(poption)))
3915 && option_color_set(poption, color));
3917 case OT_VIDEO_MODE:
3919 struct video_mode mode;
3921 return (secfile_lookup_int(sf, &mode.width, "client.%s.width",
3922 option_name(poption))
3923 && secfile_lookup_int(sf, &mode.height, "client.%s.height",
3924 option_name(poption))
3925 && option_video_mode_set(poption, mode));
3928 return FALSE;
3931 /****************************************************************************
3932 Save the option to a file.
3933 ****************************************************************************/
3934 static void client_option_save(struct option *poption,
3935 struct section_file *sf)
3937 fc_assert_ret(NULL != poption);
3938 fc_assert_ret(NULL != sf);
3940 switch (option_type(poption)) {
3941 case OT_BOOLEAN:
3942 secfile_insert_bool(sf, option_bool_get(poption),
3943 "client.%s", option_name(poption));
3944 break;
3945 case OT_INTEGER:
3946 secfile_insert_int(sf, option_int_get(poption),
3947 "client.%s", option_name(poption));
3948 break;
3949 case OT_STRING:
3950 secfile_insert_str(sf, option_str_get(poption),
3951 "client.%s", option_name(poption));
3952 break;
3953 case OT_ENUM:
3954 secfile_insert_enum_data(sf, option_enum_get_int(poption), FALSE,
3955 client_option_enum_secfile_str, poption,
3956 "client.%s", option_name(poption));
3957 break;
3958 case OT_BITWISE:
3959 secfile_insert_enum_data(sf, option_bitwise_get(poption), TRUE,
3960 client_option_bitwise_secfile_str, poption,
3961 "client.%s", option_name(poption));
3962 break;
3963 case OT_FONT:
3964 secfile_insert_str(sf, option_font_get(poption),
3965 "client.%s", option_name(poption));
3966 break;
3967 case OT_COLOR:
3969 struct ft_color color = option_color_get(poption);
3971 secfile_insert_str(sf, color.foreground, "client.%s.foreground",
3972 option_name(poption));
3973 secfile_insert_str(sf, color.background, "client.%s.background",
3974 option_name(poption));
3976 break;
3977 case OT_VIDEO_MODE:
3979 struct video_mode mode = option_video_mode_get(poption);
3981 secfile_insert_int(sf, mode.width, "client.%s.width",
3982 option_name(poption));
3983 secfile_insert_int(sf, mode.height, "client.%s.height",
3984 option_name(poption));
3986 break;
3991 /****************************************************************************
3992 Server options variables.
3993 ****************************************************************************/
3994 static char **server_options_categories = NULL;
3995 static struct server_option *server_options = NULL;
3997 static int server_options_categories_num = 0;
3998 static int server_options_num = 0;
4001 /****************************************************************************
4002 Server option set.
4003 ****************************************************************************/
4004 static struct option *server_optset_option_by_number(int id);
4005 static struct option *server_optset_option_first(void);
4006 static int server_optset_category_number(void);
4007 static const char *server_optset_category_name(int category);
4009 static struct option_set server_optset_static = {
4010 .option_by_number = server_optset_option_by_number,
4011 .option_first = server_optset_option_first,
4012 .category_number = server_optset_category_number,
4013 .category_name = server_optset_category_name
4015 const struct option_set *server_optset = &server_optset_static;
4018 /****************************************************************************
4019 Virtuals tables for the client options.
4020 ****************************************************************************/
4021 static int server_option_number(const struct option *poption);
4022 static const char *server_option_name(const struct option *poption);
4023 static const char *server_option_description(const struct option *poption);
4024 static const char *server_option_help_text(const struct option *poption);
4025 static int server_option_category(const struct option *poption);
4026 static bool server_option_is_changeable(const struct option *poption);
4027 static struct option *server_option_next(const struct option *poption);
4029 static const struct option_common_vtable server_option_common_vtable = {
4030 .number = server_option_number,
4031 .name = server_option_name,
4032 .description = server_option_description,
4033 .help_text = server_option_help_text,
4034 .category = server_option_category,
4035 .is_changeable = server_option_is_changeable,
4036 .next = server_option_next
4039 static bool server_option_bool_get(const struct option *poption);
4040 static bool server_option_bool_def(const struct option *poption);
4041 static bool server_option_bool_set(struct option *poption, bool val);
4043 static const struct option_bool_vtable server_option_bool_vtable = {
4044 .get = server_option_bool_get,
4045 .def = server_option_bool_def,
4046 .set = server_option_bool_set
4049 static int server_option_int_get(const struct option *poption);
4050 static int server_option_int_def(const struct option *poption);
4051 static int server_option_int_min(const struct option *poption);
4052 static int server_option_int_max(const struct option *poption);
4053 static bool server_option_int_set(struct option *poption, int val);
4055 static const struct option_int_vtable server_option_int_vtable = {
4056 .get = server_option_int_get,
4057 .def = server_option_int_def,
4058 .minimum = server_option_int_min,
4059 .maximum = server_option_int_max,
4060 .set = server_option_int_set
4063 static const char *server_option_str_get(const struct option *poption);
4064 static const char *server_option_str_def(const struct option *poption);
4065 static const struct strvec *
4066 server_option_str_values(const struct option *poption);
4067 static bool server_option_str_set(struct option *poption, const char *str);
4069 static const struct option_str_vtable server_option_str_vtable = {
4070 .get = server_option_str_get,
4071 .def = server_option_str_def,
4072 .values = server_option_str_values,
4073 .set = server_option_str_set
4076 static int server_option_enum_get(const struct option *poption);
4077 static int server_option_enum_def(const struct option *poption);
4078 static const struct strvec *
4079 server_option_enum_pretty(const struct option *poption);
4080 static bool server_option_enum_set(struct option *poption, int val);
4082 static const struct option_enum_vtable server_option_enum_vtable = {
4083 .get = server_option_enum_get,
4084 .def = server_option_enum_def,
4085 .values = server_option_enum_pretty,
4086 .set = server_option_enum_set,
4087 .cmp = strcmp
4090 static unsigned server_option_bitwise_get(const struct option *poption);
4091 static unsigned server_option_bitwise_def(const struct option *poption);
4092 static const struct strvec *
4093 server_option_bitwise_pretty(const struct option *poption);
4094 static bool server_option_bitwise_set(struct option *poption, unsigned val);
4096 static const struct option_bitwise_vtable server_option_bitwise_vtable = {
4097 .get = server_option_bitwise_get,
4098 .def = server_option_bitwise_def,
4099 .values = server_option_bitwise_pretty,
4100 .set = server_option_bitwise_set
4103 /****************************************************************************
4104 Derived class server option, inheriting from base class option.
4105 ****************************************************************************/
4106 struct server_option {
4107 struct option base_option; /* Base structure, must be the first! */
4109 char *name; /* Short name - used as an identifier */
4110 char *description; /* One-line description */
4111 char *help_text; /* Paragraph-length help text */
4112 unsigned char category;
4113 bool desired_sent;
4114 bool is_changeable;
4115 bool is_visible;
4117 union {
4118 /* OT_BOOLEAN type option. */
4119 struct {
4120 bool value;
4121 bool def;
4122 } boolean;
4123 /* OT_INTEGER type option. */
4124 struct {
4125 int value;
4126 int def, min, max;
4127 } integer;
4128 /* OT_STRING type option. */
4129 struct {
4130 char *value;
4131 char *def;
4132 } string;
4133 /* OT_ENUM type option. */
4134 struct {
4135 int value;
4136 int def;
4137 struct strvec *support_names;
4138 struct strvec *pretty_names; /* untranslated */
4139 } enumerator;
4140 /* OT_BITWISE type option. */
4141 struct {
4142 unsigned value;
4143 unsigned def;
4144 struct strvec *support_names;
4145 struct strvec *pretty_names; /* untranslated */
4146 } bitwise;
4150 #define SERVER_OPTION(poption) ((struct server_option *) (poption))
4152 static void desired_settable_option_send(struct option *poption);
4155 /****************************************************************************
4156 Initialize the server options (not received yet).
4157 ****************************************************************************/
4158 void server_options_init(void)
4160 fc_assert(NULL == server_options_categories);
4161 fc_assert(NULL == server_options);
4162 fc_assert(0 == server_options_categories_num);
4163 fc_assert(0 == server_options_num);
4166 /****************************************************************************
4167 Free one server option.
4168 ****************************************************************************/
4169 static void server_option_free(struct server_option *poption)
4171 switch (poption->base_option.type) {
4172 case OT_STRING:
4173 if (NULL != poption->string.value) {
4174 FC_FREE(poption->string.value);
4176 if (NULL != poption->string.def) {
4177 FC_FREE(poption->string.def);
4179 break;
4181 case OT_ENUM:
4182 if (NULL != poption->enumerator.support_names) {
4183 strvec_destroy(poption->enumerator.support_names);
4184 poption->enumerator.support_names = NULL;
4186 if (NULL != poption->enumerator.pretty_names) {
4187 strvec_destroy(poption->enumerator.pretty_names);
4188 poption->enumerator.pretty_names = NULL;
4190 break;
4192 case OT_BITWISE:
4193 if (NULL != poption->bitwise.support_names) {
4194 strvec_destroy(poption->bitwise.support_names);
4195 poption->bitwise.support_names = NULL;
4197 if (NULL != poption->bitwise.pretty_names) {
4198 strvec_destroy(poption->bitwise.pretty_names);
4199 poption->bitwise.pretty_names = NULL;
4201 break;
4203 case OT_BOOLEAN:
4204 case OT_INTEGER:
4205 case OT_FONT:
4206 case OT_COLOR:
4207 case OT_VIDEO_MODE:
4208 break;
4211 if (NULL != poption->name) {
4212 FC_FREE(poption->name);
4214 if (NULL != poption->description) {
4215 FC_FREE(poption->description);
4217 if (NULL != poption->help_text) {
4218 FC_FREE(poption->help_text);
4222 /****************************************************************************
4223 Free the server options, if already received.
4224 ****************************************************************************/
4225 void server_options_free(void)
4227 int i;
4229 /* Don't keep this dialog open. */
4230 option_dialog_popdown(server_optset);
4232 /* Free the options themselves. */
4233 if (NULL != server_options) {
4234 for (i = 0; i < server_options_num; i++) {
4235 server_option_free(server_options + i);
4237 FC_FREE(server_options);
4238 server_options_num = 0;
4241 /* Free the categories. */
4242 if (NULL != server_options_categories) {
4243 for (i = 0; i < server_options_categories_num; i++) {
4244 if (NULL != server_options_categories[i]) {
4245 FC_FREE(server_options_categories[i]);
4248 FC_FREE(server_options_categories);
4249 server_options_categories_num = 0;
4253 /****************************************************************************
4254 Allocate the server options and categories.
4255 ****************************************************************************/
4256 void handle_server_setting_control
4257 (const struct packet_server_setting_control *packet)
4259 int i;
4261 /* This packet should be received only once. */
4262 fc_assert_ret(NULL == server_options_categories);
4263 fc_assert_ret(NULL == server_options);
4264 fc_assert_ret(0 == server_options_categories_num);
4265 fc_assert_ret(0 == server_options_num);
4267 /* Allocate server option categories. */
4268 if (0 < packet->categories_num) {
4269 server_options_categories_num = packet->categories_num;
4270 server_options_categories =
4271 fc_calloc(server_options_categories_num,
4272 sizeof(*server_options_categories));
4274 for (i = 0; i < server_options_categories_num; i++) {
4275 /* NB: Translate now. */
4276 server_options_categories[i] = fc_strdup(_(packet->category_names[i]));
4280 /* Allocate server options. */
4281 if (0 < packet->settings_num) {
4282 server_options_num = packet->settings_num;
4283 server_options = fc_calloc(server_options_num, sizeof(*server_options));
4287 /****************************************************************************
4288 Receive a server setting info packet.
4289 ****************************************************************************/
4290 void handle_server_setting_const
4291 (const struct packet_server_setting_const *packet)
4293 struct option *poption = server_optset_option_by_number(packet->id);
4294 struct server_option *psoption = SERVER_OPTION(poption);
4296 fc_assert_ret(NULL != poption);
4298 fc_assert(NULL == psoption->name);
4299 psoption->name = fc_strdup(packet->name);
4300 fc_assert(NULL == psoption->description);
4301 /* NB: Translate now. */
4302 psoption->description = fc_strdup(_(packet->short_help));
4303 fc_assert(NULL == psoption->help_text);
4304 /* NB: Translate now. */
4305 psoption->help_text = fc_strdup(_(packet->extra_help));
4306 psoption->category = packet->category;
4309 /****************************************************************************
4310 Common part of handle_server_setting_*() functions. See below.
4311 ****************************************************************************/
4312 #define handle_server_setting_common(psoption, packet) \
4313 psoption->is_changeable = packet->is_changeable; \
4314 if (psoption->is_visible != packet->is_visible) { \
4315 if (psoption->is_visible) { \
4316 need_gui_remove = TRUE; \
4317 } else if (packet->is_visible) { \
4318 need_gui_add = TRUE; \
4320 psoption->is_visible = packet->is_visible; \
4323 if (!psoption->desired_sent \
4324 && psoption->is_visible \
4325 && psoption->is_changeable \
4326 && is_server_running() \
4327 && packet->initial_setting) { \
4328 /* Only send our private settings if we are running \
4329 * on a forked local server, i.e. started by the \
4330 * client with the "Start New Game" button. \
4331 * Do now override settings that are already saved to savegame \
4332 * and now loaded. */ \
4333 desired_settable_option_send(OPTION(poption)); \
4334 psoption->desired_sent = TRUE; \
4337 /* Update the GUI. */ \
4338 if (need_gui_remove) { \
4339 option_gui_remove(poption); \
4340 } else if (need_gui_add) { \
4341 option_gui_add(poption); \
4342 } else { \
4343 option_gui_update(poption); \
4346 /****************************************************************************
4347 Receive a boolean server setting info packet.
4348 ****************************************************************************/
4349 void handle_server_setting_bool
4350 (const struct packet_server_setting_bool *packet)
4352 struct option *poption = server_optset_option_by_number(packet->id);
4353 struct server_option *psoption = SERVER_OPTION(poption);
4354 bool need_gui_remove = FALSE;
4355 bool need_gui_add = FALSE;
4357 fc_assert_ret(NULL != poption);
4359 if (NULL == poption->common_vtable) {
4360 /* Not initialized yet. */
4361 poption->poptset = server_optset;
4362 poption->common_vtable = &server_option_common_vtable;
4363 poption->type = OT_BOOLEAN;
4364 poption->bool_vtable = &server_option_bool_vtable;
4366 fc_assert_ret_msg(OT_BOOLEAN == poption->type,
4367 "Server setting \"%s\" (nb %d) has type %s (%d), "
4368 "expected %s (%d)",
4369 option_name(poption), option_number(poption),
4370 option_type_name(poption->type), poption->type,
4371 option_type_name(OT_BOOLEAN), OT_BOOLEAN);
4373 if (packet->is_visible) {
4374 psoption->boolean.value = packet->val;
4375 psoption->boolean.def = packet->default_val;
4378 handle_server_setting_common(psoption, packet);
4381 /****************************************************************************
4382 Receive a integer server setting info packet.
4383 ****************************************************************************/
4384 void handle_server_setting_int
4385 (const struct packet_server_setting_int *packet)
4387 struct option *poption = server_optset_option_by_number(packet->id);
4388 struct server_option *psoption = SERVER_OPTION(poption);
4389 bool need_gui_remove = FALSE;
4390 bool need_gui_add = FALSE;
4392 fc_assert_ret(NULL != poption);
4394 if (NULL == poption->common_vtable) {
4395 /* Not initialized yet. */
4396 poption->poptset = server_optset;
4397 poption->common_vtable = &server_option_common_vtable;
4398 poption->type = OT_INTEGER;
4399 poption->int_vtable = &server_option_int_vtable;
4401 fc_assert_ret_msg(OT_INTEGER == poption->type,
4402 "Server setting \"%s\" (nb %d) has type %s (%d), "
4403 "expected %s (%d)",
4404 option_name(poption), option_number(poption),
4405 option_type_name(poption->type), poption->type,
4406 option_type_name(OT_INTEGER), OT_INTEGER);
4408 if (packet->is_visible) {
4409 psoption->integer.value = packet->val;
4410 psoption->integer.def = packet->default_val;
4411 psoption->integer.min = packet->min_val;
4412 psoption->integer.max = packet->max_val;
4415 handle_server_setting_common(psoption, packet);
4418 /****************************************************************************
4419 Receive a string server setting info packet.
4420 ****************************************************************************/
4421 void handle_server_setting_str
4422 (const struct packet_server_setting_str *packet)
4424 struct option *poption = server_optset_option_by_number(packet->id);
4425 struct server_option *psoption = SERVER_OPTION(poption);
4426 bool need_gui_remove = FALSE;
4427 bool need_gui_add = FALSE;
4429 fc_assert_ret(NULL != poption);
4431 if (NULL == poption->common_vtable) {
4432 /* Not initialized yet. */
4433 poption->poptset = server_optset;
4434 poption->common_vtable = &server_option_common_vtable;
4435 poption->type = OT_STRING;
4436 poption->str_vtable = &server_option_str_vtable;
4438 fc_assert_ret_msg(OT_STRING == poption->type,
4439 "Server setting \"%s\" (nb %d) has type %s (%d), "
4440 "expected %s (%d)",
4441 option_name(poption), option_number(poption),
4442 option_type_name(poption->type), poption->type,
4443 option_type_name(OT_STRING), OT_STRING);
4445 if (packet->is_visible) {
4446 if (NULL == psoption->string.value) {
4447 psoption->string.value = fc_strdup(packet->val);
4448 } else if (0 != strcmp(packet->val, psoption->string.value)) {
4449 free(psoption->string.value);
4450 psoption->string.value = fc_strdup(packet->val);
4452 if (NULL == psoption->string.def) {
4453 psoption->string.def = fc_strdup(packet->default_val);
4454 } else if (0 != strcmp(packet->default_val, psoption->string.def)) {
4455 free(psoption->string.def);
4456 psoption->string.def = fc_strdup(packet->default_val);
4460 handle_server_setting_common(psoption, packet);
4463 /****************************************************************************
4464 Receive an enumerator server setting info packet.
4465 ****************************************************************************/
4466 void handle_server_setting_enum
4467 (const struct packet_server_setting_enum *packet)
4469 struct option *poption = server_optset_option_by_number(packet->id);
4470 struct server_option *psoption = SERVER_OPTION(poption);
4471 bool need_gui_remove = FALSE;
4472 bool need_gui_add = FALSE;
4474 fc_assert_ret(NULL != poption);
4476 if (NULL == poption->common_vtable) {
4477 /* Not initialized yet. */
4478 poption->poptset = server_optset;
4479 poption->common_vtable = &server_option_common_vtable;
4480 poption->type = OT_ENUM;
4481 poption->enum_vtable = &server_option_enum_vtable;
4483 fc_assert_ret_msg(OT_ENUM == poption->type,
4484 "Server setting \"%s\" (nb %d) has type %s (%d), "
4485 "expected %s (%d)",
4486 option_name(poption), option_number(poption),
4487 option_type_name(poption->type), poption->type,
4488 option_type_name(OT_ENUM), OT_ENUM);
4490 if (packet->is_visible) {
4491 int i;
4493 psoption->enumerator.value = packet->val;
4494 psoption->enumerator.def = packet->default_val;
4496 if (NULL == psoption->enumerator.support_names) {
4497 /* First time we get this packet. */
4498 fc_assert(NULL == psoption->enumerator.pretty_names);
4499 psoption->enumerator.support_names = strvec_new();
4500 strvec_reserve(psoption->enumerator.support_names, packet->values_num);
4501 psoption->enumerator.pretty_names = strvec_new();
4502 strvec_reserve(psoption->enumerator.pretty_names, packet->values_num);
4503 for (i = 0; i < packet->values_num; i++) {
4504 strvec_set(psoption->enumerator.support_names, i,
4505 packet->support_names[i]);
4506 /* Store untranslated string from server. */
4507 strvec_set(psoption->enumerator.pretty_names, i,
4508 packet->pretty_names[i]);
4510 } else if (strvec_size(psoption->enumerator.support_names)
4511 != packet->values_num) {
4512 fc_assert(strvec_size(psoption->enumerator.support_names)
4513 == strvec_size(psoption->enumerator.pretty_names));
4514 /* The number of values have changed, we need to reset the list
4515 * of possible values. */
4516 strvec_reserve(psoption->enumerator.support_names, packet->values_num);
4517 strvec_reserve(psoption->enumerator.pretty_names, packet->values_num);
4518 for (i = 0; i < packet->values_num; i++) {
4519 strvec_set(psoption->enumerator.support_names, i,
4520 packet->support_names[i]);
4521 /* Store untranslated string from server. */
4522 strvec_set(psoption->enumerator.pretty_names, i,
4523 packet->pretty_names[i]);
4525 need_gui_remove = TRUE;
4526 need_gui_add = TRUE;
4527 } else {
4528 /* Check if a value changed, then we need to reset the list
4529 * of possible values. */
4530 const char *str;
4532 for (i = 0; i < packet->values_num; i++) {
4533 str = strvec_get(psoption->enumerator.pretty_names, i);
4534 if (NULL == str || 0 != strcmp(str, packet->pretty_names[i])) {
4535 /* Store untranslated string from server. */
4536 strvec_set(psoption->enumerator.pretty_names, i,
4537 packet->pretty_names[i]);
4538 need_gui_remove = TRUE;
4539 need_gui_add = TRUE;
4541 /* Support names are not visible, we don't need to check if it
4542 * has changed. */
4543 strvec_set(psoption->enumerator.support_names, i,
4544 packet->support_names[i]);
4549 handle_server_setting_common(psoption, packet);
4552 /****************************************************************************
4553 Receive a bitwise server setting info packet.
4554 ****************************************************************************/
4555 void handle_server_setting_bitwise
4556 (const struct packet_server_setting_bitwise *packet)
4558 struct option *poption = server_optset_option_by_number(packet->id);
4559 struct server_option *psoption = SERVER_OPTION(poption);
4560 bool need_gui_remove = FALSE;
4561 bool need_gui_add = FALSE;
4563 fc_assert_ret(NULL != poption);
4565 if (NULL == poption->common_vtable) {
4566 /* Not initialized yet. */
4567 poption->poptset = server_optset;
4568 poption->common_vtable = &server_option_common_vtable;
4569 poption->type = OT_BITWISE;
4570 poption->bitwise_vtable = &server_option_bitwise_vtable;
4572 fc_assert_ret_msg(OT_BITWISE == poption->type,
4573 "Server setting \"%s\" (nb %d) has type %s (%d), "
4574 "expected %s (%d)",
4575 option_name(poption), option_number(poption),
4576 option_type_name(poption->type), poption->type,
4577 option_type_name(OT_BITWISE), OT_BITWISE);
4579 if (packet->is_visible) {
4580 int i;
4582 psoption->bitwise.value = packet->val;
4583 psoption->bitwise.def = packet->default_val;
4585 if (NULL == psoption->bitwise.support_names) {
4586 /* First time we get this packet. */
4587 fc_assert(NULL == psoption->bitwise.pretty_names);
4588 psoption->bitwise.support_names = strvec_new();
4589 strvec_reserve(psoption->bitwise.support_names, packet->bits_num);
4590 psoption->bitwise.pretty_names = strvec_new();
4591 strvec_reserve(psoption->bitwise.pretty_names, packet->bits_num);
4592 for (i = 0; i < packet->bits_num; i++) {
4593 strvec_set(psoption->bitwise.support_names, i,
4594 packet->support_names[i]);
4595 /* Store untranslated string from server. */
4596 strvec_set(psoption->bitwise.pretty_names, i,
4597 packet->pretty_names[i]);
4599 } else if (strvec_size(psoption->bitwise.support_names)
4600 != packet->bits_num) {
4601 fc_assert(strvec_size(psoption->bitwise.support_names)
4602 == strvec_size(psoption->bitwise.pretty_names));
4603 /* The number of values have changed, we need to reset the list
4604 * of possible values. */
4605 strvec_reserve(psoption->bitwise.support_names, packet->bits_num);
4606 strvec_reserve(psoption->bitwise.pretty_names, packet->bits_num);
4607 for (i = 0; i < packet->bits_num; i++) {
4608 strvec_set(psoption->bitwise.support_names, i,
4609 packet->support_names[i]);
4610 /* Store untranslated string from server. */
4611 strvec_set(psoption->bitwise.pretty_names, i,
4612 packet->pretty_names[i]);
4614 need_gui_remove = TRUE;
4615 need_gui_add = TRUE;
4616 } else {
4617 /* Check if a value changed, then we need to reset the list
4618 * of possible values. */
4619 const char *str;
4621 for (i = 0; i < packet->bits_num; i++) {
4622 str = strvec_get(psoption->bitwise.pretty_names, i);
4623 if (NULL == str || 0 != strcmp(str, packet->pretty_names[i])) {
4624 /* Store untranslated string from server. */
4625 strvec_set(psoption->bitwise.pretty_names, i,
4626 packet->pretty_names[i]);
4627 need_gui_remove = TRUE;
4628 need_gui_add = TRUE;
4630 /* Support names are not visible, we don't need to check if it
4631 * has changed. */
4632 strvec_set(psoption->bitwise.support_names, i,
4633 packet->support_names[i]);
4638 handle_server_setting_common(psoption, packet);
4641 /****************************************************************************
4642 Returns the next valid option pointer for the current gui type.
4643 ****************************************************************************/
4644 static struct server_option *
4645 server_option_next_valid(struct server_option *poption)
4647 const struct server_option *const max =
4648 server_options + server_options_num;
4650 while (NULL != poption && poption < max && !poption->is_visible) {
4651 poption++;
4654 return (poption < max ? poption : NULL);
4657 /****************************************************************************
4658 Returns the server option associated to the number
4659 ****************************************************************************/
4660 struct option *server_optset_option_by_number(int id)
4662 if (0 > id || id > server_options_num) {
4663 return NULL;
4665 return OPTION(server_options + id);
4668 /****************************************************************************
4669 Returns the first valid (visible) option pointer.
4670 ****************************************************************************/
4671 struct option *server_optset_option_first(void)
4673 return OPTION(server_option_next_valid(server_options));
4676 /****************************************************************************
4677 Returns the number of server option categories.
4678 ****************************************************************************/
4679 int server_optset_category_number(void)
4681 return server_options_categories_num;
4684 /****************************************************************************
4685 Returns the name (translated) of the server option category.
4686 ****************************************************************************/
4687 const char *server_optset_category_name(int category)
4689 if (0 > category || category >= server_options_categories_num) {
4690 return NULL;
4693 return server_options_categories[category];
4696 /***************************************************************************
4697 Returns the number of this server option.
4698 ****************************************************************************/
4699 static int server_option_number(const struct option *poption)
4701 return SERVER_OPTION(poption) - server_options;
4704 /****************************************************************************
4705 Returns the name of this server option.
4706 ****************************************************************************/
4707 static const char *server_option_name(const struct option *poption)
4709 return SERVER_OPTION(poption)->name;
4712 /****************************************************************************
4713 Returns the (translated) description of this server option.
4714 ****************************************************************************/
4715 static const char *server_option_description(const struct option *poption)
4717 return SERVER_OPTION(poption)->description;
4720 /****************************************************************************
4721 Returns the (translated) help text for this server option.
4722 ****************************************************************************/
4723 static const char *server_option_help_text(const struct option *poption)
4725 return SERVER_OPTION(poption)->help_text;
4728 /****************************************************************************
4729 Returns the category of this server option.
4730 ****************************************************************************/
4731 static int server_option_category(const struct option *poption)
4733 return SERVER_OPTION(poption)->category;
4736 /****************************************************************************
4737 Returns TRUE if this client option can be modified.
4738 ****************************************************************************/
4739 static bool server_option_is_changeable(const struct option *poption)
4741 return SERVER_OPTION(poption)->is_changeable;
4744 /****************************************************************************
4745 Returns the next valid (visible) option pointer.
4746 ****************************************************************************/
4747 static struct option *server_option_next(const struct option *poption)
4749 return OPTION(server_option_next_valid(SERVER_OPTION(poption) + 1));
4752 /****************************************************************************
4753 Returns the value of this server option of type OT_BOOLEAN.
4754 ****************************************************************************/
4755 static bool server_option_bool_get(const struct option *poption)
4757 return SERVER_OPTION(poption)->boolean.value;
4760 /****************************************************************************
4761 Returns the default value of this server option of type OT_BOOLEAN.
4762 ****************************************************************************/
4763 static bool server_option_bool_def(const struct option *poption)
4765 return SERVER_OPTION(poption)->boolean.def;
4768 /****************************************************************************
4769 Set the value of this server option of type OT_BOOLEAN. Returns TRUE if
4770 the value changed.
4771 ****************************************************************************/
4772 static bool server_option_bool_set(struct option *poption, bool val)
4774 struct server_option *psoption = SERVER_OPTION(poption);
4776 if (psoption->boolean.value == val) {
4777 return FALSE;
4780 send_chat_printf("/set %s %s", psoption->name,
4781 val ? "enabled" : "disabled");
4782 return TRUE;
4785 /****************************************************************************
4786 Returns the value of this server option of type OT_INTEGER.
4787 ****************************************************************************/
4788 static int server_option_int_get(const struct option *poption)
4790 return SERVER_OPTION(poption)->integer.value;
4793 /****************************************************************************
4794 Returns the default value of this server option of type OT_INTEGER.
4795 ****************************************************************************/
4796 static int server_option_int_def(const struct option *poption)
4798 return SERVER_OPTION(poption)->integer.def;
4801 /****************************************************************************
4802 Returns the minimal value for this server option of type OT_INTEGER.
4803 ****************************************************************************/
4804 static int server_option_int_min(const struct option *poption)
4806 return SERVER_OPTION(poption)->integer.min;
4809 /****************************************************************************
4810 Returns the maximal value for this server option of type OT_INTEGER.
4811 ****************************************************************************/
4812 static int server_option_int_max(const struct option *poption)
4814 return SERVER_OPTION(poption)->integer.max;
4817 /****************************************************************************
4818 Set the value of this server option of type OT_INTEGER. Returns TRUE if
4819 the value changed.
4820 ****************************************************************************/
4821 static bool server_option_int_set(struct option *poption, int val)
4823 struct server_option *psoption = SERVER_OPTION(poption);
4825 if (val < psoption->integer.min
4826 || val > psoption->integer.max
4827 || psoption->integer.value == val) {
4828 return FALSE;
4831 send_chat_printf("/set %s %d", psoption->name, val);
4832 return TRUE;
4835 /****************************************************************************
4836 Returns the value of this server option of type OT_STRING.
4837 ****************************************************************************/
4838 static const char *server_option_str_get(const struct option *poption)
4840 return SERVER_OPTION(poption)->string.value;
4843 /****************************************************************************
4844 Returns the default value of this server option of type OT_STRING.
4845 ****************************************************************************/
4846 static const char *server_option_str_def(const struct option *poption)
4848 return SERVER_OPTION(poption)->string.def;
4851 /****************************************************************************
4852 Returns the possible string values of this server option of type
4853 OT_STRING.
4854 ****************************************************************************/
4855 static const struct strvec *
4856 server_option_str_values(const struct option *poption)
4858 return NULL;
4861 /****************************************************************************
4862 Set the value of this server option of type OT_STRING. Returns TRUE if
4863 the value changed.
4864 ****************************************************************************/
4865 static bool server_option_str_set(struct option *poption, const char *str)
4867 struct server_option *psoption = SERVER_OPTION(poption);
4869 if (0 == strcmp(psoption->string.value, str)) {
4870 return FALSE;
4873 send_chat_printf("/set %s \"%s\"", psoption->name, str);
4874 return TRUE;
4877 /****************************************************************************
4878 Returns the current value of this server option of type OT_ENUM.
4879 ****************************************************************************/
4880 static int server_option_enum_get(const struct option *poption)
4882 return SERVER_OPTION(poption)->enumerator.value;
4885 /****************************************************************************
4886 Returns the default value of this server option of type OT_ENUM.
4887 ****************************************************************************/
4888 static int server_option_enum_def(const struct option *poption)
4890 return SERVER_OPTION(poption)->enumerator.def;
4893 /****************************************************************************
4894 Returns the user-visible, translatable (but untranslated) "pretty" names
4895 of this server option of type OT_ENUM.
4896 ****************************************************************************/
4897 static const struct strvec *
4898 server_option_enum_pretty(const struct option *poption)
4900 return SERVER_OPTION(poption)->enumerator.pretty_names;
4903 /****************************************************************************
4904 Set the value of this server option of type OT_ENUM. Returns TRUE if
4905 the value changed.
4906 ****************************************************************************/
4907 static bool server_option_enum_set(struct option *poption, int val)
4909 struct server_option *psoption = SERVER_OPTION(poption);
4910 const char *name;
4912 if (val == psoption->enumerator.value
4913 || !(name = strvec_get(psoption->enumerator.support_names, val))) {
4914 return FALSE;
4917 send_chat_printf("/set %s \"%s\"", psoption->name, name);
4918 return TRUE;
4921 /****************************************************************************
4922 Returns the long support names of the values of the server option of type
4923 OT_ENUM.
4924 ****************************************************************************/
4925 static void server_option_enum_support_name(const struct option *poption,
4926 const char **pvalue,
4927 const char **pdefault)
4929 const struct server_option *psoption = SERVER_OPTION(poption);
4930 const struct strvec *values = psoption->enumerator.support_names;
4932 if (NULL != pvalue) {
4933 *pvalue = strvec_get(values, psoption->enumerator.value);
4935 if (NULL != pdefault) {
4936 *pdefault = strvec_get(values, psoption->enumerator.def);
4940 /****************************************************************************
4941 Returns the current value of this server option of type OT_BITWISE.
4942 ****************************************************************************/
4943 static unsigned server_option_bitwise_get(const struct option *poption)
4945 return SERVER_OPTION(poption)->bitwise.value;
4948 /****************************************************************************
4949 Returns the default value of this server option of type OT_BITWISE.
4950 ****************************************************************************/
4951 static unsigned server_option_bitwise_def(const struct option *poption)
4953 return SERVER_OPTION(poption)->bitwise.def;
4956 /****************************************************************************
4957 Returns the user-visible, translatable (but untranslated) "pretty" names
4958 of this server option of type OT_BITWISE.
4959 ****************************************************************************/
4960 static const struct strvec *
4961 server_option_bitwise_pretty(const struct option *poption)
4963 return SERVER_OPTION(poption)->bitwise.pretty_names;
4966 /****************************************************************************
4967 Compute the long support names of a value.
4968 ****************************************************************************/
4969 static void server_option_bitwise_support_base(const struct strvec *values,
4970 unsigned val,
4971 char *buf, size_t buf_len)
4973 int bit;
4975 buf[0] = '\0';
4976 for (bit = 0; bit < strvec_size(values); bit++) {
4977 if ((1 << bit) & val) {
4978 if ('\0' != buf[0]) {
4979 fc_strlcat(buf, "|", buf_len);
4981 fc_strlcat(buf, strvec_get(values, bit), buf_len);
4986 /****************************************************************************
4987 Set the value of this server option of type OT_BITWISE. Returns TRUE if
4988 the value changed.
4989 ****************************************************************************/
4990 static bool server_option_bitwise_set(struct option *poption, unsigned val)
4992 struct server_option *psoption = SERVER_OPTION(poption);
4993 char name[MAX_LEN_MSG];
4995 if (val == psoption->bitwise.value) {
4996 return FALSE;
4999 server_option_bitwise_support_base(psoption->bitwise.support_names, val,
5000 name, sizeof(name));
5001 send_chat_printf("/set %s \"%s\"", psoption->name, name);
5002 return TRUE;
5005 /****************************************************************************
5006 Compute the long support names of the values of the server option of type
5007 OT_BITWISE.
5008 ****************************************************************************/
5009 static void server_option_bitwise_support_name(const struct option *poption,
5010 char *val_buf, size_t val_len,
5011 char *def_buf, size_t def_len)
5013 const struct server_option *psoption = SERVER_OPTION(poption);
5014 const struct strvec *values = psoption->bitwise.support_names;
5016 if (NULL != val_buf && 0 < val_len) {
5017 server_option_bitwise_support_base(values, psoption->bitwise.value,
5018 val_buf, val_len);
5020 if (NULL != def_buf && 0 < def_len) {
5021 server_option_bitwise_support_base(values, psoption->bitwise.def,
5022 def_buf, def_len);
5027 /** Message Options: **/
5029 int messages_where[E_COUNT];
5032 /****************************************************************
5033 These could be a static table initialisation, except
5034 its easier to do it this way.
5035 *****************************************************************/
5036 static void message_options_init(void)
5038 int none[] = {
5039 E_IMP_BUY, E_IMP_SOLD, E_UNIT_BUY,
5040 E_UNIT_LOST_ATT, E_UNIT_WIN_ATT, E_GAME_START,
5041 E_CITY_BUILD, E_NEXT_YEAR,
5042 E_CITY_PRODUCTION_CHANGED,
5043 E_CITY_MAY_SOON_GROW, E_WORKLIST, E_AI_DEBUG
5045 int out_only[] = {
5046 E_NATION_SELECTED, E_CHAT_MSG, E_CHAT_ERROR, E_CONNECTION,
5047 E_LOG_ERROR, E_SETTING, E_VOTE_NEW, E_VOTE_RESOLVED, E_VOTE_ABORTED
5049 int all[] = {
5050 E_LOG_FATAL, E_SCRIPT, E_DEPRECATION_WARNING
5052 int i;
5054 for (i = 0; i <= event_type_max(); i++) {
5055 /* Include possible undefined values. */
5056 messages_where[i] = MW_MESSAGES;
5058 for (i = 0; i < ARRAY_SIZE(none); i++) {
5059 messages_where[none[i]] = 0;
5061 for (i = 0; i < ARRAY_SIZE(out_only); i++) {
5062 messages_where[out_only[i]] = MW_OUTPUT;
5064 for (i = 0; i < ARRAY_SIZE(all); i++) {
5065 messages_where[all[i]] = MW_MESSAGES | MW_POPUP;
5068 events_init();
5071 /****************************************************************
5072 Free resources allocated for message options system
5073 *****************************************************************/
5074 static void message_options_free(void)
5076 events_free();
5079 /****************************************************************
5080 Load the message options; use the function defined by
5081 specnum.h (see also events.h).
5082 *****************************************************************/
5083 static void message_options_load(struct section_file *file,
5084 const char *prefix)
5086 enum event_type event;
5087 int i, num_events;
5088 const char *p;
5090 if (!secfile_lookup_int(file, &num_events, "messages.count")) {
5091 /* version < 2.2 */
5092 /* Order of the events in 2.1. */
5093 const enum event_type old_events[] = {
5094 E_CITY_CANTBUILD, E_CITY_LOST, E_CITY_LOVE, E_CITY_DISORDER,
5095 E_CITY_FAMINE, E_CITY_FAMINE_FEARED, E_CITY_GROWTH,
5096 E_CITY_MAY_SOON_GROW, E_CITY_AQUEDUCT, E_CITY_AQ_BUILDING,
5097 E_CITY_NORMAL, E_CITY_NUKED, E_CITY_CMA_RELEASE, E_CITY_GRAN_THROTTLE,
5098 E_CITY_TRANSFER, E_CITY_BUILD, E_CITY_PRODUCTION_CHANGED,
5099 E_WORKLIST, E_UPRISING, E_CIVIL_WAR, E_ANARCHY, E_FIRST_CONTACT,
5100 E_NEW_GOVERNMENT, E_LOW_ON_FUNDS, E_POLLUTION, E_REVOLT_DONE,
5101 E_REVOLT_START, E_SPACESHIP, E_MY_DIPLOMAT_BRIBE,
5102 E_DIPLOMATIC_INCIDENT, E_MY_DIPLOMAT_ESCAPE, E_MY_DIPLOMAT_EMBASSY,
5103 E_MY_DIPLOMAT_FAILED, E_MY_DIPLOMAT_INCITE, E_MY_DIPLOMAT_POISON,
5104 E_MY_DIPLOMAT_SABOTAGE, E_MY_DIPLOMAT_THEFT, E_ENEMY_DIPLOMAT_BRIBE,
5105 E_ENEMY_DIPLOMAT_EMBASSY, E_ENEMY_DIPLOMAT_FAILED,
5106 E_ENEMY_DIPLOMAT_INCITE, E_ENEMY_DIPLOMAT_POISON,
5107 E_ENEMY_DIPLOMAT_SABOTAGE, E_ENEMY_DIPLOMAT_THEFT,
5108 E_CARAVAN_ACTION, E_SCRIPT, E_BROADCAST_REPORT, E_GAME_END,
5109 E_GAME_START, E_NATION_SELECTED, E_DESTROYED, E_REPORT, E_TURN_BELL,
5110 E_NEXT_YEAR, E_GLOBAL_ECO, E_NUKE, E_HUT_BARB, E_HUT_CITY, E_HUT_GOLD,
5111 E_HUT_BARB_KILLED, E_HUT_MERC, E_HUT_SETTLER, E_HUT_TECH,
5112 E_HUT_BARB_CITY_NEAR, E_IMP_BUY, E_IMP_BUILD, E_IMP_AUCTIONED,
5113 E_IMP_AUTO, E_IMP_SOLD, E_TECH_GAIN, E_TECH_LEARNED, E_TREATY_ALLIANCE,
5114 E_TREATY_BROKEN, E_TREATY_CEASEFIRE, E_TREATY_PEACE,
5115 E_TREATY_SHARED_VISION, E_UNIT_LOST_ATT, E_UNIT_WIN_ATT, E_UNIT_BUY,
5116 E_UNIT_BUILT, E_UNIT_LOST_DEF, E_UNIT_WIN, E_UNIT_BECAME_VET,
5117 E_UNIT_UPGRADED, E_UNIT_RELOCATED, E_UNIT_ORDERS, E_WONDER_BUILD,
5118 E_WONDER_OBSOLETE, E_WONDER_STARTED, E_WONDER_STOPPED,
5119 E_WONDER_WILL_BE_BUILT, E_DIPLOMACY, E_TREATY_EMBASSY,
5120 E_BAD_COMMAND, E_SETTING, E_CHAT_MSG, E_MESSAGE_WALL, E_CHAT_ERROR,
5121 E_CONNECTION, E_AI_DEBUG
5123 const size_t old_events_num = ARRAY_SIZE(old_events);
5125 for (i = 0; i < old_events_num; i++) {
5126 messages_where[old_events[i]] =
5127 secfile_lookup_int_default(file, messages_where[old_events[i]],
5128 "%s.message_where_%02d", prefix, i);
5130 return;
5133 for (i = 0; i < num_events; i++) {
5134 p = secfile_lookup_str(file, "messages.event%d.name", i);
5135 if (NULL == p) {
5136 log_error("Corruption in file %s: %s",
5137 secfile_name(file), secfile_error());
5138 continue;
5140 event = event_type_by_name(p, strcmp);
5141 if (!event_type_is_valid(event)) {
5142 log_error("Event not supported: %s", p);
5143 continue;
5146 if (!secfile_lookup_int(file, &messages_where[event],
5147 "messages.event%d.where", i)) {
5148 log_error("Corruption in file %s: %s",
5149 secfile_name(file), secfile_error());
5154 /****************************************************************
5155 Save the message options; use the function defined by
5156 specnum.h (see also events.h).
5157 *****************************************************************/
5158 static void message_options_save(struct section_file *file,
5159 const char *prefix)
5161 enum event_type event;
5162 int i = 0;
5164 for (event = event_type_begin(); event != event_type_end();
5165 event = event_type_next(event)) {
5166 secfile_insert_str(file, event_type_name(event),
5167 "messages.event%d.name", i);
5168 secfile_insert_int(file, messages_where[i],
5169 "messages.event%d.where", i);
5170 i++;
5173 secfile_insert_int(file, i, "messages.count");
5177 /****************************************************************
5178 Does heavy lifting for looking up a preset.
5179 *****************************************************************/
5180 static void load_cma_preset(struct section_file *file, int i)
5182 struct cm_parameter parameter;
5183 const char *name =
5184 secfile_lookup_str_default(file, "preset",
5185 "cma.preset%d.name", i);
5187 output_type_iterate(o) {
5188 parameter.minimal_surplus[o] =
5189 secfile_lookup_int_default(file, 0, "cma.preset%d.minsurp%d", i, o);
5190 parameter.factor[o] =
5191 secfile_lookup_int_default(file, 0, "cma.preset%d.factor%d", i, o);
5192 } output_type_iterate_end;
5193 parameter.require_happy =
5194 secfile_lookup_bool_default(file, FALSE, "cma.preset%d.reqhappy", i);
5195 parameter.happy_factor =
5196 secfile_lookup_int_default(file, 0, "cma.preset%d.happyfactor", i);
5197 parameter.allow_disorder = FALSE;
5198 parameter.allow_specialists = TRUE;
5200 cmafec_preset_add(name, &parameter);
5203 /****************************************************************
5204 Does heavy lifting for inserting a preset.
5205 *****************************************************************/
5206 static void save_cma_preset(struct section_file *file, int i)
5208 const struct cm_parameter *const pparam = cmafec_preset_get_parameter(i);
5209 char *name = cmafec_preset_get_descr(i);
5211 secfile_insert_str(file, name, "cma.preset%d.name", i);
5213 output_type_iterate(o) {
5214 secfile_insert_int(file, pparam->minimal_surplus[o],
5215 "cma.preset%d.minsurp%d", i, o);
5216 secfile_insert_int(file, pparam->factor[o],
5217 "cma.preset%d.factor%d", i, o);
5218 } output_type_iterate_end;
5219 secfile_insert_bool(file, pparam->require_happy,
5220 "cma.preset%d.reqhappy", i);
5221 secfile_insert_int(file, pparam->happy_factor,
5222 "cma.preset%d.happyfactor", i);
5225 /****************************************************************
5226 Insert all cma presets.
5227 *****************************************************************/
5228 static void save_cma_presets(struct section_file *file)
5230 int i;
5232 secfile_insert_int_comment(file, cmafec_preset_num(),
5233 _("If you add a preset by hand,"
5234 " also update \"number_of_presets\""),
5235 "cma.number_of_presets");
5236 for (i = 0; i < cmafec_preset_num(); i++) {
5237 save_cma_preset(file, i);
5241 /* Old rc file name. */
5242 #define OLD_OPTION_FILE_NAME ".civclientrc"
5243 /* New rc file name. */
5244 #define MID_OPTION_FILE_NAME ".freeciv-client-rc-%d.%d"
5245 #define NEW_OPTION_FILE_NAME "freeciv-client-rc-%d.%d"
5246 #if MINOR_VERSION >= 90
5247 #define MAJOR_NEW_OPTION_FILE_NAME (MAJOR_VERSION + 1)
5248 #define MINOR_NEW_OPTION_FILE_NAME 0
5249 #else /* MINOR_VERSION < 90 */
5250 #define MAJOR_NEW_OPTION_FILE_NAME MAJOR_VERSION
5251 #if IS_DEVEL_VERSION && ! IS_FREEZE_VERSION
5252 #define MINOR_NEW_OPTION_FILE_NAME (MINOR_VERSION + 1)
5253 #else
5254 #define MINOR_NEW_OPTION_FILE_NAME MINOR_VERSION
5255 #endif /* IS_DEVEL_VERSION */
5256 #endif /* MINOR_VERSION >= 90 */
5257 /* The first version the new option name appeared (2.6). */
5258 #define FIRST_MAJOR_NEW_OPTION_FILE_NAME 2
5259 #define FIRST_MINOR_NEW_OPTION_FILE_NAME 6
5260 /* The first version the mid option name appeared (2.2). */
5261 #define FIRST_MAJOR_MID_OPTION_FILE_NAME 2
5262 #define FIRST_MINOR_MID_OPTION_FILE_NAME 2
5263 /* The first version the new boolean values appeared (2.3). */
5264 #define FIRST_MAJOR_NEW_BOOLEAN 2
5265 #define FIRST_MINOR_NEW_BOOLEAN 3
5266 /****************************************************************
5267 Returns pointer to static memory containing name of the current
5268 option file. Usually used for saving.
5269 Ie, based on FREECIV_OPT env var, and freeciv storage root dir.
5270 (or a OPTION_FILE_NAME define defined in fc_config.h)
5271 Or NULL if problem.
5272 *****************************************************************/
5273 static const char *get_current_option_file_name(void)
5275 static char name_buffer[256];
5276 const char *name;
5278 name = getenv("FREECIV_OPT");
5280 if (name) {
5281 sz_strlcpy(name_buffer, name);
5282 } else {
5283 #ifdef OPTION_FILE_NAME
5284 fc_strlcpy(name_buffer, OPTION_FILE_NAME, sizeof(name_buffer));
5285 #else
5286 name = freeciv_storage_dir();
5287 if (!name) {
5288 log_error(_("Cannot find freeciv storage directory"));
5289 return NULL;
5291 fc_snprintf(name_buffer, sizeof(name_buffer),
5292 "%s" DIR_SEPARATOR NEW_OPTION_FILE_NAME, name,
5293 MAJOR_NEW_OPTION_FILE_NAME, MINOR_NEW_OPTION_FILE_NAME);
5294 #endif /* OPTION_FILE_NAME */
5296 log_verbose("settings file is %s", name_buffer);
5297 return name_buffer;
5300 /****************************************************************************
5301 Check the last option file we saved. Usually used to load. Ie, based on
5302 FREECIV_OPT env var, and home dir. (or a OPTION_FILE_NAME define defined
5303 in fc_config.h), or NULL if not found.
5305 Set in allow_digital_boolean if we should look for old boolean values
5306 (saved as 0 and 1), so if the rc file version is older than 2.3.0.
5307 ****************************************************************************/
5308 static const char *get_last_option_file_name(bool *allow_digital_boolean)
5310 static char name_buffer[256];
5311 const char *name;
5312 static int last_minors[] = {
5313 0, /* There was no 0.x releases */
5314 14, /* 1.14 */
5315 7 /* 2.7 */
5318 #if MINOR_VERSION >= 90
5319 FC_STATIC_ASSERT(MAJOR_VERSION < sizeof(last_minors) / sizeof(int), missing_last_minor);
5320 #else
5321 FC_STATIC_ASSERT(MAJOR_VERSION <= sizeof(last_minors) / sizeof(int), missing_last_minor);
5322 #endif
5324 *allow_digital_boolean = FALSE;
5325 name = getenv("FREECIV_OPT");
5326 if (name) {
5327 sz_strlcpy(name_buffer, name);
5328 } else {
5329 #ifdef OPTION_FILE_NAME
5330 fc_strlcpy(name_buffer, OPTION_FILE_NAME, sizeof(name_buffer));
5331 #else
5332 int major, minor;
5333 struct stat buf;
5335 name = freeciv_storage_dir();
5336 if (name == NULL) {
5337 log_error(_("Cannot find freeciv storage directory"));
5339 return NULL;
5342 for (major = MAJOR_NEW_OPTION_FILE_NAME,
5343 minor = MINOR_NEW_OPTION_FILE_NAME;
5344 major >= FIRST_MAJOR_NEW_OPTION_FILE_NAME; major--) {
5345 for (; (major == FIRST_MAJOR_NEW_OPTION_FILE_NAME
5346 ? minor >= FIRST_MINOR_NEW_OPTION_FILE_NAME
5347 : minor >= 0); minor--) {
5348 fc_snprintf(name_buffer, sizeof(name_buffer),
5349 "%s" DIR_SEPARATOR NEW_OPTION_FILE_NAME, name, major, minor);
5350 if (0 == fc_stat(name_buffer, &buf)) {
5351 if (MAJOR_NEW_OPTION_FILE_NAME != major
5352 || MINOR_NEW_OPTION_FILE_NAME != minor) {
5353 log_normal(_("Didn't find '%s' option file, "
5354 "loading from '%s' instead."),
5355 get_current_option_file_name() + strlen(name) + 1,
5356 name_buffer + strlen(name) + 1);
5359 return name_buffer;
5362 minor = last_minors[major - 1];
5365 /* Older versions had options file in user home directory */
5366 name = user_home_dir();
5367 if (name == NULL) {
5368 log_error(_("Cannot find your home directory"));
5370 return NULL;
5373 /* minor having max value of FIRST_MINOR_NEW_OPTION_FILE_NAME
5374 * works since MID versioning scheme was used within major version 2
5375 * only (2.2 - 2.6) so the last minor is bigger than any earlier minor. */
5376 for (major = FIRST_MAJOR_MID_OPTION_FILE_NAME,
5377 minor = FIRST_MINOR_NEW_OPTION_FILE_NAME ;
5378 minor >= FIRST_MINOR_MID_OPTION_FILE_NAME ;
5379 minor--) {
5380 fc_snprintf(name_buffer, sizeof(name_buffer),
5381 "%s" DIR_SEPARATOR MID_OPTION_FILE_NAME, name, major, minor);
5382 if (0 == fc_stat(name_buffer, &buf)) {
5383 log_normal(_("Didn't find '%s' option file, "
5384 "loading from '%s' instead."),
5385 get_current_option_file_name() + strlen(name) + 1,
5386 name_buffer + strlen(name) + 1);
5388 if (FIRST_MINOR_NEW_BOOLEAN > minor) {
5389 *allow_digital_boolean = TRUE;
5391 return name_buffer;
5395 /* Try with the old one. */
5396 fc_snprintf(name_buffer, sizeof(name_buffer),
5397 "%s" DIR_SEPARATOR OLD_OPTION_FILE_NAME, name);
5398 if (0 == fc_stat(name_buffer, &buf)) {
5399 log_normal(_("Didn't find '%s' option file, "
5400 "loading from '%s' instead."),
5401 get_current_option_file_name() + strlen(name) + 1,
5402 OLD_OPTION_FILE_NAME);
5403 *allow_digital_boolean = TRUE;
5404 return name_buffer;
5405 } else {
5406 return NULL;
5408 #endif /* OPTION_FILE_NAME */
5410 log_verbose("settings file is %s", name_buffer);
5411 return name_buffer;
5413 #undef OLD_OPTION_FILE_NAME
5414 #undef MID_OPTION_FILE_NAME
5415 #undef NEW_OPTION_FILE_NAME
5416 #undef FIRST_MAJOR_NEW_OPTION_FILE_NAME
5417 #undef FIRST_MINOR_NEW_OPTION_FILE_NAME
5418 #undef FIRST_MAJOR_MID_OPTION_FILE_NAME
5419 #undef FIRST_MINOR_MID_OPTION_FILE_NAME
5420 #undef FIRST_MINOR_NEW_BOOLEAN
5423 /****************************************************************************
5424 Desired settable options.
5425 ****************************************************************************/
5426 #define SPECHASH_TAG settable_options
5427 #define SPECHASH_ASTR_KEY_TYPE
5428 #define SPECHASH_ASTR_DATA_TYPE
5429 #include "spechash.h"
5430 #define settable_options_hash_iterate(hash, name, value) \
5431 TYPED_HASH_ITERATE(const char *, const char *, hash, name, value)
5432 #define settable_options_hash_iterate_end HASH_ITERATE_END
5434 static struct settable_options_hash *settable_options_hash = NULL;
5436 /**************************************************************************
5437 Load the server options.
5438 **************************************************************************/
5439 static void settable_options_load(struct section_file *sf)
5441 char buf[64];
5442 const struct section *psection;
5443 const struct entry_list *entries;
5444 const char *string;
5445 bool bval;
5446 int ival;
5448 fc_assert_ret(NULL != settable_options_hash);
5450 settable_options_hash_clear(settable_options_hash);
5452 psection = secfile_section_by_name(sf, "server");
5453 if (NULL == psection) {
5454 /* Does not exist! */
5455 return;
5458 entries = section_entries(psection);
5459 entry_list_iterate(entries, pentry) {
5460 string = NULL;
5461 switch (entry_type(pentry)) {
5462 case ENTRY_BOOL:
5463 if (entry_bool_get(pentry, &bval)) {
5464 fc_strlcpy(buf, bval ? "enabled" : "disabled", sizeof(buf));
5465 string = buf;
5467 break;
5469 case ENTRY_INT:
5470 if (entry_int_get(pentry, &ival)) {
5471 fc_snprintf(buf, sizeof(buf), "%d", ival);
5472 string = buf;
5474 break;
5476 case ENTRY_STR:
5477 (void) entry_str_get(pentry, &string);
5478 break;
5480 case ENTRY_FLOAT:
5481 case ENTRY_FILEREFERENCE:
5482 /* Not supported yet */
5483 break;
5486 if (NULL == string) {
5487 log_error("Entry type variant of \"%s.%s\" is not supported.",
5488 section_name(psection), entry_name(pentry));
5489 continue;
5492 settable_options_hash_insert(settable_options_hash, entry_name(pentry),
5493 string);
5494 } entry_list_iterate_end;
5497 /****************************************************************
5498 Save the desired server options.
5499 *****************************************************************/
5500 static void settable_options_save(struct section_file *sf)
5502 fc_assert_ret(NULL != settable_options_hash);
5504 settable_options_hash_iterate(settable_options_hash, name, value) {
5505 if (!fc_strcasecmp(name, "gameseed") || !fc_strcasecmp(name, "mapseed")) {
5506 /* Do not save mapseed or gameseed. */
5507 continue;
5509 if (!fc_strcasecmp(name, "topology")) {
5510 /* client_start_server() sets topology based on tileset. Don't store
5511 * its choice. The tileset is already stored. Storing topology leads
5512 * to all sort of breakage:
5513 * - it breaks ruleset default topology.
5514 * - it interacts badly with tileset ruleset change, ruleset tileset
5515 * change and topology tileset change.
5516 * - its value is probably based on what tileset was loaded when
5517 * client_start_server() decided to set topology, not on player
5518 * choice.
5520 continue;
5522 secfile_insert_str(sf, value, "server.%s", name);
5523 } settable_options_hash_iterate_end;
5526 /****************************************************************************
5527 Update the desired settable options hash table from the current
5528 setting configuration.
5529 ****************************************************************************/
5530 void desired_settable_options_update(void)
5532 char val_buf[1024], def_buf[1024];
5533 const char *value, *def_val;
5535 fc_assert_ret(NULL != settable_options_hash);
5537 options_iterate(server_optset, poption) {
5538 value = NULL;
5539 def_val = NULL;
5540 switch (option_type(poption)) {
5541 case OT_BOOLEAN:
5542 fc_strlcpy(val_buf, option_bool_get(poption) ? "enabled" : "disabled",
5543 sizeof(val_buf));
5544 value = val_buf;
5545 fc_strlcpy(def_buf, option_bool_def(poption) ? "enabled" : "disabled",
5546 sizeof(def_buf));
5547 def_val = def_buf;
5548 break;
5549 case OT_INTEGER:
5550 fc_snprintf(val_buf, sizeof(val_buf), "%d", option_int_get(poption));
5551 value = val_buf;
5552 fc_snprintf(def_buf, sizeof(def_buf), "%d", option_int_def(poption));
5553 def_val = def_buf;
5554 break;
5555 case OT_STRING:
5556 value = option_str_get(poption);
5557 def_val = option_str_def(poption);
5558 break;
5559 case OT_ENUM:
5560 server_option_enum_support_name(poption, &value, &def_val);
5561 break;
5562 case OT_BITWISE:
5563 server_option_bitwise_support_name(poption, val_buf, sizeof(val_buf),
5564 def_buf, sizeof(def_buf));
5565 value = val_buf;
5566 def_val = def_buf;
5567 break;
5568 case OT_FONT:
5569 case OT_COLOR:
5570 case OT_VIDEO_MODE:
5571 break;
5574 if (NULL == value || NULL == def_val) {
5575 log_error("Option type %s (%d) not supported for '%s'.",
5576 option_type_name(option_type(poption)), option_type(poption),
5577 option_name(poption));
5578 continue;
5581 if (0 == strcmp(value, def_val)) {
5582 /* Not set, using default... */
5583 settable_options_hash_remove(settable_options_hash,
5584 option_name(poption));
5585 } else {
5586 /* Really desired. */
5587 settable_options_hash_replace(settable_options_hash,
5588 option_name(poption), value);
5590 } options_iterate_end;
5593 /****************************************************************
5594 Update a desired settable option in the hash table from a value
5595 which can be different of the current consiguration.
5596 *****************************************************************/
5597 void desired_settable_option_update(const char *op_name,
5598 const char *op_value,
5599 bool allow_replace)
5601 fc_assert_ret(NULL != settable_options_hash);
5603 if (allow_replace) {
5604 settable_options_hash_replace(settable_options_hash, op_name, op_value);
5605 } else {
5606 settable_options_hash_insert(settable_options_hash, op_name, op_value);
5610 /****************************************************************************
5611 Convert old integer to new values (Freeciv 2.2.x to Freeciv 2.3.x).
5612 Very ugly hack. TODO: Remove this later.
5613 ****************************************************************************/
5614 static bool settable_option_upgrade_value(const struct option *poption,
5615 int old_value,
5616 char *buf, size_t buf_len)
5618 const char *name = option_name(poption);
5620 #define SETTING_CASE(ARG_name, ...) \
5621 if (0 == strcmp(ARG_name, name)) { \
5622 static const char *values[] = { __VA_ARGS__ }; \
5623 if (0 <= old_value && old_value < ARRAY_SIZE(values) \
5624 && NULL != values[old_value]) { \
5625 fc_strlcpy(buf, values[old_value], buf_len); \
5626 return TRUE; \
5627 } else { \
5628 return FALSE; \
5632 SETTING_CASE("topology", "", "WRAPX", "WRAPY", "WRAPX|WRAPY", "ISO",
5633 "WRAPX|ISO", "WRAPY|ISO", "WRAPX|WRAPY|ISO", "HEX",
5634 "WRAPX|HEX", "WRAPY|HEX", "WRAPX|WRAPY|HEX", "ISO|HEX",
5635 "WRAPX|ISO|HEX", "WRAPY|ISO|HEX", "WRAPX|WRAPY|ISO|HEX");
5636 SETTING_CASE("generator", NULL, "RANDOM", "FRACTAL", "ISLAND");
5637 SETTING_CASE("startpos", "DEFAULT", "SINGLE", "2or3", "ALL", "VARIABLE");
5638 SETTING_CASE("borders", "DISABLED", "ENABLED", "SEE_INSIDE", "EXPAND");
5639 SETTING_CASE("diplomacy", "ALL", "HUMAN", "AI", "TEAM", "DISABLED");
5640 SETTING_CASE("citynames", "NO_RESTRICTIONS", "PLAYER_UNIQUE",
5641 "GLOBAL_UNIQUE", "NO_STEALING");
5642 SETTING_CASE("barbarians", "DISABLED", "HUTS_ONLY", "NORMAL", "FREQUENT",
5643 "HORDES");
5644 SETTING_CASE("phasemode", "ALL", "PLAYER", "TEAM");
5645 SETTING_CASE("compresstype", "PLAIN", "LIBZ", "BZIP2");
5647 #undef SETTING_CASE
5648 return FALSE;
5651 /****************************************************************************
5652 Send the desired server options to the server.
5653 ****************************************************************************/
5654 static void desired_settable_option_send(struct option *poption)
5656 char *desired;
5657 int value;
5659 fc_assert_ret(NULL != settable_options_hash);
5661 if (!settable_options_hash_lookup(settable_options_hash,
5662 option_name(poption), &desired)) {
5663 /* No change explicitly desired. */
5664 return;
5667 switch (option_type(poption)) {
5668 case OT_BOOLEAN:
5669 if ((0 == fc_strcasecmp("enabled", desired)
5670 || (str_to_int(desired, &value) && 1 == value))
5671 && !option_bool_get(poption)) {
5672 send_chat_printf("/set %s enabled", option_name(poption));
5673 } else if ((0 == fc_strcasecmp("disabled", desired)
5674 || (str_to_int(desired, &value) && 0 == value))
5675 && option_bool_get(poption)) {
5676 send_chat_printf("/set %s disabled", option_name(poption));
5678 return;
5679 case OT_INTEGER:
5680 if (str_to_int(desired, &value) && value != option_int_get(poption)) {
5681 send_chat_printf("/set %s %d", option_name(poption), value);
5683 return;
5684 case OT_STRING:
5685 if (0 != strcmp(desired, option_str_get(poption))) {
5686 send_chat_printf("/set %s \"%s\"", option_name(poption), desired);
5688 return;
5689 case OT_ENUM:
5691 char desired_buf[256];
5692 const char *value_str;
5694 /* Handle old values. */
5695 if (str_to_int(desired, &value)
5696 && settable_option_upgrade_value(poption, value, desired_buf,
5697 sizeof(desired_buf))) {
5698 desired = desired_buf;
5701 server_option_enum_support_name(poption, &value_str, NULL);
5702 if (0 != strcmp(desired, value_str)) {
5703 send_chat_printf("/set %s \"%s\"", option_name(poption), desired);
5706 return;
5707 case OT_BITWISE:
5709 char desired_buf[256], value_buf[256];
5711 /* Handle old values. */
5712 if (str_to_int(desired, &value)
5713 && settable_option_upgrade_value(poption, value, desired_buf,
5714 sizeof(desired_buf))) {
5715 desired = desired_buf;
5718 server_option_bitwise_support_name(poption, value_buf,
5719 sizeof(value_buf), NULL, 0);
5720 if (0 != strcmp(desired, value_buf)) {
5721 send_chat_printf("/set %s \"%s\"", option_name(poption), desired);
5724 return;
5725 case OT_FONT:
5726 case OT_COLOR:
5727 case OT_VIDEO_MODE:
5728 break;
5731 log_error("Option type %s (%d) not supported for '%s'.",
5732 option_type_name(option_type(poption)), option_type(poption),
5733 option_name(poption));
5737 /****************************************************************************
5738 City and player report dialog options.
5739 ****************************************************************************/
5740 #define SPECHASH_TAG dialog_options
5741 #define SPECHASH_ASTR_KEY_TYPE
5742 #define SPECHASH_IDATA_TYPE bool
5743 #define SPECHASH_UDATA_TO_IDATA FC_INT_TO_PTR
5744 #define SPECHASH_IDATA_TO_UDATA FC_PTR_TO_INT
5745 #include "spechash.h"
5746 #define dialog_options_hash_iterate(hash, column, visible) \
5747 TYPED_HASH_ITERATE(const char *, intptr_t, hash, column, visible)
5748 #define dialog_options_hash_iterate_end HASH_ITERATE_END
5750 static struct dialog_options_hash *dialog_options_hash = NULL;
5752 /****************************************************************************
5753 Load the city and player report dialog options.
5754 ****************************************************************************/
5755 static void options_dialogs_load(struct section_file *sf)
5757 const struct entry_list *entries;
5758 const char *prefixes[] = { "player_dlg_", "city_report_", NULL };
5759 const char **prefix;
5760 bool visible;
5762 fc_assert_ret(NULL != dialog_options_hash);
5764 entries = section_entries(secfile_section_by_name(sf, "client"));
5766 if (NULL != entries) {
5767 entry_list_iterate(entries, pentry) {
5768 for (prefix = prefixes; NULL != *prefix; prefix++) {
5769 if (0 == strncmp(*prefix, entry_name(pentry), strlen(*prefix))
5770 && secfile_lookup_bool(sf, &visible, "client.%s",
5771 entry_name(pentry))) {
5772 dialog_options_hash_replace(dialog_options_hash,
5773 entry_name(pentry), visible);
5774 break;
5777 } entry_list_iterate_end;
5781 /****************************************************************************
5782 Save the city and player report dialog options.
5783 ****************************************************************************/
5784 static void options_dialogs_save(struct section_file *sf)
5786 fc_assert_ret(NULL != dialog_options_hash);
5788 options_dialogs_update();
5789 dialog_options_hash_iterate(dialog_options_hash, column, visible) {
5790 secfile_insert_bool(sf, visible, "client.%s", column);
5791 } dialog_options_hash_iterate_end;
5794 /****************************************************************
5795 This set the city and player report dialog options to the
5796 current ones. It's called when the client goes to
5797 C_S_DISCONNECTED state.
5798 *****************************************************************/
5799 void options_dialogs_update(void)
5801 char buf[64];
5802 int i;
5804 fc_assert_ret(NULL != dialog_options_hash);
5806 /* Player report dialog options. */
5807 for (i = 1; i < num_player_dlg_columns; i++) {
5808 fc_snprintf(buf, sizeof(buf), "player_dlg_%s",
5809 player_dlg_columns[i].tagname);
5810 dialog_options_hash_replace(dialog_options_hash, buf,
5811 player_dlg_columns[i].show);
5814 /* City report dialog options. */
5815 for (i = 0; i < num_city_report_spec(); i++) {
5816 fc_snprintf(buf, sizeof(buf), "city_report_%s",
5817 city_report_spec_tagname(i));
5818 dialog_options_hash_replace(dialog_options_hash, buf,
5819 *city_report_spec_show_ptr(i));
5823 /****************************************************************
5824 This set the city and player report dialog options. It's called
5825 when the client goes to C_S_RUNNING state.
5826 *****************************************************************/
5827 void options_dialogs_set(void)
5829 char buf[64];
5830 bool visible;
5831 int i;
5833 fc_assert_ret(NULL != dialog_options_hash);
5835 /* Player report dialog options. */
5836 for (i = 1; i < num_player_dlg_columns; i++) {
5837 fc_snprintf(buf, sizeof(buf), "player_dlg_%s",
5838 player_dlg_columns[i].tagname);
5839 if (dialog_options_hash_lookup(dialog_options_hash, buf, &visible)) {
5840 player_dlg_columns[i].show = visible;
5844 /* City report dialog options. */
5845 for (i = 0; i < num_city_report_spec(); i++) {
5846 fc_snprintf(buf, sizeof(buf), "city_report_%s",
5847 city_report_spec_tagname(i));
5848 if (dialog_options_hash_lookup(dialog_options_hash, buf, &visible)) {
5849 *city_report_spec_show_ptr(i) = visible;
5855 /****************************************************************
5856 Load from the rc file any options that are not ruleset specific.
5857 It is called after ui_init(), yet before ui_main().
5858 Unfortunately, this means that some clients cannot display.
5859 Instead, use log_*().
5860 *****************************************************************/
5861 void options_load(void)
5863 struct section_file *sf;
5864 bool allow_digital_boolean;
5865 int i, num;
5866 const char *name;
5867 const char *const prefix = "client";
5868 const char *str;
5870 name = get_last_option_file_name(&allow_digital_boolean);
5871 if (!name) {
5872 log_normal(_("Didn't find the option file. Creating a new one."));
5873 client_option_adjust_defaults();
5874 options_fully_initialized = TRUE;
5875 create_default_cma_presets();
5876 gui_options.first_boot = TRUE;
5877 return;
5879 if (!(sf = secfile_load(name, TRUE))) {
5880 log_debug("Error loading option file '%s':\n%s", name, secfile_error());
5881 /* try to create the rc file */
5882 sf = secfile_new(TRUE);
5883 secfile_insert_str(sf, VERSION_STRING, "client.version");
5885 create_default_cma_presets();
5886 save_cma_presets(sf);
5888 /* FIXME: need better messages */
5889 if (!secfile_save(sf, name, 0, FZ_PLAIN)) {
5890 log_error(_("Save failed, cannot write to file %s"), name);
5891 } else {
5892 log_normal(_("Saved settings to file %s"), name);
5894 secfile_destroy(sf);
5895 options_fully_initialized = TRUE;
5896 return;
5898 secfile_allow_digital_boolean(sf, allow_digital_boolean);
5900 /* a "secret" option for the lazy. TODO: make this saveable */
5901 sz_strlcpy(password,
5902 secfile_lookup_str_default(sf, "", "%s.password", prefix));
5904 gui_options.save_options_on_exit =
5905 secfile_lookup_bool_default(sf, gui_options.save_options_on_exit,
5906 "%s.save_options_on_exit", prefix);
5907 gui_options.migrate_fullscreen =
5908 secfile_lookup_bool_default(sf, gui_options.migrate_fullscreen,
5909 "%s.fullscreen_mode", prefix);
5911 /* Settings migrations */
5912 gui_options.gui_gtk3_migrated_from_gtk2 =
5913 secfile_lookup_bool_default(sf, gui_options.gui_gtk3_migrated_from_gtk2,
5914 "%s.migration_gtk3_from_gtk2", prefix);
5915 gui_options.gui_gtk3_22_migrated_from_gtk3 =
5916 secfile_lookup_bool_default(sf, gui_options.gui_gtk3_22_migrated_from_gtk3,
5917 "%s.migration_gtk3_22_from_gtk3", prefix);
5918 gui_options.gui_gtk4_migrated_from_gtk3_22 =
5919 secfile_lookup_bool_default(sf, gui_options.gui_gtk4_migrated_from_gtk3_22,
5920 "%s.migration_gtk4_from_gtk3_22", prefix);
5921 gui_options.gui_sdl2_migrated_from_sdl =
5922 secfile_lookup_bool_default(sf, gui_options.gui_sdl2_migrated_from_sdl,
5923 "%s.migration_sdl2_from_sdl", prefix);
5924 gui_options.gui_gtk2_migrated_from_2_5 =
5925 secfile_lookup_bool_default(sf, gui_options.gui_gtk3_migrated_from_2_5,
5926 "%s.migration_gtk2_from_2_5", prefix);
5927 gui_options.gui_gtk3_migrated_from_2_5 =
5928 secfile_lookup_bool_default(sf, gui_options.gui_gtk2_migrated_from_2_5,
5929 "%s.migration_gtk3_from_2_5", prefix);
5930 gui_options.gui_qt_migrated_from_2_5 =
5931 secfile_lookup_bool_default(sf, gui_options.gui_qt_migrated_from_2_5,
5932 "%s.migration_qt_from_2_5", prefix);
5934 /* These are not gui-enabled yet */
5935 gui_options.zoom_set =
5936 secfile_lookup_bool_default(sf, FALSE, "%s.zoom_set", prefix);
5937 gui_options.zoom_default_level =
5938 secfile_lookup_float_default(sf, 1.0,
5939 "%s.zoom_default_level", prefix);
5941 str = secfile_lookup_str_default(sf, NULL, "client.default_tileset_name");
5942 if (str != NULL) {
5943 strncpy(gui_options.default_tileset_name, str,
5944 sizeof(gui_options.default_tileset_name));
5947 /* Backwards compatibility for removed options replaced by entirely "new"
5948 * options. The equivalent "new" option will override these, if set. */
5950 /* Removed in 2.3 */
5951 /* Note: this overrides the previously specified default for
5952 * gui_gtk2_message_chat_location */
5953 /* gtk3 client never had the old form of this option. The overridden
5954 * gui_gtk2_ value will be propagated to gui_gtk3_ later by
5955 * migrate_options_from_gtk2() if necessary. */
5956 if (secfile_lookup_bool_default(sf, FALSE,
5957 "%s.gui_gtk2_merge_notebooks", prefix)) {
5958 gui_options.gui_gtk2_message_chat_location = GUI_GTK_MSGCHAT_MERGED;
5959 } else if (secfile_lookup_bool_default(sf, FALSE,
5960 "%s.gui_gtk2_split_bottom_notebook",
5961 prefix)) {
5962 gui_options.gui_gtk2_message_chat_location = GUI_GTK_MSGCHAT_SPLIT;
5963 } else {
5964 gui_options.gui_gtk2_message_chat_location = GUI_GTK_MSGCHAT_SEPARATE;
5967 /* Renamed in 2.6 */
5968 gui_options.popup_actor_arrival = secfile_lookup_bool_default(sf, TRUE,
5969 "%s.popup_caravan_arrival", prefix);
5971 /* Load all the regular options */
5972 client_options_iterate_all(poption) {
5973 client_option_load(poption, sf);
5974 } client_options_iterate_all_end;
5976 /* More backwards compatibility, for removed options that had been
5977 * folded into then-existing options. Here, the backwards-compatibility
5978 * behaviour overrides the "destination" option. */
5980 /* Removed in 2.4 */
5981 if (!secfile_lookup_bool_default(sf, TRUE,
5982 "%s.do_combat_animation", prefix)) {
5983 gui_options.smooth_combat_step_msec = 0;
5986 message_options_load(sf, prefix);
5987 options_dialogs_load(sf);
5989 /* Load cma presets. If cma.number_of_presets doesn't exist, don't load
5990 * any, the order here should be reversed to keep the order the same */
5991 if (secfile_lookup_int(sf, &num, "cma.number_of_presets")) {
5992 for (i = num - 1; i >= 0; i--) {
5993 load_cma_preset(sf, i);
5995 } else {
5996 create_default_cma_presets();
5999 settable_options_load(sf);
6000 global_worklists_load(sf);
6002 secfile_destroy(sf);
6003 options_fully_initialized = TRUE;
6006 /**************************************************************************
6007 Write messages from option saving to the output window.
6008 **************************************************************************/
6009 static void option_save_output_window_callback(enum log_level lvl,
6010 const char *msg, ...)
6012 va_list args;
6014 va_start(args, msg);
6015 output_window_vprintf(ftc_client, msg, args);
6016 va_end(args);
6019 /**************************************************************************
6020 Save all options.
6021 **************************************************************************/
6022 void options_save(option_save_log_callback log_cb)
6024 struct section_file *sf;
6025 const char *name = get_current_option_file_name();
6026 char dir_name[2048];
6027 int i;
6029 if (log_cb == NULL) {
6030 /* Default callback */
6031 log_cb = option_save_output_window_callback;
6034 if (!name) {
6035 log_cb(LOG_ERROR, _("Save failed, cannot find a filename."));
6036 return;
6039 sf = secfile_new(TRUE);
6040 secfile_insert_str(sf, VERSION_STRING, "client.version");
6042 secfile_insert_bool(sf, gui_options.save_options_on_exit,
6043 "client.save_options_on_exit");
6044 secfile_insert_bool_comment(sf, gui_options.migrate_fullscreen,
6045 "deprecated", "client.fullscreen_mode");
6047 /* Migrations */
6048 secfile_insert_bool(sf, gui_options.gui_gtk3_migrated_from_gtk2,
6049 "client.migration_gtk3_from_gtk2");
6050 secfile_insert_bool(sf, gui_options.gui_gtk3_22_migrated_from_gtk3,
6051 "client.migration_gtk3_22_from_gtk3");
6052 secfile_insert_bool(sf, gui_options.gui_gtk4_migrated_from_gtk3_22,
6053 "client.migration_gtk4_from_gtk3");
6054 secfile_insert_bool(sf, gui_options.gui_sdl2_migrated_from_sdl,
6055 "client.migration_sdl2_from_sdl");
6056 secfile_insert_bool(sf, gui_options.gui_gtk2_migrated_from_2_5,
6057 "client.migration_gtk2_from_2_5");
6058 secfile_insert_bool(sf, gui_options.gui_gtk3_migrated_from_2_5,
6059 "client.migration_gtk3_from_2_5");
6060 secfile_insert_bool(sf, gui_options.gui_qt_migrated_from_2_5,
6061 "client.migration_qt_from_2_5");
6063 /* gui-enabled options */
6064 client_options_iterate_all(poption) {
6065 if ((client_poption->specific != GUI_SDL || !gui_options.gui_sdl2_migrated_from_sdl)
6066 && (client_poption->specific != GUI_GTK2 || !gui_options.gui_gtk3_migrated_from_gtk2)) {
6067 /* Once sdl-client options have been migrated to sdl2-client, or gtk2-client options
6068 * to gtk3-client, there's no use for them any more, so no point in saving them. */
6069 client_option_save(poption, sf);
6071 } client_options_iterate_all_end;
6073 /* These are not gui-enabled yet. */
6074 secfile_insert_bool(sf, gui_options.zoom_set, "client.zoom_set");
6075 secfile_insert_float(sf, gui_options.zoom_default_level,
6076 "client.zoom_default_level");
6078 if (gui_options.default_tileset_name[0] != '\0') {
6079 secfile_insert_str(sf, gui_options.default_tileset_name,
6080 "client.default_tileset_name");
6083 message_options_save(sf, "client");
6084 options_dialogs_save(sf);
6086 /* server settings */
6087 save_cma_presets(sf);
6088 settable_options_save(sf);
6090 /* insert global worklists */
6091 global_worklists_save(sf);
6093 /* Directory name */
6094 strncpy(dir_name, name, sizeof(dir_name));
6095 for (i = strlen(dir_name) - 1 ; dir_name[i] != DIR_SEPARATOR_CHAR && i >= 0; i--) {
6096 /* Nothing */
6098 if (i > 0) {
6099 dir_name[i] = '\0';
6100 make_dir(dir_name);
6103 /* save to disk */
6104 if (!secfile_save(sf, name, 0, FZ_PLAIN)) {
6105 log_cb(LOG_ERROR, _("Save failed, cannot write to file %s"), name);
6106 } else {
6107 log_cb(LOG_VERBOSE, _("Saved settings to file %s"), name);
6109 secfile_destroy(sf);
6113 /**************************************************************************
6114 Initialize lists of names for a client option.
6115 **************************************************************************/
6116 static void options_init_names(const struct copt_val_name *(*acc)(int),
6117 struct strvec **support, struct strvec **pretty)
6119 int val;
6120 const struct copt_val_name *name;
6121 fc_assert_ret(NULL != acc);
6122 *support = strvec_new();
6123 *pretty = strvec_new();
6124 for (val=0; (name = acc(val)); val++) {
6125 strvec_append(*support, name->support);
6126 strvec_append(*pretty, name->pretty);
6130 /**************************************************************************
6131 Initialize the option module.
6132 **************************************************************************/
6133 void options_init(void)
6135 message_options_init();
6136 options_extra_init();
6137 global_worklists_init();
6139 settable_options_hash = settable_options_hash_new();
6140 dialog_options_hash = dialog_options_hash_new();
6142 client_options_iterate_all(poption) {
6143 struct client_option *pcoption = CLIENT_OPTION(poption);
6145 switch (option_type(poption)) {
6146 case OT_INTEGER:
6147 if (option_int_def(poption) < option_int_min(poption)
6148 || option_int_def(poption) > option_int_max(poption)) {
6149 int new_default = MAX(MIN(option_int_def(poption),
6150 option_int_max(poption)),
6151 option_int_min(poption));
6153 log_error("option %s has default value of %d, which is "
6154 "out of its range [%d; %d], changing to %d.",
6155 option_name(poption), option_int_def(poption),
6156 option_int_min(poption), option_int_max(poption),
6157 new_default);
6158 *((int *) &(pcoption->integer.def)) = new_default;
6160 break;
6162 case OT_STRING:
6163 if (gui_options.default_user_name == option_str_get(poption)) {
6164 /* Hack to get a default value. */
6165 *((const char **) &(pcoption->string.def)) =
6166 fc_strdup(gui_options.default_user_name);
6169 if (NULL == option_str_def(poption)) {
6170 const struct strvec *values = option_str_values(poption);
6172 if (NULL == values || strvec_size(values) == 0) {
6173 log_error("Invalid NULL default string for option %s.",
6174 option_name(poption));
6175 } else {
6176 *((const char **) &(pcoption->string.def)) =
6177 strvec_get(values, 0);
6180 break;
6182 case OT_ENUM:
6183 fc_assert(NULL == pcoption->enumerator.support_names);
6184 fc_assert(NULL == pcoption->enumerator.pretty_names);
6185 options_init_names(pcoption->enumerator.name_accessor,
6186 &pcoption->enumerator.support_names,
6187 &pcoption->enumerator.pretty_names);
6188 fc_assert(NULL != pcoption->enumerator.support_names);
6189 fc_assert(NULL != pcoption->enumerator.pretty_names);
6190 break;
6192 case OT_BITWISE:
6193 fc_assert(NULL == pcoption->bitwise.support_names);
6194 fc_assert(NULL == pcoption->bitwise.pretty_names);
6195 options_init_names(pcoption->bitwise.name_accessor,
6196 &pcoption->bitwise.support_names,
6197 &pcoption->bitwise.pretty_names);
6198 fc_assert(NULL != pcoption->bitwise.support_names);
6199 fc_assert(NULL != pcoption->bitwise.pretty_names);
6200 break;
6202 case OT_COLOR:
6204 /* Duplicate the string pointers. */
6205 struct ft_color *pcolor = pcoption->color.pvalue;
6207 if (NULL != pcolor->foreground) {
6208 pcolor->foreground = fc_strdup(pcolor->foreground);
6210 if (NULL != pcolor->background) {
6211 pcolor->background = fc_strdup(pcolor->background);
6215 case OT_BOOLEAN:
6216 case OT_FONT:
6217 case OT_VIDEO_MODE:
6218 break;
6221 /* Set to default. */
6222 option_reset(poption);
6223 } client_options_iterate_all_end;
6226 /**************************************************************************
6227 Free the option module.
6228 **************************************************************************/
6229 void options_free(void)
6231 client_options_iterate_all(poption) {
6232 struct client_option *pcoption = CLIENT_OPTION(poption);
6234 switch (option_type(poption)) {
6235 case OT_ENUM:
6236 fc_assert_action(NULL != pcoption->enumerator.support_names, break);
6237 strvec_destroy(pcoption->enumerator.support_names);
6238 pcoption->enumerator.support_names = NULL;
6239 fc_assert_action(NULL != pcoption->enumerator.pretty_names, break);
6240 strvec_destroy(pcoption->enumerator.pretty_names);
6241 pcoption->enumerator.pretty_names = NULL;
6242 break;
6244 case OT_BITWISE:
6245 fc_assert_action(NULL != pcoption->bitwise.support_names, break);
6246 strvec_destroy(pcoption->bitwise.support_names);
6247 pcoption->bitwise.support_names = NULL;
6248 fc_assert_action(NULL != pcoption->bitwise.pretty_names, break);
6249 strvec_destroy(pcoption->bitwise.pretty_names);
6250 pcoption->bitwise.pretty_names = NULL;
6251 break;
6253 case OT_BOOLEAN:
6254 case OT_INTEGER:
6255 case OT_STRING:
6256 case OT_FONT:
6257 case OT_COLOR:
6258 case OT_VIDEO_MODE:
6259 break;
6261 } client_options_iterate_all_end;
6263 if (NULL != settable_options_hash) {
6264 settable_options_hash_destroy(settable_options_hash);
6265 settable_options_hash = NULL;
6268 if (NULL != dialog_options_hash) {
6269 dialog_options_hash_destroy(dialog_options_hash);
6270 dialog_options_hash = NULL;
6273 message_options_free();
6274 global_worklists_free();
6277 /****************************************************************************
6278 Callback when the reqtree show icons option is changed. The tree is
6279 recalculated.
6280 ****************************************************************************/
6281 static void reqtree_show_icons_callback(struct option *poption)
6283 science_report_dialog_redraw();
6286 /****************************************************************************
6287 Callback for when any view option is changed.
6288 ****************************************************************************/
6289 static void view_option_changed_callback(struct option *poption)
6291 menus_init();
6292 update_map_canvas_visible();
6295 /****************************************************************************
6296 Callback for when ai_manual_turn_done is changed.
6297 ****************************************************************************/
6298 static void manual_turn_done_callback(struct option *poption)
6300 update_turn_done_button_state();
6301 if (!gui_options.ai_manual_turn_done && is_ai(client.conn.playing)) {
6302 if (can_end_turn()) {
6303 user_ended_turn();
6308 /****************************************************************************
6309 Callback for when any voteinfo bar option is changed.
6310 ****************************************************************************/
6311 static void voteinfo_bar_callback(struct option *poption)
6313 voteinfo_gui_update();
6316 /****************************************************************************
6317 Callback for font options.
6318 ****************************************************************************/
6319 static void font_changed_callback(struct option *poption)
6321 fc_assert_ret(OT_FONT == option_type(OPTION(poption)));
6322 gui_update_font(option_font_target(poption), option_font_get(poption));
6325 /****************************************************************************
6326 Callback for mapimg options.
6327 ****************************************************************************/
6328 static void mapimg_changed_callback(struct option *poption)
6330 if (!mapimg_client_define()) {
6331 bool success;
6333 log_normal("Error setting the value for %s (%s). Restoring the default "
6334 "value.", option_name(poption), mapimg_error());
6336 /* Reset the value to the default value. */
6337 success = option_reset(poption);
6338 fc_assert_msg(success == TRUE,
6339 "Failed to reset the option \"%s\".",
6340 option_name(poption));
6341 success = mapimg_client_define();
6342 fc_assert_msg(success == TRUE,
6343 "Failed to restore mapimg definition for option \"%s\".",
6344 option_name(poption));
6348 /****************************************************************************
6349 Callback for music enabling option.
6350 ****************************************************************************/
6351 static void game_music_enable_callback(struct option *poption)
6353 if (client_state() == C_S_RUNNING) {
6354 if (gui_options.sound_enable_game_music) {
6355 start_style_music();
6356 } else {
6357 stop_style_music();
6362 /****************************************************************************
6363 Callback for music enabling option.
6364 ****************************************************************************/
6365 static void menu_music_enable_callback(struct option *poption)
6367 if (client_state() != C_S_RUNNING) {
6368 if (gui_options.sound_enable_menu_music) {
6369 start_menu_music("music_menu", NULL);
6370 } else {
6371 stop_menu_music();
6376 /****************************************************************************
6377 Make dynamic adjustments to first-launch default options.
6378 ****************************************************************************/
6379 static void client_option_adjust_defaults(void)
6381 adjust_default_options();
6384 /****************************************************************************
6385 Convert a video mode to string. Returns TRUE on success.
6386 ****************************************************************************/
6387 bool video_mode_to_string(char *buf, size_t buf_len, struct video_mode *mode)
6389 return (2 < fc_snprintf(buf, buf_len, "%dx%d", mode->width, mode->height));
6392 /****************************************************************************
6393 Convert a string to video mode. Returns TRUE on success.
6394 ****************************************************************************/
6395 bool string_to_video_mode(const char *buf, struct video_mode *mode)
6397 return (2 == sscanf(buf, "%dx%d", &mode->width, &mode->height));
6400 /****************************************************************************
6401 Option framework wrapper for mapimg_get_format_list()
6402 ****************************************************************************/
6403 static const struct strvec *get_mapimg_format_list(const struct option *poption)
6405 return mapimg_get_format_list();
6408 /****************************************************************************
6409 What is the user defined tileset for the given topology
6410 ****************************************************************************/
6411 const char *tileset_name_for_topology(int topology_id)
6413 const char *tsn = NULL;
6415 switch (topology_id & (TF_ISO | TF_HEX)) {
6416 case 0:
6417 tsn = gui_options.default_tileset_overhead_name;
6418 break;
6419 case TF_ISO:
6420 tsn = gui_options.default_tileset_iso_name;
6421 break;
6422 case TF_HEX:
6423 tsn = gui_options.default_tileset_hex_name;
6424 break;
6425 case TF_ISO | TF_HEX:
6426 tsn = gui_options.default_tileset_isohex_name;
6427 break;
6430 if (tsn == NULL) {
6431 tsn = gui_options.default_tileset_name;
6434 return tsn;
6437 /****************************************************************************
6438 Set given tileset as the default for suitable topology
6439 ****************************************************************************/
6440 void option_set_default_ts(struct tileset *t)
6442 const char *optname = "<not set>";
6443 struct option *opt;
6445 switch (tileset_topo_index(t)) {
6446 case TS_TOPO_OVERHEAD:
6447 /* Overhead */
6448 optname = "default_tileset_overhead_name";
6449 break;
6450 case TS_TOPO_ISO:
6451 /* Iso */
6452 optname = "default_tileset_iso_name";
6453 break;
6454 case TS_TOPO_HEX:
6455 /* Hex */
6456 optname = "default_tileset_hex_name";
6457 break;
6458 case TS_TOPO_ISOHEX:
6459 /* Isohex */
6460 optname = "default_tileset_isohex_name";
6461 break;
6464 opt = optset_option_by_name(client_optset, optname);
6466 if (opt == NULL) {
6467 log_error("Unknown option name \"%s\" in option_set_default_ts()", optname);
6468 return;
6471 /* Do not call option_str_set() since we don't want option changed callback
6472 * to reload this tileset. */
6473 opt->str_vtable->set(opt, tileset_basename(t));
6474 option_gui_update(opt);
6477 /****************************************************************************
6478 Does topology-specific tileset option lack value?
6479 ****************************************************************************/
6480 static bool is_ts_option_unset(const char *optname)
6482 struct option *opt;
6483 const char *val;
6485 opt = optset_option_by_name(client_optset, optname);
6487 if (opt == NULL) {
6488 return TRUE;
6491 val = opt->str_vtable->get(opt);
6493 if (val == NULL || val[0] == '\0') {
6494 return TRUE;
6497 return FALSE;
6500 /****************************************************************************
6501 Fill default tilesets for topology-specific settings.
6502 ****************************************************************************/
6503 void fill_topo_ts_default(void)
6505 if (is_ts_option_unset("default_tileset_overhead_name")) {
6506 log_debug("Setting tileset for overhead topology.");
6507 tilespec_try_read(NULL, FALSE, 0, FALSE);
6509 if (is_ts_option_unset("default_tileset_iso_name")) {
6510 log_debug("Setting tileset for iso topology.");
6511 tilespec_try_read(NULL, FALSE, TF_ISO, FALSE);
6513 if (is_ts_option_unset("default_tileset_hex_name")) {
6514 log_debug("Setting tileset for hex topology.");
6515 tilespec_try_read(NULL, FALSE, TF_HEX, FALSE);
6517 if (is_ts_option_unset("default_tileset_isohex_name")) {
6518 log_debug("Setting tileset for isohex topology.");
6519 tilespec_try_read(NULL, FALSE, TF_ISO | TF_HEX, FALSE);