Stop sharing requirement_unit_state_ereq().
[freeciv.git] / client / options.c
blob447962fce100af313b0d8be821a7515b45c7f614
1 /***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12 ***********************************************************************/
14 #ifdef HAVE_CONFIG_H
15 #include <fc_config.h>
16 #endif
18 #include <stdarg.h>
19 #include <string.h>
20 #include <sys/stat.h>
21 #include <sys/types.h>
23 /* utility */
24 #include "fcintl.h"
25 #include "ioz.h"
26 #include "log.h"
27 #include "mem.h"
28 #include "registry.h"
29 #include "shared.h"
30 #include "string_vector.h"
31 #include "support.h"
33 /* common */
34 #include "events.h"
35 #include "version.h"
37 /* client/agents */
38 #include "cma_fec.h"
40 /* client/include */
41 #include "chatline_g.h"
42 #include "dialogs_g.h"
43 #include "gui_main_g.h"
44 #include "menu_g.h"
45 #include "optiondlg_g.h"
46 #include "repodlgs_g.h"
47 #include "voteinfo_bar_g.h"
49 /* client */
50 #include "audio.h"
51 #include "cityrepdata.h"
52 #include "client_main.h"
53 #include "climisc.h"
54 #include "connectdlg_common.h"
55 #include "global_worklist.h"
56 #include "mapview_common.h"
57 #include "music.h"
58 #include "overview_common.h"
59 #include "packhand_gen.h"
60 #include "plrdlg_common.h"
61 #include "repodlgs_common.h"
62 #include "servers.h"
63 #include "themes_common.h"
64 #include "tilespec.h"
66 #include "options.h"
69 struct client_options gui_options = {
70 /** Defaults for options normally on command line **/
72 .default_user_name = "\0",
73 .default_server_host = "localhost",
74 .default_server_port = DEFAULT_SOCK_PORT,
75 .default_metaserver = DEFAULT_METASERVER_OPTION,
76 .default_tileset_overhead_name = "\0",
77 .default_tileset_iso_name = "\0",
78 .default_tileset_hex_name = "\0",
79 .default_tileset_isohex_name = "\0",
80 .default_sound_set_name = "stdsounds",
81 .default_music_set_name = "stdmusic",
82 .default_sound_plugin_name = "\0",
83 .default_chat_logfile = GUI_DEFAULT_CHAT_LOGFILE,
85 .save_options_on_exit = TRUE,
87 .use_prev_server = FALSE,
88 .heartbeat_enabled = FALSE,
90 /** Migrations **/
91 .first_boot = FALSE,
92 .default_tileset_name = "\0",
93 .gui_gtk3_migrated_from_gtk2 = FALSE,
94 .gui_gtk3_22_migrated_from_gtk3 = FALSE,
95 .gui_gtk4_migrated_from_gtk3_22 = FALSE,
96 .gui_sdl2_migrated_from_sdl = FALSE,
97 .gui_gtk2_migrated_from_2_5 = FALSE,
98 .gui_gtk3_migrated_from_2_5 = FALSE,
99 .gui_qt_migrated_from_2_5 = FALSE,
101 .migrate_fullscreen = FALSE,
103 /** Local Options: **/
105 .solid_color_behind_units = FALSE,
106 .sound_bell_at_new_turn = FALSE,
107 .smooth_move_unit_msec = 30,
108 .smooth_center_slide_msec = 200,
109 .smooth_combat_step_msec = 10,
110 .ai_manual_turn_done = TRUE,
111 .auto_center_on_unit = TRUE,
112 .auto_center_on_automated = TRUE,
113 .auto_center_on_combat = FALSE,
114 .auto_center_each_turn = TRUE,
115 .wakeup_focus = TRUE,
116 .goto_into_unknown = TRUE,
117 .center_when_popup_city = TRUE,
118 .show_previous_turn_messages = TRUE,
119 .concise_city_production = FALSE,
120 .auto_turn_done = FALSE,
121 .meta_accelerators = TRUE,
122 .ask_city_name = TRUE,
123 .popup_new_cities = TRUE,
124 .popup_actor_arrival = TRUE,
125 .popup_attack_actions = TRUE,
126 .keyboardless_goto = TRUE,
127 .enable_cursor_changes = TRUE,
128 .separate_unit_selection = FALSE,
129 .unit_selection_clears_orders = TRUE,
130 .highlight_our_names = FT_COLOR("#000000", "#FFFF00"),
132 .voteinfo_bar_use = TRUE,
133 .voteinfo_bar_always_show = FALSE,
134 .voteinfo_bar_hide_when_not_player = FALSE,
135 .voteinfo_bar_new_at_front = FALSE,
137 .autoaccept_tileset_suggestion = FALSE,
138 .autoaccept_soundset_suggestion = FALSE,
139 .autoaccept_musicset_suggestion = FALSE,
141 .sound_enable_effects = TRUE,
142 .sound_enable_menu_music = TRUE,
143 .sound_enable_game_music = TRUE,
145 /* This option is currently set by the client - not by the user. */
146 .update_city_text_in_refresh_tile = TRUE,
148 .draw_city_outlines = TRUE,
149 .draw_city_output = FALSE,
150 .draw_map_grid = FALSE,
151 .draw_city_names = TRUE,
152 .draw_city_growth = TRUE,
153 .draw_city_productions = TRUE,
154 .draw_city_buycost = FALSE,
155 .draw_city_trade_routes = FALSE,
156 .draw_terrain = TRUE,
157 .draw_coastline = FALSE,
158 .draw_roads_rails = TRUE,
159 .draw_irrigation = TRUE,
160 .draw_mines = TRUE,
161 .draw_fortress_airbase = TRUE,
162 .draw_specials = TRUE,
163 .draw_huts = TRUE,
164 .draw_pollution = TRUE,
165 .draw_cities = TRUE,
166 .draw_units = TRUE,
167 .draw_focus_unit = FALSE,
168 .draw_fog_of_war = TRUE,
169 .draw_borders = TRUE,
170 .draw_native = FALSE,
171 .draw_full_citybar = TRUE,
172 .draw_unit_shields = TRUE,
173 .player_dlg_show_dead_players = TRUE,
174 .reqtree_show_icons = TRUE,
175 .reqtree_curved_lines = FALSE,
177 /* options for map images */
178 /* .mapimg_format, */
179 .mapimg_zoom = 2,
180 /* See the definition of MAPIMG_LAYER in mapimg.h. */
181 .mapimg_layer = {
182 FALSE, /* a - MAPIMG_LAYER_AREA */
183 TRUE, /* b - MAPIMG_LAYER_BORDERS */
184 TRUE, /* c - MAPIMG_LAYER_CITIES */
185 TRUE, /* f - MAPIMG_LAYER_FOGOFWAR */
186 TRUE, /* k - MAPIMG_LAYER_KNOWLEDGE */
187 TRUE, /* t - MAPIMG_LAYER_TERRAIN */
188 TRUE /* u - MAPIMG_LAYER_UNITS */
190 /* .mapimg_filename, */
192 .zoom_set = FALSE,
193 .zoom_default_level = 1.0,
195 /* gui-gtk-2.0 client specific options. */
196 .gui_gtk2_default_theme_name = FC_GTK2_DEFAULT_THEME_NAME,
197 .gui_gtk2_fullscreen = FALSE,
198 .gui_gtk2_map_scrollbars = FALSE,
199 .gui_gtk2_dialogs_on_top = TRUE,
200 .gui_gtk2_show_task_icons = TRUE,
201 .gui_gtk2_enable_tabs = TRUE,
202 .gui_gtk2_better_fog = TRUE,
203 .gui_gtk2_show_chat_message_time = FALSE,
204 .gui_gtk2_new_messages_go_to_top = FALSE,
205 .gui_gtk2_show_message_window_buttons = TRUE,
206 .gui_gtk2_metaserver_tab_first = FALSE,
207 .gui_gtk2_allied_chat_only = FALSE,
208 .gui_gtk2_message_chat_location = GUI_GTK_MSGCHAT_MERGED,
209 .gui_gtk2_small_display_layout = TRUE,
210 .gui_gtk2_mouse_over_map_focus = FALSE,
211 .gui_gtk2_chatline_autocompletion = TRUE,
212 .gui_gtk2_citydlg_xsize = GUI_GTK2_CITYDLG_DEFAULT_XSIZE,
213 .gui_gtk2_citydlg_ysize = GUI_GTK2_CITYDLG_DEFAULT_YSIZE,
214 .gui_gtk2_popup_tech_help = GUI_POPUP_TECH_HELP_RULESET,
215 .gui_gtk2_font_city_label = "Monospace 8",
216 .gui_gtk2_font_notify_label = "Monospace Bold 9",
217 .gui_gtk2_font_spaceship_label = "Monospace 8",
218 .gui_gtk2_font_help_label = "Sans Bold 10",
219 .gui_gtk2_font_help_link = "Sans 9",
220 .gui_gtk2_font_help_text = "Monospace 8",
221 .gui_gtk2_font_chatline = "Monospace 8",
222 .gui_gtk2_font_beta_label = "Sans Italic 10",
223 .gui_gtk2_font_small = "Sans 9",
224 .gui_gtk2_font_comment_label = "Sans Italic 9",
225 .gui_gtk2_font_city_names = "Sans Bold 10",
226 .gui_gtk2_font_city_productions = "Serif 10",
227 .gui_gtk2_font_reqtree_text = "Serif 10",
229 /* gui-gtk-3.0 client specific options. */
230 .gui_gtk3_default_theme_name = FC_GTK3_DEFAULT_THEME_NAME,
231 .gui_gtk3_fullscreen = FALSE,
232 .gui_gtk3_map_scrollbars = FALSE,
233 .gui_gtk3_dialogs_on_top = TRUE,
234 .gui_gtk3_show_task_icons = TRUE,
235 .gui_gtk3_enable_tabs = TRUE,
236 .gui_gtk3_show_chat_message_time = FALSE,
237 .gui_gtk3_new_messages_go_to_top = FALSE,
238 .gui_gtk3_show_message_window_buttons = TRUE,
239 .gui_gtk3_metaserver_tab_first = FALSE,
240 .gui_gtk3_allied_chat_only = FALSE,
241 .gui_gtk3_message_chat_location = GUI_GTK_MSGCHAT_MERGED,
242 .gui_gtk3_small_display_layout = TRUE,
243 .gui_gtk3_mouse_over_map_focus = FALSE,
244 .gui_gtk3_chatline_autocompletion = TRUE,
245 .gui_gtk3_citydlg_xsize = GUI_GTK3_CITYDLG_DEFAULT_XSIZE,
246 .gui_gtk3_citydlg_ysize = GUI_GTK3_CITYDLG_DEFAULT_YSIZE,
247 .gui_gtk3_popup_tech_help = GUI_POPUP_TECH_HELP_RULESET,
248 .gui_gtk3_governor_range_min = -20,
249 .gui_gtk3_governor_range_max = 20,
250 .gui_gtk3_font_city_label = "Monospace 8",
251 .gui_gtk3_font_notify_label = "Monospace Bold 9",
252 .gui_gtk3_font_spaceship_label = "Monospace 8",
253 .gui_gtk3_font_help_label = "Sans Bold 10",
254 .gui_gtk3_font_help_link = "Sans 9",
255 .gui_gtk3_font_help_text = "Monospace 8",
256 .gui_gtk3_font_chatline = "Monospace 8",
257 .gui_gtk3_font_beta_label = "Sans Italic 10",
258 .gui_gtk3_font_small = "Sans 9",
259 .gui_gtk3_font_comment_label = "Sans Italic 9",
260 .gui_gtk3_font_city_names = "Sans Bold 10",
261 .gui_gtk3_font_city_productions = "Serif 10",
262 .gui_gtk3_font_reqtree_text = "Serif 10",
264 /* gui-gtk-3.22 client specific options. */
265 .gui_gtk3_22_default_theme_name = FC_GTK3_22_DEFAULT_THEME_NAME,
266 .gui_gtk3_22_fullscreen = FALSE,
267 .gui_gtk3_22_map_scrollbars = FALSE,
268 .gui_gtk3_22_dialogs_on_top = TRUE,
269 .gui_gtk3_22_show_task_icons = TRUE,
270 .gui_gtk3_22_enable_tabs = TRUE,
271 .gui_gtk3_22_show_chat_message_time = FALSE,
272 .gui_gtk3_22_new_messages_go_to_top = FALSE,
273 .gui_gtk3_22_show_message_window_buttons = TRUE,
274 .gui_gtk3_22_metaserver_tab_first = FALSE,
275 .gui_gtk3_22_allied_chat_only = FALSE,
276 .gui_gtk3_22_message_chat_location = GUI_GTK_MSGCHAT_MERGED,
277 .gui_gtk3_22_small_display_layout = TRUE,
278 .gui_gtk3_22_mouse_over_map_focus = FALSE,
279 .gui_gtk3_22_chatline_autocompletion = TRUE,
280 .gui_gtk3_22_citydlg_xsize = GUI_GTK3_22_CITYDLG_DEFAULT_XSIZE,
281 .gui_gtk3_22_citydlg_ysize = GUI_GTK3_22_CITYDLG_DEFAULT_YSIZE,
282 .gui_gtk3_22_popup_tech_help = GUI_POPUP_TECH_HELP_RULESET,
283 .gui_gtk3_22_governor_range_min = -20,
284 .gui_gtk3_22_governor_range_max = 20,
285 .gui_gtk3_22_font_city_label = "Monospace 8",
286 .gui_gtk3_22_font_notify_label = "Monospace Bold 9",
287 .gui_gtk3_22_font_spaceship_label = "Monospace 8",
288 .gui_gtk3_22_font_help_label = "Sans Bold 10",
289 .gui_gtk3_22_font_help_link = "Sans 9",
290 .gui_gtk3_22_font_help_text = "Monospace 8",
291 .gui_gtk3_22_font_chatline = "Monospace 8",
292 .gui_gtk3_22_font_beta_label = "Sans Italic 10",
293 .gui_gtk3_22_font_small = "Sans 9",
294 .gui_gtk3_22_font_comment_label = "Sans Italic 9",
295 .gui_gtk3_22_font_city_names = "Sans Bold 10",
296 .gui_gtk3_22_font_city_productions = "Serif 10",
297 .gui_gtk3_22_font_reqtree_text = "Serif 10",
299 /* gui-gtk-3.x client specific options. */
300 .gui_gtk4_default_theme_name = FC_GTK4_DEFAULT_THEME_NAME,
301 .gui_gtk4_fullscreen = FALSE,
302 .gui_gtk4_map_scrollbars = FALSE,
303 .gui_gtk4_dialogs_on_top = TRUE,
304 .gui_gtk4_show_task_icons = TRUE,
305 .gui_gtk4_enable_tabs = TRUE,
306 .gui_gtk4_show_chat_message_time = FALSE,
307 .gui_gtk4_new_messages_go_to_top = FALSE,
308 .gui_gtk4_show_message_window_buttons = TRUE,
309 .gui_gtk4_metaserver_tab_first = FALSE,
310 .gui_gtk4_allied_chat_only = FALSE,
311 .gui_gtk4_message_chat_location = GUI_GTK_MSGCHAT_MERGED,
312 .gui_gtk4_small_display_layout = TRUE,
313 .gui_gtk4_mouse_over_map_focus = FALSE,
314 .gui_gtk4_chatline_autocompletion = TRUE,
315 .gui_gtk4_citydlg_xsize = GUI_GTK4_CITYDLG_DEFAULT_XSIZE,
316 .gui_gtk4_citydlg_ysize = GUI_GTK4_CITYDLG_DEFAULT_YSIZE,
317 .gui_gtk4_popup_tech_help = GUI_POPUP_TECH_HELP_RULESET,
318 .gui_gtk4_governor_range_min = -20,
319 .gui_gtk4_governor_range_max = 20,
320 .gui_gtk4_font_city_label = "Monospace 8",
321 .gui_gtk4_font_notify_label = "Monospace Bold 9",
322 .gui_gtk4_font_spaceship_label = "Monospace 8",
323 .gui_gtk4_font_help_label = "Sans Bold 10",
324 .gui_gtk4_font_help_link = "Sans 9",
325 .gui_gtk4_font_help_text = "Monospace 8",
326 .gui_gtk4_font_chatline = "Monospace 8",
327 .gui_gtk4_font_beta_label = "Sans Italic 10",
328 .gui_gtk4_font_small = "Sans 9",
329 .gui_gtk4_font_comment_label = "Sans Italic 9",
330 .gui_gtk4_font_city_names = "Sans Bold 10",
331 .gui_gtk4_font_city_productions = "Serif 10",
332 .gui_gtk4_font_reqtree_text = "Serif 10",
334 /* gui-sdl client specific options. */
335 .gui_sdl_fullscreen = FALSE,
336 .gui_sdl_screen = VIDEO_MODE(640, 480),
337 .gui_sdl_do_cursor_animation = TRUE,
338 .gui_sdl_use_color_cursors = TRUE,
340 /* gui-sdl2 client specific options. */
341 .gui_sdl2_default_theme_name = FC_SDL2_DEFAULT_THEME_NAME,
342 .gui_sdl2_fullscreen = FALSE,
343 .gui_sdl2_screen = VIDEO_MODE(640, 480),
344 .gui_sdl2_swrenderer = FALSE,
345 .gui_sdl2_do_cursor_animation = TRUE,
346 .gui_sdl2_use_color_cursors = TRUE,
348 /* gui-qt client specific options. */
349 .gui_qt_fullscreen = FALSE,
350 .gui_qt_show_preview = TRUE,
351 .gui_qt_sidebar_left = TRUE,
352 .gui_qt_default_theme_name = FC_QT_DEFAULT_THEME_NAME,
353 .gui_qt_font_city_label = "Monospace,8,-1,5,50,0,0,0,0,0",
354 .gui_qt_font_default = "Sans Serif,10,-1,5,75,0,0,0,0,0",
355 .gui_qt_font_notify_label = "Monospace,8,-1,5,75,0,0,0,0,0",
356 .gui_qt_font_spaceship_label = "Monospace,8,-1,5,50,0,0,0,0,0",
357 .gui_qt_font_help_label = "Sans Serif,9,-1,5,50,0,0,0,0,0",
358 .gui_qt_font_help_link = "Sans Serif,9,-1,5,50,0,0,0,0,0",
359 .gui_qt_font_help_text = "Monospace,8,-1,5,50,0,0,0,0,0",
360 .gui_qt_font_help_title = "Sans Serif,10,-1,5,75,0,0,0,0,0",
361 .gui_qt_font_chatline = "Monospace,8,-1,5,50,0,0,0,0,0",
362 .gui_qt_font_beta_label = "Sans Serif,10,-1,5,50,1,0,0,0,0",
363 .gui_qt_font_small = "Sans Serif,9,-1,5,50,0,0,0,0,0",
364 .gui_qt_font_comment_label = "Sans Serif,9,-1,5,50,1,0,0,0,0",
365 .gui_qt_font_city_names = "Sans Serif,10,-1,5,75,0,0,0,0,0",
366 .gui_qt_font_city_productions = "Sans Serif,10,-1,5,50,1,0,0,0,0",
367 .gui_qt_font_reqtree_text = "Sans Serif,10,-1,5,50,1,0,0,0,0",
368 .gui_qt_show_titlebar = TRUE,
369 .gui_qt_wakeup_text = "Wake up %1"
372 /* Set to TRUE after the first call to options_init(), to avoid the usage
373 * of non-initialized datas when calling the changed callback. */
374 static bool options_fully_initialized = FALSE;
376 static const struct strvec *get_mapimg_format_list(const struct option *poption);
378 /****************************************************************************
379 Option set structure.
380 ****************************************************************************/
381 struct option_set {
382 struct option * (*option_by_number) (int);
383 struct option * (*option_first) (void);
385 int (*category_number) (void);
386 const char * (*category_name) (int);
389 /****************************************************************************
390 Returns the option corresponding of the number in this option set.
391 ****************************************************************************/
392 struct option *optset_option_by_number(const struct option_set *poptset,
393 int id)
395 fc_assert_ret_val(NULL != poptset, NULL);
397 return poptset->option_by_number(id);
400 /****************************************************************************
401 Returns the option corresponding of the name in this option set.
402 ****************************************************************************/
403 struct option *optset_option_by_name(const struct option_set *poptset,
404 const char *name)
406 fc_assert_ret_val(NULL != poptset, NULL);
408 options_iterate(poptset, poption) {
409 if (0 == strcmp(option_name(poption), name)) {
410 return poption;
412 } options_iterate_end;
413 return NULL;
416 /****************************************************************************
417 Returns the first option of this option set.
418 ****************************************************************************/
419 struct option *optset_option_first(const struct option_set *poptset)
421 fc_assert_ret_val(NULL != poptset, NULL);
423 return poptset->option_first();
426 /****************************************************************************
427 Returns the number of categories of this option set.
428 ****************************************************************************/
429 int optset_category_number(const struct option_set *poptset)
431 fc_assert_ret_val(NULL != poptset, 0);
433 return poptset->category_number();
436 /****************************************************************************
437 Returns the name (translated) of the category of this option set.
438 ****************************************************************************/
439 const char *optset_category_name(const struct option_set *poptset,
440 int category)
442 fc_assert_ret_val(NULL != poptset, NULL);
444 return poptset->category_name(category);
448 /****************************************************************************
449 The base class for options.
450 ****************************************************************************/
451 struct option {
452 /* A link to the option set. */
453 const struct option_set *poptset;
454 /* Type of the option. */
455 enum option_type type;
457 /* Common accessors. */
458 const struct option_common_vtable {
459 int (*number) (const struct option *);
460 const char * (*name) (const struct option *);
461 const char * (*description) (const struct option *);
462 const char * (*help_text) (const struct option *);
463 int (*category) (const struct option *);
464 bool (*is_changeable) (const struct option *);
465 struct option * (*next) (const struct option *);
466 } *common_vtable;
467 /* Specific typed accessors. */
468 union {
469 /* Specific boolean accessors (OT_BOOLEAN == type). */
470 const struct option_bool_vtable {
471 bool (*get) (const struct option *);
472 bool (*def) (const struct option *);
473 bool (*set) (struct option *, bool);
474 } *bool_vtable;
475 /* Specific integer accessors (OT_INTEGER == type). */
476 const struct option_int_vtable {
477 int (*get) (const struct option *);
478 int (*def) (const struct option *);
479 int (*minimum) (const struct option *);
480 int (*maximum) (const struct option *);
481 bool (*set) (struct option *, int);
482 } *int_vtable;
483 /* Specific string accessors (OT_STRING == type). */
484 const struct option_str_vtable {
485 const char * (*get) (const struct option *);
486 const char * (*def) (const struct option *);
487 const struct strvec * (*values) (const struct option *);
488 bool (*set) (struct option *, const char *);
489 } *str_vtable;
490 /* Specific enum accessors (OT_ENUM == type). */
491 const struct option_enum_vtable {
492 int (*get) (const struct option *);
493 int (*def) (const struct option *);
494 const struct strvec * (*values) (const struct option *);
495 bool (*set) (struct option *, int);
496 int (*cmp) (const char *, const char *);
497 } *enum_vtable;
498 /* Specific bitwise accessors (OT_BITWISE == type). */
499 const struct option_bitwise_vtable {
500 unsigned (*get) (const struct option *);
501 unsigned (*def) (const struct option *);
502 const struct strvec * (*values) (const struct option *);
503 bool (*set) (struct option *, unsigned);
504 } *bitwise_vtable;
505 /* Specific font accessors (OT_FONT == type). */
506 const struct option_font_vtable {
507 const char * (*get) (const struct option *);
508 const char * (*def) (const struct option *);
509 const char * (*target) (const struct option *);
510 bool (*set) (struct option *, const char *);
511 } *font_vtable;
512 /* Specific color accessors (OT_COLOR == type). */
513 const struct option_color_vtable {
514 struct ft_color (*get) (const struct option *);
515 struct ft_color (*def) (const struct option *);
516 bool (*set) (struct option *, struct ft_color);
517 } *color_vtable;
518 /* Specific video mode accessors (OT_VIDEO_MODE == type). */
519 const struct option_video_mode_vtable {
520 struct video_mode (*get) (const struct option *);
521 struct video_mode (*def) (const struct option *);
522 bool (*set) (struct option *, struct video_mode);
523 } *video_mode_vtable;
526 /* Called after the value changed. */
527 void (*changed_callback) (struct option *option);
529 int callback_data;
531 /* Volatile. */
532 void *gui_data;
535 #define OPTION(poption) ((struct option *) (poption))
537 #define OPTION_INIT(optset, spec_type, spec_table_var, common_table, \
538 spec_table, changed_cb, cb_data) { \
539 .poptset = optset, \
540 .type = spec_type, \
541 .common_vtable = &common_table, \
542 INIT_BRACE_BEGIN \
543 .spec_table_var = &spec_table \
544 INIT_BRACE_END, \
545 .changed_callback = changed_cb, \
546 .callback_data = cb_data, \
547 .gui_data = NULL \
549 #define OPTION_BOOL_INIT(optset, common_table, bool_table, changed_cb) \
550 OPTION_INIT(optset, OT_BOOLEAN, bool_vtable, common_table, bool_table, \
551 changed_cb, 0)
552 #define OPTION_INT_INIT(optset, common_table, int_table, changed_cb) \
553 OPTION_INIT(optset, OT_INTEGER, int_vtable, common_table, int_table, \
554 changed_cb, 0)
555 #define OPTION_STR_INIT(optset, common_table, str_table, changed_cb, cb_data) \
556 OPTION_INIT(optset, OT_STRING, str_vtable, common_table, str_table, \
557 changed_cb, cb_data)
558 #define OPTION_ENUM_INIT(optset, common_table, enum_table, changed_cb) \
559 OPTION_INIT(optset, OT_ENUM, enum_vtable, common_table, enum_table, \
560 changed_cb, 0)
561 #define OPTION_BITWISE_INIT(optset, common_table, bitwise_table, \
562 changed_cb) \
563 OPTION_INIT(optset, OT_BITWISE, bitwise_vtable, common_table, \
564 bitwise_table, changed_cb, 0)
565 #define OPTION_FONT_INIT(optset, common_table, font_table, changed_cb) \
566 OPTION_INIT(optset, OT_FONT, font_vtable, common_table, font_table, \
567 changed_cb, 0)
568 #define OPTION_COLOR_INIT(optset, common_table, color_table, changed_cb) \
569 OPTION_INIT(optset, OT_COLOR, color_vtable, common_table, color_table, \
570 changed_cb, 0)
571 #define OPTION_VIDEO_MODE_INIT(optset, common_table, video_mode_table, \
572 changed_cb) \
573 OPTION_INIT(optset, OT_VIDEO_MODE, video_mode_vtable, common_table, \
574 video_mode_table, changed_cb, 0)
577 /****************************************************************************
578 Returns the option set owner of this option.
579 ****************************************************************************/
580 const struct option_set *option_optset(const struct option *poption)
582 fc_assert_ret_val(NULL != poption, NULL);
584 return poption->poptset;
587 /****************************************************************************
588 Returns the number of the option.
589 ****************************************************************************/
590 int option_number(const struct option *poption)
592 fc_assert_ret_val(NULL != poption, -1);
594 return poption->common_vtable->number(poption);
597 /****************************************************************************
598 Returns the name of the option.
599 ****************************************************************************/
600 const char *option_name(const struct option *poption)
602 fc_assert_ret_val(NULL != poption, NULL);
604 return poption->common_vtable->name(poption);
607 /****************************************************************************
608 Returns the description (translated) of the option.
609 ****************************************************************************/
610 const char *option_description(const struct option *poption)
612 fc_assert_ret_val(NULL != poption, NULL);
614 return poption->common_vtable->description(poption);
617 /****************************************************************************
618 Returns the help text (translated) of the option.
619 ****************************************************************************/
620 const char *option_help_text(const struct option *poption)
622 fc_assert_ret_val(NULL != poption, NULL);
624 return poption->common_vtable->help_text(poption);
627 /****************************************************************************
628 Returns the type of the option.
629 ****************************************************************************/
630 enum option_type option_type(const struct option *poption)
632 fc_assert_ret_val(NULL != poption, -1);
634 return poption->type;
637 /****************************************************************************
638 Returns the category of the option.
639 ****************************************************************************/
640 int option_category(const struct option *poption)
642 fc_assert_ret_val(NULL != poption, -1);
644 return poption->common_vtable->category(poption);
647 /****************************************************************************
648 Returns the name (tranlated) of the category of the option.
649 ****************************************************************************/
650 const char *option_category_name(const struct option *poption)
652 fc_assert_ret_val(NULL != poption, NULL);
654 return optset_category_name(poption->poptset,
655 poption->common_vtable->category(poption));
658 /****************************************************************************
659 Returns TRUE if this option can be modified.
660 ****************************************************************************/
661 bool option_is_changeable(const struct option *poption)
663 fc_assert_ret_val(NULL != poption, FALSE);
665 return poption->common_vtable->is_changeable(poption);
668 /****************************************************************************
669 Returns the next option or NULL if this is the last.
670 ****************************************************************************/
671 struct option *option_next(const struct option *poption)
673 fc_assert_ret_val(NULL != poption, NULL);
675 return poption->common_vtable->next(poption);
678 /****************************************************************************
679 Set the option to its default value. Returns TRUE if the option changed.
680 ****************************************************************************/
681 bool option_reset(struct option *poption)
683 fc_assert_ret_val(NULL != poption, FALSE);
685 switch (option_type(poption)) {
686 case OT_BOOLEAN:
687 return option_bool_set(poption, option_bool_def(poption));
688 case OT_INTEGER:
689 return option_int_set(poption, option_int_def(poption));
690 case OT_STRING:
691 return option_str_set(poption, option_str_def(poption));
692 case OT_ENUM:
693 return option_enum_set_int(poption, option_enum_def_int(poption));
694 case OT_BITWISE:
695 return option_bitwise_set(poption, option_bitwise_def(poption));
696 case OT_FONT:
697 return option_font_set(poption, option_font_def(poption));
698 case OT_COLOR:
699 return option_color_set(poption, option_color_def(poption));
700 case OT_VIDEO_MODE:
701 return option_video_mode_set(poption, option_video_mode_def(poption));
703 return FALSE;
706 /****************************************************************************
707 Set the function to call every time this option changes. Can be NULL.
708 ****************************************************************************/
709 void option_set_changed_callback(struct option *poption,
710 void (*callback) (struct option *))
712 fc_assert_ret(NULL != poption);
714 poption->changed_callback = callback;
717 /****************************************************************************
718 Force to use the option changed callback.
719 ****************************************************************************/
720 void option_changed(struct option *poption)
722 fc_assert_ret(NULL != poption);
724 if (!options_fully_initialized) {
725 /* Prevent to use non-initialized datas. */
726 return;
729 if (poption->changed_callback) {
730 poption->changed_callback(poption);
733 option_gui_update(poption);
736 /****************************************************************************
737 Set the gui data for this option.
738 ****************************************************************************/
739 void option_set_gui_data(struct option *poption, void *data)
741 fc_assert_ret(NULL != poption);
743 poption->gui_data = data;
746 /****************************************************************************
747 Returns the gui data of this option.
748 ****************************************************************************/
749 void *option_get_gui_data(const struct option *poption)
751 fc_assert_ret_val(NULL != poption, NULL);
753 return poption->gui_data;
756 /****************************************************************************
757 Returns the callback data of this option.
758 ****************************************************************************/
759 int option_get_cb_data(const struct option *poption)
761 fc_assert_ret_val(NULL != poption, 0);
763 return poption->callback_data;
766 /****************************************************************************
767 Returns the current value of this boolean option.
768 ****************************************************************************/
769 bool option_bool_get(const struct option *poption)
771 fc_assert_ret_val(NULL != poption, FALSE);
772 fc_assert_ret_val(OT_BOOLEAN == poption->type, FALSE);
774 return poption->bool_vtable->get(poption);
777 /****************************************************************************
778 Returns the default value of this boolean option.
779 ****************************************************************************/
780 bool option_bool_def(const struct option *poption)
782 fc_assert_ret_val(NULL != poption, FALSE);
783 fc_assert_ret_val(OT_BOOLEAN == poption->type, FALSE);
785 return poption->bool_vtable->def(poption);
788 /****************************************************************************
789 Sets the value of this boolean option. Returns TRUE if the value changed.
790 ****************************************************************************/
791 bool option_bool_set(struct option *poption, bool val)
793 fc_assert_ret_val(NULL != poption, FALSE);
794 fc_assert_ret_val(OT_BOOLEAN == poption->type, FALSE);
796 if (poption->bool_vtable->set(poption, val)) {
797 option_changed(poption);
798 return TRUE;
800 return FALSE;
803 /****************************************************************************
804 Returns the current value of this integer option.
805 ****************************************************************************/
806 int option_int_get(const struct option *poption)
808 fc_assert_ret_val(NULL != poption, 0);
809 fc_assert_ret_val(OT_INTEGER == poption->type, 0);
811 return poption->int_vtable->get(poption);
814 /****************************************************************************
815 Returns the default value of this integer option.
816 ****************************************************************************/
817 int option_int_def(const struct option *poption)
819 fc_assert_ret_val(NULL != poption, 0);
820 fc_assert_ret_val(OT_INTEGER == poption->type, 0);
822 return poption->int_vtable->def(poption);
825 /****************************************************************************
826 Returns the minimal value of this integer option.
827 ****************************************************************************/
828 int option_int_min(const struct option *poption)
830 fc_assert_ret_val(NULL != poption, 0);
831 fc_assert_ret_val(OT_INTEGER == poption->type, 0);
833 return poption->int_vtable->minimum(poption);
836 /****************************************************************************
837 Returns the maximal value of this integer option.
838 ****************************************************************************/
839 int option_int_max(const struct option *poption)
841 fc_assert_ret_val(NULL != poption, 0);
842 fc_assert_ret_val(OT_INTEGER == poption->type, 0);
844 return poption->int_vtable->maximum(poption);
847 /****************************************************************************
848 Sets the value of this integer option. Returns TRUE if the value changed.
849 ****************************************************************************/
850 bool option_int_set(struct option *poption, int val)
852 fc_assert_ret_val(NULL != poption, FALSE);
853 fc_assert_ret_val(OT_INTEGER == poption->type, FALSE);
855 if (poption->int_vtable->set(poption, val)) {
856 option_changed(poption);
857 return TRUE;
859 return FALSE;
862 /****************************************************************************
863 Returns the current value of this string option.
864 ****************************************************************************/
865 const char *option_str_get(const struct option *poption)
867 fc_assert_ret_val(NULL != poption, NULL);
868 fc_assert_ret_val(OT_STRING == poption->type, NULL);
870 return poption->str_vtable->get(poption);
873 /****************************************************************************
874 Returns the default value of this string option.
875 ****************************************************************************/
876 const char *option_str_def(const struct option *poption)
878 fc_assert_ret_val(NULL != poption, NULL);
879 fc_assert_ret_val(OT_STRING == poption->type, NULL);
881 return poption->str_vtable->def(poption);
884 /****************************************************************************
885 Returns the possible string values of this string option.
886 ****************************************************************************/
887 const struct strvec *option_str_values(const struct option *poption)
889 fc_assert_ret_val(NULL != poption, NULL);
890 fc_assert_ret_val(OT_STRING == poption->type, NULL);
892 return poption->str_vtable->values(poption);
895 /****************************************************************************
896 Sets the value of this string option. Returns TRUE if the value changed.
897 ****************************************************************************/
898 bool option_str_set(struct option *poption, const char *str)
900 fc_assert_ret_val(NULL != poption, FALSE);
901 fc_assert_ret_val(OT_STRING == poption->type, FALSE);
902 fc_assert_ret_val(NULL != str, FALSE);
904 if (poption->str_vtable->set(poption, str)) {
905 option_changed(poption);
906 return TRUE;
908 return FALSE;
911 /****************************************************************************
912 Returns the value corresponding to the user-visible (translatable but not
913 translated) string. Returns -1 if not matched.
914 ****************************************************************************/
915 int option_enum_str_to_int(const struct option *poption, const char *str)
917 const struct strvec *values;
918 int val;
920 fc_assert_ret_val(NULL != poption, -1);
921 fc_assert_ret_val(OT_ENUM == poption->type, -1);
922 values = poption->enum_vtable->values(poption);
923 fc_assert_ret_val(NULL != values, -1);
925 for (val = 0; val < strvec_size(values); val++) {
926 if (0 == poption->enum_vtable->cmp(strvec_get(values, val), str)) {
927 return val;
930 return -1;
933 /****************************************************************************
934 Returns the user-visible (translatable but not translated) string
935 corresponding to the value. Returns NULL on error.
936 ****************************************************************************/
937 const char *option_enum_int_to_str(const struct option *poption, int val)
939 const struct strvec *values;
941 fc_assert_ret_val(NULL != poption, NULL);
942 fc_assert_ret_val(OT_ENUM == poption->type, NULL);
943 values = poption->enum_vtable->values(poption);
944 fc_assert_ret_val(NULL != values, NULL);
946 return strvec_get(values, val);
949 /****************************************************************************
950 Returns the current value of this enum option (as an integer).
951 ****************************************************************************/
952 int option_enum_get_int(const struct option *poption)
954 fc_assert_ret_val(NULL != poption, -1);
955 fc_assert_ret_val(OT_ENUM == poption->type, -1);
957 return poption->enum_vtable->get(poption);
960 /****************************************************************************
961 Returns the current value of this enum option as a user-visible
962 (translatable but not translated) string.
963 ****************************************************************************/
964 const char *option_enum_get_str(const struct option *poption)
966 fc_assert_ret_val(NULL != poption, NULL);
967 fc_assert_ret_val(OT_ENUM == poption->type, NULL);
969 return strvec_get(poption->enum_vtable->values(poption),
970 poption->enum_vtable->get(poption));
973 /****************************************************************************
974 Returns the default value of this enum option (as an integer).
975 ****************************************************************************/
976 int option_enum_def_int(const struct option *poption)
978 fc_assert_ret_val(NULL != poption, -1);
979 fc_assert_ret_val(OT_ENUM == poption->type, -1);
981 return poption->enum_vtable->def(poption);
984 /****************************************************************************
985 Returns the default value of this enum option as a user-visible
986 (translatable but not translated) string.
987 ****************************************************************************/
988 const char *option_enum_def_str(const struct option *poption)
990 fc_assert_ret_val(NULL != poption, NULL);
991 fc_assert_ret_val(OT_ENUM == poption->type, NULL);
993 return strvec_get(poption->enum_vtable->values(poption),
994 poption->enum_vtable->def(poption));
997 /****************************************************************************
998 Returns the possible string values of this enum option, as user-visible
999 (translatable but not translated) strings.
1000 ****************************************************************************/
1001 const struct strvec *option_enum_values(const struct option *poption)
1003 fc_assert_ret_val(NULL != poption, NULL);
1004 fc_assert_ret_val(OT_ENUM == poption->type, NULL);
1006 return poption->enum_vtable->values(poption);
1009 /****************************************************************************
1010 Sets the value of this enum option. Returns TRUE if the value changed.
1011 ****************************************************************************/
1012 bool option_enum_set_int(struct option *poption, int val)
1014 fc_assert_ret_val(NULL != poption, FALSE);
1015 fc_assert_ret_val(OT_ENUM == poption->type, FALSE);
1017 if (poption->enum_vtable->set(poption, val)) {
1018 option_changed(poption);
1019 return TRUE;
1021 return FALSE;
1024 /****************************************************************************
1025 Sets the value of this enum option from a string, which is matched as a
1026 user-visible (translatable but not translated) string. Returns TRUE if the
1027 value changed.
1028 ****************************************************************************/
1029 bool option_enum_set_str(struct option *poption, const char *str)
1031 fc_assert_ret_val(NULL != poption, FALSE);
1032 fc_assert_ret_val(OT_ENUM == poption->type, FALSE);
1033 fc_assert_ret_val(NULL != str, FALSE);
1035 if (poption->enum_vtable->set(poption,
1036 option_enum_str_to_int(poption, str))) {
1037 option_changed(poption);
1038 return TRUE;
1040 return FALSE;
1043 /****************************************************************************
1044 Returns the current value of this bitwise option.
1045 ****************************************************************************/
1046 unsigned option_bitwise_get(const struct option *poption)
1048 fc_assert_ret_val(NULL != poption, 0);
1049 fc_assert_ret_val(OT_BITWISE == poption->type, 0);
1051 return poption->bitwise_vtable->get(poption);
1054 /****************************************************************************
1055 Returns the default value of this bitwise option.
1056 ****************************************************************************/
1057 unsigned option_bitwise_def(const struct option *poption)
1059 fc_assert_ret_val(NULL != poption, 0);
1060 fc_assert_ret_val(OT_BITWISE == poption->type, 0);
1062 return poption->bitwise_vtable->def(poption);
1065 /****************************************************************************
1066 Returns the mask of this bitwise option.
1067 ****************************************************************************/
1068 unsigned option_bitwise_mask(const struct option *poption)
1070 const struct strvec *values;
1072 fc_assert_ret_val(NULL != poption, 0);
1073 fc_assert_ret_val(OT_BITWISE == poption->type, 0);
1075 values = poption->bitwise_vtable->values(poption);
1076 fc_assert_ret_val(NULL != values, 0);
1078 return (1 << strvec_size(values)) - 1;
1081 /****************************************************************************
1082 Returns a vector of strings describing every bit of this option, as
1083 user-visible (translatable but not translated) strings.
1084 ****************************************************************************/
1085 const struct strvec *option_bitwise_values(const struct option *poption)
1087 fc_assert_ret_val(NULL != poption, NULL);
1088 fc_assert_ret_val(OT_BITWISE == poption->type, NULL);
1090 return poption->bitwise_vtable->values(poption);
1093 /****************************************************************************
1094 Sets the value of this bitwise option. Returns TRUE if the value changed.
1095 ****************************************************************************/
1096 bool option_bitwise_set(struct option *poption, unsigned val)
1098 fc_assert_ret_val(NULL != poption, FALSE);
1099 fc_assert_ret_val(OT_BITWISE == poption->type, FALSE);
1101 if (0 != (val & ~option_bitwise_mask(poption))
1102 || !poption->bitwise_vtable->set(poption, val)) {
1103 return FALSE;
1106 option_changed(poption);
1107 return TRUE;
1110 /****************************************************************************
1111 Returns the current value of this font option.
1112 ****************************************************************************/
1113 const char *option_font_get(const struct option *poption)
1115 fc_assert_ret_val(NULL != poption, NULL);
1116 fc_assert_ret_val(OT_FONT == poption->type, NULL);
1118 return poption->font_vtable->get(poption);
1121 /****************************************************************************
1122 Returns the default value of this font option.
1123 ****************************************************************************/
1124 const char *option_font_def(const struct option *poption)
1126 fc_assert_ret_val(NULL != poption, NULL);
1127 fc_assert_ret_val(OT_FONT == poption->type, NULL);
1129 return poption->font_vtable->def(poption);
1132 /****************************************************************************
1133 Returns the target style name of this font option.
1134 ****************************************************************************/
1135 const char *option_font_target(const struct option *poption)
1137 fc_assert_ret_val(NULL != poption, NULL);
1138 fc_assert_ret_val(OT_FONT == poption->type, NULL);
1140 return poption->font_vtable->target(poption);
1143 /****************************************************************************
1144 Sets the value of this font option. Returns TRUE if the value changed.
1145 ****************************************************************************/
1146 bool option_font_set(struct option *poption, const char *font)
1148 fc_assert_ret_val(NULL != poption, FALSE);
1149 fc_assert_ret_val(OT_FONT == poption->type, FALSE);
1150 fc_assert_ret_val(NULL != font, FALSE);
1152 if (poption->font_vtable->set(poption, font)) {
1153 option_changed(poption);
1154 return TRUE;
1156 return FALSE;
1159 /****************************************************************************
1160 Returns the current value of this color option.
1161 ****************************************************************************/
1162 struct ft_color option_color_get(const struct option *poption)
1164 fc_assert_ret_val(NULL != poption, ft_color_construct(NULL, NULL));
1165 fc_assert_ret_val(OT_COLOR == poption->type, ft_color_construct(NULL, NULL));
1167 return poption->color_vtable->get(poption);
1170 /****************************************************************************
1171 Returns the default value of this color option.
1172 ****************************************************************************/
1173 struct ft_color option_color_def(const struct option *poption)
1175 fc_assert_ret_val(NULL != poption, ft_color_construct(NULL, NULL));
1176 fc_assert_ret_val(OT_COLOR == poption->type, ft_color_construct(NULL, NULL));
1178 return poption->color_vtable->def(poption);
1181 /****************************************************************************
1182 Sets the value of this color option. Returns TRUE if the value
1183 changed.
1184 ****************************************************************************/
1185 bool option_color_set(struct option *poption, struct ft_color color)
1187 fc_assert_ret_val(NULL != poption, FALSE);
1188 fc_assert_ret_val(OT_COLOR == poption->type, FALSE);
1190 if (poption->color_vtable->set(poption, color)) {
1191 option_changed(poption);
1192 return TRUE;
1194 return FALSE;
1197 /****************************************************************************
1198 Returns the current value of this video mode option.
1199 ****************************************************************************/
1200 struct video_mode option_video_mode_get(const struct option *poption)
1202 fc_assert_ret_val(NULL != poption, video_mode_construct(-1, -1));
1203 fc_assert_ret_val(OT_VIDEO_MODE == poption->type,
1204 video_mode_construct(-1, -1));
1206 return poption->video_mode_vtable->get(poption);
1209 /****************************************************************************
1210 Returns the default value of this video mode option.
1211 ****************************************************************************/
1212 struct video_mode option_video_mode_def(const struct option *poption)
1214 fc_assert_ret_val(NULL != poption, video_mode_construct(-1, -1));
1215 fc_assert_ret_val(OT_VIDEO_MODE == poption->type,
1216 video_mode_construct(-1, -1));
1218 return poption->video_mode_vtable->def(poption);
1221 /****************************************************************************
1222 Sets the value of this video mode option. Returns TRUE if the value
1223 changed.
1224 ****************************************************************************/
1225 bool option_video_mode_set(struct option *poption, struct video_mode mode)
1227 fc_assert_ret_val(NULL != poption, FALSE);
1228 fc_assert_ret_val(OT_VIDEO_MODE == poption->type, FALSE);
1230 if (poption->video_mode_vtable->set(poption, mode)) {
1231 option_changed(poption);
1232 return TRUE;
1234 return FALSE;
1238 /****************************************************************************
1239 Client option set.
1240 ****************************************************************************/
1241 static struct option *client_optset_option_by_number(int id);
1242 static struct option *client_optset_option_first(void);
1243 static int client_optset_category_number(void);
1244 static const char *client_optset_category_name(int category);
1246 static struct option_set client_optset_static = {
1247 .option_by_number = client_optset_option_by_number,
1248 .option_first = client_optset_option_first,
1249 .category_number = client_optset_category_number,
1250 .category_name = client_optset_category_name
1252 const struct option_set *client_optset = &client_optset_static;
1254 struct copt_val_name {
1255 const char *support; /* Untranslated long support name, used
1256 * for saving. */
1257 const char *pretty; /* Translated, used to display to the
1258 * users. */
1261 /****************************************************************************
1262 Virtuals tables for the client options.
1263 ****************************************************************************/
1264 static int client_option_number(const struct option *poption);
1265 static const char *client_option_name(const struct option *poption);
1266 static const char *client_option_description(const struct option *poption);
1267 static const char *client_option_help_text(const struct option *poption);
1268 static int client_option_category(const struct option *poption);
1269 static bool client_option_is_changeable(const struct option *poption);
1270 static struct option *client_option_next(const struct option *poption);
1271 static void client_option_adjust_defaults(void);
1273 static const struct option_common_vtable client_option_common_vtable = {
1274 .number = client_option_number,
1275 .name = client_option_name,
1276 .description = client_option_description,
1277 .help_text = client_option_help_text,
1278 .category = client_option_category,
1279 .is_changeable = client_option_is_changeable,
1280 .next = client_option_next
1283 static bool client_option_bool_get(const struct option *poption);
1284 static bool client_option_bool_def(const struct option *poption);
1285 static bool client_option_bool_set(struct option *poption, bool val);
1287 static const struct option_bool_vtable client_option_bool_vtable = {
1288 .get = client_option_bool_get,
1289 .def = client_option_bool_def,
1290 .set = client_option_bool_set
1293 static int client_option_int_get(const struct option *poption);
1294 static int client_option_int_def(const struct option *poption);
1295 static int client_option_int_min(const struct option *poption);
1296 static int client_option_int_max(const struct option *poption);
1297 static bool client_option_int_set(struct option *poption, int val);
1299 static const struct option_int_vtable client_option_int_vtable = {
1300 .get = client_option_int_get,
1301 .def = client_option_int_def,
1302 .minimum = client_option_int_min,
1303 .maximum = client_option_int_max,
1304 .set = client_option_int_set
1307 static const char *client_option_str_get(const struct option *poption);
1308 static const char *client_option_str_def(const struct option *poption);
1309 static const struct strvec *
1310 client_option_str_values(const struct option *poption);
1311 static bool client_option_str_set(struct option *poption, const char *str);
1313 static const struct option_str_vtable client_option_str_vtable = {
1314 .get = client_option_str_get,
1315 .def = client_option_str_def,
1316 .values = client_option_str_values,
1317 .set = client_option_str_set
1320 static int client_option_enum_get(const struct option *poption);
1321 static int client_option_enum_def(const struct option *poption);
1322 static const struct strvec *
1323 client_option_enum_pretty_names(const struct option *poption);
1324 static bool client_option_enum_set(struct option *poption, int val);
1326 static const struct option_enum_vtable client_option_enum_vtable = {
1327 .get = client_option_enum_get,
1328 .def = client_option_enum_def,
1329 .values = client_option_enum_pretty_names,
1330 .set = client_option_enum_set,
1331 .cmp = fc_strcasecmp
1334 #if 0 /* There's no bitwise options currently */
1335 static unsigned client_option_bitwise_get(const struct option *poption);
1336 static unsigned client_option_bitwise_def(const struct option *poption);
1337 static const struct strvec *
1338 client_option_bitwise_pretty_names(const struct option *poption);
1339 static bool client_option_bitwise_set(struct option *poption, unsigned val);
1341 static const struct option_bitwise_vtable client_option_bitwise_vtable = {
1342 .get = client_option_bitwise_get,
1343 .def = client_option_bitwise_def,
1344 .values = client_option_bitwise_pretty_names,
1345 .set = client_option_bitwise_set
1347 #endif /* 0 */
1349 static const char *client_option_font_get(const struct option *poption);
1350 static const char *client_option_font_def(const struct option *poption);
1351 static const char *client_option_font_target(const struct option *poption);
1352 static bool client_option_font_set(struct option *poption, const char *font);
1354 static const struct option_font_vtable client_option_font_vtable = {
1355 .get = client_option_font_get,
1356 .def = client_option_font_def,
1357 .target = client_option_font_target,
1358 .set = client_option_font_set
1361 static struct ft_color client_option_color_get(const struct option *poption);
1362 static struct ft_color client_option_color_def(const struct option *poption);
1363 static bool client_option_color_set(struct option *poption,
1364 struct ft_color color);
1366 static const struct option_color_vtable client_option_color_vtable = {
1367 .get = client_option_color_get,
1368 .def = client_option_color_def,
1369 .set = client_option_color_set
1372 static struct video_mode
1373 client_option_video_mode_get(const struct option *poption);
1374 static struct video_mode
1375 client_option_video_mode_def(const struct option *poption);
1376 static bool client_option_video_mode_set(struct option *poption,
1377 struct video_mode mode);
1379 static const struct option_video_mode_vtable client_option_video_mode_vtable = {
1380 .get = client_option_video_mode_get,
1381 .def = client_option_video_mode_def,
1382 .set = client_option_video_mode_set
1385 enum client_option_category {
1386 COC_GRAPHICS,
1387 COC_OVERVIEW,
1388 COC_SOUND,
1389 COC_INTERFACE,
1390 COC_MAPIMG,
1391 COC_NETWORK,
1392 COC_FONT,
1393 COC_MAX
1396 /****************************************************************************
1397 Derived class client option, inherinting of base class option.
1398 ****************************************************************************/
1399 struct client_option {
1400 struct option base_option; /* Base structure, must be the first! */
1402 const char *name; /* Short name - used as an identifier */
1403 const char *description; /* One-line description */
1404 const char *help_text; /* Paragraph-length help text */
1405 enum client_option_category category;
1406 enum gui_type specific; /* GUI_STUB for common options. */
1408 union {
1409 /* OT_BOOLEAN type option. */
1410 struct {
1411 bool *const pvalue;
1412 const bool def;
1413 } boolean;
1414 /* OT_INTEGER type option. */
1415 struct {
1416 int *const pvalue;
1417 const int def, min, max;
1418 } integer;
1419 /* OT_STRING type option. */
1420 struct {
1421 char *const pvalue;
1422 const size_t size;
1423 const char *const def;
1425 * A function to return a string vector of possible string values,
1426 * or NULL for none.
1428 const struct strvec *(*const val_accessor) (const struct option *);
1429 } string;
1430 /* OT_ENUM type option. */
1431 struct {
1432 int *const pvalue;
1433 const int def;
1434 struct strvec *support_names, *pretty_names; /* untranslated */
1435 const struct copt_val_name * (*const name_accessor) (int value);
1436 } enumerator;
1437 /* OT_BITWISE type option. */
1438 struct {
1439 unsigned *const pvalue;
1440 const unsigned def;
1441 struct strvec *support_names, *pretty_names; /* untranslated */
1442 const struct copt_val_name * (*const name_accessor) (int value);
1443 } bitwise;
1444 /* OT_FONT type option. */
1445 struct {
1446 char *const pvalue;
1447 const size_t size;
1448 const char *const def;
1449 const char *const target;
1450 } font;
1451 /* OT_COLOR type option. */
1452 struct {
1453 struct ft_color *const pvalue;
1454 const struct ft_color def;
1455 } color;
1456 /* OT_VIDEO_MODE type option. */
1457 struct {
1458 struct video_mode *const pvalue;
1459 const struct video_mode def;
1460 } video_mode;
1464 #define CLIENT_OPTION(poption) ((struct client_option *) (poption))
1467 * Generate a client option of type OT_BOOLEAN.
1469 * oname: The option data. Note it is used as name to be loaded or saved.
1470 * So, you shouldn't change the name of this variable in any case.
1471 * odesc: A short description of the client option. Should be used with the
1472 * N_() macro.
1473 * ohelp: The help text for the client option. Should be used with the N_()
1474 * macro.
1475 * ocat: The client_option_class of this client option.
1476 * ospec: A gui_type enumerator which determin for what particular client
1477 * gui this option is for. Sets to GUI_STUB for common options.
1478 * odef: The default value of this client option (FALSE or TRUE).
1479 * ocb: A callback function of type void (*)(struct option *) called when
1480 * the option changed.
1482 #define GEN_BOOL_OPTION(oname, odesc, ohelp, ocat, ospec, odef, ocb) \
1484 .base_option = OPTION_BOOL_INIT(&client_optset_static, \
1485 client_option_common_vtable, \
1486 client_option_bool_vtable, ocb), \
1487 .name = #oname, \
1488 .description = odesc, \
1489 .help_text = ohelp, \
1490 .category = ocat, \
1491 .specific = ospec, \
1492 INIT_BRACE_BEGIN \
1493 .boolean = { \
1494 .pvalue = &gui_options.oname, \
1495 .def = odef, \
1497 INIT_BRACE_END \
1501 * Generate a client option of type OT_INTEGER.
1503 * oname: The option data. Note it is used as name to be loaded or saved.
1504 * So, you shouldn't change the name of this variable in any case.
1505 * odesc: A short description of the client option. Should be used with the
1506 * N_() macro.
1507 * ohelp: The help text for the client option. Should be used with the N_()
1508 * macro.
1509 * ocat: The client_option_class of this client option.
1510 * ospec: A gui_type enumerator which determin for what particular client
1511 * gui this option is for. Sets to GUI_STUB for common options.
1512 * odef: The default value of this client option.
1513 * omin: The minimal value of this client option.
1514 * omax: The maximal value of this client option.
1515 * ocb: A callback function of type void (*)(struct option *) called when
1516 * the option changed.
1518 #define GEN_INT_OPTION(oname, odesc, ohelp, ocat, ospec, odef, omin, omax, ocb) \
1520 .base_option = OPTION_INT_INIT(&client_optset_static, \
1521 client_option_common_vtable, \
1522 client_option_int_vtable, ocb), \
1523 .name = #oname, \
1524 .description = odesc, \
1525 .help_text = ohelp, \
1526 .category = ocat, \
1527 .specific = ospec, \
1528 INIT_BRACE_BEGIN \
1529 .integer = { \
1530 .pvalue = &gui_options.oname, \
1531 .def = odef, \
1532 .min = omin, \
1533 .max = omax \
1535 INIT_BRACE_END \
1539 * Generate a client option of type OT_STRING.
1541 * oname: The option data. Note it is used as name to be loaded or saved.
1542 * So, you shouldn't change the name of this variable in any case.
1543 * Be sure to pass the array variable and not a pointer to it because
1544 * the size is calculated with sizeof().
1545 * odesc: A short description of the client option. Should be used with the
1546 * N_() macro.
1547 * ohelp: The help text for the client option. Should be used with the N_()
1548 * macro.
1549 * ocat: The client_option_class of this client option.
1550 * ospec: A gui_type enumerator which determines for what particular client
1551 * gui this option is for. Set to GUI_STUB for common options.
1552 * odef: The default string for this client option.
1553 * ocb: A callback function of type void (*)(struct option *) called when
1554 * the option changed.
1556 #define GEN_STR_OPTION(oname, odesc, ohelp, ocat, ospec, odef, ocb, cbd) \
1558 .base_option = OPTION_STR_INIT(&client_optset_static, \
1559 client_option_common_vtable, \
1560 client_option_str_vtable, ocb, cbd), \
1561 .name = #oname, \
1562 .description = odesc, \
1563 .help_text = ohelp, \
1564 .category = ocat, \
1565 .specific = ospec, \
1566 INIT_BRACE_BEGIN \
1567 .string = { \
1568 .pvalue = gui_options.oname, \
1569 .size = sizeof(gui_options.oname), \
1570 .def = odef, \
1571 .val_accessor = NULL \
1573 INIT_BRACE_END \
1577 * Generate a client option of type OT_STRING with a string accessor
1578 * function.
1580 * oname: The option data. Note it is used as name to be loaded or saved.
1581 * So, you shouldn't change the name of this variable in any case.
1582 * Be sure to pass the array variable and not a pointer to it because
1583 * the size is calculated with sizeof().
1584 * odesc: A short description of the client option. Should be used with the
1585 * N_() macro.
1586 * ohelp: The help text for the client option. Should be used with the N_()
1587 * macro.
1588 * ocat: The client_option_class of this client option.
1589 * ospec: A gui_type enumerator which determin for what particular client
1590 * gui this option is for. Sets to GUI_STUB for common options.
1591 * odef: The default string for this client option.
1592 * oacc: The string accessor where to find the allowed values of type
1593 * 'const struct strvec * (*) (void)'.
1594 * ocb: A callback function of type void (*)(struct option *) called when
1595 * the option changed.
1597 #define GEN_STR_LIST_OPTION(oname, odesc, ohelp, ocat, ospec, odef, oacc, ocb, cbd) \
1599 .base_option = OPTION_STR_INIT(&client_optset_static, \
1600 client_option_common_vtable, \
1601 client_option_str_vtable, ocb, cbd), \
1602 .name = #oname, \
1603 .description = odesc, \
1604 .help_text = ohelp, \
1605 .category = ocat, \
1606 .specific = ospec, \
1607 INIT_BRACE_BEGIN \
1608 .string = { \
1609 .pvalue = gui_options.oname, \
1610 .size = sizeof(gui_options.oname), \
1611 .def = odef, \
1612 .val_accessor = oacc \
1614 INIT_BRACE_END \
1618 * Generate a client option of type OT_ENUM.
1620 * oname: The option data. Note it is used as name to be loaded or saved.
1621 * So, you shouldn't change the name of this variable in any case.
1622 * odesc: A short description of the client option. Should be used with the
1623 * N_() macro.
1624 * ohelp: The help text for the client option. Should be used with the N_()
1625 * macro.
1626 * ocat: The client_option_class of this client option.
1627 * ospec: A gui_type enumerator which determin for what particular client
1628 * gui this option is for. Sets to GUI_STUB for common options.
1629 * odef: The default value for this client option.
1630 * oacc: The name accessor of type 'const struct copt_val_name * (*) (int)'.
1631 * ocb: A callback function of type void (*) (struct option *) called when
1632 * the option changed.
1634 #define GEN_ENUM_OPTION(oname, odesc, ohelp, ocat, ospec, odef, oacc, ocb) \
1636 .base_option = OPTION_ENUM_INIT(&client_optset_static, \
1637 client_option_common_vtable, \
1638 client_option_enum_vtable, ocb), \
1639 .name = #oname, \
1640 .description = odesc, \
1641 .help_text = ohelp, \
1642 .category = ocat, \
1643 .specific = ospec, \
1644 INIT_BRACE_BEGIN \
1645 .enumerator = { \
1646 .pvalue = (int *) &gui_options.oname, \
1647 .def = odef, \
1648 .support_names = NULL, /* Set in options_init(). */ \
1649 .pretty_names = NULL, \
1650 .name_accessor = oacc \
1652 INIT_BRACE_END \
1656 * Generate a client option of type OT_BITWISE.
1658 * oname: The option data. Note it is used as name to be loaded or saved.
1659 * So, you shouldn't change the name of this variable in any case.
1660 * odesc: A short description of the client option. Should be used with the
1661 * N_() macro.
1662 * ohelp: The help text for the client option. Should be used with the N_()
1663 * macro.
1664 * ocat: The client_option_class of this client option.
1665 * ospec: A gui_type enumerator which determin for what particular client
1666 * gui this option is for. Sets to GUI_STUB for common options.
1667 * odef: The default value for this client option.
1668 * oacc: The name accessor of type 'const struct copt_val_name * (*) (int)'.
1669 * ocb: A callback function of type void (*) (struct option *) called when
1670 * the option changed.
1672 #define GEN_BITWISE_OPTION(oname, odesc, ohelp, ocat, ospec, odef, oacc, \
1673 ocb) \
1675 .base_option = OPTION_BITWISE_INIT(&client_optset_static, \
1676 client_option_common_vtable, \
1677 client_option_bitwise_vtable, ocb), \
1678 .name = #oname, \
1679 .description = odesc, \
1680 .help_text = ohelp, \
1681 .category = ocat, \
1682 .specific = ospec, \
1683 INIT_BRACE_BEGIN \
1684 .bitwise = { \
1685 .pvalue = &gui_options.oname, \
1686 .def = odef, \
1687 .support_names = NULL, /* Set in options_init(). */ \
1688 .pretty_names = NULL, \
1689 .name_accessor = oacc \
1691 INIT_BRACE_END \
1695 * Generate a client option of type OT_FONT.
1697 * oname: The option data. Note it is used as name to be loaded or saved.
1698 * So, you shouldn't change the name of this variable in any case.
1699 * Be sure to pass the array variable and not a pointer to it because
1700 * the size is calculated with sizeof().
1701 * otgt: The target widget style.
1702 * odesc: A short description of the client option. Should be used with the
1703 * N_() macro.
1704 * ohelp: The help text for the client option. Should be used with the N_()
1705 * macro.
1706 * ocat: The client_option_class of this client option.
1707 * ospec: A gui_type enumerator which determin for what particular client
1708 * gui this option is for. Sets to GUI_STUB for common options.
1709 * odef: The default string for this client option.
1710 * ocb: A callback function of type void (*)(struct option *) called when
1711 * the option changed.
1713 #define GEN_FONT_OPTION(oname, otgt, odesc, ohelp, ocat, ospec, odef, ocb) \
1715 .base_option = OPTION_FONT_INIT(&client_optset_static, \
1716 client_option_common_vtable, \
1717 client_option_font_vtable, ocb), \
1718 .name = #oname, \
1719 .description = odesc, \
1720 .help_text = ohelp, \
1721 .category = ocat, \
1722 .specific = ospec, \
1723 INIT_BRACE_BEGIN \
1724 .font = { \
1725 .pvalue = gui_options.oname, \
1726 .size = sizeof(gui_options.oname), \
1727 .def = odef, \
1728 .target = otgt, \
1730 INIT_BRACE_END \
1734 * Generate a client option of type OT_COLOR.
1736 * oname: The option data. Note it is used as name to be loaded or saved.
1737 * So, you shouldn't change the name of this variable in any case.
1738 * odesc: A short description of the client option. Should be used with the
1739 * N_() macro.
1740 * ohelp: The help text for the client option. Should be used with the N_()
1741 * macro.
1742 * ocat: The client_option_class of this client option.
1743 * ospec: A gui_type enumerator which determin for what particular client
1744 * gui this option is for. Sets to GUI_STUB for common options.
1745 * odef_fg, odef_bg: The default values for this client option.
1746 * ocb: A callback function of type void (*)(struct option *) called when
1747 * the option changed.
1749 #define GEN_COLOR_OPTION(oname, odesc, ohelp, ocat, ospec, odef_fg, \
1750 odef_bg, ocb) \
1752 .base_option = OPTION_COLOR_INIT(&client_optset_static, \
1753 client_option_common_vtable, \
1754 client_option_color_vtable, ocb), \
1755 .name = #oname, \
1756 .description = odesc, \
1757 .help_text = ohelp, \
1758 .category = ocat, \
1759 .specific = ospec, \
1760 INIT_BRACE_BEGIN \
1761 .color = { \
1762 .pvalue = &gui_options.oname, \
1763 .def = FT_COLOR(odef_fg, odef_bg) \
1765 INIT_BRACE_END \
1769 * Generate a client option of type OT_VIDEO_MODE.
1771 * oname: The option data. Note it is used as name to be loaded or saved.
1772 * So, you shouldn't change the name of this variable in any case.
1773 * odesc: A short description of the client option. Should be used with the
1774 * N_() macro.
1775 * ohelp: The help text for the client option. Should be used with the N_()
1776 * macro.
1777 * ocat: The client_option_class of this client option.
1778 * ospec: A gui_type enumerator which determin for what particular client
1779 * gui this option is for. Sets to GUI_STUB for common options.
1780 * odef_width, odef_height: The default values for this client option.
1781 * ocb: A callback function of type void (*)(struct option *) called when
1782 * the option changed.
1784 #define GEN_VIDEO_OPTION(oname, odesc, ohelp, ocat, ospec, odef_width, \
1785 odef_height, ocb) \
1787 .base_option = OPTION_VIDEO_MODE_INIT(&client_optset_static, \
1788 client_option_common_vtable, \
1789 client_option_video_mode_vtable, \
1790 ocb), \
1791 .name = #oname, \
1792 .description = odesc, \
1793 .help_text = ohelp, \
1794 .category = ocat, \
1795 .specific = ospec, \
1796 INIT_BRACE_BEGIN \
1797 .video_mode = { \
1798 .pvalue = &gui_options.oname, \
1799 .def = VIDEO_MODE(odef_width, odef_height) \
1801 INIT_BRACE_END \
1804 /****************************************************************************
1805 Enumerator name accessors.
1806 ****************************************************************************/
1808 /****************************************************************************
1809 GTK message/chat layout setting names accessor.
1810 ****************************************************************************/
1811 static const struct copt_val_name
1812 *gui_gtk_message_chat_location_name(int value)
1814 /* Order must match enum GUI_GTK_MSGCHAT_* */
1815 static const struct copt_val_name names[] = {
1816 /* TRANS: enum value for 'gui_gtk2/gtk3/gtk3x_message_chat_location' */
1817 { "SPLIT", N_("Split") },
1818 /* TRANS: enum value for 'gui_gtk2/gtk3/gtk3x_message_chat_location' */
1819 { "SEPARATE", N_("Separate") },
1820 /* TRANS: enum value for 'gui_gtk2/gtk3/gtk3x_message_chat_location' */
1821 { "MERGED", N_("Merged") }
1824 return (0 <= value && value < ARRAY_SIZE(names)
1825 ? names + value : NULL);
1828 /****************************************************************************
1829 Popup tech help setting names accessor.
1830 ****************************************************************************/
1831 static const struct copt_val_name
1832 *gui_popup_tech_help_name(int value)
1834 /* Order must match enum GUI_POPUP_TECH_HELP_* */
1835 static const struct copt_val_name names[] = {
1836 /* TRANS: enum value for 'gui_popup_tech_help' */
1837 { "ENABLED", N_("Enabled") },
1838 /* TRANS: enum value for 'gui_popup_tech_help' */
1839 { "DISABLED", N_("Disabled") },
1840 /* TRANS: enum value for 'gui_popup_tech_help' */
1841 { "RULESET", N_("Ruleset") }
1844 return (0 <= value && value < ARRAY_SIZE(names)
1845 ? names + value : NULL);
1848 /* Some changed callbacks. */
1849 static void reqtree_show_icons_callback(struct option *poption);
1850 static void view_option_changed_callback(struct option *poption);
1851 static void voteinfo_bar_callback(struct option *poption);
1852 static void font_changed_callback(struct option *poption);
1853 static void mapimg_changed_callback(struct option *poption);
1854 static void game_music_enable_callback(struct option *poption);
1855 static void menu_music_enable_callback(struct option *poption);
1857 static struct client_option client_options[] = {
1858 GEN_STR_OPTION(default_user_name,
1859 N_("Login name"),
1860 N_("This is the default login username that will be used "
1861 "in the connection dialogs or with the -a command-line "
1862 "parameter."),
1863 COC_NETWORK, GUI_STUB, NULL, NULL, 0),
1864 GEN_BOOL_OPTION(use_prev_server, N_("Default to previously used server"),
1865 N_("Automatically update \"Server\" and \"Server port\" "
1866 "options to match your latest connection, so by "
1867 "default you connect to the same server you used "
1868 "on the previous run. You should enable "
1869 "saving options on exit too, so that the automatic "
1870 "updates to the options get saved too."),
1871 COC_NETWORK, GUI_STUB, NULL, NULL),
1872 GEN_STR_OPTION(default_server_host,
1873 N_("Server"),
1874 N_("This is the default server hostname that will be used "
1875 "in the connection dialogs or with the -a command-line "
1876 "parameter."),
1877 COC_NETWORK, GUI_STUB, "localhost", NULL, 0),
1878 GEN_INT_OPTION(default_server_port,
1879 N_("Server port"),
1880 N_("This is the default server port that will be used "
1881 "in the connection dialogs or with the -a command-line "
1882 "parameter."),
1883 COC_NETWORK, GUI_STUB, DEFAULT_SOCK_PORT, 0, 65535, NULL),
1884 GEN_STR_OPTION(default_metaserver,
1885 N_("Metaserver"),
1886 N_("The metaserver is a host that the client contacts to "
1887 "find out about games on the internet. Don't change "
1888 "this from its default value unless you know what "
1889 "you're doing."),
1890 COC_NETWORK, GUI_STUB, DEFAULT_METASERVER_OPTION, NULL, 0),
1891 GEN_BOOL_OPTION(heartbeat_enabled, N_("Send heartbeat messages to server"),
1892 N_("Regularly send empty heartbeat message to the server "
1893 "to make sure that the connection is still up. This "
1894 "can be useful if the client otherwise may sit for a "
1895 "long time with no data being sent or received at all."),
1896 COC_NETWORK, GUI_STUB, NULL, NULL),
1897 GEN_STR_LIST_OPTION(default_sound_set_name,
1898 N_("Soundset"),
1899 N_("This is the soundset that will be used. Changing "
1900 "this is the same as using the -S command-line "
1901 "parameter."),
1902 COC_SOUND, GUI_STUB, "stdsounds", get_soundset_list, NULL, 0),
1903 GEN_STR_LIST_OPTION(default_music_set_name,
1904 N_("Musicset"),
1905 N_("This is the musicset that will be used. Changing "
1906 "this is the same as using the -m command-line "
1907 "parameter."),
1908 COC_SOUND, GUI_STUB, "stdmusic", get_musicset_list, musicspec_reread_callback, 0),
1909 GEN_STR_LIST_OPTION(default_sound_plugin_name,
1910 N_("Sound plugin"),
1911 N_("If you have a problem with sound, try changing "
1912 "the sound plugin. The new plugin won't take "
1913 "effect until you restart Freeciv. Changing this "
1914 "is the same as using the -P command-line option."),
1915 COC_SOUND, GUI_STUB, NULL, get_soundplugin_list, NULL, 0),
1916 GEN_STR_OPTION(default_chat_logfile,
1917 N_("The chat log file"),
1918 N_("The name of the chat log file."),
1919 COC_INTERFACE, GUI_STUB, GUI_DEFAULT_CHAT_LOGFILE, NULL, 0),
1920 /* gui_gtk3/4_default_theme_name and gui_sdl2_default_theme_name are
1921 * different settings to avoid client crash after loading the
1922 * style for the other gui. Keeps 5 different options! */
1923 GEN_STR_LIST_OPTION(gui_gtk3_default_theme_name, N_("Theme"),
1924 N_("By changing this option you change the "
1925 "active theme."),
1926 COC_GRAPHICS, GUI_GTK3, FC_GTK3_DEFAULT_THEME_NAME,
1927 get_themes_list, theme_reread_callback, 0),
1928 GEN_STR_LIST_OPTION(gui_gtk3_22_default_theme_name, N_("Theme"),
1929 N_("By changing this option you change the "
1930 "active theme."),
1931 COC_GRAPHICS, GUI_GTK3_22, FC_GTK3_22_DEFAULT_THEME_NAME,
1932 get_themes_list, theme_reread_callback, 0),
1933 GEN_STR_LIST_OPTION(gui_gtk4_default_theme_name, N_("Theme"),
1934 N_("By changing this option you change the "
1935 "active theme."),
1936 COC_GRAPHICS, GUI_GTK3x, FC_GTK4_DEFAULT_THEME_NAME,
1937 get_themes_list, theme_reread_callback, 0),
1938 GEN_STR_LIST_OPTION(gui_sdl2_default_theme_name, N_("Theme"),
1939 N_("By changing this option you change the "
1940 "active theme."),
1941 COC_GRAPHICS, GUI_SDL2, FC_SDL2_DEFAULT_THEME_NAME,
1942 get_themes_list, theme_reread_callback, 0),
1943 GEN_STR_LIST_OPTION(gui_qt_default_theme_name, N_("Theme"),
1944 N_("By changing this option you change the "
1945 "active theme."),
1946 COC_GRAPHICS, GUI_QT, FC_QT_DEFAULT_THEME_NAME,
1947 get_themes_list, theme_reread_callback, 0),
1949 /* It's important to give empty string instead of NULL as as default
1950 * value. For NULL value it would default to assigning first value
1951 * from the tileset list returned by get_tileset_list() as default
1952 * tileset. We don't want default tileset assigned at all here, but
1953 * leave it to tilespec code that can handle tileset priority. */
1954 GEN_STR_LIST_OPTION(default_tileset_overhead_name, N_("Tileset (Overhead)"),
1955 N_("Select the tileset used with Overhead maps. "
1956 "This may change currently active tileset, if "
1957 "you are playing on such a map, in which "
1958 "case this is the same as using the -t "
1959 "command-line parameter."),
1960 COC_GRAPHICS, GUI_STUB, "",
1961 get_tileset_list, tilespec_reread_callback, 0),
1962 GEN_STR_LIST_OPTION(default_tileset_iso_name, N_("Tileset (Isometric)"),
1963 N_("Select the tileset used with Isometric maps. "
1964 "This may change currently active tileset, if "
1965 "you are playing on such a map, in which "
1966 "case this is the same as using the -t "
1967 "command-line parameter."),
1968 COC_GRAPHICS, GUI_STUB, "",
1969 get_tileset_list, tilespec_reread_callback, TF_ISO),
1970 GEN_STR_LIST_OPTION(default_tileset_hex_name, N_("Tileset (Hex)"),
1971 N_("Select the tileset used with Hex maps. "
1972 "This may change currently active tileset, if "
1973 "you are playing on such a map, in which "
1974 "case this is the same as using the -t "
1975 "command-line parameter."),
1976 COC_GRAPHICS, GUI_STUB, "",
1977 get_tileset_list, tilespec_reread_callback, TF_HEX),
1978 GEN_STR_LIST_OPTION(default_tileset_isohex_name, N_("Tileset (Isometric Hex)"),
1979 N_("Select the tileset used with Isometric Hex maps. "
1980 "This may change currently active tileset, if "
1981 "you are playing on such a map, in which "
1982 "case this is the same as using the -t "
1983 "command-line parameter."),
1984 COC_GRAPHICS, GUI_STUB, "",
1985 get_tileset_list, tilespec_reread_callback, TF_ISO | TF_HEX),
1987 GEN_BOOL_OPTION(draw_city_outlines, N_("Draw city outlines"),
1988 N_("Setting this option will draw a line at the city "
1989 "workable limit."),
1990 COC_GRAPHICS, GUI_STUB, TRUE,
1991 view_option_changed_callback),
1992 GEN_BOOL_OPTION(draw_city_output, N_("Draw city output"),
1993 N_("Setting this option will draw city output for every "
1994 "citizen."),
1995 COC_GRAPHICS, GUI_STUB, FALSE,
1996 view_option_changed_callback),
1997 GEN_BOOL_OPTION(draw_map_grid, N_("Draw the map grid"),
1998 N_("Setting this option will draw a grid over the map."),
1999 COC_GRAPHICS, GUI_STUB, FALSE,
2000 view_option_changed_callback),
2001 GEN_BOOL_OPTION(draw_full_citybar, N_("Draw the city bar"),
2002 N_("Setting this option will display a 'city bar' "
2003 "containing useful information beneath each city. "
2004 "Disabling this option will display only the city's "
2005 "name and, optionally, production."),
2006 COC_GRAPHICS, GUI_STUB,
2007 TRUE, view_option_changed_callback),
2008 GEN_BOOL_OPTION(draw_city_names, N_("Draw the city names"),
2009 N_("Setting this option will draw the names of the cities "
2010 "on the map."),
2011 COC_GRAPHICS, GUI_STUB, TRUE,
2012 view_option_changed_callback),
2013 GEN_BOOL_OPTION(draw_city_growth, N_("Draw the city growth"),
2014 N_("Setting this option will draw in how many turns the "
2015 "cities will grow or shrink."),
2016 COC_GRAPHICS, GUI_STUB, TRUE,
2017 view_option_changed_callback),
2018 GEN_BOOL_OPTION(draw_city_productions, N_("Draw the city productions"),
2019 N_("Setting this option will draw what the cities are "
2020 "currently building on the map."),
2021 COC_GRAPHICS, GUI_STUB, TRUE,
2022 view_option_changed_callback),
2023 GEN_BOOL_OPTION(draw_city_buycost, N_("Draw the city buy costs"),
2024 N_("Setting this option will draw how much gold is "
2025 "needed to buy the production of the cities."),
2026 COC_GRAPHICS, GUI_STUB, FALSE,
2027 view_option_changed_callback),
2028 GEN_BOOL_OPTION(draw_city_trade_routes, N_("Draw the city trade routes"),
2029 N_("Setting this option will draw trade route lines "
2030 "between cities which have trade routes."),
2031 COC_GRAPHICS, GUI_STUB, FALSE,
2032 view_option_changed_callback),
2033 GEN_BOOL_OPTION(draw_terrain, N_("Draw the terrain"),
2034 N_("Setting this option will draw the terrain."),
2035 COC_GRAPHICS, GUI_STUB, TRUE,
2036 view_option_changed_callback),
2037 GEN_BOOL_OPTION(draw_coastline, N_("Draw the coast line"),
2038 N_("Setting this option will draw a line to separate the "
2039 "land from the ocean."),
2040 COC_GRAPHICS, GUI_STUB, FALSE,
2041 view_option_changed_callback),
2042 GEN_BOOL_OPTION(draw_roads_rails, N_("Draw the roads and the railroads"),
2043 N_("Setting this option will draw the roads and the "
2044 "railroads on the map."),
2045 COC_GRAPHICS, GUI_STUB, TRUE,
2046 view_option_changed_callback),
2047 GEN_BOOL_OPTION(draw_irrigation, N_("Draw the irrigation"),
2048 N_("Setting this option will draw the irrigation systems "
2049 "on the map."),
2050 COC_GRAPHICS, GUI_STUB, TRUE,
2051 view_option_changed_callback),
2052 GEN_BOOL_OPTION(draw_mines, N_("Draw the mines"),
2053 N_("Setting this option will draw the mines on the map."),
2054 COC_GRAPHICS, GUI_STUB, TRUE,
2055 view_option_changed_callback),
2056 GEN_BOOL_OPTION(draw_fortress_airbase, N_("Draw the bases"),
2057 N_("Setting this option will draw the bases on the map."),
2058 COC_GRAPHICS, GUI_STUB, TRUE,
2059 view_option_changed_callback),
2060 GEN_BOOL_OPTION(draw_specials, N_("Draw the resources"),
2061 N_("Setting this option will draw the resources on the "
2062 "map."),
2063 COC_GRAPHICS, GUI_STUB, TRUE,
2064 view_option_changed_callback),
2065 GEN_BOOL_OPTION(draw_huts, N_("Draw the huts"),
2066 N_("Setting this option will draw the huts on the "
2067 "map."),
2068 COC_GRAPHICS, GUI_STUB, TRUE,
2069 view_option_changed_callback),
2070 GEN_BOOL_OPTION(draw_pollution, N_("Draw the pollution/nuclear fallout"),
2071 N_("Setting this option will draw pollution and "
2072 "nuclear fallout on the map."),
2073 COC_GRAPHICS, GUI_STUB, TRUE,
2074 view_option_changed_callback),
2075 GEN_BOOL_OPTION(draw_cities, N_("Draw the cities"),
2076 N_("Setting this option will draw the cities on the map."),
2077 COC_GRAPHICS, GUI_STUB, TRUE,
2078 view_option_changed_callback),
2079 GEN_BOOL_OPTION(draw_units, N_("Draw the units"),
2080 N_("Setting this option will draw the units on the map."),
2081 COC_GRAPHICS, GUI_STUB, TRUE,
2082 view_option_changed_callback),
2083 GEN_BOOL_OPTION(solid_color_behind_units,
2084 N_("Solid unit background color"),
2085 N_("Setting this option will cause units on the map "
2086 "view to be drawn with a solid background color "
2087 "instead of the flag backdrop."),
2088 COC_GRAPHICS, GUI_STUB,
2089 FALSE, view_option_changed_callback),
2090 GEN_BOOL_OPTION(draw_unit_shields, N_("Draw shield graphics for units"),
2091 N_("Setting this option will draw a shield icon "
2092 "as the flags on units. If unset, the full flag will "
2093 "be drawn."),
2094 COC_GRAPHICS, GUI_STUB, TRUE, view_option_changed_callback),
2095 GEN_BOOL_OPTION(draw_focus_unit, N_("Draw the units in focus"),
2096 N_("Setting this option will cause the currently focused "
2097 "unit(s) to always be drawn, even if units are not "
2098 "otherwise being drawn (for instance if 'Draw the units' "
2099 "is unset)."),
2100 COC_GRAPHICS, GUI_STUB, FALSE,
2101 view_option_changed_callback),
2102 GEN_BOOL_OPTION(draw_fog_of_war, N_("Draw the fog of war"),
2103 N_("Setting this option will draw the fog of war."),
2104 COC_GRAPHICS, GUI_STUB, TRUE,
2105 view_option_changed_callback),
2106 GEN_BOOL_OPTION(draw_borders, N_("Draw the borders"),
2107 N_("Setting this option will draw the national borders."),
2108 COC_GRAPHICS, GUI_STUB, TRUE,
2109 view_option_changed_callback),
2110 GEN_BOOL_OPTION(draw_native, N_("Draw whether tiles are native to "
2111 "selected unit"),
2112 N_("Setting this option will highlight tiles that the "
2113 "currently selected unit cannot enter unaided due to "
2114 "non-native terrain. (If multiple units are selected, "
2115 "only tiles that all of them can enter are indicated.)"),
2116 COC_GRAPHICS, GUI_STUB, FALSE,
2117 view_option_changed_callback),
2118 GEN_BOOL_OPTION(player_dlg_show_dead_players,
2119 N_("Show dead players in Nations report"),
2120 N_("This option controls whether defeated nations are "
2121 "shown on the Nations report page."),
2122 COC_GRAPHICS, GUI_STUB, TRUE,
2123 view_option_changed_callback),
2124 GEN_BOOL_OPTION(sound_bell_at_new_turn, N_("Sound bell at new turn"),
2125 N_("Set this option to have a \"bell\" event be generated "
2126 "at the start of a new turn. You can control the "
2127 "behavior of the \"bell\" event by editing the message "
2128 "options."),
2129 COC_SOUND, GUI_STUB, FALSE, NULL),
2130 GEN_INT_OPTION(smooth_move_unit_msec,
2131 N_("Unit movement animation time (milliseconds)"),
2132 N_("This option controls how long unit \"animation\" takes "
2133 "when a unit moves on the map view. Set it to 0 to "
2134 "disable animation entirely."),
2135 COC_GRAPHICS, GUI_STUB, 30, 0, 2000, NULL),
2136 GEN_INT_OPTION(smooth_center_slide_msec,
2137 N_("Mapview recentering time (milliseconds)"),
2138 N_("When the map view is recentered, it will slide "
2139 "smoothly over the map to its new position. This "
2140 "option controls how long this slide lasts. Set it to "
2141 "0 to disable mapview sliding entirely."),
2142 COC_GRAPHICS, GUI_STUB, 200, 0, 5000, NULL),
2143 GEN_INT_OPTION(smooth_combat_step_msec,
2144 N_("Combat animation step time (milliseconds)"),
2145 N_("This option controls the speed of combat animation "
2146 "between units on the mapview. Set it to 0 to disable "
2147 "animation entirely."),
2148 COC_GRAPHICS, GUI_STUB, 10, 0, 100, NULL),
2149 GEN_BOOL_OPTION(reqtree_show_icons,
2150 N_("Show icons in the technology tree"),
2151 N_("Setting this option will display icons "
2152 "on the technology tree diagram. Turning "
2153 "this option off makes the technology tree "
2154 "more compact."),
2155 COC_GRAPHICS, GUI_STUB, TRUE, reqtree_show_icons_callback),
2156 GEN_BOOL_OPTION(reqtree_curved_lines,
2157 N_("Use curved lines in the technology tree"),
2158 N_("Setting this option make the technology tree "
2159 "diagram use curved lines to show technology "
2160 "relations. Turning this option off causes "
2161 "the lines to be drawn straight."),
2162 COC_GRAPHICS, GUI_STUB, FALSE,
2163 reqtree_show_icons_callback),
2164 GEN_COLOR_OPTION(highlight_our_names,
2165 N_("Color to highlight your player/user name"),
2166 N_("If set, your player and user name in the new chat "
2167 "messages will be highlighted using this color as "
2168 "background. If not set, it will just not highlight "
2169 "anything."),
2170 COC_GRAPHICS, GUI_STUB, "#000000", "#FFFF00", NULL),
2171 GEN_BOOL_OPTION(ai_manual_turn_done, N_("Manual Turn Done in AI mode"),
2172 N_("Disable this option if you do not want to "
2173 "press the Turn Done button manually when watching "
2174 "an AI player."),
2175 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2176 GEN_BOOL_OPTION(auto_center_on_unit, N_("Auto center on units"),
2177 N_("Set this option to have the active unit centered "
2178 "automatically when the unit focus changes."),
2179 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2180 GEN_BOOL_OPTION(auto_center_on_automated, N_("Show automated units"),
2181 N_("Disable this option if you do not want to see "
2182 "automated units autocentered and animated"),
2183 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2184 GEN_BOOL_OPTION(auto_center_on_combat, N_("Auto center on combat"),
2185 N_("Set this option to have any combat be centered "
2186 "automatically. Disabling this will speed up the time "
2187 "between turns but may cause you to miss combat "
2188 "entirely."),
2189 COC_INTERFACE, GUI_STUB, FALSE, NULL),
2190 GEN_BOOL_OPTION(auto_center_each_turn, N_("Auto center on new turn"),
2191 N_("Set this option to have the client automatically "
2192 "recenter the map on a suitable location at the "
2193 "start of each turn."),
2194 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2195 GEN_BOOL_OPTION(wakeup_focus, N_("Focus on awakened units"),
2196 N_("Set this option to have newly awoken units be "
2197 "focused automatically."),
2198 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2199 GEN_BOOL_OPTION(keyboardless_goto, N_("Keyboardless goto"),
2200 N_("If this option is set then a goto may be initiated "
2201 "by left-clicking and then holding down the mouse "
2202 "button while dragging the mouse onto a different "
2203 "tile."),
2204 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2205 GEN_BOOL_OPTION(goto_into_unknown, N_("Allow goto into the unknown"),
2206 N_("Setting this option will make the game consider "
2207 "moving into unknown tiles. If not, then goto routes "
2208 "will detour around or be blocked by unknown tiles."),
2209 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2210 GEN_BOOL_OPTION(center_when_popup_city, N_("Center map when popup city"),
2211 N_("Setting this option makes the mapview center on a "
2212 "city when its city dialog is popped up."),
2213 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2214 GEN_BOOL_OPTION(show_previous_turn_messages, N_("Show messages from previous turn"),
2215 N_("Message Window shows messages also from previous turn. "
2216 "This makes sure you don't miss messages received in the end of "
2217 "the turn, just before the window gets cleared."),
2218 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2219 GEN_BOOL_OPTION(concise_city_production, N_("Concise city production"),
2220 N_("Set this option to make the city production (as shown "
2221 "in the city dialog) to be more compact."),
2222 COC_INTERFACE, GUI_STUB, FALSE, NULL),
2223 GEN_BOOL_OPTION(auto_turn_done, N_("End turn when done moving"),
2224 N_("Setting this option makes your turn end automatically "
2225 "when all your units are done moving."),
2226 COC_INTERFACE, GUI_STUB, FALSE, NULL),
2227 GEN_BOOL_OPTION(ask_city_name, N_("Prompt for city names"),
2228 N_("Disabling this option will make the names of newly "
2229 "founded cities be chosen automatically by the server."),
2230 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2231 GEN_BOOL_OPTION(popup_new_cities, N_("Pop up city dialog for new cities"),
2232 N_("Setting this option will pop up a newly-founded "
2233 "city's city dialog automatically."),
2234 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2235 GEN_BOOL_OPTION(popup_actor_arrival, N_("Pop up caravan and spy actions"),
2236 N_("If this option is enabled, when a unit arrives at "
2237 "a city where it can perform an action like "
2238 "establishing a trade route, helping build a wonder, or "
2239 "establishing an embassy, a window will pop up asking "
2240 "which action should be performed. "
2241 "Disabling this option means you will have to do the "
2242 "action manually by pressing either 'r' (for a trade "
2243 "route), 'b' (for building a wonder) or 'd' (for a "
2244 "spy action) when the unit is in the city."),
2245 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2246 GEN_BOOL_OPTION(popup_attack_actions, N_("Pop up attack questions"),
2247 N_("If this option is enabled, when a unit arrives at a "
2248 "target it can attack, a window will pop up asking "
2249 "which action should be performed even if an attack "
2250 "action is legal and no other interesting action are. "
2251 "This allows you to change you mind or to select an "
2252 "uninteresting action."),
2253 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2254 GEN_BOOL_OPTION(enable_cursor_changes, N_("Enable cursor changing"),
2255 N_("This option controls whether the client should "
2256 "try to change the mouse cursor depending on what "
2257 "is being pointed at, as well as to indicate "
2258 "changes in the client or server state."),
2259 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2260 GEN_BOOL_OPTION(separate_unit_selection, N_("Select cities before units"),
2261 N_("If this option is enabled, when both cities and "
2262 "units are present in the selection rectangle, only "
2263 "cities will be selected. See the help on Controls."),
2264 COC_INTERFACE, GUI_STUB, FALSE, NULL),
2265 GEN_BOOL_OPTION(unit_selection_clears_orders,
2266 N_("Clear unit orders on selection"),
2267 N_("Enabling this option will cause unit orders to be "
2268 "cleared as soon as one or more units are selected. If "
2269 "this option is disabled, busy units will not stop "
2270 "their current activity when selected. Giving them "
2271 "new orders will clear their current ones; pressing "
2272 "<space> once will clear their orders and leave them "
2273 "selected, and pressing <space> a second time will "
2274 "dismiss them."),
2275 COC_INTERFACE, GUI_STUB, TRUE, NULL),
2276 GEN_BOOL_OPTION(voteinfo_bar_use, N_("Enable vote bar"),
2277 N_("If this option is turned on, the vote bar will be "
2278 "displayed to show vote information."),
2279 COC_GRAPHICS, GUI_STUB, TRUE, voteinfo_bar_callback),
2280 GEN_BOOL_OPTION(voteinfo_bar_always_show,
2281 N_("Always display the vote bar"),
2282 N_("If this option is turned on, the vote bar will never "
2283 "be hidden, even if there is no running vote."),
2284 COC_GRAPHICS, GUI_STUB, FALSE, voteinfo_bar_callback),
2285 GEN_BOOL_OPTION(voteinfo_bar_hide_when_not_player,
2286 N_("Do not show vote bar if not a player"),
2287 N_("If this option is enabled, the client won't show the "
2288 "vote bar if you are not a player."),
2289 COC_GRAPHICS, GUI_STUB, FALSE, voteinfo_bar_callback),
2290 GEN_BOOL_OPTION(voteinfo_bar_new_at_front, N_("Set new votes at front"),
2291 N_("If this option is enabled, then new votes will go "
2292 "to the front of the vote list."),
2293 COC_GRAPHICS, GUI_STUB, FALSE, voteinfo_bar_callback),
2294 GEN_BOOL_OPTION(autoaccept_tileset_suggestion,
2295 N_("Autoaccept tileset suggestions"),
2296 N_("If this option is enabled, any tileset suggested by "
2297 "the ruleset is automatically used; otherwise you "
2298 "are prompted to change tileset."),
2299 COC_GRAPHICS, GUI_STUB, FALSE, NULL),
2301 GEN_BOOL_OPTION(sound_enable_effects,
2302 N_("Enable sound effects"),
2303 N_("Play sound effects, assuming there's suitable "
2304 "sound plugin and soundset with the sounds."),
2305 COC_SOUND, GUI_STUB, TRUE, NULL),
2306 GEN_BOOL_OPTION(sound_enable_game_music,
2307 N_("Enable in-game music"),
2308 N_("Play music during the game, assuming there's suitable "
2309 "sound plugin and musicset with in-game tracks."),
2310 COC_SOUND, GUI_STUB, TRUE, game_music_enable_callback),
2311 GEN_BOOL_OPTION(sound_enable_menu_music,
2312 N_("Enable menu music"),
2313 N_("Play music while not in actual game, "
2314 "assuming there's suitable "
2315 "sound plugin and musicset with menu music tracks."),
2316 COC_SOUND, GUI_STUB, TRUE, menu_music_enable_callback),
2317 GEN_BOOL_OPTION(autoaccept_soundset_suggestion,
2318 N_("Autoaccept soundset suggestions"),
2319 N_("If this option is enabled, any soundset suggested by "
2320 "the ruleset is automatically used."),
2321 COC_SOUND, GUI_STUB, FALSE, NULL),
2322 GEN_BOOL_OPTION(autoaccept_musicset_suggestion,
2323 N_("Autoaccept musicset suggestions"),
2324 N_("If this option is enabled, any musicset suggested by "
2325 "the ruleset is automatically used."),
2326 COC_SOUND, GUI_STUB, FALSE, NULL),
2328 GEN_BOOL_OPTION(overview.layers[OLAYER_BACKGROUND],
2329 N_("Background layer"),
2330 N_("The background layer of the overview shows just "
2331 "ocean and land."),
2332 COC_OVERVIEW, GUI_STUB, TRUE, NULL),
2333 GEN_BOOL_OPTION(overview.layers[OLAYER_RELIEF],
2334 N_("Terrain relief map layer"),
2335 N_("The relief layer shows all terrains on the map."),
2336 COC_OVERVIEW, GUI_STUB, FALSE, overview_redraw_callback),
2337 GEN_BOOL_OPTION(overview.layers[OLAYER_BORDERS],
2338 N_("Borders layer"),
2339 N_("The borders layer of the overview shows which tiles "
2340 "are owned by each player."),
2341 COC_OVERVIEW, GUI_STUB, FALSE, overview_redraw_callback),
2342 GEN_BOOL_OPTION(overview.layers[OLAYER_BORDERS_ON_OCEAN],
2343 N_("Borders layer on ocean tiles"),
2344 N_("The borders layer of the overview are drawn on "
2345 "ocean tiles as well (this may look ugly with many "
2346 "islands). This option is only of interest if you "
2347 "have set the option \"Borders layer\" already."),
2348 COC_OVERVIEW, GUI_STUB, TRUE, overview_redraw_callback),
2349 GEN_BOOL_OPTION(overview.layers[OLAYER_UNITS],
2350 N_("Units layer"),
2351 N_("Enabling this will draw units on the overview."),
2352 COC_OVERVIEW, GUI_STUB, TRUE, overview_redraw_callback),
2353 GEN_BOOL_OPTION(overview.layers[OLAYER_CITIES],
2354 N_("Cities layer"),
2355 N_("Enabling this will draw cities on the overview."),
2356 COC_OVERVIEW, GUI_STUB, TRUE, overview_redraw_callback),
2357 GEN_BOOL_OPTION(overview.fog,
2358 N_("Overview fog of war"),
2359 N_("Enabling this will show fog of war on the "
2360 "overview."),
2361 COC_OVERVIEW, GUI_STUB, TRUE, overview_redraw_callback),
2363 /* options for map images */
2364 GEN_STR_LIST_OPTION(mapimg_format,
2365 N_("Image format"),
2366 N_("The image toolkit and file format used for "
2367 "map images."),
2368 COC_MAPIMG, GUI_STUB, NULL, get_mapimg_format_list,
2369 NULL, 0),
2370 GEN_INT_OPTION(mapimg_zoom,
2371 N_("Zoom factor for map images"),
2372 N_("The magnification used for map images."),
2373 COC_MAPIMG, GUI_STUB, 2, 1, 5, mapimg_changed_callback),
2374 GEN_BOOL_OPTION(mapimg_layer[MAPIMG_LAYER_AREA],
2375 N_("Show area within borders"),
2376 N_("If set, the territory of each nation is shown "
2377 "on the saved image."),
2378 COC_MAPIMG, GUI_STUB, FALSE, mapimg_changed_callback),
2379 GEN_BOOL_OPTION(mapimg_layer[MAPIMG_LAYER_BORDERS],
2380 N_("Show borders"),
2381 N_("If set, the border of each nation is shown on the "
2382 "saved image."),
2383 COC_MAPIMG, GUI_STUB, TRUE, mapimg_changed_callback),
2384 GEN_BOOL_OPTION(mapimg_layer[MAPIMG_LAYER_CITIES],
2385 N_("Show cities"),
2386 N_("If set, cities are shown on the saved image."),
2387 COC_MAPIMG, GUI_STUB, TRUE, mapimg_changed_callback),
2388 GEN_BOOL_OPTION(mapimg_layer[MAPIMG_LAYER_FOGOFWAR],
2389 N_("Show fog of war"),
2390 N_("If set, the extent of fog of war is shown on the "
2391 "saved image."),
2392 COC_MAPIMG, GUI_STUB, TRUE, mapimg_changed_callback),
2393 GEN_BOOL_OPTION(mapimg_layer[MAPIMG_LAYER_TERRAIN],
2394 N_("Show full terrain"),
2395 N_("If set, terrain relief is shown with different colors "
2396 "in the saved image; otherwise, only land and water are "
2397 "distinguished."),
2398 COC_MAPIMG, GUI_STUB, TRUE, mapimg_changed_callback),
2399 GEN_BOOL_OPTION(mapimg_layer[MAPIMG_LAYER_UNITS],
2400 N_("Show units"),
2401 N_("If set, units are shown in the saved image."),
2402 COC_MAPIMG, GUI_STUB, TRUE, mapimg_changed_callback),
2403 GEN_STR_OPTION(mapimg_filename,
2404 N_("Map image file name"),
2405 N_("The base part of the filename for saved map images. "
2406 "A string identifying the game turn and map options will "
2407 "be appended."),
2408 COC_MAPIMG, GUI_STUB, GUI_DEFAULT_MAPIMG_FILENAME, NULL, 0),
2410 /* gui-gtk-2.0 client specific options.
2411 * These are still kept just so users can migrate them to gtk3-client */
2412 GEN_BOOL_OPTION(gui_gtk2_fullscreen, NULL, NULL,
2413 COC_INTERFACE, GUI_GTK2, FALSE, NULL),
2414 GEN_BOOL_OPTION(gui_gtk2_map_scrollbars, NULL, NULL,
2415 COC_INTERFACE, GUI_GTK2, FALSE, NULL),
2416 GEN_BOOL_OPTION(gui_gtk2_dialogs_on_top, NULL, NULL,
2417 COC_INTERFACE, GUI_GTK2, TRUE, NULL),
2418 GEN_BOOL_OPTION(gui_gtk2_show_task_icons, NULL, NULL,
2419 COC_GRAPHICS, GUI_GTK2, TRUE, NULL),
2420 GEN_BOOL_OPTION(gui_gtk2_enable_tabs, NULL, NULL,
2421 COC_INTERFACE, GUI_GTK2, TRUE, NULL),
2422 GEN_BOOL_OPTION(gui_gtk2_better_fog, NULL, NULL,
2423 COC_GRAPHICS, GUI_GTK2,
2424 TRUE, view_option_changed_callback),
2425 GEN_BOOL_OPTION(gui_gtk2_show_chat_message_time, NULL, NULL,
2426 COC_INTERFACE, GUI_GTK2, FALSE, NULL),
2427 GEN_BOOL_OPTION(gui_gtk2_new_messages_go_to_top, NULL, NULL,
2428 COC_INTERFACE, GUI_GTK2, FALSE, NULL),
2429 GEN_BOOL_OPTION(gui_gtk2_show_message_window_buttons, NULL, NULL,
2430 COC_INTERFACE, GUI_GTK2, TRUE, NULL),
2431 GEN_BOOL_OPTION(gui_gtk2_metaserver_tab_first, NULL, NULL,
2432 COC_NETWORK, GUI_GTK2, FALSE, NULL),
2433 GEN_BOOL_OPTION(gui_gtk2_allied_chat_only, NULL, NULL,
2434 COC_INTERFACE, GUI_GTK2, FALSE, NULL),
2435 GEN_ENUM_OPTION(gui_gtk2_message_chat_location, NULL, NULL,
2436 COC_INTERFACE, GUI_GTK2,
2437 GUI_GTK_MSGCHAT_MERGED /* Ignored! See options_load(). */,
2438 gui_gtk_message_chat_location_name, NULL),
2439 GEN_BOOL_OPTION(gui_gtk2_small_display_layout, NULL, NULL,
2440 COC_INTERFACE, GUI_GTK2, TRUE, NULL),
2441 GEN_BOOL_OPTION(gui_gtk2_mouse_over_map_focus, NULL, NULL,
2442 COC_INTERFACE, GUI_GTK2, FALSE, NULL),
2443 GEN_BOOL_OPTION(gui_gtk2_chatline_autocompletion, NULL, NULL,
2444 COC_INTERFACE, GUI_GTK2, TRUE, NULL),
2445 GEN_INT_OPTION(gui_gtk2_citydlg_xsize, NULL, NULL,
2446 COC_INTERFACE, GUI_GTK2, GUI_GTK2_CITYDLG_DEFAULT_XSIZE,
2447 GUI_GTK2_CITYDLG_MIN_XSIZE, GUI_GTK2_CITYDLG_MAX_XSIZE,
2448 NULL),
2449 GEN_INT_OPTION(gui_gtk2_citydlg_ysize, NULL, NULL,
2450 COC_INTERFACE, GUI_GTK2, GUI_GTK2_CITYDLG_DEFAULT_YSIZE,
2451 GUI_GTK2_CITYDLG_MIN_YSIZE, GUI_GTK2_CITYDLG_MAX_YSIZE,
2452 NULL),
2453 GEN_ENUM_OPTION(gui_gtk2_popup_tech_help, NULL, NULL,
2454 COC_INTERFACE, GUI_GTK2,
2455 GUI_POPUP_TECH_HELP_RULESET,
2456 gui_popup_tech_help_name, NULL),
2457 GEN_FONT_OPTION(gui_gtk2_font_city_label, "city_label",
2458 NULL, NULL,
2459 COC_FONT, GUI_GTK2,
2460 "Monospace 8", font_changed_callback),
2461 GEN_FONT_OPTION(gui_gtk2_font_notify_label, "notify_label",
2462 NULL, NULL,
2463 COC_FONT, GUI_GTK2,
2464 "Monospace Bold 9", font_changed_callback),
2465 GEN_FONT_OPTION(gui_gtk2_font_spaceship_label, "spaceship_label",
2466 NULL, NULL,
2467 COC_FONT, GUI_GTK2,
2468 "Monospace 8", font_changed_callback),
2469 GEN_FONT_OPTION(gui_gtk2_font_help_label, "help_label",
2470 NULL, NULL,
2471 COC_FONT, GUI_GTK2,
2472 "Sans Bold 10", font_changed_callback),
2473 GEN_FONT_OPTION(gui_gtk2_font_help_link, "help_link",
2474 NULL, NULL,
2475 COC_FONT, GUI_GTK2,
2476 "Sans 9", font_changed_callback),
2477 GEN_FONT_OPTION(gui_gtk2_font_help_text, "help_text",
2478 NULL, NULL,
2479 COC_FONT, GUI_GTK2,
2480 "Monospace 8", font_changed_callback),
2481 GEN_FONT_OPTION(gui_gtk2_font_chatline, "chatline",
2482 NULL, NULL,
2483 COC_FONT, GUI_GTK2,
2484 "Monospace 8", font_changed_callback),
2485 GEN_FONT_OPTION(gui_gtk2_font_beta_label, "beta_label",
2486 NULL, NULL,
2487 COC_FONT, GUI_GTK2,
2488 "Sans Italic 10", font_changed_callback),
2489 GEN_FONT_OPTION(gui_gtk2_font_small, "small_font",
2490 NULL, NULL,
2491 COC_FONT, GUI_GTK2,
2492 "Sans 9", NULL),
2493 GEN_FONT_OPTION(gui_gtk2_font_comment_label, "comment_label",
2494 NULL, NULL,
2495 COC_FONT, GUI_GTK2,
2496 "Sans Italic 9", font_changed_callback),
2497 GEN_FONT_OPTION(gui_gtk2_font_city_names, "city_names",
2498 NULL, NULL,
2499 COC_FONT, GUI_GTK2,
2500 "Sans Bold 10", NULL),
2501 GEN_FONT_OPTION(gui_gtk2_font_city_productions, "city_productions",
2502 NULL, NULL,
2503 COC_FONT, GUI_GTK2,
2504 "Serif 10", NULL),
2505 GEN_FONT_OPTION(gui_gtk2_font_reqtree_text, "reqtree_text",
2506 NULL, NULL,
2507 COC_FONT, GUI_GTK2,
2508 "Serif 10", NULL),
2510 /* gui-gtk-3.0 client specific options. */
2511 GEN_BOOL_OPTION(gui_gtk3_fullscreen, N_("Fullscreen"),
2512 N_("If this option is set the client will use the "
2513 "whole screen area for drawing."),
2514 COC_INTERFACE, GUI_GTK3, FALSE, NULL),
2515 GEN_BOOL_OPTION(gui_gtk3_map_scrollbars, N_("Show map scrollbars"),
2516 N_("Disable this option to hide the scrollbars on the "
2517 "map view."),
2518 COC_INTERFACE, GUI_GTK3, FALSE, NULL),
2519 GEN_BOOL_OPTION(gui_gtk3_dialogs_on_top, N_("Keep dialogs on top"),
2520 N_("If this option is set then dialog windows will always "
2521 "remain in front of the main Freeciv window. "
2522 "Disabling this has no effect in fullscreen mode."),
2523 COC_INTERFACE, GUI_GTK3, TRUE, NULL),
2524 GEN_BOOL_OPTION(gui_gtk3_show_task_icons, N_("Show worklist task icons"),
2525 N_("Disabling this will turn off the unit and building "
2526 "icons in the worklist dialog and the production "
2527 "tab of the city dialog."),
2528 COC_GRAPHICS, GUI_GTK3, TRUE, NULL),
2529 GEN_BOOL_OPTION(gui_gtk3_enable_tabs, N_("Enable status report tabs"),
2530 N_("If this option is enabled then report dialogs will "
2531 "be shown as separate tabs rather than in popup "
2532 "dialogs."),
2533 COC_INTERFACE, GUI_GTK3, TRUE, NULL),
2534 GEN_BOOL_OPTION(gui_gtk3_show_chat_message_time,
2535 N_("Show time for each chat message"),
2536 N_("If this option is enabled then all chat messages "
2537 "will be prefixed by a time string of the form "
2538 "[hour:minute:second]."),
2539 COC_INTERFACE, GUI_GTK3, FALSE, NULL),
2540 GEN_BOOL_OPTION(gui_gtk3_new_messages_go_to_top,
2541 N_("New message events go to top of list"),
2542 N_("If this option is enabled, new events in the "
2543 "message window will appear at the top of the list, "
2544 "rather than being appended at the bottom."),
2545 COC_INTERFACE, GUI_GTK3, FALSE, NULL),
2546 GEN_BOOL_OPTION(gui_gtk3_show_message_window_buttons,
2547 N_("Show extra message window buttons"),
2548 N_("If this option is enabled, there will be two "
2549 "buttons displayed in the message window for "
2550 "inspecting a city and going to a location. If this "
2551 "option is disabled, these buttons will not appear "
2552 "(you can still double-click with the left mouse "
2553 "button or right-click on a row to inspect or goto "
2554 "respectively). This option will only take effect "
2555 "once the message window is closed and reopened."),
2556 COC_INTERFACE, GUI_GTK3, TRUE, NULL),
2557 GEN_BOOL_OPTION(gui_gtk3_metaserver_tab_first,
2558 N_("Metaserver tab first in network page"),
2559 N_("If this option is enabled, the metaserver tab will "
2560 "be the first notebook tab in the network page. This "
2561 "option requires a restart in order to take effect."),
2562 COC_NETWORK, GUI_GTK3, FALSE, NULL),
2563 GEN_BOOL_OPTION(gui_gtk3_allied_chat_only,
2564 N_("Plain chat messages are sent to allies only"),
2565 N_("If this option is enabled, then plain messages "
2566 "typed into the chat entry while the game is "
2567 "running will only be sent to your allies. "
2568 "Otherwise plain messages will be sent as "
2569 "public chat messages. To send a public chat "
2570 "message with this option enabled, prefix the "
2571 "message with a single colon ':'. This option "
2572 "can also be set using a toggle button beside "
2573 "the chat entry (only visible in multiplayer "
2574 "games)."),
2575 COC_INTERFACE, GUI_GTK3, FALSE, NULL),
2576 GEN_ENUM_OPTION(gui_gtk3_message_chat_location,
2577 N_("Messages and Chat reports location"),
2578 /* TRANS: The strings used in the UI for 'Split' etc are
2579 * tagged 'gui_gtk2/gtk3/gtk3x_message_chat_location' */
2580 N_("Controls where the Messages and Chat reports "
2581 "appear relative to the main view containing the map.\n"
2582 "'Split' allows all three to be seen simultaneously, "
2583 "which is best for multiplayer, but requires a large "
2584 "window to be usable.\n"
2585 "'Separate' puts Messages and Chat in a notebook "
2586 "separate from the main view, so that one of them "
2587 "can always be seen alongside the main view.\n"
2588 "'Merged' makes the Messages and Chat reports into "
2589 "tabs alongside the map and other reports; this "
2590 "allows a larger map view on small screens.\n"
2591 "This option requires a restart in order to take "
2592 "effect."), COC_INTERFACE, GUI_GTK3,
2593 GUI_GTK_MSGCHAT_MERGED /* Ignored! See options_load(). */,
2594 gui_gtk_message_chat_location_name, NULL),
2595 GEN_BOOL_OPTION(gui_gtk3_small_display_layout,
2596 N_("Arrange widgets for small displays"),
2597 N_("If this option is enabled, widgets in the main "
2598 "window will be arranged so that they take up the "
2599 "least amount of total screen space. Specifically, "
2600 "the left panel containing the overview, player "
2601 "status, and the unit information box will be "
2602 "extended over the entire left side of the window. "
2603 "This option requires a restart in order to take "
2604 "effect."), COC_INTERFACE, GUI_GTK3, TRUE, NULL),
2605 GEN_BOOL_OPTION(gui_gtk3_mouse_over_map_focus,
2606 N_("Mouse over the map widget selects it automatically"),
2607 N_("If this option is enabled, then the map will be "
2608 "focused when the mouse hovers over it."),
2609 COC_INTERFACE, GUI_GTK3, FALSE, NULL),
2610 GEN_BOOL_OPTION(gui_gtk3_chatline_autocompletion,
2611 N_("Player or user name autocompletion"),
2612 N_("If this option is turned on, the tabulation key "
2613 "will be used in the chatline to complete the word you "
2614 "are typing with the name of a player or a user."),
2615 COC_INTERFACE, GUI_GTK3, TRUE, NULL),
2616 GEN_INT_OPTION(gui_gtk3_citydlg_xsize,
2617 N_("Width of the city dialog"),
2618 N_("This value is only used if the width of the city "
2619 "dialog is saved."),
2620 COC_INTERFACE, GUI_GTK3, GUI_GTK3_CITYDLG_DEFAULT_XSIZE,
2621 GUI_GTK3_CITYDLG_MIN_XSIZE, GUI_GTK3_CITYDLG_MAX_XSIZE,
2622 NULL),
2623 GEN_INT_OPTION(gui_gtk3_citydlg_ysize,
2624 N_("Height of the city dialog"),
2625 N_("This value is only used if the height of the city "
2626 "dialog is saved."),
2627 COC_INTERFACE, GUI_GTK3, GUI_GTK3_CITYDLG_DEFAULT_YSIZE,
2628 GUI_GTK3_CITYDLG_MIN_YSIZE, GUI_GTK3_CITYDLG_MAX_YSIZE,
2629 NULL),
2630 GEN_ENUM_OPTION(gui_gtk3_popup_tech_help,
2631 N_("Popup tech help when gained"),
2632 N_("Controls if tech help should be opened when "
2633 "new tech has been gained.\n"
2634 "'Ruleset' means that behavior suggested by "
2635 "current ruleset is used."), COC_INTERFACE, GUI_GTK3,
2636 GUI_POPUP_TECH_HELP_RULESET,
2637 gui_popup_tech_help_name, NULL),
2638 GEN_INT_OPTION(gui_gtk3_governor_range_min,
2639 N_("Minimum surplus for a governor"),
2640 N_("The lower limit of the range for requesting surpluses "
2641 "from the governor."),
2642 COC_INTERFACE, GUI_GTK3, GUI_GTK3_GOV_RANGE_MIN_DEFAULT,
2643 GUI_GTK3_GOV_RANGE_MIN_MIN, GUI_GTK3_GOV_RANGE_MIN_MAX,
2644 NULL),
2645 GEN_INT_OPTION(gui_gtk3_governor_range_max,
2646 N_("Maximum surplus for a governor"),
2647 N_("The higher limit of the range for requesting surpluses "
2648 "from the governor."),
2649 COC_INTERFACE, GUI_GTK3, GUI_GTK3_GOV_RANGE_MAX_DEFAULT,
2650 GUI_GTK3_GOV_RANGE_MAX_MIN, GUI_GTK3_GOV_RANGE_MAX_MAX,
2651 NULL),
2652 GEN_FONT_OPTION(gui_gtk3_font_city_label, "city_label",
2653 N_("City Label"),
2654 N_("This font is used to display the city labels on city "
2655 "dialogs."),
2656 COC_FONT, GUI_GTK3,
2657 "Monospace 8", font_changed_callback),
2658 GEN_FONT_OPTION(gui_gtk3_font_notify_label, "notify_label",
2659 N_("Notify Label"),
2660 N_("This font is used to display server reports such "
2661 "as the demographic report or historian publications."),
2662 COC_FONT, GUI_GTK3,
2663 "Monospace Bold 9", font_changed_callback),
2664 GEN_FONT_OPTION(gui_gtk3_font_spaceship_label, "spaceship_label",
2665 N_("Spaceship Label"),
2666 N_("This font is used to display the spaceship widgets."),
2667 COC_FONT, GUI_GTK3,
2668 "Monospace 8", font_changed_callback),
2669 GEN_FONT_OPTION(gui_gtk3_font_help_label, "help_label",
2670 N_("Help Label"),
2671 N_("This font is used to display the help headers in the "
2672 "help window."),
2673 COC_FONT, GUI_GTK3,
2674 "Sans Bold 10", font_changed_callback),
2675 GEN_FONT_OPTION(gui_gtk3_font_help_link, "help_link",
2676 N_("Help Link"),
2677 N_("This font is used to display the help links in the "
2678 "help window."),
2679 COC_FONT, GUI_GTK3,
2680 "Sans 9", font_changed_callback),
2681 GEN_FONT_OPTION(gui_gtk3_font_help_text, "help_text",
2682 N_("Help Text"),
2683 N_("This font is used to display the help body text in "
2684 "the help window."),
2685 COC_FONT, GUI_GTK3,
2686 "Monospace 8", font_changed_callback),
2687 GEN_FONT_OPTION(gui_gtk3_font_chatline, "chatline",
2688 N_("Chatline Area"),
2689 N_("This font is used to display the text in the "
2690 "chatline area."),
2691 COC_FONT, GUI_GTK3,
2692 "Monospace 8", font_changed_callback),
2693 GEN_FONT_OPTION(gui_gtk3_font_beta_label, "beta_label",
2694 N_("Beta Label"),
2695 N_("This font is used to display the beta label."),
2696 COC_FONT, GUI_GTK3,
2697 "Sans Italic 10", font_changed_callback),
2698 GEN_FONT_OPTION(gui_gtk3_font_small, "small_font",
2699 N_("Small Font"),
2700 N_("This font is used for any small font request. For "
2701 "example, it is used for display the building lists "
2702 "in the city dialog, the Economy report or the Units "
2703 "report."),
2704 COC_FONT, GUI_GTK3,
2705 "Sans 9", NULL),
2706 GEN_FONT_OPTION(gui_gtk3_font_comment_label, "comment_label",
2707 N_("Comment Label"),
2708 N_("This font is used to display comment labels, such as "
2709 "in the governor page of the city dialogs."),
2710 COC_FONT, GUI_GTK3,
2711 "Sans Italic 9", font_changed_callback),
2712 GEN_FONT_OPTION(gui_gtk3_font_city_names, "city_names",
2713 N_("City Names"),
2714 N_("This font is used to the display the city names "
2715 "on the map."),
2716 COC_FONT, GUI_GTK3,
2717 "Sans Bold 10", NULL),
2718 GEN_FONT_OPTION(gui_gtk3_font_city_productions, "city_productions",
2719 N_("City Productions"),
2720 N_("This font is used to the display the city production "
2721 "names on the map."),
2722 COC_FONT, GUI_GTK3,
2723 "Serif 10", NULL),
2724 GEN_FONT_OPTION(gui_gtk3_font_reqtree_text, "reqtree_text",
2725 N_("Requirement Tree"),
2726 N_("This font is used to the display the requirement tree "
2727 "in the Research report."),
2728 COC_FONT, GUI_GTK3,
2729 "Serif 10", NULL),
2731 /* gui-gtk-3.22 client specific options. */
2732 GEN_BOOL_OPTION(gui_gtk3_22_fullscreen, N_("Fullscreen"),
2733 N_("If this option is set the client will use the "
2734 "whole screen area for drawing."),
2735 COC_INTERFACE, GUI_GTK3_22, FALSE, NULL),
2736 GEN_BOOL_OPTION(gui_gtk3_22_map_scrollbars, N_("Show map scrollbars"),
2737 N_("Disable this option to hide the scrollbars on the "
2738 "map view."),
2739 COC_INTERFACE, GUI_GTK3_22, FALSE, NULL),
2740 GEN_BOOL_OPTION(gui_gtk3_22_dialogs_on_top, N_("Keep dialogs on top"),
2741 N_("If this option is set then dialog windows will always "
2742 "remain in front of the main Freeciv window. "
2743 "Disabling this has no effect in fullscreen mode."),
2744 COC_INTERFACE, GUI_GTK3_22, TRUE, NULL),
2745 GEN_BOOL_OPTION(gui_gtk3_22_show_task_icons, N_("Show worklist task icons"),
2746 N_("Disabling this will turn off the unit and building "
2747 "icons in the worklist dialog and the production "
2748 "tab of the city dialog."),
2749 COC_GRAPHICS, GUI_GTK3_22, TRUE, NULL),
2750 GEN_BOOL_OPTION(gui_gtk3_22_enable_tabs, N_("Enable status report tabs"),
2751 N_("If this option is enabled then report dialogs will "
2752 "be shown as separate tabs rather than in popup "
2753 "dialogs."),
2754 COC_INTERFACE, GUI_GTK3_22, TRUE, NULL),
2755 GEN_BOOL_OPTION(gui_gtk3_22_show_chat_message_time,
2756 N_("Show time for each chat message"),
2757 N_("If this option is enabled then all chat messages "
2758 "will be prefixed by a time string of the form "
2759 "[hour:minute:second]."),
2760 COC_INTERFACE, GUI_GTK3_22, FALSE, NULL),
2761 GEN_BOOL_OPTION(gui_gtk3_22_new_messages_go_to_top,
2762 N_("New message events go to top of list"),
2763 N_("If this option is enabled, new events in the "
2764 "message window will appear at the top of the list, "
2765 "rather than being appended at the bottom."),
2766 COC_INTERFACE, GUI_GTK3_22, FALSE, NULL),
2767 GEN_BOOL_OPTION(gui_gtk3_22_show_message_window_buttons,
2768 N_("Show extra message window buttons"),
2769 N_("If this option is enabled, there will be two "
2770 "buttons displayed in the message window for "
2771 "inspecting a city and going to a location. If this "
2772 "option is disabled, these buttons will not appear "
2773 "(you can still double-click with the left mouse "
2774 "button or right-click on a row to inspect or goto "
2775 "respectively). This option will only take effect "
2776 "once the message window is closed and reopened."),
2777 COC_INTERFACE, GUI_GTK3_22, TRUE, NULL),
2778 GEN_BOOL_OPTION(gui_gtk3_22_metaserver_tab_first,
2779 N_("Metaserver tab first in network page"),
2780 N_("If this option is enabled, the metaserver tab will "
2781 "be the first notebook tab in the network page. This "
2782 "option requires a restart in order to take effect."),
2783 COC_NETWORK, GUI_GTK3_22, FALSE, NULL),
2784 GEN_BOOL_OPTION(gui_gtk3_22_allied_chat_only,
2785 N_("Plain chat messages are sent to allies only"),
2786 N_("If this option is enabled, then plain messages "
2787 "typed into the chat entry while the game is "
2788 "running will only be sent to your allies. "
2789 "Otherwise plain messages will be sent as "
2790 "public chat messages. To send a public chat "
2791 "message with this option enabled, prefix the "
2792 "message with a single colon ':'. This option "
2793 "can also be set using a toggle button beside "
2794 "the chat entry (only visible in multiplayer "
2795 "games)."),
2796 COC_INTERFACE, GUI_GTK3_22, FALSE, NULL),
2797 GEN_ENUM_OPTION(gui_gtk3_22_message_chat_location,
2798 N_("Messages and Chat reports location"),
2799 /* TRANS: The strings used in the UI for 'Split' etc are
2800 * tagged 'gui_gtk2/gtk3/gtk3x_message_chat_location' */
2801 N_("Controls where the Messages and Chat reports "
2802 "appear relative to the main view containing the map.\n"
2803 "'Split' allows all three to be seen simultaneously, "
2804 "which is best for multiplayer, but requires a large "
2805 "window to be usable.\n"
2806 "'Separate' puts Messages and Chat in a notebook "
2807 "separate from the main view, so that one of them "
2808 "can always be seen alongside the main view.\n"
2809 "'Merged' makes the Messages and Chat reports into "
2810 "tabs alongside the map and other reports; this "
2811 "allows a larger map view on small screens.\n"
2812 "This option requires a restart in order to take "
2813 "effect."), COC_INTERFACE, GUI_GTK3_22,
2814 GUI_GTK_MSGCHAT_MERGED /* Ignored! See options_load(). */,
2815 gui_gtk_message_chat_location_name, NULL),
2816 GEN_BOOL_OPTION(gui_gtk3_22_small_display_layout,
2817 N_("Arrange widgets for small displays"),
2818 N_("If this option is enabled, widgets in the main "
2819 "window will be arranged so that they take up the "
2820 "least amount of total screen space. Specifically, "
2821 "the left panel containing the overview, player "
2822 "status, and the unit information box will be "
2823 "extended over the entire left side of the window. "
2824 "This option requires a restart in order to take "
2825 "effect."), COC_INTERFACE, GUI_GTK3_22, TRUE, NULL),
2826 GEN_BOOL_OPTION(gui_gtk3_22_mouse_over_map_focus,
2827 N_("Mouse over the map widget selects it automatically"),
2828 N_("If this option is enabled, then the map will be "
2829 "focused when the mouse hovers over it."),
2830 COC_INTERFACE, GUI_GTK3_22, FALSE, NULL),
2831 GEN_BOOL_OPTION(gui_gtk3_22_chatline_autocompletion,
2832 N_("Player or user name autocompletion"),
2833 N_("If this option is turned on, the tabulation key "
2834 "will be used in the chatline to complete the word you "
2835 "are typing with the name of a player or a user."),
2836 COC_INTERFACE, GUI_GTK3_22, TRUE, NULL),
2837 GEN_INT_OPTION(gui_gtk3_22_citydlg_xsize,
2838 N_("Width of the city dialog"),
2839 N_("This value is only used if the width of the city "
2840 "dialog is saved."),
2841 COC_INTERFACE, GUI_GTK3_22, GUI_GTK3_22_CITYDLG_DEFAULT_XSIZE,
2842 GUI_GTK3_22_CITYDLG_MIN_XSIZE, GUI_GTK3_22_CITYDLG_MAX_XSIZE,
2843 NULL),
2844 GEN_INT_OPTION(gui_gtk3_22_citydlg_ysize,
2845 N_("Height of the city dialog"),
2846 N_("This value is only used if the height of the city "
2847 "dialog is saved."),
2848 COC_INTERFACE, GUI_GTK3_22, GUI_GTK3_22_CITYDLG_DEFAULT_YSIZE,
2849 GUI_GTK3_22_CITYDLG_MIN_YSIZE, GUI_GTK3_22_CITYDLG_MAX_YSIZE,
2850 NULL),
2851 GEN_ENUM_OPTION(gui_gtk3_22_popup_tech_help,
2852 N_("Popup tech help when gained"),
2853 N_("Controls if tech help should be opened when "
2854 "new tech has been gained.\n"
2855 "'Ruleset' means that behavior suggested by "
2856 "current ruleset is used."), COC_INTERFACE, GUI_GTK3_22,
2857 GUI_POPUP_TECH_HELP_RULESET,
2858 gui_popup_tech_help_name, NULL),
2859 GEN_INT_OPTION(gui_gtk3_22_governor_range_min,
2860 N_("Minimum surplus for a governor"),
2861 N_("The lower limit of the range for requesting surpluses "
2862 "from the governor."),
2863 COC_INTERFACE, GUI_GTK3_22, GUI_GTK3_22_GOV_RANGE_MIN_DEFAULT,
2864 GUI_GTK3_22_GOV_RANGE_MIN_MIN, GUI_GTK3_22_GOV_RANGE_MIN_MAX,
2865 NULL),
2866 GEN_INT_OPTION(gui_gtk3_22_governor_range_max,
2867 N_("Maximum surplus for a governor"),
2868 N_("The higher limit of the range for requesting surpluses "
2869 "from the governor."),
2870 COC_INTERFACE, GUI_GTK3_22, GUI_GTK3_22_GOV_RANGE_MAX_DEFAULT,
2871 GUI_GTK3_22_GOV_RANGE_MAX_MIN, GUI_GTK3_22_GOV_RANGE_MAX_MAX,
2872 NULL),
2873 GEN_FONT_OPTION(gui_gtk3_22_font_city_label, "city_label",
2874 N_("City Label"),
2875 N_("This font is used to display the city labels on city "
2876 "dialogs."),
2877 COC_FONT, GUI_GTK3_22,
2878 "Monospace 8", font_changed_callback),
2879 GEN_FONT_OPTION(gui_gtk3_22_font_notify_label, "notify_label",
2880 N_("Notify Label"),
2881 N_("This font is used to display server reports such "
2882 "as the demographic report or historian publications."),
2883 COC_FONT, GUI_GTK3_22,
2884 "Monospace Bold 9", font_changed_callback),
2885 GEN_FONT_OPTION(gui_gtk3_22_font_spaceship_label, "spaceship_label",
2886 N_("Spaceship Label"),
2887 N_("This font is used to display the spaceship widgets."),
2888 COC_FONT, GUI_GTK3_22,
2889 "Monospace 8", font_changed_callback),
2890 GEN_FONT_OPTION(gui_gtk3_22_font_help_label, "help_label",
2891 N_("Help Label"),
2892 N_("This font is used to display the help headers in the "
2893 "help window."),
2894 COC_FONT, GUI_GTK3_22,
2895 "Sans Bold 10", font_changed_callback),
2896 GEN_FONT_OPTION(gui_gtk3_22_font_help_link, "help_link",
2897 N_("Help Link"),
2898 N_("This font is used to display the help links in the "
2899 "help window."),
2900 COC_FONT, GUI_GTK3_22,
2901 "Sans 9", font_changed_callback),
2902 GEN_FONT_OPTION(gui_gtk3_22_font_help_text, "help_text",
2903 N_("Help Text"),
2904 N_("This font is used to display the help body text in "
2905 "the help window."),
2906 COC_FONT, GUI_GTK3_22,
2907 "Monospace 8", font_changed_callback),
2908 GEN_FONT_OPTION(gui_gtk3_22_font_chatline, "chatline",
2909 N_("Chatline Area"),
2910 N_("This font is used to display the text in the "
2911 "chatline area."),
2912 COC_FONT, GUI_GTK3_22,
2913 "Monospace 8", font_changed_callback),
2914 GEN_FONT_OPTION(gui_gtk3_22_font_beta_label, "beta_label",
2915 N_("Beta Label"),
2916 N_("This font is used to display the beta label."),
2917 COC_FONT, GUI_GTK3_22,
2918 "Sans Italic 10", font_changed_callback),
2919 GEN_FONT_OPTION(gui_gtk3_22_font_small, "small_font",
2920 N_("Small Font"),
2921 N_("This font is used for any small font request. For "
2922 "example, it is used for display the building lists "
2923 "in the city dialog, the Economy report or the Units "
2924 "report."),
2925 COC_FONT, GUI_GTK3_22,
2926 "Sans 9", NULL),
2927 GEN_FONT_OPTION(gui_gtk3_22_font_comment_label, "comment_label",
2928 N_("Comment Label"),
2929 N_("This font is used to display comment labels, such as "
2930 "in the governor page of the city dialogs."),
2931 COC_FONT, GUI_GTK3_22,
2932 "Sans Italic 9", font_changed_callback),
2933 GEN_FONT_OPTION(gui_gtk3_22_font_city_names, "city_names",
2934 N_("City Names"),
2935 N_("This font is used to the display the city names "
2936 "on the map."),
2937 COC_FONT, GUI_GTK3_22,
2938 "Sans Bold 10", NULL),
2939 GEN_FONT_OPTION(gui_gtk3_22_font_city_productions, "city_productions",
2940 N_("City Productions"),
2941 N_("This font is used to the display the city production "
2942 "names on the map."),
2943 COC_FONT, GUI_GTK3_22,
2944 "Serif 10", NULL),
2945 GEN_FONT_OPTION(gui_gtk3_22_font_reqtree_text, "reqtree_text",
2946 N_("Requirement Tree"),
2947 N_("This font is used to the display the requirement tree "
2948 "in the Research report."),
2949 COC_FONT, GUI_GTK3_22,
2950 "Serif 10", NULL),
2952 /* gui-gtk-3.x client specific options. */
2953 GEN_BOOL_OPTION(gui_gtk4_fullscreen, N_("Fullscreen"),
2954 N_("If this option is set the client will use the "
2955 "whole screen area for drawing."),
2956 COC_INTERFACE, GUI_GTK3x, FALSE, NULL),
2957 GEN_BOOL_OPTION(gui_gtk4_map_scrollbars, N_("Show map scrollbars"),
2958 N_("Disable this option to hide the scrollbars on the "
2959 "map view."),
2960 COC_INTERFACE, GUI_GTK3x, FALSE, NULL),
2961 GEN_BOOL_OPTION(gui_gtk4_dialogs_on_top, N_("Keep dialogs on top"),
2962 N_("If this option is set then dialog windows will always "
2963 "remain in front of the main Freeciv window. "
2964 "Disabling this has no effect in fullscreen mode."),
2965 COC_INTERFACE, GUI_GTK3x, TRUE, NULL),
2966 GEN_BOOL_OPTION(gui_gtk4_show_task_icons, N_("Show worklist task icons"),
2967 N_("Disabling this will turn off the unit and building "
2968 "icons in the worklist dialog and the production "
2969 "tab of the city dialog."),
2970 COC_GRAPHICS, GUI_GTK3x, TRUE, NULL),
2971 GEN_BOOL_OPTION(gui_gtk4_enable_tabs, N_("Enable status report tabs"),
2972 N_("If this option is enabled then report dialogs will "
2973 "be shown as separate tabs rather than in popup "
2974 "dialogs."),
2975 COC_INTERFACE, GUI_GTK3x, TRUE, NULL),
2976 GEN_BOOL_OPTION(gui_gtk4_show_chat_message_time,
2977 N_("Show time for each chat message"),
2978 N_("If this option is enabled then all chat messages "
2979 "will be prefixed by a time string of the form "
2980 "[hour:minute:second]."),
2981 COC_INTERFACE, GUI_GTK3x, FALSE, NULL),
2982 GEN_BOOL_OPTION(gui_gtk4_new_messages_go_to_top,
2983 N_("New message events go to top of list"),
2984 N_("If this option is enabled, new events in the "
2985 "message window will appear at the top of the list, "
2986 "rather than being appended at the bottom."),
2987 COC_INTERFACE, GUI_GTK3x, FALSE, NULL),
2988 GEN_BOOL_OPTION(gui_gtk4_show_message_window_buttons,
2989 N_("Show extra message window buttons"),
2990 N_("If this option is enabled, there will be two "
2991 "buttons displayed in the message window for "
2992 "inspecting a city and going to a location. If this "
2993 "option is disabled, these buttons will not appear "
2994 "(you can still double-click with the left mouse "
2995 "button or right-click on a row to inspect or goto "
2996 "respectively). This option will only take effect "
2997 "once the message window is closed and reopened."),
2998 COC_INTERFACE, GUI_GTK3x, TRUE, NULL),
2999 GEN_BOOL_OPTION(gui_gtk4_metaserver_tab_first,
3000 N_("Metaserver tab first in network page"),
3001 N_("If this option is enabled, the metaserver tab will "
3002 "be the first notebook tab in the network page. This "
3003 "option requires a restart in order to take effect."),
3004 COC_NETWORK, GUI_GTK3x, FALSE, NULL),
3005 GEN_BOOL_OPTION(gui_gtk4_allied_chat_only,
3006 N_("Plain chat messages are sent to allies only"),
3007 N_("If this option is enabled, then plain messages "
3008 "typed into the chat entry while the game is "
3009 "running will only be sent to your allies. "
3010 "Otherwise plain messages will be sent as "
3011 "public chat messages. To send a public chat "
3012 "message with this option enabled, prefix the "
3013 "message with a single colon ':'. This option "
3014 "can also be set using a toggle button beside "
3015 "the chat entry (only visible in multiplayer "
3016 "games)."),
3017 COC_INTERFACE, GUI_GTK3x, FALSE, NULL),
3018 GEN_ENUM_OPTION(gui_gtk4_message_chat_location,
3019 N_("Messages and Chat reports location"),
3020 /* TRANS: The strings used in the UI for 'Split' etc are
3021 * tagged 'gui_gtk2/gtk3/gtk3x_message_chat_location' */
3022 N_("Controls where the Messages and Chat reports "
3023 "appear relative to the main view containing the map.\n"
3024 "'Split' allows all three to be seen simultaneously, "
3025 "which is best for multiplayer, but requires a large "
3026 "window to be usable.\n"
3027 "'Separate' puts Messages and Chat in a notebook "
3028 "separate from the main view, so that one of them "
3029 "can always be seen alongside the main view.\n"
3030 "'Merged' makes the Messages and Chat reports into "
3031 "tabs alongside the map and other reports; this "
3032 "allows a larger map view on small screens.\n"
3033 "This option requires a restart in order to take "
3034 "effect."), COC_INTERFACE, GUI_GTK3x,
3035 GUI_GTK_MSGCHAT_MERGED /* Ignored! See options_load(). */,
3036 gui_gtk_message_chat_location_name, NULL),
3037 GEN_BOOL_OPTION(gui_gtk4_small_display_layout,
3038 N_("Arrange widgets for small displays"),
3039 N_("If this option is enabled, widgets in the main "
3040 "window will be arranged so that they take up the "
3041 "least amount of total screen space. Specifically, "
3042 "the left panel containing the overview, player "
3043 "status, and the unit information box will be "
3044 "extended over the entire left side of the window. "
3045 "This option requires a restart in order to take "
3046 "effect."), COC_INTERFACE, GUI_GTK3x, TRUE, NULL),
3047 GEN_BOOL_OPTION(gui_gtk4_mouse_over_map_focus,
3048 N_("Mouse over the map widget selects it automatically"),
3049 N_("If this option is enabled, then the map will be "
3050 "focused when the mouse hovers over it."),
3051 COC_INTERFACE, GUI_GTK3x, FALSE, NULL),
3052 GEN_BOOL_OPTION(gui_gtk4_chatline_autocompletion,
3053 N_("Player or user name autocompletion"),
3054 N_("If this option is turned on, the tabulation key "
3055 "will be used in the chatline to complete the word you "
3056 "are typing with the name of a player or a user."),
3057 COC_INTERFACE, GUI_GTK3x, TRUE, NULL),
3058 GEN_INT_OPTION(gui_gtk4_citydlg_xsize,
3059 N_("Width of the city dialog"),
3060 N_("This value is only used if the width of the city "
3061 "dialog is saved."),
3062 COC_INTERFACE, GUI_GTK3x, GUI_GTK4_CITYDLG_DEFAULT_XSIZE,
3063 GUI_GTK4_CITYDLG_MIN_XSIZE, GUI_GTK4_CITYDLG_MAX_XSIZE,
3064 NULL),
3065 GEN_INT_OPTION(gui_gtk4_citydlg_ysize,
3066 N_("Height of the city dialog"),
3067 N_("This value is only used if the height of the city "
3068 "dialog is saved."),
3069 COC_INTERFACE, GUI_GTK3x, GUI_GTK4_CITYDLG_DEFAULT_YSIZE,
3070 GUI_GTK4_CITYDLG_MIN_YSIZE, GUI_GTK4_CITYDLG_MAX_YSIZE,
3071 NULL),
3072 GEN_ENUM_OPTION(gui_gtk4_popup_tech_help,
3073 N_("Popup tech help when gained"),
3074 N_("Controls if tech help should be opened when "
3075 "new tech has been gained.\n"
3076 "'Ruleset' means that behavior suggested by "
3077 "current ruleset is used."), COC_INTERFACE, GUI_GTK3x,
3078 GUI_POPUP_TECH_HELP_RULESET,
3079 gui_popup_tech_help_name, NULL),
3080 GEN_INT_OPTION(gui_gtk4_governor_range_min,
3081 N_("Minimum surplus for a governor"),
3082 N_("The lower limit of the range for requesting surpluses "
3083 "from the governor."),
3084 COC_INTERFACE, GUI_GTK3x, GUI_GTK4_GOV_RANGE_MIN_DEFAULT,
3085 GUI_GTK4_GOV_RANGE_MIN_MIN, GUI_GTK4_GOV_RANGE_MIN_MAX,
3086 NULL),
3087 GEN_INT_OPTION(gui_gtk4_governor_range_max,
3088 N_("Maximum surplus for a governor"),
3089 N_("The higher limit of the range for requesting surpluses "
3090 "from the governor."),
3091 COC_INTERFACE, GUI_GTK3x, GUI_GTK4_GOV_RANGE_MAX_DEFAULT,
3092 GUI_GTK4_GOV_RANGE_MAX_MIN, GUI_GTK4_GOV_RANGE_MAX_MAX,
3093 NULL),
3094 GEN_FONT_OPTION(gui_gtk4_font_city_label, "city_label",
3095 N_("City Label"),
3096 N_("This font is used to display the city labels on city "
3097 "dialogs."),
3098 COC_FONT, GUI_GTK3x,
3099 "Monospace 8", font_changed_callback),
3100 GEN_FONT_OPTION(gui_gtk4_font_notify_label, "notify_label",
3101 N_("Notify Label"),
3102 N_("This font is used to display server reports such "
3103 "as the demographic report or historian publications."),
3104 COC_FONT, GUI_GTK3x,
3105 "Monospace Bold 9", font_changed_callback),
3106 GEN_FONT_OPTION(gui_gtk4_font_spaceship_label, "spaceship_label",
3107 N_("Spaceship Label"),
3108 N_("This font is used to display the spaceship widgets."),
3109 COC_FONT, GUI_GTK3x,
3110 "Monospace 8", font_changed_callback),
3111 GEN_FONT_OPTION(gui_gtk4_font_help_label, "help_label",
3112 N_("Help Label"),
3113 N_("This font is used to display the help headers in the "
3114 "help window."),
3115 COC_FONT, GUI_GTK3x,
3116 "Sans Bold 10", font_changed_callback),
3117 GEN_FONT_OPTION(gui_gtk4_font_help_link, "help_link",
3118 N_("Help Link"),
3119 N_("This font is used to display the help links in the "
3120 "help window."),
3121 COC_FONT, GUI_GTK3x,
3122 "Sans 9", font_changed_callback),
3123 GEN_FONT_OPTION(gui_gtk4_font_help_text, "help_text",
3124 N_("Help Text"),
3125 N_("This font is used to display the help body text in "
3126 "the help window."),
3127 COC_FONT, GUI_GTK3x,
3128 "Monospace 8", font_changed_callback),
3129 GEN_FONT_OPTION(gui_gtk4_font_chatline, "chatline",
3130 N_("Chatline Area"),
3131 N_("This font is used to display the text in the "
3132 "chatline area."),
3133 COC_FONT, GUI_GTK3x,
3134 "Monospace 8", font_changed_callback),
3135 GEN_FONT_OPTION(gui_gtk4_font_beta_label, "beta_label",
3136 N_("Beta Label"),
3137 N_("This font is used to display the beta label."),
3138 COC_FONT, GUI_GTK3x,
3139 "Sans Italic 10", font_changed_callback),
3140 GEN_FONT_OPTION(gui_gtk4_font_small, "small_font",
3141 N_("Small Font"),
3142 N_("This font is used for any small font request. For "
3143 "example, it is used for display the building lists "
3144 "in the city dialog, the Economy report or the Units "
3145 "report."),
3146 COC_FONT, GUI_GTK3x,
3147 "Sans 9", NULL),
3148 GEN_FONT_OPTION(gui_gtk4_font_comment_label, "comment_label",
3149 N_("Comment Label"),
3150 N_("This font is used to display comment labels, such as "
3151 "in the governor page of the city dialogs."),
3152 COC_FONT, GUI_GTK3x,
3153 "Sans Italic 9", font_changed_callback),
3154 GEN_FONT_OPTION(gui_gtk4_font_city_names, "city_names",
3155 N_("City Names"),
3156 N_("This font is used to the display the city names "
3157 "on the map."),
3158 COC_FONT, GUI_GTK3x,
3159 "Sans Bold 10", NULL),
3160 GEN_FONT_OPTION(gui_gtk4_font_city_productions, "city_productions",
3161 N_("City Productions"),
3162 N_("This font is used to the display the city production "
3163 "names on the map."),
3164 COC_FONT, GUI_GTK3x,
3165 "Serif 10", NULL),
3166 GEN_FONT_OPTION(gui_gtk4_font_reqtree_text, "reqtree_text",
3167 N_("Requirement Tree"),
3168 N_("This font is used to the display the requirement tree "
3169 "in the Research report."),
3170 COC_FONT, GUI_GTK3x,
3171 "Serif 10", NULL),
3173 /* gui-sdl client specific options.
3174 * These are still kept just so users can migrate them to sdl2-client */
3175 GEN_BOOL_OPTION(gui_sdl_fullscreen, NULL, NULL,
3176 COC_INTERFACE, GUI_SDL, FALSE, NULL),
3177 GEN_VIDEO_OPTION(gui_sdl_screen, NULL, NULL,
3178 COC_INTERFACE, GUI_SDL, 640, 480, NULL),
3179 GEN_BOOL_OPTION(gui_sdl_do_cursor_animation, NULL, NULL,
3180 COC_INTERFACE, GUI_SDL, TRUE, NULL),
3181 GEN_BOOL_OPTION(gui_sdl_use_color_cursors, NULL, NULL,
3182 COC_INTERFACE, GUI_SDL, TRUE, NULL),
3184 /* gui-sdl2 client specific options. */
3185 GEN_BOOL_OPTION(gui_sdl2_fullscreen, N_("Fullscreen"),
3186 N_("If this option is set the client will use the "
3187 "whole screen area for drawing."),
3188 COC_INTERFACE, GUI_SDL2, FALSE, NULL),
3189 GEN_VIDEO_OPTION(gui_sdl2_screen, N_("Screen resolution"),
3190 N_("This option controls the resolution of the "
3191 "selected screen."),
3192 COC_INTERFACE, GUI_SDL2, 640, 480, NULL),
3193 GEN_BOOL_OPTION(gui_sdl2_swrenderer, N_("Use software rendering"),
3194 N_("Usually hardware rendering is used when possible. "
3195 "With this option set, software rendering is always used."),
3196 COC_GRAPHICS, GUI_SDL2, FALSE, NULL),
3197 GEN_BOOL_OPTION(gui_sdl2_do_cursor_animation, N_("Do cursor animation"),
3198 N_("If this option is disabled, the cursor will "
3199 "always be displayed as static."),
3200 COC_INTERFACE, GUI_SDL2, TRUE, NULL),
3201 GEN_BOOL_OPTION(gui_sdl2_use_color_cursors, N_("Use color cursors"),
3202 N_("If this option is disabled, the cursor will "
3203 "always be displayed in black and white."),
3204 COC_INTERFACE, GUI_SDL2, TRUE, NULL),
3206 /* gui-qt client specific options. */
3207 GEN_BOOL_OPTION(gui_qt_fullscreen, N_("Fullscreen"),
3208 N_("If this option is set the client will use the "
3209 "whole screen area for drawing."),
3210 COC_INTERFACE, GUI_QT, FALSE, NULL),
3211 GEN_BOOL_OPTION(gui_qt_show_titlebar, N_("Show titlebar"),
3212 N_("If this option is set the client will show a titlebar. "
3213 "If disabled, then no titlebar will be shown, and "
3214 "minimize/maximize/etc buttons will be placed on the "
3215 "menu bar."),
3216 COC_INTERFACE, GUI_QT, TRUE, NULL),
3217 GEN_FONT_OPTION(gui_qt_font_city_label, "city_label",
3218 N_("City Label"),
3219 N_("This font is used to display the city labels on city "
3220 "dialogs."),
3221 COC_FONT, GUI_QT,
3222 "Monospace,8,-1,5,50,0,0,0,0,0", font_changed_callback),
3223 GEN_FONT_OPTION(gui_qt_font_default, "default_font",
3224 N_("Default font"),
3225 N_("This is default font"),
3226 COC_FONT, GUI_QT,
3227 "Sans Serif,10,-1,5,75,0,0,0,0,0", font_changed_callback),
3228 GEN_FONT_OPTION(gui_qt_font_notify_label, "notify_label",
3229 N_("Notify Label"),
3230 N_("This font is used to display server reports such "
3231 "as the demographic report or historian publications."),
3232 COC_FONT, GUI_QT,
3233 "Monospace,9,-1,5,75,0,0,0,0,0", font_changed_callback),
3234 GEN_FONT_OPTION(gui_qt_font_spaceship_label, "spaceship_label",
3235 N_("Spaceship Label"),
3236 N_("This font is used to display the spaceship widgets."),
3237 COC_FONT, GUI_QT,
3238 "Monospace,8,-1,5,50,0,0,0,0,0", font_changed_callback),
3239 GEN_FONT_OPTION(gui_qt_font_help_label, "help_label",
3240 N_("Help Label"),
3241 N_("This font is used to display the help labels in the "
3242 "help window."),
3243 COC_FONT, GUI_QT,
3244 "Sans Serif,9,-1,5,50,0,0,0,0,0", font_changed_callback),
3245 GEN_FONT_OPTION(gui_qt_font_help_link, "help_link",
3246 N_("Help Link"),
3247 N_("This font is used to display the help links in the "
3248 "help window."),
3249 COC_FONT, GUI_QT,
3250 "Sans Serif,9,-1,5,50,0,0,0,0,0", font_changed_callback),
3251 GEN_FONT_OPTION(gui_qt_font_help_text, "help_text",
3252 N_("Help Text"),
3253 N_("This font is used to display the help body text in "
3254 "the help window."),
3255 COC_FONT, GUI_QT,
3256 "Monospace,8,-1,5,50,0,0,0,0,0", font_changed_callback),
3257 GEN_FONT_OPTION(gui_qt_font_help_title, "help_title",
3258 N_("Help Title"),
3259 N_("This font is used to display the help title in "
3260 "the help window."),
3261 COC_FONT, GUI_QT,
3262 "Sans Serif,10,-1,5,75,0,0,0,0,0", font_changed_callback),
3263 GEN_FONT_OPTION(gui_qt_font_chatline, "chatline",
3264 N_("Chatline Area"),
3265 N_("This font is used to display the text in the "
3266 "chatline area."),
3267 COC_FONT, GUI_QT,
3268 "Monospace,8,-1,5,50,0,0,0,0,0", font_changed_callback),
3269 GEN_FONT_OPTION(gui_qt_font_beta_label, "beta_label",
3270 N_("Beta Label"),
3271 N_("This font is used to display the beta label."),
3272 COC_FONT, GUI_QT,
3273 "Sans Serif,10,-1,5,50,1,0,0,0,0", font_changed_callback),
3274 GEN_FONT_OPTION(gui_qt_font_small, "small_font",
3275 N_("Small Font"),
3276 N_("This font is used for any small font request. For "
3277 "example, it is used for display the building lists "
3278 "in the city dialog, the Economy report or the Units "
3279 "report."),
3280 COC_FONT, GUI_QT,
3281 "Sans Serif,9,-1,5,50,0,0,0,0,0", font_changed_callback),
3282 GEN_FONT_OPTION(gui_qt_font_comment_label, "comment_label",
3283 N_("Comment Label"),
3284 N_("This font is used to display comment labels, such as "
3285 "in the governor page of the city dialogs."),
3286 COC_FONT, GUI_QT,
3287 "Sans Serif,9,-1,5,50,1,0,0,0,0", font_changed_callback),
3288 GEN_FONT_OPTION(gui_qt_font_city_names, "city_names",
3289 N_("City Names"),
3290 N_("This font is used to the display the city names "
3291 "on the map."),
3292 COC_FONT, GUI_QT,
3293 "Sans Serif,10,-1,5,75,0,0,0,0,0", font_changed_callback),
3294 GEN_FONT_OPTION(gui_qt_font_city_productions, "city_productions",
3295 N_("City Productions"),
3296 N_("This font is used to the display the city production "
3297 "names on the map."),
3298 COC_FONT, GUI_QT,
3299 "Sans Serif,10,-1,5,50,1,0,0,0,0", font_changed_callback),
3300 GEN_FONT_OPTION(gui_qt_font_reqtree_text, "reqtree_text",
3301 N_("Requirement Tree"),
3302 N_("This font is used to the display the requirement tree "
3303 "in the Research report."),
3304 COC_FONT, GUI_QT,
3305 "Sans Serif,10,-1,5,50,1,0,0,0,0", font_changed_callback),
3306 GEN_BOOL_OPTION(gui_qt_show_preview, N_("Show savegame information"),
3307 N_("If this option is set the client will show "
3308 "information and map preview about current savegame "),
3309 COC_GRAPHICS, GUI_QT, TRUE, NULL),
3310 GEN_BOOL_OPTION(gui_qt_sidebar_left, N_("Sidebar position"),
3311 N_("If this option is set sidebar will be on left, "
3312 "otherwise it will on right side of map"),
3313 COC_INTERFACE, GUI_QT, TRUE, NULL),
3314 GEN_STR_OPTION(gui_qt_wakeup_text,
3315 N_("Wake up sequence"),
3316 N_("String which will trigger sound in pregame page, "
3317 "%1 stands for nick"),
3318 COC_INTERFACE, GUI_QT, "Wake up %1", NULL, 0)
3321 static const int client_options_num = ARRAY_SIZE(client_options);
3323 /* Iteration loop, including invalid options for the current gui type. */
3324 #define client_options_iterate_all(poption) \
3326 const struct client_option *const poption##_max = \
3327 client_options + client_options_num; \
3328 struct client_option *client_##poption = client_options; \
3329 struct option *poption; \
3330 for (; client_##poption < poption##_max; client_##poption++) { \
3331 poption = OPTION(client_##poption);
3333 #define client_options_iterate_all_end \
3338 /****************************************************************************
3339 Returns the next valid option pointer for the current gui type.
3340 ****************************************************************************/
3341 static struct client_option *
3342 client_option_next_valid(struct client_option *poption)
3344 const struct client_option *const max =
3345 client_options + client_options_num;
3346 const enum gui_type our_type = get_gui_type();
3348 while (poption < max
3349 && poption->specific != GUI_STUB
3350 && poption->specific != our_type) {
3351 poption++;
3354 return (poption < max ? poption : NULL);
3357 /****************************************************************************
3358 Returns the option corresponding to this id.
3359 ****************************************************************************/
3360 static struct option *client_optset_option_by_number(int id)
3362 if (0 > id || id > client_options_num) {
3363 return NULL;
3365 return OPTION(client_options + id);
3368 /****************************************************************************
3369 Returns the first valid option pointer for the current gui type.
3370 ****************************************************************************/
3371 static struct option *client_optset_option_first(void)
3373 return OPTION(client_option_next_valid(client_options));
3376 /****************************************************************************
3377 Returns the number of client option categories.
3378 ****************************************************************************/
3379 static int client_optset_category_number(void)
3381 return COC_MAX;
3384 /****************************************************************************
3385 Returns the name (translated) of the option class.
3386 ****************************************************************************/
3387 static const char *client_optset_category_name(int category)
3389 switch (category) {
3390 case COC_GRAPHICS:
3391 return _("Graphics");
3392 case COC_OVERVIEW:
3393 /* TRANS: Options section for overview map (mini-map) */
3394 return Q_("?map:Overview");
3395 case COC_SOUND:
3396 return _("Sound");
3397 case COC_INTERFACE:
3398 return _("Interface");
3399 case COC_MAPIMG:
3400 return _("Map Image");
3401 case COC_NETWORK:
3402 return _("Network");
3403 case COC_FONT:
3404 return _("Font");
3405 case COC_MAX:
3406 break;
3409 log_error("%s: invalid option category number %d.",
3410 __FUNCTION__, category);
3411 return NULL;
3414 /***************************************************************************
3415 Returns the number of this client option.
3416 ****************************************************************************/
3417 static int client_option_number(const struct option *poption)
3419 return CLIENT_OPTION(poption) - client_options;
3422 /****************************************************************************
3423 Returns the name of this client option.
3424 ****************************************************************************/
3425 static const char *client_option_name(const struct option *poption)
3427 return CLIENT_OPTION(poption)->name;
3430 /****************************************************************************
3431 Returns the description of this client option.
3432 ****************************************************************************/
3433 static const char *client_option_description(const struct option *poption)
3435 return _(CLIENT_OPTION(poption)->description);
3438 /****************************************************************************
3439 Returns the help text for this client option.
3440 ****************************************************************************/
3441 static const char *client_option_help_text(const struct option *poption)
3443 return _(CLIENT_OPTION(poption)->help_text);
3446 /****************************************************************************
3447 Returns the category of this client option.
3448 ****************************************************************************/
3449 static int client_option_category(const struct option *poption)
3451 return CLIENT_OPTION(poption)->category;
3454 /****************************************************************************
3455 Returns TRUE if this client option can be modified.
3456 ****************************************************************************/
3457 static bool client_option_is_changeable(const struct option *poption)
3459 return TRUE;
3462 /****************************************************************************
3463 Returns the next valid option pointer for the current gui type.
3464 ****************************************************************************/
3465 static struct option *client_option_next(const struct option *poption)
3467 return OPTION(client_option_next_valid(CLIENT_OPTION(poption) + 1));
3470 /****************************************************************************
3471 Returns the value of this client option of type OT_BOOLEAN.
3472 ****************************************************************************/
3473 static bool client_option_bool_get(const struct option *poption)
3475 return *(CLIENT_OPTION(poption)->boolean.pvalue);
3478 /****************************************************************************
3479 Returns the default value of this client option of type OT_BOOLEAN.
3480 ****************************************************************************/
3481 static bool client_option_bool_def(const struct option *poption)
3483 return CLIENT_OPTION(poption)->boolean.def;
3486 /****************************************************************************
3487 Set the value of this client option of type OT_BOOLEAN. Returns TRUE if
3488 the value changed.
3489 ****************************************************************************/
3490 static bool client_option_bool_set(struct option *poption, bool val)
3492 struct client_option *pcoption = CLIENT_OPTION(poption);
3494 if (*pcoption->boolean.pvalue == val) {
3495 return FALSE;
3498 *pcoption->boolean.pvalue = val;
3499 return TRUE;
3502 /****************************************************************************
3503 Returns the value of this client option of type OT_INTEGER.
3504 ****************************************************************************/
3505 static int client_option_int_get(const struct option *poption)
3507 return *(CLIENT_OPTION(poption)->integer.pvalue);
3510 /****************************************************************************
3511 Returns the default value of this client option of type OT_INTEGER.
3512 ****************************************************************************/
3513 static int client_option_int_def(const struct option *poption)
3515 return CLIENT_OPTION(poption)->integer.def;
3518 /****************************************************************************
3519 Returns the minimal value for this client option of type OT_INTEGER.
3520 ****************************************************************************/
3521 static int client_option_int_min(const struct option *poption)
3523 return CLIENT_OPTION(poption)->integer.min;
3526 /****************************************************************************
3527 Returns the maximal value for this client option of type OT_INTEGER.
3528 ****************************************************************************/
3529 static int client_option_int_max(const struct option *poption)
3531 return CLIENT_OPTION(poption)->integer.max;
3534 /****************************************************************************
3535 Set the value of this client option of type OT_INTEGER. Returns TRUE if
3536 the value changed.
3537 ****************************************************************************/
3538 static bool client_option_int_set(struct option *poption, int val)
3540 struct client_option *pcoption = CLIENT_OPTION(poption);
3542 if (val < pcoption->integer.min
3543 || val > pcoption->integer.max
3544 || *pcoption->integer.pvalue == val) {
3545 return FALSE;
3548 *pcoption->integer.pvalue = val;
3549 return TRUE;
3552 /****************************************************************************
3553 Returns the value of this client option of type OT_STRING.
3554 ****************************************************************************/
3555 static const char *client_option_str_get(const struct option *poption)
3557 return CLIENT_OPTION(poption)->string.pvalue;
3560 /****************************************************************************
3561 Returns the default value of this client option of type OT_STRING.
3562 ****************************************************************************/
3563 static const char *client_option_str_def(const struct option *poption)
3565 return CLIENT_OPTION(poption)->string.def;
3568 /****************************************************************************
3569 Returns the possible string values of this client option of type
3570 OT_STRING.
3571 ****************************************************************************/
3572 static const struct strvec *
3573 client_option_str_values(const struct option *poption)
3575 return (CLIENT_OPTION(poption)->string.val_accessor
3576 ? CLIENT_OPTION(poption)->string.val_accessor(poption) : NULL);
3579 /****************************************************************************
3580 Set the value of this client option of type OT_STRING. Returns TRUE if
3581 the value changed.
3582 ****************************************************************************/
3583 static bool client_option_str_set(struct option *poption, const char *str)
3585 struct client_option *pcoption = CLIENT_OPTION(poption);
3587 if (strlen(str) >= pcoption->string.size
3588 || 0 == strcmp(pcoption->string.pvalue, str)) {
3589 return FALSE;
3592 fc_strlcpy(pcoption->string.pvalue, str, pcoption->string.size);
3593 return TRUE;
3596 /****************************************************************************
3597 Returns the current value of this client option of type OT_ENUM.
3598 ****************************************************************************/
3599 static int client_option_enum_get(const struct option *poption)
3601 return *(CLIENT_OPTION(poption)->enumerator.pvalue);
3604 /****************************************************************************
3605 Returns the default value of this client option of type OT_ENUM.
3606 ****************************************************************************/
3607 static int client_option_enum_def(const struct option *poption)
3609 return CLIENT_OPTION(poption)->enumerator.def;
3612 /****************************************************************************
3613 Returns the possible values of this client option of type OT_ENUM, as
3614 user-visible (translatable but not translated) strings.
3615 ****************************************************************************/
3616 static const struct strvec *
3617 client_option_enum_pretty_names(const struct option *poption)
3619 return CLIENT_OPTION(poption)->enumerator.pretty_names;
3622 /****************************************************************************
3623 Set the value of this client option of type OT_ENUM. Returns TRUE if
3624 the value changed.
3625 ****************************************************************************/
3626 static bool client_option_enum_set(struct option *poption, int val)
3628 struct client_option *pcoption = CLIENT_OPTION(poption);
3630 if (*pcoption->enumerator.pvalue == val
3631 || 0 > val
3632 || val >= strvec_size(pcoption->enumerator.support_names)) {
3633 return FALSE;
3636 *pcoption->enumerator.pvalue = val;
3637 return TRUE;
3640 /****************************************************************************
3641 Returns the "support" name of the value for this client option of type
3642 OT_ENUM (a string suitable for saving in a file).
3643 The prototype must match the 'secfile_enum_name_data_fn_t' type.
3644 ****************************************************************************/
3645 static const char *client_option_enum_secfile_str(secfile_data_t data,
3646 int val)
3648 const struct strvec *names = CLIENT_OPTION(data)->enumerator.support_names;
3650 return (0 <= val && val < strvec_size(names)
3651 ? strvec_get(names, val) : NULL);
3654 #if 0 /* There's no bitwise options currently */
3655 /****************************************************************************
3656 Returns the current value of this client option of type OT_BITWISE.
3657 ****************************************************************************/
3658 static unsigned client_option_bitwise_get(const struct option *poption)
3660 return *(CLIENT_OPTION(poption)->bitwise.pvalue);
3663 /****************************************************************************
3664 Returns the default value of this client option of type OT_BITWISE.
3665 ****************************************************************************/
3666 static unsigned client_option_bitwise_def(const struct option *poption)
3668 return CLIENT_OPTION(poption)->bitwise.def;
3671 /****************************************************************************
3672 Returns the possible values of this client option of type OT_BITWISE, as
3673 user-visible (translatable but not translated) strings.
3674 ****************************************************************************/
3675 static const struct strvec *
3676 client_option_bitwise_pretty_names(const struct option *poption)
3678 return CLIENT_OPTION(poption)->bitwise.pretty_names;
3681 /****************************************************************************
3682 Set the value of this client option of type OT_BITWISE. Returns TRUE if
3683 the value changed.
3684 ****************************************************************************/
3685 static bool client_option_bitwise_set(struct option *poption, unsigned val)
3687 struct client_option *pcoption = CLIENT_OPTION(poption);
3689 if (*pcoption->bitwise.pvalue == val) {
3690 return FALSE;
3693 *pcoption->bitwise.pvalue = val;
3694 return TRUE;
3696 #endif /* 0 */
3698 /****************************************************************************
3699 Returns the "support" name of a single value for this client option of type
3700 OT_BITWISE (a string suitable for saving in a file).
3701 The prototype must match the 'secfile_enum_name_data_fn_t' type.
3702 ****************************************************************************/
3703 static const char *client_option_bitwise_secfile_str(secfile_data_t data,
3704 int val)
3706 const struct strvec *names = CLIENT_OPTION(data)->bitwise.support_names;
3708 return (0 <= val && val < strvec_size(names)
3709 ? strvec_get(names, val) : NULL);
3712 /****************************************************************************
3713 Returns the value of this client option of type OT_FONT.
3714 ****************************************************************************/
3715 static const char *client_option_font_get(const struct option *poption)
3717 return CLIENT_OPTION(poption)->font.pvalue;
3720 /****************************************************************************
3721 Returns the default value of this client option of type OT_FONT.
3722 ****************************************************************************/
3723 static const char *client_option_font_def(const struct option *poption)
3725 return CLIENT_OPTION(poption)->font.def;
3728 /****************************************************************************
3729 Returns the target style name of this client option of type OT_FONT.
3730 ****************************************************************************/
3731 static const char *client_option_font_target(const struct option *poption)
3733 return CLIENT_OPTION(poption)->font.target;
3736 /****************************************************************************
3737 Set the value of this client option of type OT_FONT. Returns TRUE if
3738 the value changed.
3739 ****************************************************************************/
3740 static bool client_option_font_set(struct option *poption, const char *font)
3742 struct client_option *pcoption = CLIENT_OPTION(poption);
3744 if (strlen(font) >= pcoption->font.size
3745 || 0 == strcmp(pcoption->font.pvalue, font)) {
3746 return FALSE;
3749 fc_strlcpy(pcoption->font.pvalue, font, pcoption->font.size);
3750 return TRUE;
3753 /****************************************************************************
3754 Returns the value of this client option of type OT_COLOR.
3755 ****************************************************************************/
3756 static struct ft_color client_option_color_get(const struct option *poption)
3758 return *CLIENT_OPTION(poption)->color.pvalue;
3761 /****************************************************************************
3762 Returns the default value of this client option of type OT_COLOR.
3763 ****************************************************************************/
3764 static struct ft_color client_option_color_def(const struct option *poption)
3766 return CLIENT_OPTION(poption)->color.def;
3769 /****************************************************************************
3770 Set the value of this client option of type OT_COLOR. Returns TRUE if
3771 the value changed.
3772 ****************************************************************************/
3773 static bool client_option_color_set(struct option *poption,
3774 struct ft_color color)
3776 struct ft_color *pcolor = CLIENT_OPTION(poption)->color.pvalue;
3777 bool changed = FALSE;
3779 #define color_set(color_tgt, color) \
3780 if (NULL == color_tgt) { \
3781 if (NULL != color) { \
3782 color_tgt = fc_strdup(color); \
3783 changed = TRUE; \
3785 } else { \
3786 if (NULL == color) { \
3787 free((void *) color_tgt); \
3788 color_tgt = NULL; \
3789 changed = TRUE; \
3790 } else if (0 != strcmp(color_tgt, color)) { \
3791 free((void *) color_tgt); \
3792 color_tgt = fc_strdup(color); \
3793 changed = TRUE; \
3797 color_set(pcolor->foreground, color.foreground);
3798 color_set(pcolor->background, color.background);
3800 #undef color_set
3802 return changed;
3805 /****************************************************************************
3806 Returns the value of this client option of type OT_VIDEO_MODE.
3807 ****************************************************************************/
3808 static struct video_mode
3809 client_option_video_mode_get(const struct option *poption)
3811 return *CLIENT_OPTION(poption)->video_mode.pvalue;
3814 /****************************************************************************
3815 Returns the default value of this client option of type OT_VIDEO_MODE.
3816 ****************************************************************************/
3817 static struct video_mode
3818 client_option_video_mode_def(const struct option *poption)
3820 return CLIENT_OPTION(poption)->video_mode.def;
3823 /****************************************************************************
3824 Set the value of this client option of type OT_VIDEO_MODE. Returns TRUE
3825 if the value changed.
3826 ****************************************************************************/
3827 static bool client_option_video_mode_set(struct option *poption,
3828 struct video_mode mode)
3830 struct client_option *pcoption = CLIENT_OPTION(poption);
3832 if (0 == memcmp(&mode, pcoption->video_mode.pvalue,
3833 sizeof(struct video_mode))) {
3834 return FALSE;
3837 *pcoption->video_mode.pvalue = mode;
3838 return TRUE;
3841 /****************************************************************************
3842 Load the option from a file. Returns TRUE if the option changed.
3843 ****************************************************************************/
3844 static bool client_option_load(struct option *poption,
3845 struct section_file *sf)
3847 fc_assert_ret_val(NULL != poption, FALSE);
3848 fc_assert_ret_val(NULL != sf, FALSE);
3850 switch (option_type(poption)) {
3851 case OT_BOOLEAN:
3853 bool value;
3855 return (secfile_lookup_bool(sf, &value, "client.%s",
3856 option_name(poption))
3857 && option_bool_set(poption, value));
3859 case OT_INTEGER:
3861 int value;
3863 return (secfile_lookup_int(sf, &value, "client.%s",
3864 option_name(poption))
3865 && option_int_set(poption, value));
3867 case OT_STRING:
3869 const char *string;
3871 return ((string = secfile_lookup_str(sf, "client.%s",
3872 option_name(poption)))
3873 && option_str_set(poption, string));
3875 case OT_ENUM:
3877 int value;
3879 return (secfile_lookup_enum_data(sf, &value, FALSE,
3880 client_option_enum_secfile_str,
3881 poption, "client.%s",
3882 option_name(poption))
3883 && option_enum_set_int(poption, value));
3885 case OT_BITWISE:
3887 int value;
3889 return (secfile_lookup_enum_data(sf, &value, TRUE,
3890 client_option_bitwise_secfile_str,
3891 poption, "client.%s",
3892 option_name(poption))
3893 && option_bitwise_set(poption, value));
3895 case OT_FONT:
3897 const char *string;
3899 return ((string = secfile_lookup_str(sf, "client.%s",
3900 option_name(poption)))
3901 && option_font_set(poption, string));
3903 case OT_COLOR:
3905 struct ft_color color;
3907 return ((color.foreground =
3908 secfile_lookup_str(sf, "client.%s.foreground",
3909 option_name(poption)))
3910 && (color.background =
3911 secfile_lookup_str(sf, "client.%s.background",
3912 option_name(poption)))
3913 && option_color_set(poption, color));
3915 case OT_VIDEO_MODE:
3917 struct video_mode mode;
3919 return (secfile_lookup_int(sf, &mode.width, "client.%s.width",
3920 option_name(poption))
3921 && secfile_lookup_int(sf, &mode.height, "client.%s.height",
3922 option_name(poption))
3923 && option_video_mode_set(poption, mode));
3926 return FALSE;
3929 /****************************************************************************
3930 Save the option to a file.
3931 ****************************************************************************/
3932 static void client_option_save(struct option *poption,
3933 struct section_file *sf)
3935 fc_assert_ret(NULL != poption);
3936 fc_assert_ret(NULL != sf);
3938 switch (option_type(poption)) {
3939 case OT_BOOLEAN:
3940 secfile_insert_bool(sf, option_bool_get(poption),
3941 "client.%s", option_name(poption));
3942 break;
3943 case OT_INTEGER:
3944 secfile_insert_int(sf, option_int_get(poption),
3945 "client.%s", option_name(poption));
3946 break;
3947 case OT_STRING:
3948 secfile_insert_str(sf, option_str_get(poption),
3949 "client.%s", option_name(poption));
3950 break;
3951 case OT_ENUM:
3952 secfile_insert_enum_data(sf, option_enum_get_int(poption), FALSE,
3953 client_option_enum_secfile_str, poption,
3954 "client.%s", option_name(poption));
3955 break;
3956 case OT_BITWISE:
3957 secfile_insert_enum_data(sf, option_bitwise_get(poption), TRUE,
3958 client_option_bitwise_secfile_str, poption,
3959 "client.%s", option_name(poption));
3960 break;
3961 case OT_FONT:
3962 secfile_insert_str(sf, option_font_get(poption),
3963 "client.%s", option_name(poption));
3964 break;
3965 case OT_COLOR:
3967 struct ft_color color = option_color_get(poption);
3969 secfile_insert_str(sf, color.foreground, "client.%s.foreground",
3970 option_name(poption));
3971 secfile_insert_str(sf, color.background, "client.%s.background",
3972 option_name(poption));
3974 break;
3975 case OT_VIDEO_MODE:
3977 struct video_mode mode = option_video_mode_get(poption);
3979 secfile_insert_int(sf, mode.width, "client.%s.width",
3980 option_name(poption));
3981 secfile_insert_int(sf, mode.height, "client.%s.height",
3982 option_name(poption));
3984 break;
3989 /****************************************************************************
3990 Server options variables.
3991 ****************************************************************************/
3992 static char **server_options_categories = NULL;
3993 static struct server_option *server_options = NULL;
3995 static int server_options_categories_num = 0;
3996 static int server_options_num = 0;
3999 /****************************************************************************
4000 Server option set.
4001 ****************************************************************************/
4002 static struct option *server_optset_option_by_number(int id);
4003 static struct option *server_optset_option_first(void);
4004 static int server_optset_category_number(void);
4005 static const char *server_optset_category_name(int category);
4007 static struct option_set server_optset_static = {
4008 .option_by_number = server_optset_option_by_number,
4009 .option_first = server_optset_option_first,
4010 .category_number = server_optset_category_number,
4011 .category_name = server_optset_category_name
4013 const struct option_set *server_optset = &server_optset_static;
4016 /****************************************************************************
4017 Virtuals tables for the client options.
4018 ****************************************************************************/
4019 static int server_option_number(const struct option *poption);
4020 static const char *server_option_name(const struct option *poption);
4021 static const char *server_option_description(const struct option *poption);
4022 static const char *server_option_help_text(const struct option *poption);
4023 static int server_option_category(const struct option *poption);
4024 static bool server_option_is_changeable(const struct option *poption);
4025 static struct option *server_option_next(const struct option *poption);
4027 static const struct option_common_vtable server_option_common_vtable = {
4028 .number = server_option_number,
4029 .name = server_option_name,
4030 .description = server_option_description,
4031 .help_text = server_option_help_text,
4032 .category = server_option_category,
4033 .is_changeable = server_option_is_changeable,
4034 .next = server_option_next
4037 static bool server_option_bool_get(const struct option *poption);
4038 static bool server_option_bool_def(const struct option *poption);
4039 static bool server_option_bool_set(struct option *poption, bool val);
4041 static const struct option_bool_vtable server_option_bool_vtable = {
4042 .get = server_option_bool_get,
4043 .def = server_option_bool_def,
4044 .set = server_option_bool_set
4047 static int server_option_int_get(const struct option *poption);
4048 static int server_option_int_def(const struct option *poption);
4049 static int server_option_int_min(const struct option *poption);
4050 static int server_option_int_max(const struct option *poption);
4051 static bool server_option_int_set(struct option *poption, int val);
4053 static const struct option_int_vtable server_option_int_vtable = {
4054 .get = server_option_int_get,
4055 .def = server_option_int_def,
4056 .minimum = server_option_int_min,
4057 .maximum = server_option_int_max,
4058 .set = server_option_int_set
4061 static const char *server_option_str_get(const struct option *poption);
4062 static const char *server_option_str_def(const struct option *poption);
4063 static const struct strvec *
4064 server_option_str_values(const struct option *poption);
4065 static bool server_option_str_set(struct option *poption, const char *str);
4067 static const struct option_str_vtable server_option_str_vtable = {
4068 .get = server_option_str_get,
4069 .def = server_option_str_def,
4070 .values = server_option_str_values,
4071 .set = server_option_str_set
4074 static int server_option_enum_get(const struct option *poption);
4075 static int server_option_enum_def(const struct option *poption);
4076 static const struct strvec *
4077 server_option_enum_pretty(const struct option *poption);
4078 static bool server_option_enum_set(struct option *poption, int val);
4080 static const struct option_enum_vtable server_option_enum_vtable = {
4081 .get = server_option_enum_get,
4082 .def = server_option_enum_def,
4083 .values = server_option_enum_pretty,
4084 .set = server_option_enum_set,
4085 .cmp = strcmp
4088 static unsigned server_option_bitwise_get(const struct option *poption);
4089 static unsigned server_option_bitwise_def(const struct option *poption);
4090 static const struct strvec *
4091 server_option_bitwise_pretty(const struct option *poption);
4092 static bool server_option_bitwise_set(struct option *poption, unsigned val);
4094 static const struct option_bitwise_vtable server_option_bitwise_vtable = {
4095 .get = server_option_bitwise_get,
4096 .def = server_option_bitwise_def,
4097 .values = server_option_bitwise_pretty,
4098 .set = server_option_bitwise_set
4101 /****************************************************************************
4102 Derived class server option, inheriting from base class option.
4103 ****************************************************************************/
4104 struct server_option {
4105 struct option base_option; /* Base structure, must be the first! */
4107 char *name; /* Short name - used as an identifier */
4108 char *description; /* One-line description */
4109 char *help_text; /* Paragraph-length help text */
4110 unsigned char category;
4111 bool desired_sent;
4112 bool is_changeable;
4113 bool is_visible;
4115 union {
4116 /* OT_BOOLEAN type option. */
4117 struct {
4118 bool value;
4119 bool def;
4120 } boolean;
4121 /* OT_INTEGER type option. */
4122 struct {
4123 int value;
4124 int def, min, max;
4125 } integer;
4126 /* OT_STRING type option. */
4127 struct {
4128 char *value;
4129 char *def;
4130 } string;
4131 /* OT_ENUM type option. */
4132 struct {
4133 int value;
4134 int def;
4135 struct strvec *support_names;
4136 struct strvec *pretty_names; /* untranslated */
4137 } enumerator;
4138 /* OT_BITWISE type option. */
4139 struct {
4140 unsigned value;
4141 unsigned def;
4142 struct strvec *support_names;
4143 struct strvec *pretty_names; /* untranslated */
4144 } bitwise;
4148 #define SERVER_OPTION(poption) ((struct server_option *) (poption))
4150 static void desired_settable_option_send(struct option *poption);
4153 /****************************************************************************
4154 Initialize the server options (not received yet).
4155 ****************************************************************************/
4156 void server_options_init(void)
4158 fc_assert(NULL == server_options_categories);
4159 fc_assert(NULL == server_options);
4160 fc_assert(0 == server_options_categories_num);
4161 fc_assert(0 == server_options_num);
4164 /****************************************************************************
4165 Free one server option.
4166 ****************************************************************************/
4167 static void server_option_free(struct server_option *poption)
4169 switch (poption->base_option.type) {
4170 case OT_STRING:
4171 if (NULL != poption->string.value) {
4172 FC_FREE(poption->string.value);
4174 if (NULL != poption->string.def) {
4175 FC_FREE(poption->string.def);
4177 break;
4179 case OT_ENUM:
4180 if (NULL != poption->enumerator.support_names) {
4181 strvec_destroy(poption->enumerator.support_names);
4182 poption->enumerator.support_names = NULL;
4184 if (NULL != poption->enumerator.pretty_names) {
4185 strvec_destroy(poption->enumerator.pretty_names);
4186 poption->enumerator.pretty_names = NULL;
4188 break;
4190 case OT_BITWISE:
4191 if (NULL != poption->bitwise.support_names) {
4192 strvec_destroy(poption->bitwise.support_names);
4193 poption->bitwise.support_names = NULL;
4195 if (NULL != poption->bitwise.pretty_names) {
4196 strvec_destroy(poption->bitwise.pretty_names);
4197 poption->bitwise.pretty_names = NULL;
4199 break;
4201 case OT_BOOLEAN:
4202 case OT_INTEGER:
4203 case OT_FONT:
4204 case OT_COLOR:
4205 case OT_VIDEO_MODE:
4206 break;
4209 if (NULL != poption->name) {
4210 FC_FREE(poption->name);
4212 if (NULL != poption->description) {
4213 FC_FREE(poption->description);
4215 if (NULL != poption->help_text) {
4216 FC_FREE(poption->help_text);
4220 /****************************************************************************
4221 Free the server options, if already received.
4222 ****************************************************************************/
4223 void server_options_free(void)
4225 int i;
4227 /* Don't keep this dialog open. */
4228 option_dialog_popdown(server_optset);
4230 /* Free the options themselves. */
4231 if (NULL != server_options) {
4232 for (i = 0; i < server_options_num; i++) {
4233 server_option_free(server_options + i);
4235 FC_FREE(server_options);
4236 server_options_num = 0;
4239 /* Free the categories. */
4240 if (NULL != server_options_categories) {
4241 for (i = 0; i < server_options_categories_num; i++) {
4242 if (NULL != server_options_categories[i]) {
4243 FC_FREE(server_options_categories[i]);
4246 FC_FREE(server_options_categories);
4247 server_options_categories_num = 0;
4251 /****************************************************************************
4252 Allocate the server options and categories.
4253 ****************************************************************************/
4254 void handle_server_setting_control
4255 (const struct packet_server_setting_control *packet)
4257 int i;
4259 /* This packet should be received only once. */
4260 fc_assert_ret(NULL == server_options_categories);
4261 fc_assert_ret(NULL == server_options);
4262 fc_assert_ret(0 == server_options_categories_num);
4263 fc_assert_ret(0 == server_options_num);
4265 /* Allocate server option categories. */
4266 if (0 < packet->categories_num) {
4267 server_options_categories_num = packet->categories_num;
4268 server_options_categories =
4269 fc_calloc(server_options_categories_num,
4270 sizeof(*server_options_categories));
4272 for (i = 0; i < server_options_categories_num; i++) {
4273 /* NB: Translate now. */
4274 server_options_categories[i] = fc_strdup(_(packet->category_names[i]));
4278 /* Allocate server options. */
4279 if (0 < packet->settings_num) {
4280 server_options_num = packet->settings_num;
4281 server_options = fc_calloc(server_options_num, sizeof(*server_options));
4285 /****************************************************************************
4286 Receive a server setting info packet.
4287 ****************************************************************************/
4288 void handle_server_setting_const
4289 (const struct packet_server_setting_const *packet)
4291 struct option *poption = server_optset_option_by_number(packet->id);
4292 struct server_option *psoption = SERVER_OPTION(poption);
4294 fc_assert_ret(NULL != poption);
4296 fc_assert(NULL == psoption->name);
4297 psoption->name = fc_strdup(packet->name);
4298 fc_assert(NULL == psoption->description);
4299 /* NB: Translate now. */
4300 psoption->description = fc_strdup(_(packet->short_help));
4301 fc_assert(NULL == psoption->help_text);
4302 /* NB: Translate now. */
4303 psoption->help_text = fc_strdup(_(packet->extra_help));
4304 psoption->category = packet->category;
4307 /****************************************************************************
4308 Common part of handle_server_setting_*() functions. See below.
4309 ****************************************************************************/
4310 #define handle_server_setting_common(psoption, packet) \
4311 psoption->is_changeable = packet->is_changeable; \
4312 if (psoption->is_visible != packet->is_visible) { \
4313 if (psoption->is_visible) { \
4314 need_gui_remove = TRUE; \
4315 } else if (packet->is_visible) { \
4316 need_gui_add = TRUE; \
4318 psoption->is_visible = packet->is_visible; \
4321 if (!psoption->desired_sent \
4322 && psoption->is_visible \
4323 && psoption->is_changeable \
4324 && is_server_running() \
4325 && packet->initial_setting) { \
4326 /* Only send our private settings if we are running \
4327 * on a forked local server, i.e. started by the \
4328 * client with the "Start New Game" button. \
4329 * Do now override settings that are already saved to savegame \
4330 * and now loaded. */ \
4331 desired_settable_option_send(OPTION(poption)); \
4332 psoption->desired_sent = TRUE; \
4335 /* Update the GUI. */ \
4336 if (need_gui_remove) { \
4337 option_gui_remove(poption); \
4338 } else if (need_gui_add) { \
4339 option_gui_add(poption); \
4340 } else { \
4341 option_gui_update(poption); \
4344 /****************************************************************************
4345 Receive a boolean server setting info packet.
4346 ****************************************************************************/
4347 void handle_server_setting_bool
4348 (const struct packet_server_setting_bool *packet)
4350 struct option *poption = server_optset_option_by_number(packet->id);
4351 struct server_option *psoption = SERVER_OPTION(poption);
4352 bool need_gui_remove = FALSE;
4353 bool need_gui_add = FALSE;
4355 fc_assert_ret(NULL != poption);
4357 if (NULL == poption->common_vtable) {
4358 /* Not initialized yet. */
4359 poption->poptset = server_optset;
4360 poption->common_vtable = &server_option_common_vtable;
4361 poption->type = OT_BOOLEAN;
4362 poption->bool_vtable = &server_option_bool_vtable;
4364 fc_assert_ret_msg(OT_BOOLEAN == poption->type,
4365 "Server setting \"%s\" (nb %d) has type %s (%d), "
4366 "expected %s (%d)",
4367 option_name(poption), option_number(poption),
4368 option_type_name(poption->type), poption->type,
4369 option_type_name(OT_BOOLEAN), OT_BOOLEAN);
4371 if (packet->is_visible) {
4372 psoption->boolean.value = packet->val;
4373 psoption->boolean.def = packet->default_val;
4376 handle_server_setting_common(psoption, packet);
4379 /****************************************************************************
4380 Receive a integer server setting info packet.
4381 ****************************************************************************/
4382 void handle_server_setting_int
4383 (const struct packet_server_setting_int *packet)
4385 struct option *poption = server_optset_option_by_number(packet->id);
4386 struct server_option *psoption = SERVER_OPTION(poption);
4387 bool need_gui_remove = FALSE;
4388 bool need_gui_add = FALSE;
4390 fc_assert_ret(NULL != poption);
4392 if (NULL == poption->common_vtable) {
4393 /* Not initialized yet. */
4394 poption->poptset = server_optset;
4395 poption->common_vtable = &server_option_common_vtable;
4396 poption->type = OT_INTEGER;
4397 poption->int_vtable = &server_option_int_vtable;
4399 fc_assert_ret_msg(OT_INTEGER == poption->type,
4400 "Server setting \"%s\" (nb %d) has type %s (%d), "
4401 "expected %s (%d)",
4402 option_name(poption), option_number(poption),
4403 option_type_name(poption->type), poption->type,
4404 option_type_name(OT_INTEGER), OT_INTEGER);
4406 if (packet->is_visible) {
4407 psoption->integer.value = packet->val;
4408 psoption->integer.def = packet->default_val;
4409 psoption->integer.min = packet->min_val;
4410 psoption->integer.max = packet->max_val;
4413 handle_server_setting_common(psoption, packet);
4416 /****************************************************************************
4417 Receive a string server setting info packet.
4418 ****************************************************************************/
4419 void handle_server_setting_str
4420 (const struct packet_server_setting_str *packet)
4422 struct option *poption = server_optset_option_by_number(packet->id);
4423 struct server_option *psoption = SERVER_OPTION(poption);
4424 bool need_gui_remove = FALSE;
4425 bool need_gui_add = FALSE;
4427 fc_assert_ret(NULL != poption);
4429 if (NULL == poption->common_vtable) {
4430 /* Not initialized yet. */
4431 poption->poptset = server_optset;
4432 poption->common_vtable = &server_option_common_vtable;
4433 poption->type = OT_STRING;
4434 poption->str_vtable = &server_option_str_vtable;
4436 fc_assert_ret_msg(OT_STRING == poption->type,
4437 "Server setting \"%s\" (nb %d) has type %s (%d), "
4438 "expected %s (%d)",
4439 option_name(poption), option_number(poption),
4440 option_type_name(poption->type), poption->type,
4441 option_type_name(OT_STRING), OT_STRING);
4443 if (packet->is_visible) {
4444 if (NULL == psoption->string.value) {
4445 psoption->string.value = fc_strdup(packet->val);
4446 } else if (0 != strcmp(packet->val, psoption->string.value)) {
4447 free(psoption->string.value);
4448 psoption->string.value = fc_strdup(packet->val);
4450 if (NULL == psoption->string.def) {
4451 psoption->string.def = fc_strdup(packet->default_val);
4452 } else if (0 != strcmp(packet->default_val, psoption->string.def)) {
4453 free(psoption->string.def);
4454 psoption->string.def = fc_strdup(packet->default_val);
4458 handle_server_setting_common(psoption, packet);
4461 /****************************************************************************
4462 Receive an enumerator server setting info packet.
4463 ****************************************************************************/
4464 void handle_server_setting_enum
4465 (const struct packet_server_setting_enum *packet)
4467 struct option *poption = server_optset_option_by_number(packet->id);
4468 struct server_option *psoption = SERVER_OPTION(poption);
4469 bool need_gui_remove = FALSE;
4470 bool need_gui_add = FALSE;
4472 fc_assert_ret(NULL != poption);
4474 if (NULL == poption->common_vtable) {
4475 /* Not initialized yet. */
4476 poption->poptset = server_optset;
4477 poption->common_vtable = &server_option_common_vtable;
4478 poption->type = OT_ENUM;
4479 poption->enum_vtable = &server_option_enum_vtable;
4481 fc_assert_ret_msg(OT_ENUM == poption->type,
4482 "Server setting \"%s\" (nb %d) has type %s (%d), "
4483 "expected %s (%d)",
4484 option_name(poption), option_number(poption),
4485 option_type_name(poption->type), poption->type,
4486 option_type_name(OT_ENUM), OT_ENUM);
4488 if (packet->is_visible) {
4489 int i;
4491 psoption->enumerator.value = packet->val;
4492 psoption->enumerator.def = packet->default_val;
4494 if (NULL == psoption->enumerator.support_names) {
4495 /* First time we get this packet. */
4496 fc_assert(NULL == psoption->enumerator.pretty_names);
4497 psoption->enumerator.support_names = strvec_new();
4498 strvec_reserve(psoption->enumerator.support_names, packet->values_num);
4499 psoption->enumerator.pretty_names = strvec_new();
4500 strvec_reserve(psoption->enumerator.pretty_names, packet->values_num);
4501 for (i = 0; i < packet->values_num; i++) {
4502 strvec_set(psoption->enumerator.support_names, i,
4503 packet->support_names[i]);
4504 /* Store untranslated string from server. */
4505 strvec_set(psoption->enumerator.pretty_names, i,
4506 packet->pretty_names[i]);
4508 } else if (strvec_size(psoption->enumerator.support_names)
4509 != packet->values_num) {
4510 fc_assert(strvec_size(psoption->enumerator.support_names)
4511 == strvec_size(psoption->enumerator.pretty_names));
4512 /* The number of values have changed, we need to reset the list
4513 * of possible values. */
4514 strvec_reserve(psoption->enumerator.support_names, packet->values_num);
4515 strvec_reserve(psoption->enumerator.pretty_names, packet->values_num);
4516 for (i = 0; i < packet->values_num; i++) {
4517 strvec_set(psoption->enumerator.support_names, i,
4518 packet->support_names[i]);
4519 /* Store untranslated string from server. */
4520 strvec_set(psoption->enumerator.pretty_names, i,
4521 packet->pretty_names[i]);
4523 need_gui_remove = TRUE;
4524 need_gui_add = TRUE;
4525 } else {
4526 /* Check if a value changed, then we need to reset the list
4527 * of possible values. */
4528 const char *str;
4530 for (i = 0; i < packet->values_num; i++) {
4531 str = strvec_get(psoption->enumerator.pretty_names, i);
4532 if (NULL == str || 0 != strcmp(str, packet->pretty_names[i])) {
4533 /* Store untranslated string from server. */
4534 strvec_set(psoption->enumerator.pretty_names, i,
4535 packet->pretty_names[i]);
4536 need_gui_remove = TRUE;
4537 need_gui_add = TRUE;
4539 /* Support names are not visible, we don't need to check if it
4540 * has changed. */
4541 strvec_set(psoption->enumerator.support_names, i,
4542 packet->support_names[i]);
4547 handle_server_setting_common(psoption, packet);
4550 /****************************************************************************
4551 Receive a bitwise server setting info packet.
4552 ****************************************************************************/
4553 void handle_server_setting_bitwise
4554 (const struct packet_server_setting_bitwise *packet)
4556 struct option *poption = server_optset_option_by_number(packet->id);
4557 struct server_option *psoption = SERVER_OPTION(poption);
4558 bool need_gui_remove = FALSE;
4559 bool need_gui_add = FALSE;
4561 fc_assert_ret(NULL != poption);
4563 if (NULL == poption->common_vtable) {
4564 /* Not initialized yet. */
4565 poption->poptset = server_optset;
4566 poption->common_vtable = &server_option_common_vtable;
4567 poption->type = OT_BITWISE;
4568 poption->bitwise_vtable = &server_option_bitwise_vtable;
4570 fc_assert_ret_msg(OT_BITWISE == poption->type,
4571 "Server setting \"%s\" (nb %d) has type %s (%d), "
4572 "expected %s (%d)",
4573 option_name(poption), option_number(poption),
4574 option_type_name(poption->type), poption->type,
4575 option_type_name(OT_BITWISE), OT_BITWISE);
4577 if (packet->is_visible) {
4578 int i;
4580 psoption->bitwise.value = packet->val;
4581 psoption->bitwise.def = packet->default_val;
4583 if (NULL == psoption->bitwise.support_names) {
4584 /* First time we get this packet. */
4585 fc_assert(NULL == psoption->bitwise.pretty_names);
4586 psoption->bitwise.support_names = strvec_new();
4587 strvec_reserve(psoption->bitwise.support_names, packet->bits_num);
4588 psoption->bitwise.pretty_names = strvec_new();
4589 strvec_reserve(psoption->bitwise.pretty_names, packet->bits_num);
4590 for (i = 0; i < packet->bits_num; i++) {
4591 strvec_set(psoption->bitwise.support_names, i,
4592 packet->support_names[i]);
4593 /* Store untranslated string from server. */
4594 strvec_set(psoption->bitwise.pretty_names, i,
4595 packet->pretty_names[i]);
4597 } else if (strvec_size(psoption->bitwise.support_names)
4598 != packet->bits_num) {
4599 fc_assert(strvec_size(psoption->bitwise.support_names)
4600 == strvec_size(psoption->bitwise.pretty_names));
4601 /* The number of values have changed, we need to reset the list
4602 * of possible values. */
4603 strvec_reserve(psoption->bitwise.support_names, packet->bits_num);
4604 strvec_reserve(psoption->bitwise.pretty_names, packet->bits_num);
4605 for (i = 0; i < packet->bits_num; i++) {
4606 strvec_set(psoption->bitwise.support_names, i,
4607 packet->support_names[i]);
4608 /* Store untranslated string from server. */
4609 strvec_set(psoption->bitwise.pretty_names, i,
4610 packet->pretty_names[i]);
4612 need_gui_remove = TRUE;
4613 need_gui_add = TRUE;
4614 } else {
4615 /* Check if a value changed, then we need to reset the list
4616 * of possible values. */
4617 const char *str;
4619 for (i = 0; i < packet->bits_num; i++) {
4620 str = strvec_get(psoption->bitwise.pretty_names, i);
4621 if (NULL == str || 0 != strcmp(str, packet->pretty_names[i])) {
4622 /* Store untranslated string from server. */
4623 strvec_set(psoption->bitwise.pretty_names, i,
4624 packet->pretty_names[i]);
4625 need_gui_remove = TRUE;
4626 need_gui_add = TRUE;
4628 /* Support names are not visible, we don't need to check if it
4629 * has changed. */
4630 strvec_set(psoption->bitwise.support_names, i,
4631 packet->support_names[i]);
4636 handle_server_setting_common(psoption, packet);
4639 /****************************************************************************
4640 Returns the next valid option pointer for the current gui type.
4641 ****************************************************************************/
4642 static struct server_option *
4643 server_option_next_valid(struct server_option *poption)
4645 const struct server_option *const max =
4646 server_options + server_options_num;
4648 while (NULL != poption && poption < max && !poption->is_visible) {
4649 poption++;
4652 return (poption < max ? poption : NULL);
4655 /****************************************************************************
4656 Returns the server option associated to the number
4657 ****************************************************************************/
4658 struct option *server_optset_option_by_number(int id)
4660 if (0 > id || id > server_options_num) {
4661 return NULL;
4663 return OPTION(server_options + id);
4666 /****************************************************************************
4667 Returns the first valid (visible) option pointer.
4668 ****************************************************************************/
4669 struct option *server_optset_option_first(void)
4671 return OPTION(server_option_next_valid(server_options));
4674 /****************************************************************************
4675 Returns the number of server option categories.
4676 ****************************************************************************/
4677 int server_optset_category_number(void)
4679 return server_options_categories_num;
4682 /****************************************************************************
4683 Returns the name (translated) of the server option category.
4684 ****************************************************************************/
4685 const char *server_optset_category_name(int category)
4687 if (0 > category || category >= server_options_categories_num) {
4688 return NULL;
4691 return server_options_categories[category];
4694 /***************************************************************************
4695 Returns the number of this server option.
4696 ****************************************************************************/
4697 static int server_option_number(const struct option *poption)
4699 return SERVER_OPTION(poption) - server_options;
4702 /****************************************************************************
4703 Returns the name of this server option.
4704 ****************************************************************************/
4705 static const char *server_option_name(const struct option *poption)
4707 return SERVER_OPTION(poption)->name;
4710 /****************************************************************************
4711 Returns the (translated) description of this server option.
4712 ****************************************************************************/
4713 static const char *server_option_description(const struct option *poption)
4715 return SERVER_OPTION(poption)->description;
4718 /****************************************************************************
4719 Returns the (translated) help text for this server option.
4720 ****************************************************************************/
4721 static const char *server_option_help_text(const struct option *poption)
4723 return SERVER_OPTION(poption)->help_text;
4726 /****************************************************************************
4727 Returns the category of this server option.
4728 ****************************************************************************/
4729 static int server_option_category(const struct option *poption)
4731 return SERVER_OPTION(poption)->category;
4734 /****************************************************************************
4735 Returns TRUE if this client option can be modified.
4736 ****************************************************************************/
4737 static bool server_option_is_changeable(const struct option *poption)
4739 return SERVER_OPTION(poption)->is_changeable;
4742 /****************************************************************************
4743 Returns the next valid (visible) option pointer.
4744 ****************************************************************************/
4745 static struct option *server_option_next(const struct option *poption)
4747 return OPTION(server_option_next_valid(SERVER_OPTION(poption) + 1));
4750 /****************************************************************************
4751 Returns the value of this server option of type OT_BOOLEAN.
4752 ****************************************************************************/
4753 static bool server_option_bool_get(const struct option *poption)
4755 return SERVER_OPTION(poption)->boolean.value;
4758 /****************************************************************************
4759 Returns the default value of this server option of type OT_BOOLEAN.
4760 ****************************************************************************/
4761 static bool server_option_bool_def(const struct option *poption)
4763 return SERVER_OPTION(poption)->boolean.def;
4766 /****************************************************************************
4767 Set the value of this server option of type OT_BOOLEAN. Returns TRUE if
4768 the value changed.
4769 ****************************************************************************/
4770 static bool server_option_bool_set(struct option *poption, bool val)
4772 struct server_option *psoption = SERVER_OPTION(poption);
4774 if (psoption->boolean.value == val) {
4775 return FALSE;
4778 send_chat_printf("/set %s %s", psoption->name,
4779 val ? "enabled" : "disabled");
4780 return TRUE;
4783 /****************************************************************************
4784 Returns the value of this server option of type OT_INTEGER.
4785 ****************************************************************************/
4786 static int server_option_int_get(const struct option *poption)
4788 return SERVER_OPTION(poption)->integer.value;
4791 /****************************************************************************
4792 Returns the default value of this server option of type OT_INTEGER.
4793 ****************************************************************************/
4794 static int server_option_int_def(const struct option *poption)
4796 return SERVER_OPTION(poption)->integer.def;
4799 /****************************************************************************
4800 Returns the minimal value for this server option of type OT_INTEGER.
4801 ****************************************************************************/
4802 static int server_option_int_min(const struct option *poption)
4804 return SERVER_OPTION(poption)->integer.min;
4807 /****************************************************************************
4808 Returns the maximal value for this server option of type OT_INTEGER.
4809 ****************************************************************************/
4810 static int server_option_int_max(const struct option *poption)
4812 return SERVER_OPTION(poption)->integer.max;
4815 /****************************************************************************
4816 Set the value of this server option of type OT_INTEGER. Returns TRUE if
4817 the value changed.
4818 ****************************************************************************/
4819 static bool server_option_int_set(struct option *poption, int val)
4821 struct server_option *psoption = SERVER_OPTION(poption);
4823 if (val < psoption->integer.min
4824 || val > psoption->integer.max
4825 || psoption->integer.value == val) {
4826 return FALSE;
4829 send_chat_printf("/set %s %d", psoption->name, val);
4830 return TRUE;
4833 /****************************************************************************
4834 Returns the value of this server option of type OT_STRING.
4835 ****************************************************************************/
4836 static const char *server_option_str_get(const struct option *poption)
4838 return SERVER_OPTION(poption)->string.value;
4841 /****************************************************************************
4842 Returns the default value of this server option of type OT_STRING.
4843 ****************************************************************************/
4844 static const char *server_option_str_def(const struct option *poption)
4846 return SERVER_OPTION(poption)->string.def;
4849 /****************************************************************************
4850 Returns the possible string values of this server option of type
4851 OT_STRING.
4852 ****************************************************************************/
4853 static const struct strvec *
4854 server_option_str_values(const struct option *poption)
4856 return NULL;
4859 /****************************************************************************
4860 Set the value of this server option of type OT_STRING. Returns TRUE if
4861 the value changed.
4862 ****************************************************************************/
4863 static bool server_option_str_set(struct option *poption, const char *str)
4865 struct server_option *psoption = SERVER_OPTION(poption);
4867 if (0 == strcmp(psoption->string.value, str)) {
4868 return FALSE;
4871 send_chat_printf("/set %s \"%s\"", psoption->name, str);
4872 return TRUE;
4875 /****************************************************************************
4876 Returns the current value of this server option of type OT_ENUM.
4877 ****************************************************************************/
4878 static int server_option_enum_get(const struct option *poption)
4880 return SERVER_OPTION(poption)->enumerator.value;
4883 /****************************************************************************
4884 Returns the default value of this server option of type OT_ENUM.
4885 ****************************************************************************/
4886 static int server_option_enum_def(const struct option *poption)
4888 return SERVER_OPTION(poption)->enumerator.def;
4891 /****************************************************************************
4892 Returns the user-visible, translatable (but untranslated) "pretty" names
4893 of this server option of type OT_ENUM.
4894 ****************************************************************************/
4895 static const struct strvec *
4896 server_option_enum_pretty(const struct option *poption)
4898 return SERVER_OPTION(poption)->enumerator.pretty_names;
4901 /****************************************************************************
4902 Set the value of this server option of type OT_ENUM. Returns TRUE if
4903 the value changed.
4904 ****************************************************************************/
4905 static bool server_option_enum_set(struct option *poption, int val)
4907 struct server_option *psoption = SERVER_OPTION(poption);
4908 const char *name;
4910 if (val == psoption->enumerator.value
4911 || !(name = strvec_get(psoption->enumerator.support_names, val))) {
4912 return FALSE;
4915 send_chat_printf("/set %s \"%s\"", psoption->name, name);
4916 return TRUE;
4919 /****************************************************************************
4920 Returns the long support names of the values of the server option of type
4921 OT_ENUM.
4922 ****************************************************************************/
4923 static void server_option_enum_support_name(const struct option *poption,
4924 const char **pvalue,
4925 const char **pdefault)
4927 const struct server_option *psoption = SERVER_OPTION(poption);
4928 const struct strvec *values = psoption->enumerator.support_names;
4930 if (NULL != pvalue) {
4931 *pvalue = strvec_get(values, psoption->enumerator.value);
4933 if (NULL != pdefault) {
4934 *pdefault = strvec_get(values, psoption->enumerator.def);
4938 /****************************************************************************
4939 Returns the current value of this server option of type OT_BITWISE.
4940 ****************************************************************************/
4941 static unsigned server_option_bitwise_get(const struct option *poption)
4943 return SERVER_OPTION(poption)->bitwise.value;
4946 /****************************************************************************
4947 Returns the default value of this server option of type OT_BITWISE.
4948 ****************************************************************************/
4949 static unsigned server_option_bitwise_def(const struct option *poption)
4951 return SERVER_OPTION(poption)->bitwise.def;
4954 /****************************************************************************
4955 Returns the user-visible, translatable (but untranslated) "pretty" names
4956 of this server option of type OT_BITWISE.
4957 ****************************************************************************/
4958 static const struct strvec *
4959 server_option_bitwise_pretty(const struct option *poption)
4961 return SERVER_OPTION(poption)->bitwise.pretty_names;
4964 /****************************************************************************
4965 Compute the long support names of a value.
4966 ****************************************************************************/
4967 static void server_option_bitwise_support_base(const struct strvec *values,
4968 unsigned val,
4969 char *buf, size_t buf_len)
4971 int bit;
4973 buf[0] = '\0';
4974 for (bit = 0; bit < strvec_size(values); bit++) {
4975 if ((1 << bit) & val) {
4976 if ('\0' != buf[0]) {
4977 fc_strlcat(buf, "|", buf_len);
4979 fc_strlcat(buf, strvec_get(values, bit), buf_len);
4984 /****************************************************************************
4985 Set the value of this server option of type OT_BITWISE. Returns TRUE if
4986 the value changed.
4987 ****************************************************************************/
4988 static bool server_option_bitwise_set(struct option *poption, unsigned val)
4990 struct server_option *psoption = SERVER_OPTION(poption);
4991 char name[MAX_LEN_MSG];
4993 if (val == psoption->bitwise.value) {
4994 return FALSE;
4997 server_option_bitwise_support_base(psoption->bitwise.support_names, val,
4998 name, sizeof(name));
4999 send_chat_printf("/set %s \"%s\"", psoption->name, name);
5000 return TRUE;
5003 /****************************************************************************
5004 Compute the long support names of the values of the server option of type
5005 OT_BITWISE.
5006 ****************************************************************************/
5007 static void server_option_bitwise_support_name(const struct option *poption,
5008 char *val_buf, size_t val_len,
5009 char *def_buf, size_t def_len)
5011 const struct server_option *psoption = SERVER_OPTION(poption);
5012 const struct strvec *values = psoption->bitwise.support_names;
5014 if (NULL != val_buf && 0 < val_len) {
5015 server_option_bitwise_support_base(values, psoption->bitwise.value,
5016 val_buf, val_len);
5018 if (NULL != def_buf && 0 < def_len) {
5019 server_option_bitwise_support_base(values, psoption->bitwise.def,
5020 def_buf, def_len);
5025 /** Message Options: **/
5027 int messages_where[E_COUNT];
5030 /****************************************************************
5031 These could be a static table initialisation, except
5032 its easier to do it this way.
5033 *****************************************************************/
5034 static void message_options_init(void)
5036 int none[] = {
5037 E_IMP_BUY, E_IMP_SOLD, E_UNIT_BUY,
5038 E_UNIT_LOST_ATT, E_UNIT_WIN_ATT, E_GAME_START,
5039 E_CITY_BUILD, E_NEXT_YEAR,
5040 E_CITY_PRODUCTION_CHANGED,
5041 E_CITY_MAY_SOON_GROW, E_WORKLIST, E_AI_DEBUG
5043 int out_only[] = {
5044 E_NATION_SELECTED, E_CHAT_MSG, E_CHAT_ERROR, E_CONNECTION,
5045 E_LOG_ERROR, E_SETTING, E_VOTE_NEW, E_VOTE_RESOLVED, E_VOTE_ABORTED
5047 int all[] = {
5048 E_LOG_FATAL, E_SCRIPT, E_DEPRECATION_WARNING
5050 int i;
5052 for (i = 0; i <= event_type_max(); i++) {
5053 /* Include possible undefined values. */
5054 messages_where[i] = MW_MESSAGES;
5056 for (i = 0; i < ARRAY_SIZE(none); i++) {
5057 messages_where[none[i]] = 0;
5059 for (i = 0; i < ARRAY_SIZE(out_only); i++) {
5060 messages_where[out_only[i]] = MW_OUTPUT;
5062 for (i = 0; i < ARRAY_SIZE(all); i++) {
5063 messages_where[all[i]] = MW_MESSAGES | MW_POPUP;
5066 events_init();
5069 /****************************************************************
5070 Free resources allocated for message options system
5071 *****************************************************************/
5072 static void message_options_free(void)
5074 events_free();
5077 /****************************************************************
5078 Load the message options; use the function defined by
5079 specnum.h (see also events.h).
5080 *****************************************************************/
5081 static void message_options_load(struct section_file *file,
5082 const char *prefix)
5084 enum event_type event;
5085 int i, num_events;
5086 const char *p;
5088 if (!secfile_lookup_int(file, &num_events, "messages.count")) {
5089 /* version < 2.2 */
5090 /* Order of the events in 2.1. */
5091 const enum event_type old_events[] = {
5092 E_CITY_CANTBUILD, E_CITY_LOST, E_CITY_LOVE, E_CITY_DISORDER,
5093 E_CITY_FAMINE, E_CITY_FAMINE_FEARED, E_CITY_GROWTH,
5094 E_CITY_MAY_SOON_GROW, E_CITY_AQUEDUCT, E_CITY_AQ_BUILDING,
5095 E_CITY_NORMAL, E_CITY_NUKED, E_CITY_CMA_RELEASE, E_CITY_GRAN_THROTTLE,
5096 E_CITY_TRANSFER, E_CITY_BUILD, E_CITY_PRODUCTION_CHANGED,
5097 E_WORKLIST, E_UPRISING, E_CIVIL_WAR, E_ANARCHY, E_FIRST_CONTACT,
5098 E_NEW_GOVERNMENT, E_LOW_ON_FUNDS, E_POLLUTION, E_REVOLT_DONE,
5099 E_REVOLT_START, E_SPACESHIP, E_MY_DIPLOMAT_BRIBE,
5100 E_DIPLOMATIC_INCIDENT, E_MY_DIPLOMAT_ESCAPE, E_MY_DIPLOMAT_EMBASSY,
5101 E_MY_DIPLOMAT_FAILED, E_MY_DIPLOMAT_INCITE, E_MY_DIPLOMAT_POISON,
5102 E_MY_DIPLOMAT_SABOTAGE, E_MY_DIPLOMAT_THEFT, E_ENEMY_DIPLOMAT_BRIBE,
5103 E_ENEMY_DIPLOMAT_EMBASSY, E_ENEMY_DIPLOMAT_FAILED,
5104 E_ENEMY_DIPLOMAT_INCITE, E_ENEMY_DIPLOMAT_POISON,
5105 E_ENEMY_DIPLOMAT_SABOTAGE, E_ENEMY_DIPLOMAT_THEFT,
5106 E_CARAVAN_ACTION, E_SCRIPT, E_BROADCAST_REPORT, E_GAME_END,
5107 E_GAME_START, E_NATION_SELECTED, E_DESTROYED, E_REPORT, E_TURN_BELL,
5108 E_NEXT_YEAR, E_GLOBAL_ECO, E_NUKE, E_HUT_BARB, E_HUT_CITY, E_HUT_GOLD,
5109 E_HUT_BARB_KILLED, E_HUT_MERC, E_HUT_SETTLER, E_HUT_TECH,
5110 E_HUT_BARB_CITY_NEAR, E_IMP_BUY, E_IMP_BUILD, E_IMP_AUCTIONED,
5111 E_IMP_AUTO, E_IMP_SOLD, E_TECH_GAIN, E_TECH_LEARNED, E_TREATY_ALLIANCE,
5112 E_TREATY_BROKEN, E_TREATY_CEASEFIRE, E_TREATY_PEACE,
5113 E_TREATY_SHARED_VISION, E_UNIT_LOST_ATT, E_UNIT_WIN_ATT, E_UNIT_BUY,
5114 E_UNIT_BUILT, E_UNIT_LOST_DEF, E_UNIT_WIN, E_UNIT_BECAME_VET,
5115 E_UNIT_UPGRADED, E_UNIT_RELOCATED, E_UNIT_ORDERS, E_WONDER_BUILD,
5116 E_WONDER_OBSOLETE, E_WONDER_STARTED, E_WONDER_STOPPED,
5117 E_WONDER_WILL_BE_BUILT, E_DIPLOMACY, E_TREATY_EMBASSY,
5118 E_BAD_COMMAND, E_SETTING, E_CHAT_MSG, E_MESSAGE_WALL, E_CHAT_ERROR,
5119 E_CONNECTION, E_AI_DEBUG
5121 const size_t old_events_num = ARRAY_SIZE(old_events);
5123 for (i = 0; i < old_events_num; i++) {
5124 messages_where[old_events[i]] =
5125 secfile_lookup_int_default(file, messages_where[old_events[i]],
5126 "%s.message_where_%02d", prefix, i);
5128 return;
5131 for (i = 0; i < num_events; i++) {
5132 p = secfile_lookup_str(file, "messages.event%d.name", i);
5133 if (NULL == p) {
5134 log_error("Corruption in file %s: %s",
5135 secfile_name(file), secfile_error());
5136 continue;
5138 event = event_type_by_name(p, strcmp);
5139 if (!event_type_is_valid(event)) {
5140 log_error("Event not supported: %s", p);
5141 continue;
5144 if (!secfile_lookup_int(file, &messages_where[event],
5145 "messages.event%d.where", i)) {
5146 log_error("Corruption in file %s: %s",
5147 secfile_name(file), secfile_error());
5152 /****************************************************************
5153 Save the message options; use the function defined by
5154 specnum.h (see also events.h).
5155 *****************************************************************/
5156 static void message_options_save(struct section_file *file,
5157 const char *prefix)
5159 enum event_type event;
5160 int i = 0;
5162 for (event = event_type_begin(); event != event_type_end();
5163 event = event_type_next(event)) {
5164 secfile_insert_str(file, event_type_name(event),
5165 "messages.event%d.name", i);
5166 secfile_insert_int(file, messages_where[i],
5167 "messages.event%d.where", i);
5168 i++;
5171 secfile_insert_int(file, i, "messages.count");
5175 /****************************************************************
5176 Does heavy lifting for looking up a preset.
5177 *****************************************************************/
5178 static void load_cma_preset(struct section_file *file, int i)
5180 struct cm_parameter parameter;
5181 const char *name =
5182 secfile_lookup_str_default(file, "preset",
5183 "cma.preset%d.name", i);
5185 output_type_iterate(o) {
5186 parameter.minimal_surplus[o] =
5187 secfile_lookup_int_default(file, 0, "cma.preset%d.minsurp%d", i, o);
5188 parameter.factor[o] =
5189 secfile_lookup_int_default(file, 0, "cma.preset%d.factor%d", i, o);
5190 } output_type_iterate_end;
5191 parameter.require_happy =
5192 secfile_lookup_bool_default(file, FALSE, "cma.preset%d.reqhappy", i);
5193 parameter.happy_factor =
5194 secfile_lookup_int_default(file, 0, "cma.preset%d.happyfactor", i);
5195 parameter.allow_disorder = FALSE;
5196 parameter.allow_specialists = TRUE;
5198 cmafec_preset_add(name, &parameter);
5201 /****************************************************************
5202 Does heavy lifting for inserting a preset.
5203 *****************************************************************/
5204 static void save_cma_preset(struct section_file *file, int i)
5206 const struct cm_parameter *const pparam = cmafec_preset_get_parameter(i);
5207 char *name = cmafec_preset_get_descr(i);
5209 secfile_insert_str(file, name, "cma.preset%d.name", i);
5211 output_type_iterate(o) {
5212 secfile_insert_int(file, pparam->minimal_surplus[o],
5213 "cma.preset%d.minsurp%d", i, o);
5214 secfile_insert_int(file, pparam->factor[o],
5215 "cma.preset%d.factor%d", i, o);
5216 } output_type_iterate_end;
5217 secfile_insert_bool(file, pparam->require_happy,
5218 "cma.preset%d.reqhappy", i);
5219 secfile_insert_int(file, pparam->happy_factor,
5220 "cma.preset%d.happyfactor", i);
5223 /****************************************************************
5224 Insert all cma presets.
5225 *****************************************************************/
5226 static void save_cma_presets(struct section_file *file)
5228 int i;
5230 secfile_insert_int_comment(file, cmafec_preset_num(),
5231 _("If you add a preset by hand,"
5232 " also update \"number_of_presets\""),
5233 "cma.number_of_presets");
5234 for (i = 0; i < cmafec_preset_num(); i++) {
5235 save_cma_preset(file, i);
5239 /* Old rc file name. */
5240 #define OLD_OPTION_FILE_NAME ".civclientrc"
5241 /* New rc file name. */
5242 #define MID_OPTION_FILE_NAME ".freeciv-client-rc-%d.%d"
5243 #define NEW_OPTION_FILE_NAME "freeciv-client-rc-%d.%d"
5244 #if MINOR_VERSION >= 90
5245 #define MAJOR_NEW_OPTION_FILE_NAME (MAJOR_VERSION + 1)
5246 #define MINOR_NEW_OPTION_FILE_NAME 0
5247 #else /* MINOR_VERSION < 90 */
5248 #define MAJOR_NEW_OPTION_FILE_NAME MAJOR_VERSION
5249 #if IS_DEVEL_VERSION && ! IS_FREEZE_VERSION
5250 #define MINOR_NEW_OPTION_FILE_NAME (MINOR_VERSION + 1)
5251 #else
5252 #define MINOR_NEW_OPTION_FILE_NAME MINOR_VERSION
5253 #endif /* IS_DEVEL_VERSION */
5254 #endif /* MINOR_VERSION >= 90 */
5255 /* The first version the new option name appeared (2.6). */
5256 #define FIRST_MAJOR_NEW_OPTION_FILE_NAME 2
5257 #define FIRST_MINOR_NEW_OPTION_FILE_NAME 6
5258 /* The first version the mid option name appeared (2.2). */
5259 #define FIRST_MAJOR_MID_OPTION_FILE_NAME 2
5260 #define FIRST_MINOR_MID_OPTION_FILE_NAME 2
5261 /* The first version the new boolean values appeared (2.3). */
5262 #define FIRST_MAJOR_NEW_BOOLEAN 2
5263 #define FIRST_MINOR_NEW_BOOLEAN 3
5264 /****************************************************************
5265 Returns pointer to static memory containing name of the current
5266 option file. Usually used for saving.
5267 Ie, based on FREECIV_OPT env var, and freeciv storage root dir.
5268 (or a OPTION_FILE_NAME define defined in fc_config.h)
5269 Or NULL if problem.
5270 *****************************************************************/
5271 static const char *get_current_option_file_name(void)
5273 static char name_buffer[256];
5274 const char *name;
5276 name = getenv("FREECIV_OPT");
5278 if (name) {
5279 sz_strlcpy(name_buffer, name);
5280 } else {
5281 #ifdef OPTION_FILE_NAME
5282 fc_strlcpy(name_buffer, OPTION_FILE_NAME, sizeof(name_buffer));
5283 #else
5284 name = freeciv_storage_dir();
5285 if (!name) {
5286 log_error(_("Cannot find freeciv storage directory"));
5287 return NULL;
5289 fc_snprintf(name_buffer, sizeof(name_buffer),
5290 "%s" DIR_SEPARATOR NEW_OPTION_FILE_NAME, name,
5291 MAJOR_NEW_OPTION_FILE_NAME, MINOR_NEW_OPTION_FILE_NAME);
5292 #endif /* OPTION_FILE_NAME */
5294 log_verbose("settings file is %s", name_buffer);
5295 return name_buffer;
5298 /****************************************************************************
5299 Check the last option file we saved. Usually used to load. Ie, based on
5300 FREECIV_OPT env var, and home dir. (or a OPTION_FILE_NAME define defined
5301 in fc_config.h), or NULL if not found.
5303 Set in allow_digital_boolean if we should look for old boolean values
5304 (saved as 0 and 1), so if the rc file version is older than 2.3.0.
5305 ****************************************************************************/
5306 static const char *get_last_option_file_name(bool *allow_digital_boolean)
5308 static char name_buffer[256];
5309 const char *name;
5310 static int last_minors[] = {
5311 0, /* There was no 0.x releases */
5312 14, /* 1.14 */
5313 7 /* 2.7 */
5316 #if MINOR_VERSION >= 90
5317 FC_STATIC_ASSERT(MAJOR_VERSION < sizeof(last_minors) / sizeof(int), missing_last_minor);
5318 #else
5319 FC_STATIC_ASSERT(MAJOR_VERSION <= sizeof(last_minors) / sizeof(int), missing_last_minor);
5320 #endif
5322 *allow_digital_boolean = FALSE;
5323 name = getenv("FREECIV_OPT");
5324 if (name) {
5325 sz_strlcpy(name_buffer, name);
5326 } else {
5327 #ifdef OPTION_FILE_NAME
5328 fc_strlcpy(name_buffer, OPTION_FILE_NAME, sizeof(name_buffer));
5329 #else
5330 int major, minor;
5331 struct stat buf;
5333 name = freeciv_storage_dir();
5334 if (name == NULL) {
5335 log_error(_("Cannot find freeciv storage directory"));
5337 return NULL;
5340 for (major = MAJOR_NEW_OPTION_FILE_NAME,
5341 minor = MINOR_NEW_OPTION_FILE_NAME;
5342 major >= FIRST_MAJOR_NEW_OPTION_FILE_NAME; major--) {
5343 for (; (major == FIRST_MAJOR_NEW_OPTION_FILE_NAME
5344 ? minor >= FIRST_MINOR_NEW_OPTION_FILE_NAME
5345 : minor >= 0); minor--) {
5346 fc_snprintf(name_buffer, sizeof(name_buffer),
5347 "%s" DIR_SEPARATOR NEW_OPTION_FILE_NAME, name, major, minor);
5348 if (0 == fc_stat(name_buffer, &buf)) {
5349 if (MAJOR_NEW_OPTION_FILE_NAME != major
5350 || MINOR_NEW_OPTION_FILE_NAME != minor) {
5351 log_normal(_("Didn't find '%s' option file, "
5352 "loading from '%s' instead."),
5353 get_current_option_file_name() + strlen(name) + 1,
5354 name_buffer + strlen(name) + 1);
5357 return name_buffer;
5360 minor = last_minors[major - 1];
5363 /* Older versions had options file in user home directory */
5364 name = user_home_dir();
5365 if (name == NULL) {
5366 log_error(_("Cannot find your home directory"));
5368 return NULL;
5371 /* minor having max value of FIRST_MINOR_NEW_OPTION_FILE_NAME
5372 * works since MID versioning scheme was used within major version 2
5373 * only (2.2 - 2.6) so the last minor is bigger than any earlier minor. */
5374 for (major = FIRST_MAJOR_MID_OPTION_FILE_NAME,
5375 minor = FIRST_MINOR_NEW_OPTION_FILE_NAME ;
5376 minor >= FIRST_MINOR_MID_OPTION_FILE_NAME ;
5377 minor--) {
5378 fc_snprintf(name_buffer, sizeof(name_buffer),
5379 "%s" DIR_SEPARATOR MID_OPTION_FILE_NAME, name, major, minor);
5380 if (0 == fc_stat(name_buffer, &buf)) {
5381 log_normal(_("Didn't find '%s' option file, "
5382 "loading from '%s' instead."),
5383 get_current_option_file_name() + strlen(name) + 1,
5384 name_buffer + strlen(name) + 1);
5386 if (FIRST_MINOR_NEW_BOOLEAN > minor) {
5387 *allow_digital_boolean = TRUE;
5389 return name_buffer;
5393 /* Try with the old one. */
5394 fc_snprintf(name_buffer, sizeof(name_buffer),
5395 "%s" DIR_SEPARATOR OLD_OPTION_FILE_NAME, name);
5396 if (0 == fc_stat(name_buffer, &buf)) {
5397 log_normal(_("Didn't find '%s' option file, "
5398 "loading from '%s' instead."),
5399 get_current_option_file_name() + strlen(name) + 1,
5400 OLD_OPTION_FILE_NAME);
5401 *allow_digital_boolean = TRUE;
5402 return name_buffer;
5403 } else {
5404 return NULL;
5406 #endif /* OPTION_FILE_NAME */
5408 log_verbose("settings file is %s", name_buffer);
5409 return name_buffer;
5411 #undef OLD_OPTION_FILE_NAME
5412 #undef MID_OPTION_FILE_NAME
5413 #undef NEW_OPTION_FILE_NAME
5414 #undef FIRST_MAJOR_NEW_OPTION_FILE_NAME
5415 #undef FIRST_MINOR_NEW_OPTION_FILE_NAME
5416 #undef FIRST_MAJOR_MID_OPTION_FILE_NAME
5417 #undef FIRST_MINOR_MID_OPTION_FILE_NAME
5418 #undef FIRST_MINOR_NEW_BOOLEAN
5421 /****************************************************************************
5422 Desired settable options.
5423 ****************************************************************************/
5424 #define SPECHASH_TAG settable_options
5425 #define SPECHASH_ASTR_KEY_TYPE
5426 #define SPECHASH_ASTR_DATA_TYPE
5427 #include "spechash.h"
5428 #define settable_options_hash_iterate(hash, name, value) \
5429 TYPED_HASH_ITERATE(const char *, const char *, hash, name, value)
5430 #define settable_options_hash_iterate_end HASH_ITERATE_END
5432 static struct settable_options_hash *settable_options_hash = NULL;
5434 /**************************************************************************
5435 Load the server options.
5436 **************************************************************************/
5437 static void settable_options_load(struct section_file *sf)
5439 char buf[64];
5440 const struct section *psection;
5441 const struct entry_list *entries;
5442 const char *string;
5443 bool bval;
5444 int ival;
5446 fc_assert_ret(NULL != settable_options_hash);
5448 settable_options_hash_clear(settable_options_hash);
5450 psection = secfile_section_by_name(sf, "server");
5451 if (NULL == psection) {
5452 /* Does not exist! */
5453 return;
5456 entries = section_entries(psection);
5457 entry_list_iterate(entries, pentry) {
5458 string = NULL;
5459 switch (entry_type(pentry)) {
5460 case ENTRY_BOOL:
5461 if (entry_bool_get(pentry, &bval)) {
5462 fc_strlcpy(buf, bval ? "enabled" : "disabled", sizeof(buf));
5463 string = buf;
5465 break;
5467 case ENTRY_INT:
5468 if (entry_int_get(pentry, &ival)) {
5469 fc_snprintf(buf, sizeof(buf), "%d", ival);
5470 string = buf;
5472 break;
5474 case ENTRY_STR:
5475 (void) entry_str_get(pentry, &string);
5476 break;
5478 case ENTRY_FLOAT:
5479 case ENTRY_FILEREFERENCE:
5480 /* Not supported yet */
5481 break;
5484 if (NULL == string) {
5485 log_error("Entry type variant of \"%s.%s\" is not supported.",
5486 section_name(psection), entry_name(pentry));
5487 continue;
5490 settable_options_hash_insert(settable_options_hash, entry_name(pentry),
5491 string);
5492 } entry_list_iterate_end;
5495 /****************************************************************
5496 Save the desired server options.
5497 *****************************************************************/
5498 static void settable_options_save(struct section_file *sf)
5500 fc_assert_ret(NULL != settable_options_hash);
5502 settable_options_hash_iterate(settable_options_hash, name, value) {
5503 if (!fc_strcasecmp(name, "gameseed") || !fc_strcasecmp(name, "mapseed")) {
5504 /* Do not save mapseed or gameseed. */
5505 continue;
5507 if (!fc_strcasecmp(name, "topology")) {
5508 /* client_start_server() sets topology based on tileset. Don't store
5509 * its choice. The tileset is already stored. Storing topology leads
5510 * to all sort of breakage:
5511 * - it breaks ruleset default topology.
5512 * - it interacts badly with tileset ruleset change, ruleset tileset
5513 * change and topology tileset change.
5514 * - its value is probably based on what tileset was loaded when
5515 * client_start_server() decided to set topology, not on player
5516 * choice.
5518 continue;
5520 secfile_insert_str(sf, value, "server.%s", name);
5521 } settable_options_hash_iterate_end;
5524 /****************************************************************************
5525 Update the desired settable options hash table from the current
5526 setting configuration.
5527 ****************************************************************************/
5528 void desired_settable_options_update(void)
5530 char val_buf[1024], def_buf[1024];
5531 const char *value, *def_val;
5533 fc_assert_ret(NULL != settable_options_hash);
5535 options_iterate(server_optset, poption) {
5536 value = NULL;
5537 def_val = NULL;
5538 switch (option_type(poption)) {
5539 case OT_BOOLEAN:
5540 fc_strlcpy(val_buf, option_bool_get(poption) ? "enabled" : "disabled",
5541 sizeof(val_buf));
5542 value = val_buf;
5543 fc_strlcpy(def_buf, option_bool_def(poption) ? "enabled" : "disabled",
5544 sizeof(def_buf));
5545 def_val = def_buf;
5546 break;
5547 case OT_INTEGER:
5548 fc_snprintf(val_buf, sizeof(val_buf), "%d", option_int_get(poption));
5549 value = val_buf;
5550 fc_snprintf(def_buf, sizeof(def_buf), "%d", option_int_def(poption));
5551 def_val = def_buf;
5552 break;
5553 case OT_STRING:
5554 value = option_str_get(poption);
5555 def_val = option_str_def(poption);
5556 break;
5557 case OT_ENUM:
5558 server_option_enum_support_name(poption, &value, &def_val);
5559 break;
5560 case OT_BITWISE:
5561 server_option_bitwise_support_name(poption, val_buf, sizeof(val_buf),
5562 def_buf, sizeof(def_buf));
5563 value = val_buf;
5564 def_val = def_buf;
5565 break;
5566 case OT_FONT:
5567 case OT_COLOR:
5568 case OT_VIDEO_MODE:
5569 break;
5572 if (NULL == value || NULL == def_val) {
5573 log_error("Option type %s (%d) not supported for '%s'.",
5574 option_type_name(option_type(poption)), option_type(poption),
5575 option_name(poption));
5576 continue;
5579 if (0 == strcmp(value, def_val)) {
5580 /* Not set, using default... */
5581 settable_options_hash_remove(settable_options_hash,
5582 option_name(poption));
5583 } else {
5584 /* Really desired. */
5585 settable_options_hash_replace(settable_options_hash,
5586 option_name(poption), value);
5588 } options_iterate_end;
5591 /****************************************************************
5592 Update a desired settable option in the hash table from a value
5593 which can be different of the current consiguration.
5594 *****************************************************************/
5595 void desired_settable_option_update(const char *op_name,
5596 const char *op_value,
5597 bool allow_replace)
5599 fc_assert_ret(NULL != settable_options_hash);
5601 if (allow_replace) {
5602 settable_options_hash_replace(settable_options_hash, op_name, op_value);
5603 } else {
5604 settable_options_hash_insert(settable_options_hash, op_name, op_value);
5608 /****************************************************************************
5609 Convert old integer to new values (Freeciv 2.2.x to Freeciv 2.3.x).
5610 Very ugly hack. TODO: Remove this later.
5611 ****************************************************************************/
5612 static bool settable_option_upgrade_value(const struct option *poption,
5613 int old_value,
5614 char *buf, size_t buf_len)
5616 const char *name = option_name(poption);
5618 #define SETTING_CASE(ARG_name, ...) \
5619 if (0 == strcmp(ARG_name, name)) { \
5620 static const char *values[] = { __VA_ARGS__ }; \
5621 if (0 <= old_value && old_value < ARRAY_SIZE(values) \
5622 && NULL != values[old_value]) { \
5623 fc_strlcpy(buf, values[old_value], buf_len); \
5624 return TRUE; \
5625 } else { \
5626 return FALSE; \
5630 SETTING_CASE("topology", "", "WRAPX", "WRAPY", "WRAPX|WRAPY", "ISO",
5631 "WRAPX|ISO", "WRAPY|ISO", "WRAPX|WRAPY|ISO", "HEX",
5632 "WRAPX|HEX", "WRAPY|HEX", "WRAPX|WRAPY|HEX", "ISO|HEX",
5633 "WRAPX|ISO|HEX", "WRAPY|ISO|HEX", "WRAPX|WRAPY|ISO|HEX");
5634 SETTING_CASE("generator", NULL, "RANDOM", "FRACTAL", "ISLAND");
5635 SETTING_CASE("startpos", "DEFAULT", "SINGLE", "2or3", "ALL", "VARIABLE");
5636 SETTING_CASE("borders", "DISABLED", "ENABLED", "SEE_INSIDE", "EXPAND");
5637 SETTING_CASE("diplomacy", "ALL", "HUMAN", "AI", "TEAM", "DISABLED");
5638 SETTING_CASE("citynames", "NO_RESTRICTIONS", "PLAYER_UNIQUE",
5639 "GLOBAL_UNIQUE", "NO_STEALING");
5640 SETTING_CASE("barbarians", "DISABLED", "HUTS_ONLY", "NORMAL", "FREQUENT",
5641 "HORDES");
5642 SETTING_CASE("phasemode", "ALL", "PLAYER", "TEAM");
5643 SETTING_CASE("compresstype", "PLAIN", "LIBZ", "BZIP2");
5645 #undef SETTING_CASE
5646 return FALSE;
5649 /****************************************************************************
5650 Send the desired server options to the server.
5651 ****************************************************************************/
5652 static void desired_settable_option_send(struct option *poption)
5654 char *desired;
5655 int value;
5657 fc_assert_ret(NULL != settable_options_hash);
5659 if (!settable_options_hash_lookup(settable_options_hash,
5660 option_name(poption), &desired)) {
5661 /* No change explicitly desired. */
5662 return;
5665 switch (option_type(poption)) {
5666 case OT_BOOLEAN:
5667 if ((0 == fc_strcasecmp("enabled", desired)
5668 || (str_to_int(desired, &value) && 1 == value))
5669 && !option_bool_get(poption)) {
5670 send_chat_printf("/set %s enabled", option_name(poption));
5671 } else if ((0 == fc_strcasecmp("disabled", desired)
5672 || (str_to_int(desired, &value) && 0 == value))
5673 && option_bool_get(poption)) {
5674 send_chat_printf("/set %s disabled", option_name(poption));
5676 return;
5677 case OT_INTEGER:
5678 if (str_to_int(desired, &value) && value != option_int_get(poption)) {
5679 send_chat_printf("/set %s %d", option_name(poption), value);
5681 return;
5682 case OT_STRING:
5683 if (0 != strcmp(desired, option_str_get(poption))) {
5684 send_chat_printf("/set %s \"%s\"", option_name(poption), desired);
5686 return;
5687 case OT_ENUM:
5689 char desired_buf[256];
5690 const char *value_str;
5692 /* Handle old values. */
5693 if (str_to_int(desired, &value)
5694 && settable_option_upgrade_value(poption, value, desired_buf,
5695 sizeof(desired_buf))) {
5696 desired = desired_buf;
5699 server_option_enum_support_name(poption, &value_str, NULL);
5700 if (0 != strcmp(desired, value_str)) {
5701 send_chat_printf("/set %s \"%s\"", option_name(poption), desired);
5704 return;
5705 case OT_BITWISE:
5707 char desired_buf[256], value_buf[256];
5709 /* Handle old values. */
5710 if (str_to_int(desired, &value)
5711 && settable_option_upgrade_value(poption, value, desired_buf,
5712 sizeof(desired_buf))) {
5713 desired = desired_buf;
5716 server_option_bitwise_support_name(poption, value_buf,
5717 sizeof(value_buf), NULL, 0);
5718 if (0 != strcmp(desired, value_buf)) {
5719 send_chat_printf("/set %s \"%s\"", option_name(poption), desired);
5722 return;
5723 case OT_FONT:
5724 case OT_COLOR:
5725 case OT_VIDEO_MODE:
5726 break;
5729 log_error("Option type %s (%d) not supported for '%s'.",
5730 option_type_name(option_type(poption)), option_type(poption),
5731 option_name(poption));
5735 /****************************************************************************
5736 City and player report dialog options.
5737 ****************************************************************************/
5738 #define SPECHASH_TAG dialog_options
5739 #define SPECHASH_ASTR_KEY_TYPE
5740 #define SPECHASH_IDATA_TYPE bool
5741 #define SPECHASH_UDATA_TO_IDATA FC_INT_TO_PTR
5742 #define SPECHASH_IDATA_TO_UDATA FC_PTR_TO_INT
5743 #include "spechash.h"
5744 #define dialog_options_hash_iterate(hash, column, visible) \
5745 TYPED_HASH_ITERATE(const char *, intptr_t, hash, column, visible)
5746 #define dialog_options_hash_iterate_end HASH_ITERATE_END
5748 static struct dialog_options_hash *dialog_options_hash = NULL;
5750 /****************************************************************************
5751 Load the city and player report dialog options.
5752 ****************************************************************************/
5753 static void options_dialogs_load(struct section_file *sf)
5755 const struct entry_list *entries;
5756 const char *prefixes[] = { "player_dlg_", "city_report_", NULL };
5757 const char **prefix;
5758 bool visible;
5760 fc_assert_ret(NULL != dialog_options_hash);
5762 entries = section_entries(secfile_section_by_name(sf, "client"));
5764 if (NULL != entries) {
5765 entry_list_iterate(entries, pentry) {
5766 for (prefix = prefixes; NULL != *prefix; prefix++) {
5767 if (0 == strncmp(*prefix, entry_name(pentry), strlen(*prefix))
5768 && secfile_lookup_bool(sf, &visible, "client.%s",
5769 entry_name(pentry))) {
5770 dialog_options_hash_replace(dialog_options_hash,
5771 entry_name(pentry), visible);
5772 break;
5775 } entry_list_iterate_end;
5779 /****************************************************************************
5780 Save the city and player report dialog options.
5781 ****************************************************************************/
5782 static void options_dialogs_save(struct section_file *sf)
5784 fc_assert_ret(NULL != dialog_options_hash);
5786 options_dialogs_update();
5787 dialog_options_hash_iterate(dialog_options_hash, column, visible) {
5788 secfile_insert_bool(sf, visible, "client.%s", column);
5789 } dialog_options_hash_iterate_end;
5792 /****************************************************************
5793 This set the city and player report dialog options to the
5794 current ones. It's called when the client goes to
5795 C_S_DISCONNECTED state.
5796 *****************************************************************/
5797 void options_dialogs_update(void)
5799 char buf[64];
5800 int i;
5802 fc_assert_ret(NULL != dialog_options_hash);
5804 /* Player report dialog options. */
5805 for (i = 1; i < num_player_dlg_columns; i++) {
5806 fc_snprintf(buf, sizeof(buf), "player_dlg_%s",
5807 player_dlg_columns[i].tagname);
5808 dialog_options_hash_replace(dialog_options_hash, buf,
5809 player_dlg_columns[i].show);
5812 /* City report dialog options. */
5813 for (i = 0; i < num_city_report_spec(); i++) {
5814 fc_snprintf(buf, sizeof(buf), "city_report_%s",
5815 city_report_spec_tagname(i));
5816 dialog_options_hash_replace(dialog_options_hash, buf,
5817 *city_report_spec_show_ptr(i));
5821 /****************************************************************
5822 This set the city and player report dialog options. It's called
5823 when the client goes to C_S_RUNNING state.
5824 *****************************************************************/
5825 void options_dialogs_set(void)
5827 char buf[64];
5828 bool visible;
5829 int i;
5831 fc_assert_ret(NULL != dialog_options_hash);
5833 /* Player report dialog options. */
5834 for (i = 1; i < num_player_dlg_columns; i++) {
5835 fc_snprintf(buf, sizeof(buf), "player_dlg_%s",
5836 player_dlg_columns[i].tagname);
5837 if (dialog_options_hash_lookup(dialog_options_hash, buf, &visible)) {
5838 player_dlg_columns[i].show = visible;
5842 /* City report dialog options. */
5843 for (i = 0; i < num_city_report_spec(); i++) {
5844 fc_snprintf(buf, sizeof(buf), "city_report_%s",
5845 city_report_spec_tagname(i));
5846 if (dialog_options_hash_lookup(dialog_options_hash, buf, &visible)) {
5847 *city_report_spec_show_ptr(i) = visible;
5853 /****************************************************************
5854 Load from the rc file any options that are not ruleset specific.
5855 It is called after ui_init(), yet before ui_main().
5856 Unfortunately, this means that some clients cannot display.
5857 Instead, use log_*().
5858 *****************************************************************/
5859 void options_load(void)
5861 struct section_file *sf;
5862 bool allow_digital_boolean;
5863 int i, num;
5864 const char *name;
5865 const char *const prefix = "client";
5866 const char *str;
5868 name = get_last_option_file_name(&allow_digital_boolean);
5869 if (!name) {
5870 log_normal(_("Didn't find the option file. Creating a new one."));
5871 client_option_adjust_defaults();
5872 options_fully_initialized = TRUE;
5873 create_default_cma_presets();
5874 gui_options.first_boot = TRUE;
5875 return;
5877 if (!(sf = secfile_load(name, TRUE))) {
5878 log_debug("Error loading option file '%s':\n%s", name, secfile_error());
5879 /* try to create the rc file */
5880 sf = secfile_new(TRUE);
5881 secfile_insert_str(sf, VERSION_STRING, "client.version");
5883 create_default_cma_presets();
5884 save_cma_presets(sf);
5886 /* FIXME: need better messages */
5887 if (!secfile_save(sf, name, 0, FZ_PLAIN)) {
5888 log_error(_("Save failed, cannot write to file %s"), name);
5889 } else {
5890 log_normal(_("Saved settings to file %s"), name);
5892 secfile_destroy(sf);
5893 options_fully_initialized = TRUE;
5894 return;
5896 secfile_allow_digital_boolean(sf, allow_digital_boolean);
5898 /* a "secret" option for the lazy. TODO: make this saveable */
5899 sz_strlcpy(password,
5900 secfile_lookup_str_default(sf, "", "%s.password", prefix));
5902 gui_options.save_options_on_exit =
5903 secfile_lookup_bool_default(sf, gui_options.save_options_on_exit,
5904 "%s.save_options_on_exit", prefix);
5905 gui_options.migrate_fullscreen =
5906 secfile_lookup_bool_default(sf, gui_options.migrate_fullscreen,
5907 "%s.fullscreen_mode", prefix);
5909 /* Settings migrations */
5910 gui_options.gui_gtk3_migrated_from_gtk2 =
5911 secfile_lookup_bool_default(sf, gui_options.gui_gtk3_migrated_from_gtk2,
5912 "%s.migration_gtk3_from_gtk2", prefix);
5913 gui_options.gui_gtk3_22_migrated_from_gtk3 =
5914 secfile_lookup_bool_default(sf, gui_options.gui_gtk3_22_migrated_from_gtk3,
5915 "%s.migration_gtk3_22_from_gtk3", prefix);
5916 gui_options.gui_gtk4_migrated_from_gtk3_22 =
5917 secfile_lookup_bool_default(sf, gui_options.gui_gtk4_migrated_from_gtk3_22,
5918 "%s.migration_gtk4_from_gtk3_22", prefix);
5919 gui_options.gui_sdl2_migrated_from_sdl =
5920 secfile_lookup_bool_default(sf, gui_options.gui_sdl2_migrated_from_sdl,
5921 "%s.migration_sdl2_from_sdl", prefix);
5922 gui_options.gui_gtk2_migrated_from_2_5 =
5923 secfile_lookup_bool_default(sf, gui_options.gui_gtk3_migrated_from_2_5,
5924 "%s.migration_gtk2_from_2_5", prefix);
5925 gui_options.gui_gtk3_migrated_from_2_5 =
5926 secfile_lookup_bool_default(sf, gui_options.gui_gtk2_migrated_from_2_5,
5927 "%s.migration_gtk3_from_2_5", prefix);
5928 gui_options.gui_qt_migrated_from_2_5 =
5929 secfile_lookup_bool_default(sf, gui_options.gui_qt_migrated_from_2_5,
5930 "%s.migration_qt_from_2_5", prefix);
5932 /* These are not gui-enabled yet */
5933 gui_options.zoom_set =
5934 secfile_lookup_bool_default(sf, FALSE, "%s.zoom_set", prefix);
5935 gui_options.zoom_default_level =
5936 secfile_lookup_float_default(sf, 1.0,
5937 "%s.zoom_default_level", prefix);
5939 str = secfile_lookup_str_default(sf, NULL, "client.default_tileset_name");
5940 if (str != NULL) {
5941 strncpy(gui_options.default_tileset_name, str,
5942 sizeof(gui_options.default_tileset_name));
5945 /* Backwards compatibility for removed options replaced by entirely "new"
5946 * options. The equivalent "new" option will override these, if set. */
5948 /* Removed in 2.3 */
5949 /* Note: this overrides the previously specified default for
5950 * gui_gtk2_message_chat_location */
5951 /* gtk3 client never had the old form of this option. The overridden
5952 * gui_gtk2_ value will be propagated to gui_gtk3_ later by
5953 * migrate_options_from_gtk2() if necessary. */
5954 if (secfile_lookup_bool_default(sf, FALSE,
5955 "%s.gui_gtk2_merge_notebooks", prefix)) {
5956 gui_options.gui_gtk2_message_chat_location = GUI_GTK_MSGCHAT_MERGED;
5957 } else if (secfile_lookup_bool_default(sf, FALSE,
5958 "%s.gui_gtk2_split_bottom_notebook",
5959 prefix)) {
5960 gui_options.gui_gtk2_message_chat_location = GUI_GTK_MSGCHAT_SPLIT;
5961 } else {
5962 gui_options.gui_gtk2_message_chat_location = GUI_GTK_MSGCHAT_SEPARATE;
5965 /* Renamed in 2.6 */
5966 gui_options.popup_actor_arrival = secfile_lookup_bool_default(sf, TRUE,
5967 "%s.popup_caravan_arrival", prefix);
5969 /* Load all the regular options */
5970 client_options_iterate_all(poption) {
5971 client_option_load(poption, sf);
5972 } client_options_iterate_all_end;
5974 /* More backwards compatibility, for removed options that had been
5975 * folded into then-existing options. Here, the backwards-compatibility
5976 * behaviour overrides the "destination" option. */
5978 /* Removed in 2.4 */
5979 if (!secfile_lookup_bool_default(sf, TRUE,
5980 "%s.do_combat_animation", prefix)) {
5981 gui_options.smooth_combat_step_msec = 0;
5984 message_options_load(sf, prefix);
5985 options_dialogs_load(sf);
5987 /* Load cma presets. If cma.number_of_presets doesn't exist, don't load
5988 * any, the order here should be reversed to keep the order the same */
5989 if (secfile_lookup_int(sf, &num, "cma.number_of_presets")) {
5990 for (i = num - 1; i >= 0; i--) {
5991 load_cma_preset(sf, i);
5993 } else {
5994 create_default_cma_presets();
5997 settable_options_load(sf);
5998 global_worklists_load(sf);
6000 secfile_destroy(sf);
6001 options_fully_initialized = TRUE;
6004 /**************************************************************************
6005 Write messages from option saving to the output window.
6006 **************************************************************************/
6007 static void option_save_output_window_callback(enum log_level lvl,
6008 const char *msg, ...)
6010 va_list args;
6012 va_start(args, msg);
6013 output_window_vprintf(ftc_client, msg, args);
6014 va_end(args);
6017 /**************************************************************************
6018 Save all options.
6019 **************************************************************************/
6020 void options_save(option_save_log_callback log_cb)
6022 struct section_file *sf;
6023 const char *name = get_current_option_file_name();
6024 char dir_name[2048];
6025 int i;
6027 if (log_cb == NULL) {
6028 /* Default callback */
6029 log_cb = option_save_output_window_callback;
6032 if (!name) {
6033 log_cb(LOG_ERROR, _("Save failed, cannot find a filename."));
6034 return;
6037 sf = secfile_new(TRUE);
6038 secfile_insert_str(sf, VERSION_STRING, "client.version");
6040 secfile_insert_bool(sf, gui_options.save_options_on_exit,
6041 "client.save_options_on_exit");
6042 secfile_insert_bool_comment(sf, gui_options.migrate_fullscreen,
6043 "deprecated", "client.fullscreen_mode");
6045 /* Migrations */
6046 secfile_insert_bool(sf, gui_options.gui_gtk3_migrated_from_gtk2,
6047 "client.migration_gtk3_from_gtk2");
6048 secfile_insert_bool(sf, gui_options.gui_gtk3_22_migrated_from_gtk3,
6049 "client.migration_gtk3_22_from_gtk3");
6050 secfile_insert_bool(sf, gui_options.gui_gtk4_migrated_from_gtk3_22,
6051 "client.migration_gtk4_from_gtk3");
6052 secfile_insert_bool(sf, gui_options.gui_sdl2_migrated_from_sdl,
6053 "client.migration_sdl2_from_sdl");
6054 secfile_insert_bool(sf, gui_options.gui_gtk2_migrated_from_2_5,
6055 "client.migration_gtk2_from_2_5");
6056 secfile_insert_bool(sf, gui_options.gui_gtk3_migrated_from_2_5,
6057 "client.migration_gtk3_from_2_5");
6058 secfile_insert_bool(sf, gui_options.gui_qt_migrated_from_2_5,
6059 "client.migration_qt_from_2_5");
6061 /* gui-enabled options */
6062 client_options_iterate_all(poption) {
6063 if ((client_poption->specific != GUI_SDL || !gui_options.gui_sdl2_migrated_from_sdl)
6064 && (client_poption->specific != GUI_GTK2 || !gui_options.gui_gtk3_migrated_from_gtk2)) {
6065 /* Once sdl-client options have been migrated to sdl2-client, or gtk2-client options
6066 * to gtk3-client, there's no use for them any more, so no point in saving them. */
6067 client_option_save(poption, sf);
6069 } client_options_iterate_all_end;
6071 /* These are not gui-enabled yet. */
6072 secfile_insert_bool(sf, gui_options.zoom_set, "client.zoom_set");
6073 secfile_insert_float(sf, gui_options.zoom_default_level,
6074 "client.zoom_default_level");
6076 if (gui_options.default_tileset_name[0] != '\0') {
6077 secfile_insert_str(sf, gui_options.default_tileset_name,
6078 "client.default_tileset_name");
6081 message_options_save(sf, "client");
6082 options_dialogs_save(sf);
6084 /* server settings */
6085 save_cma_presets(sf);
6086 settable_options_save(sf);
6088 /* insert global worklists */
6089 global_worklists_save(sf);
6091 /* Directory name */
6092 strncpy(dir_name, name, sizeof(dir_name));
6093 for (i = strlen(dir_name) - 1 ; dir_name[i] != DIR_SEPARATOR_CHAR && i >= 0; i--) {
6094 /* Nothing */
6096 if (i > 0) {
6097 dir_name[i] = '\0';
6098 make_dir(dir_name);
6101 /* save to disk */
6102 if (!secfile_save(sf, name, 0, FZ_PLAIN)) {
6103 log_cb(LOG_ERROR, _("Save failed, cannot write to file %s"), name);
6104 } else {
6105 log_cb(LOG_VERBOSE, _("Saved settings to file %s"), name);
6107 secfile_destroy(sf);
6111 /**************************************************************************
6112 Initialize lists of names for a client option.
6113 **************************************************************************/
6114 static void options_init_names(const struct copt_val_name *(*acc)(int),
6115 struct strvec **support, struct strvec **pretty)
6117 int val;
6118 const struct copt_val_name *name;
6119 fc_assert_ret(NULL != acc);
6120 *support = strvec_new();
6121 *pretty = strvec_new();
6122 for (val=0; (name = acc(val)); val++) {
6123 strvec_append(*support, name->support);
6124 strvec_append(*pretty, name->pretty);
6128 /**************************************************************************
6129 Initialize the option module.
6130 **************************************************************************/
6131 void options_init(void)
6133 message_options_init();
6134 options_extra_init();
6135 global_worklists_init();
6137 settable_options_hash = settable_options_hash_new();
6138 dialog_options_hash = dialog_options_hash_new();
6140 client_options_iterate_all(poption) {
6141 struct client_option *pcoption = CLIENT_OPTION(poption);
6143 switch (option_type(poption)) {
6144 case OT_INTEGER:
6145 if (option_int_def(poption) < option_int_min(poption)
6146 || option_int_def(poption) > option_int_max(poption)) {
6147 int new_default = MAX(MIN(option_int_def(poption),
6148 option_int_max(poption)),
6149 option_int_min(poption));
6151 log_error("option %s has default value of %d, which is "
6152 "out of its range [%d; %d], changing to %d.",
6153 option_name(poption), option_int_def(poption),
6154 option_int_min(poption), option_int_max(poption),
6155 new_default);
6156 *((int *) &(pcoption->integer.def)) = new_default;
6158 break;
6160 case OT_STRING:
6161 if (gui_options.default_user_name == option_str_get(poption)) {
6162 /* Hack to get a default value. */
6163 *((const char **) &(pcoption->string.def)) =
6164 fc_strdup(gui_options.default_user_name);
6167 if (NULL == option_str_def(poption)) {
6168 const struct strvec *values = option_str_values(poption);
6170 if (NULL == values || strvec_size(values) == 0) {
6171 log_error("Invalid NULL default string for option %s.",
6172 option_name(poption));
6173 } else {
6174 *((const char **) &(pcoption->string.def)) =
6175 strvec_get(values, 0);
6178 break;
6180 case OT_ENUM:
6181 fc_assert(NULL == pcoption->enumerator.support_names);
6182 fc_assert(NULL == pcoption->enumerator.pretty_names);
6183 options_init_names(pcoption->enumerator.name_accessor,
6184 &pcoption->enumerator.support_names,
6185 &pcoption->enumerator.pretty_names);
6186 fc_assert(NULL != pcoption->enumerator.support_names);
6187 fc_assert(NULL != pcoption->enumerator.pretty_names);
6188 break;
6190 case OT_BITWISE:
6191 fc_assert(NULL == pcoption->bitwise.support_names);
6192 fc_assert(NULL == pcoption->bitwise.pretty_names);
6193 options_init_names(pcoption->bitwise.name_accessor,
6194 &pcoption->bitwise.support_names,
6195 &pcoption->bitwise.pretty_names);
6196 fc_assert(NULL != pcoption->bitwise.support_names);
6197 fc_assert(NULL != pcoption->bitwise.pretty_names);
6198 break;
6200 case OT_COLOR:
6202 /* Duplicate the string pointers. */
6203 struct ft_color *pcolor = pcoption->color.pvalue;
6205 if (NULL != pcolor->foreground) {
6206 pcolor->foreground = fc_strdup(pcolor->foreground);
6208 if (NULL != pcolor->background) {
6209 pcolor->background = fc_strdup(pcolor->background);
6213 case OT_BOOLEAN:
6214 case OT_FONT:
6215 case OT_VIDEO_MODE:
6216 break;
6219 /* Set to default. */
6220 option_reset(poption);
6221 } client_options_iterate_all_end;
6224 /**************************************************************************
6225 Free the option module.
6226 **************************************************************************/
6227 void options_free(void)
6229 client_options_iterate_all(poption) {
6230 struct client_option *pcoption = CLIENT_OPTION(poption);
6232 switch (option_type(poption)) {
6233 case OT_ENUM:
6234 fc_assert_action(NULL != pcoption->enumerator.support_names, break);
6235 strvec_destroy(pcoption->enumerator.support_names);
6236 pcoption->enumerator.support_names = NULL;
6237 fc_assert_action(NULL != pcoption->enumerator.pretty_names, break);
6238 strvec_destroy(pcoption->enumerator.pretty_names);
6239 pcoption->enumerator.pretty_names = NULL;
6240 break;
6242 case OT_BITWISE:
6243 fc_assert_action(NULL != pcoption->bitwise.support_names, break);
6244 strvec_destroy(pcoption->bitwise.support_names);
6245 pcoption->bitwise.support_names = NULL;
6246 fc_assert_action(NULL != pcoption->bitwise.pretty_names, break);
6247 strvec_destroy(pcoption->bitwise.pretty_names);
6248 pcoption->bitwise.pretty_names = NULL;
6249 break;
6251 case OT_BOOLEAN:
6252 case OT_INTEGER:
6253 case OT_STRING:
6254 case OT_FONT:
6255 case OT_COLOR:
6256 case OT_VIDEO_MODE:
6257 break;
6259 } client_options_iterate_all_end;
6261 if (NULL != settable_options_hash) {
6262 settable_options_hash_destroy(settable_options_hash);
6263 settable_options_hash = NULL;
6266 if (NULL != dialog_options_hash) {
6267 dialog_options_hash_destroy(dialog_options_hash);
6268 dialog_options_hash = NULL;
6271 message_options_free();
6272 global_worklists_free();
6275 /****************************************************************************
6276 Callback when the reqtree show icons option is changed. The tree is
6277 recalculated.
6278 ****************************************************************************/
6279 static void reqtree_show_icons_callback(struct option *poption)
6281 science_report_dialog_redraw();
6284 /****************************************************************************
6285 Callback for when any view option is changed.
6286 ****************************************************************************/
6287 static void view_option_changed_callback(struct option *poption)
6289 menus_init();
6290 update_map_canvas_visible();
6293 /****************************************************************************
6294 Callback for when any voteinfo bar option is changed.
6295 ****************************************************************************/
6296 static void voteinfo_bar_callback(struct option *poption)
6298 voteinfo_gui_update();
6301 /****************************************************************************
6302 Callback for font options.
6303 ****************************************************************************/
6304 static void font_changed_callback(struct option *poption)
6306 fc_assert_ret(OT_FONT == option_type(OPTION(poption)));
6307 gui_update_font(option_font_target(poption), option_font_get(poption));
6310 /****************************************************************************
6311 Callback for mapimg options.
6312 ****************************************************************************/
6313 static void mapimg_changed_callback(struct option *poption)
6315 if (!mapimg_client_define()) {
6316 bool success;
6318 log_normal("Error setting the value for %s (%s). Restoring the default "
6319 "value.", option_name(poption), mapimg_error());
6321 /* Reset the value to the default value. */
6322 success = option_reset(poption);
6323 fc_assert_msg(success == TRUE,
6324 "Failed to reset the option \"%s\".",
6325 option_name(poption));
6326 success = mapimg_client_define();
6327 fc_assert_msg(success == TRUE,
6328 "Failed to restore mapimg definition for option \"%s\".",
6329 option_name(poption));
6333 /****************************************************************************
6334 Callback for music enabling option.
6335 ****************************************************************************/
6336 static void game_music_enable_callback(struct option *poption)
6338 if (client_state() == C_S_RUNNING) {
6339 if (gui_options.sound_enable_game_music) {
6340 start_style_music();
6341 } else {
6342 stop_style_music();
6347 /****************************************************************************
6348 Callback for music enabling option.
6349 ****************************************************************************/
6350 static void menu_music_enable_callback(struct option *poption)
6352 if (client_state() != C_S_RUNNING) {
6353 if (gui_options.sound_enable_menu_music) {
6354 start_menu_music("music_menu", NULL);
6355 } else {
6356 stop_menu_music();
6361 /****************************************************************************
6362 Make dynamic adjustments to first-launch default options.
6363 ****************************************************************************/
6364 static void client_option_adjust_defaults(void)
6366 adjust_default_options();
6369 /****************************************************************************
6370 Convert a video mode to string. Returns TRUE on success.
6371 ****************************************************************************/
6372 bool video_mode_to_string(char *buf, size_t buf_len, struct video_mode *mode)
6374 return (2 < fc_snprintf(buf, buf_len, "%dx%d", mode->width, mode->height));
6377 /****************************************************************************
6378 Convert a string to video mode. Returns TRUE on success.
6379 ****************************************************************************/
6380 bool string_to_video_mode(const char *buf, struct video_mode *mode)
6382 return (2 == sscanf(buf, "%dx%d", &mode->width, &mode->height));
6385 /****************************************************************************
6386 Option framework wrapper for mapimg_get_format_list()
6387 ****************************************************************************/
6388 static const struct strvec *get_mapimg_format_list(const struct option *poption)
6390 return mapimg_get_format_list();
6393 /****************************************************************************
6394 What is the user defined tileset for the given topology
6395 ****************************************************************************/
6396 const char *tileset_name_for_topology(int topology_id)
6398 const char *tsn = NULL;
6400 switch (topology_id & (TF_ISO | TF_HEX)) {
6401 case 0:
6402 tsn = gui_options.default_tileset_overhead_name;
6403 break;
6404 case TF_ISO:
6405 tsn = gui_options.default_tileset_iso_name;
6406 break;
6407 case TF_HEX:
6408 tsn = gui_options.default_tileset_hex_name;
6409 break;
6410 case TF_ISO | TF_HEX:
6411 tsn = gui_options.default_tileset_isohex_name;
6412 break;
6415 if (tsn == NULL) {
6416 tsn = gui_options.default_tileset_name;
6419 return tsn;
6422 /****************************************************************************
6423 Set given tileset as the default for suitable topology
6424 ****************************************************************************/
6425 void option_set_default_ts(struct tileset *t)
6427 const char *optname = "<not set>";
6428 struct option *opt;
6430 switch (tileset_topo_index(t)) {
6431 case TS_TOPO_OVERHEAD:
6432 /* Overhead */
6433 optname = "default_tileset_overhead_name";
6434 break;
6435 case TS_TOPO_ISO:
6436 /* Iso */
6437 optname = "default_tileset_iso_name";
6438 break;
6439 case TS_TOPO_HEX:
6440 /* Hex */
6441 optname = "default_tileset_hex_name";
6442 break;
6443 case TS_TOPO_ISOHEX:
6444 /* Isohex */
6445 optname = "default_tileset_isohex_name";
6446 break;
6449 opt = optset_option_by_name(client_optset, optname);
6451 if (opt == NULL) {
6452 log_error("Unknown option name \"%s\" in option_set_default_ts()", optname);
6453 return;
6456 /* Do not call option_str_set() since we don't want option changed callback
6457 * to reload this tileset. */
6458 opt->str_vtable->set(opt, tileset_basename(t));
6459 option_gui_update(opt);
6462 /****************************************************************************
6463 Does topology-specific tileset option lack value?
6464 ****************************************************************************/
6465 static bool is_ts_option_unset(const char *optname)
6467 struct option *opt;
6468 const char *val;
6470 opt = optset_option_by_name(client_optset, optname);
6472 if (opt == NULL) {
6473 return TRUE;
6476 val = opt->str_vtable->get(opt);
6478 if (val == NULL || val[0] == '\0') {
6479 return TRUE;
6482 return FALSE;
6485 /****************************************************************************
6486 Fill default tilesets for topology-specific settings.
6487 ****************************************************************************/
6488 void fill_topo_ts_default(void)
6490 if (is_ts_option_unset("default_tileset_overhead_name")) {
6491 log_debug("Setting tileset for overhead topology.");
6492 tilespec_try_read(NULL, FALSE, 0, FALSE);
6494 if (is_ts_option_unset("default_tileset_iso_name")) {
6495 log_debug("Setting tileset for iso topology.");
6496 tilespec_try_read(NULL, FALSE, TF_ISO, FALSE);
6498 if (is_ts_option_unset("default_tileset_hex_name")) {
6499 log_debug("Setting tileset for hex topology.");
6500 tilespec_try_read(NULL, FALSE, TF_HEX, FALSE);
6502 if (is_ts_option_unset("default_tileset_isohex_name")) {
6503 log_debug("Setting tileset for isohex topology.");
6504 tilespec_try_read(NULL, FALSE, TF_ISO | TF_HEX, FALSE);