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