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 /***********************************************************************
15                           optiondlg.c  -  description
16                              -------------------
17     begin                : Sun Aug 11 2002
18     copyright            : (C) 2002 by Rafał Bursig
19     email                : Rafał Bursig <bursig@poczta.fm>
20 ***********************************************************************/
21 
22 #ifdef HAVE_CONFIG_H
23 #include <fc_config.h>
24 #endif
25 
26 #include <stdarg.h>
27 #include <stdlib.h>
28 
29 /* SDL2 */
30 #ifdef SDL2_PLAIN_INCLUDE
31 #include <SDL.h>
32 #else  /* SDL2_PLAIN_INCLUDE */
33 #include <SDL2/SDL.h>
34 #endif /* SDL2_PLAIN_INCLUDE */
35 
36 /* utility */
37 #include "fcintl.h"
38 #include "log.h"
39 #include "string_vector.h"
40 
41 /* common */
42 #include "fc_types.h"
43 #include "game.h"
44 
45 /* client */
46 #include "client_main.h"
47 #include "climisc.h"
48 #include "clinet.h"
49 #include "connectdlg_common.h"
50 #include "global_worklist.h"
51 
52 /* gui-sdl2 */
53 #include "colors.h"
54 #include "connectdlg.h"
55 #include "dialogs.h"
56 #include "graphics.h"
57 #include "gui_iconv.h"
58 #include "gui_id.h"
59 #include "gui_main.h"
60 #include "gui_tilespec.h"
61 #include "helpdlg.h"
62 #include "mapctrl.h"
63 #include "mapview.h"
64 #include "menu.h"
65 #include "messagewin.h"
66 #include "pages.h"
67 #include "themespec.h"
68 #include "widget.h"
69 #include "wldlg.h"
70 
71 #include "optiondlg.h"
72 
73 enum option_dialog_mode {
74   ODM_MAIN,
75   ODM_OPTSET,
76   ODM_WORKLIST
77 };
78 
79 struct option_dialog_optset {
80   const struct option_set *poptset;
81   struct widget *widget_list;
82   int category;
83 };
84 
85 struct option_dialog_worklist {
86   struct widget *edited_name;
87 };
88 
89 struct option_dialog {
90   struct widget *end_widget_list;
91   struct widget *core_widget_list;
92   struct widget *main_widget_list;
93   struct widget *begin_widget_list;
94   struct ADVANCED_DLG *advanced;
95   enum option_dialog_mode mode;
96   union {
97     struct option_dialog_optset optset;
98     struct option_dialog_worklist worklist;
99   };
100 };
101 
102 
103 static struct option_dialog *option_dialog = NULL;
104 struct widget *pOptions_Button = NULL;
105 static bool restore_meswin_dialog = FALSE;
106 
107 
108 static struct widget *option_widget_new(struct option *poption,
109                                         struct widget *window,
110                                         bool hide);
111 static void option_widget_update(struct option *poption);
112 static void option_widget_apply(struct option *poption);
113 
114 static struct option_dialog *option_dialog_new(void);
115 static void option_dialog_destroy(struct option_dialog *pdialog);
116 
117 static void option_dialog_optset(struct option_dialog *pdialog,
118                                  const struct option_set *poptset);
119 static void option_dialog_optset_category(struct option_dialog *pdialog,
120                                           int category);
121 
122 static void option_dialog_worklist(struct option_dialog *pdialog);
123 
124 /****************************************************************************
125   Arrange the widgets. NB: end argument is excluded. End the argument
126   list with the icons on the top, terminated by NULL.
127 ****************************************************************************/
arrange_widgets(struct widget * window,int widgets_per_row,int rows_shown,struct widget * begin,struct widget * end,...)128 static void arrange_widgets(struct widget *window, int widgets_per_row,
129                             int rows_shown, struct widget *begin,
130                             struct widget *end, ...)
131 {
132   struct widget *widget;
133   SDL_Surface *logo;
134   SDL_Rect area;
135   int longest[widgets_per_row], xpos[widgets_per_row];
136   int w, h, i, j;
137   va_list args;
138 
139   fc_assert_ret(NULL != window);
140   fc_assert_ret(NULL != begin);
141   fc_assert_ret(NULL != end);
142   fc_assert_ret(0 < widgets_per_row);
143 
144   /* Get window dimensions. */
145   memset(longest, 0, sizeof(longest));
146   for (widget = begin, i = 0; widget != end; widget = widget->next, i++) {
147     j = i % widgets_per_row;
148     longest[j] = MAX(longest[j], widget->size.w);
149   }
150 
151   fc_assert(0 == (i % widgets_per_row));
152 
153   if (-1 == rows_shown) {
154     h = 30 * (i / widgets_per_row);
155   } else {
156     h = 30 * MIN((i / widgets_per_row), rows_shown);
157   }
158 
159   w = (1 - widgets_per_row) * adj_size(20);
160   for (j = 0; j < widgets_per_row; j++) {
161     w += longest[j];
162   }
163   if (-1 != rows_shown) {
164     w += adj_size(20);
165   }
166 
167   /* Clear former area. */
168   area = window->area;
169   area.w += window->size.x;
170   area.h += window->size.y;
171   dirty_sdl_rect(&area);
172 
173   /* Resize window. */
174   logo = theme_get_background(theme, BACKGROUND_OPTIONDLG);
175   if (resize_window(window, logo, NULL,
176                     adj_size(w + 80), adj_size(h + 80))) {
177     FREESURFACE(logo);
178   }
179 
180   /* Set window position. */
181   widget_set_position(window, (main_window_width() - window->size.w) / 2,
182                       (main_window_height() - window->size.h) / 2);
183 
184   area = window->area;
185 
186   /* Set icons position. */
187   va_start(args, end);
188   w = 0;
189   while ((widget = va_arg(args, struct widget *))) {
190     w += widget->size.w;
191     widget_set_position(widget, area.x + area.w - w - 1,
192                         window->size.y + adj_size(2));
193   }
194   va_end(args);
195 
196   if (1 < widgets_per_row) {
197     xpos[widgets_per_row - 1] = area.x + adj_size(20);
198     for (j = widgets_per_row - 2; j >= 0; j--) {
199       xpos[j] = xpos[j + 1] + adj_size(20) + longest[j + 1];
200     }
201   }
202 
203   /* Set button position. */
204   h = 30 * (i / widgets_per_row + 1);
205   for (widget = begin, i = 0; widget != end; widget = widget->next, i++) {
206     j = i % widgets_per_row;
207     if (0 == j) {
208       h -= 30;
209     }
210     widget_resize(widget, longest[j], widget->size.h);
211     if (1 == widgets_per_row) {
212       widget_set_position(widget, area.x + (area.w - widget->size.w) / 2,
213                           area.y + adj_size(h));
214     } else {
215       widget_set_position(widget, xpos[j], area.y + adj_size(h));
216     }
217   }
218 
219   redraw_group(begin, window, 0);
220   widget_mark_dirty(window);
221   flush_all();
222 }
223 
224 /****************************************************************************
225   User interacted with the option dialog window.
226 ****************************************************************************/
main_optiondlg_callback(struct widget * pWindow)227 static int main_optiondlg_callback(struct widget *pWindow)
228 {
229   if (NULL != option_dialog && PRESSED_EVENT(Main.event)) {
230     move_window_group(option_dialog->begin_widget_list,
231                       option_dialog->end_widget_list);
232   }
233 
234   return -1;
235 }
236 
237 /****************************************************************************
238   Back requested.
239 ****************************************************************************/
back_callback(struct widget * pWidget)240 static int back_callback(struct widget *pWidget)
241 {
242   if (NULL == option_dialog || !PRESSED_EVENT(Main.event)) {
243     return -1;
244   }
245 
246   if (ODM_MAIN == option_dialog->mode) {
247     if (client.conn.established) {
248       /* Back to game. */
249       popdown_optiondlg(FALSE);
250       enable_options_button();
251       widget_redraw(pOptions_Button);
252       widget_mark_dirty(pOptions_Button);
253       flush_dirty();
254     } else {
255       /* Back to main page. */
256       popdown_optiondlg(TRUE);
257       set_client_page(PAGE_MAIN);
258     }
259     return -1;
260   }
261 
262   if (ODM_OPTSET == option_dialog->mode
263       && -1 != option_dialog->optset.category) {
264     /* Back to option set category menu. */
265     options_iterate(option_dialog->optset.poptset, poption) {
266       if (option_dialog->optset.category == option_category(poption)) {
267         option_set_gui_data(poption, NULL);
268       }
269     } options_iterate_end;
270     option_dialog->optset.category = -1;
271     FC_FREE(option_dialog->advanced->pScroll);
272     FC_FREE(option_dialog->advanced);
273 
274     del_group_of_widgets_from_gui_list(option_dialog->begin_widget_list,
275                                        option_dialog->optset.widget_list->prev);
276 
277     option_dialog->begin_widget_list = option_dialog->optset.widget_list;
278 
279     show_group(option_dialog->begin_widget_list,
280                option_dialog->main_widget_list->prev);
281 
282     arrange_widgets(option_dialog->end_widget_list, 1, -1,
283                     option_dialog->begin_widget_list,
284                     option_dialog->main_widget_list,
285                     option_dialog->core_widget_list, NULL);
286     return -1;
287   }
288 
289   if (ODM_WORKLIST == option_dialog->mode
290       && NULL != option_dialog->advanced) {
291     FC_FREE(option_dialog->advanced->pScroll);
292     FC_FREE(option_dialog->advanced);
293     option_dialog->worklist.edited_name = NULL;
294   }
295 
296   /* Back to main options menu. */
297   del_group_of_widgets_from_gui_list(option_dialog->begin_widget_list,
298                                      option_dialog->main_widget_list->prev);
299 
300   option_dialog->begin_widget_list = option_dialog->main_widget_list;
301 
302   show_group(option_dialog->begin_widget_list,
303              option_dialog->core_widget_list->prev);
304   option_dialog->mode = ODM_MAIN;
305   arrange_widgets(option_dialog->end_widget_list, 1, -1,
306                   option_dialog->begin_widget_list,
307                   option_dialog->core_widget_list,
308                   option_dialog->core_widget_list, NULL);
309 
310   return -1;
311 }
312 
313 /****************************************************************************
314   Create the client options dialog.
315 ****************************************************************************/
client_options_callback(struct widget * pWidget)316 static int client_options_callback(struct widget *pWidget)
317 {
318   if (PRESSED_EVENT(Main.event)) {
319     option_dialog_popup(_("Local Options"), client_optset);
320   }
321 
322   return -1;
323 }
324 
325 /****************************************************************************
326   Create the server options dialog.
327 ****************************************************************************/
server_options_callback(struct widget * pWidget)328 static int server_options_callback(struct widget *pWidget)
329 {
330   if (PRESSED_EVENT(Main.event)) {
331     option_dialog_popup(_("Server options"), server_optset);
332   }
333 
334   return -1;
335 }
336 
337 /****************************************************************************
338   Create the worklist editor.
339 ****************************************************************************/
work_lists_callback(struct widget * widget)340 static int work_lists_callback(struct widget *widget)
341 {
342   if (PRESSED_EVENT(Main.event)) {
343     option_dialog_worklist(option_dialog);
344   }
345 
346   return -1;
347 }
348 
349 /****************************************************************************
350   Option set category selected.
351 ****************************************************************************/
save_client_options_callback(struct widget * pWidget)352 static int save_client_options_callback(struct widget *pWidget)
353 {
354   if (PRESSED_EVENT(Main.event)) {
355     options_save(NULL);
356   }
357 
358   return -1;
359 }
360 
361 /****************************************************************************
362   Save game callback.
363 ****************************************************************************/
save_game_callback(struct widget * pWidget)364 static int save_game_callback(struct widget *pWidget)
365 {
366   if (PRESSED_EVENT(Main.event)) {
367     send_save_game(NULL);
368     back_callback(NULL);
369   }
370 
371   return -1;
372 }
373 
374 /****************************************************************************
375   Open Help Browser callback
376 ****************************************************************************/
help_browser_callback(struct widget * pwidget)377 static int help_browser_callback(struct widget *pwidget)
378 {
379   if (PRESSED_EVENT(Main.event)) {
380     popup_help_browser();
381   }
382 
383   return -1;
384 }
385 
386 /****************************************************************************
387   Client disconnect from server callback.
388 ****************************************************************************/
disconnect_callback(struct widget * pWidget)389 static int disconnect_callback(struct widget *pWidget)
390 {
391   if (PRESSED_EVENT(Main.event)) {
392     popdown_optiondlg(TRUE);
393     enable_options_button();
394     disconnect_from_server();
395   }
396 
397   return -1;
398 }
399 
400 /****************************************************************************
401   Exit callback.
402 ****************************************************************************/
exit_callback(struct widget * pWidget)403 static int exit_callback(struct widget *pWidget)
404 {
405   if (PRESSED_EVENT(Main.event)) {
406     popdown_optiondlg(TRUE);
407     force_exit_from_event_loop();
408   }
409 
410   return 0;
411 }
412 
413 /****************************************************************************
414   Option set category selected.
415 ****************************************************************************/
option_category_callback(struct widget * widget)416 static int option_category_callback(struct widget *widget)
417 {
418   if (PRESSED_EVENT(Main.event)) {
419     option_dialog_optset_category(option_dialog, MAX_ID - widget->ID);
420   }
421 
422   return -1;
423 }
424 
425 /****************************************************************************
426   Apply the changes for the option category.
427 ****************************************************************************/
apply_callback(struct widget * widget)428 static int apply_callback(struct widget *widget)
429 {
430   if (PRESSED_EVENT(Main.event)
431       && NULL != option_dialog
432       && ODM_OPTSET == option_dialog->mode
433       && -1 != option_dialog->optset.category) {
434     options_iterate(option_dialog->optset.poptset, poption) {
435       if (option_dialog->optset.category == option_category(poption)) {
436         option_widget_apply(poption);
437       }
438     } options_iterate_end;
439   }
440 
441   return back_callback(widget);
442 }
443 
444 /****************************************************************************
445   Dummy callback. Disable exit().
446 ****************************************************************************/
none_callback(struct widget * widget)447 static int none_callback(struct widget *widget)
448 {
449   return -1;
450 }
451 
452 /****************************************************************************
453   Return a string vector containing all video modes.
454 ****************************************************************************/
video_mode_list(void)455 static struct strvec *video_mode_list(void)
456 {
457   struct strvec *video_modes = strvec_new();
458   int active_display = 0; /* TODO: Support multiple displays */
459   int mode_count;
460   int i;
461 
462   mode_count = SDL_GetNumDisplayModes(active_display);
463   for (i = 0; i < mode_count; i++) {
464     SDL_DisplayMode mode;
465 
466     if (!SDL_GetDisplayMode(active_display, i, &mode)) {
467       char buf[64];
468       struct video_mode vmod = { .width = mode.w, .height = mode.h };
469 
470       if (video_mode_to_string(buf, sizeof(buf), &vmod)) {
471         strvec_append(video_modes, buf);
472       }
473     }
474   }
475 
476   return video_modes;
477 }
478 
479 /****************************************************************************
480   Free correctly the memory assigned to the enum_widget.
481 ****************************************************************************/
enum_widget_destroy(struct widget * widget)482 static void enum_widget_destroy(struct widget *widget)
483 {
484   strvec_destroy((struct strvec *) widget->data.vector);
485 }
486 
487 /****************************************************************************
488   Free correctly the memory assigned to the video_mode_widget.
489 ****************************************************************************/
video_mode_widget_destroy(struct widget * widget)490 static void video_mode_widget_destroy(struct widget *widget)
491 {
492   combo_popdown(widget);
493   strvec_destroy((struct strvec *) widget->data.vector);
494 }
495 
496 /****************************************************************************
497   Create a widget for the option.
498 ****************************************************************************/
option_widget_new(struct option * poption,struct widget * window,bool hide)499 static struct widget *option_widget_new(struct option *poption,
500                                         struct widget *window,
501                                         bool hide)
502 {
503   struct widget *widget;
504   char *help_text;
505   Uint32 flags = (hide ? WF_HIDDEN | WF_RESTORE_BACKGROUND
506                   : WF_RESTORE_BACKGROUND);
507 
508   fc_assert_ret_val(NULL != poption, NULL);
509   fc_assert_ret_val(NULL != window, NULL);
510 
511   help_text = fc_strdup(option_help_text(poption));
512   fc_break_lines(help_text, 50);
513 
514   widget = create_iconlabel_from_chars(NULL, window->dst,
515                                        option_description(poption),
516                                        adj_font(12),
517                                        flags | WF_WIDGET_HAS_INFO_LABEL);
518   widget->string_utf8->style |= TTF_STYLE_BOLD;
519   widget->info_label = create_utf8_from_char(help_text, adj_font(12));
520   widget->action = none_callback;
521   set_wstate(widget, FC_WS_NORMAL);
522   remake_label_size(widget);
523   add_to_gui_list(MAX_ID - option_number(poption), widget);
524 
525   widget = NULL;
526   switch (option_type(poption)) {
527   case OT_BOOLEAN:
528     widget = create_checkbox(window->dst, option_bool_get(poption),
529                              flags | WF_WIDGET_HAS_INFO_LABEL);
530     break;
531 
532   case OT_INTEGER:
533     {
534       char buf[64];
535 
536       fc_snprintf(buf, sizeof(buf), "%d", option_int_get(poption));
537       widget = create_edit_from_chars(NULL, window->dst, buf, adj_font(12),
538                                       adj_size(25),
539                                       flags | WF_WIDGET_HAS_INFO_LABEL);
540     }
541     break;
542 
543   case OT_STRING:
544     {
545       const struct strvec *values = option_str_values(poption);
546 
547       if (NULL != values) {
548         widget = combo_new_from_chars(NULL, window->dst, adj_font(12),
549                                       option_str_get(poption), values,
550                                       adj_size(25),
551                                       flags | WF_WIDGET_HAS_INFO_LABEL);
552       } else {
553         widget = create_edit_from_chars(NULL, window->dst,
554                                         option_str_get(poption),
555                                         adj_font(12), adj_size(25),
556                                         flags | WF_WIDGET_HAS_INFO_LABEL);
557       }
558     }
559     break;
560 
561   case OT_ENUM:
562     {
563       const struct strvec *values = option_enum_values(poption);
564       struct strvec *translated_values = strvec_new();
565       int i;
566 
567       strvec_reserve(translated_values, strvec_size(values));
568       for (i = 0; i < strvec_size(values); i++) {
569         strvec_set(translated_values, i, _(strvec_get(values, i)));
570       }
571 
572       widget = combo_new_from_chars(NULL, window->dst, adj_font(12),
573                                     _(option_enum_get_str(poption)),
574                                     translated_values, adj_size(25),
575                                     flags | WF_WIDGET_HAS_INFO_LABEL);
576       widget->destroy = enum_widget_destroy;
577     }
578     break;
579 
580   case OT_VIDEO_MODE:
581     {
582       char buf[64];
583       struct video_mode vmod;
584 
585       vmod = option_video_mode_get(poption);
586       if (!video_mode_to_string(buf, sizeof(buf), &vmod)) {
587         /* Always fails. */
588         fc_assert(video_mode_to_string(buf, sizeof(buf), &vmod));
589       }
590 
591       widget = combo_new_from_chars(NULL, window->dst, adj_font(12),
592                                     buf, video_mode_list(), adj_size(25),
593                                     flags | WF_WIDGET_HAS_INFO_LABEL);
594       widget->destroy = video_mode_widget_destroy;
595     }
596     break;
597 
598   case OT_BITWISE:
599   case OT_FONT:
600   case OT_COLOR:
601     log_error("Option type %s (%d) not supported yet.",
602               option_type_name(option_type(poption)),
603               option_type(poption));
604     break;
605   }
606 
607   if (NULL == widget) {
608     /* Not implemented. */
609     widget = create_iconlabel_from_chars(NULL, window->dst, "",
610                                          adj_font(12), flags);
611   } else {
612     widget->info_label = create_utf8_from_char(help_text, adj_font(12));
613     widget->action = none_callback;
614     if (option_is_changeable(poption)) {
615       set_wstate(widget, FC_WS_NORMAL);
616     }
617   }
618 
619   add_to_gui_list(MAX_ID - option_number(poption), widget);
620   option_set_gui_data(poption, widget);
621 
622   free(help_text);
623 
624   return widget;
625 }
626 
627 /****************************************************************************
628   Update the widget of the option.
629 ****************************************************************************/
option_widget_update(struct option * poption)630 static void option_widget_update(struct option *poption)
631 {
632   struct widget *widget;
633 
634   fc_assert_ret(NULL != poption);
635   widget = (struct widget *) option_get_gui_data(poption);
636   fc_assert_ret(NULL != widget);
637 
638   set_wstate(widget,
639              option_is_changeable(poption)
640              ? FC_WS_NORMAL : FC_WS_DISABLED);
641 
642   switch (option_type(poption)) {
643   case OT_BOOLEAN:
644     if (option_bool_get(poption) != get_checkbox_state(widget)) {
645       toggle_checkbox(widget);
646     }
647     break;
648 
649   case OT_INTEGER:
650     {
651       char buf[64];
652 
653       fc_snprintf(buf, sizeof(buf), "%d", option_int_get(poption));
654       copy_chars_to_utf8_str(widget->string_utf8, buf);
655     }
656     break;
657 
658   case OT_STRING:
659     copy_chars_to_utf8_str(widget->string_utf8, option_str_get(poption));
660     break;
661 
662   case OT_ENUM:
663     copy_chars_to_utf8_str(widget->string_utf8,
664                            _(option_enum_get_str(poption)));
665     break;
666 
667   case OT_VIDEO_MODE:
668     {
669       char buf[64];
670       struct video_mode vmod;
671 
672       vmod = option_video_mode_get(poption);
673       if (video_mode_to_string(buf, sizeof(buf), &vmod)) {
674         copy_chars_to_utf8_str(widget->string_utf8, buf);
675       } else {
676         /* Always fails. */
677         fc_assert(video_mode_to_string(buf, sizeof(buf), &vmod));
678       }
679     }
680     break;
681 
682   case OT_BITWISE:
683   case OT_FONT:
684   case OT_COLOR:
685     log_error("Option type %s (%d) not supported yet.",
686               option_type_name(option_type(poption)),
687               option_type(poption));
688     break;
689   }
690 
691   widget_redraw(widget);
692   widget_mark_dirty(widget);
693 }
694 
695 /****************************************************************************
696   Apply the changes for the option.
697 ****************************************************************************/
option_widget_apply(struct option * poption)698 static void option_widget_apply(struct option *poption)
699 {
700   struct widget *widget;
701 
702   fc_assert_ret(NULL != poption);
703   widget = (struct widget *) option_get_gui_data(poption);
704   fc_assert_ret(NULL != widget);
705 
706   switch (option_type(poption)) {
707   case OT_BOOLEAN:
708     (void) option_bool_set(poption, get_checkbox_state(widget));
709     break;
710 
711   case OT_INTEGER:
712     {
713       int value;
714 
715       if (str_to_int(widget->string_utf8->text, &value)) {
716         (void) option_int_set(poption, value);
717       }
718     }
719     break;
720 
721   case OT_STRING:
722     (void) option_str_set(poption, widget->string_utf8->text);
723     break;
724 
725   case OT_ENUM:
726     {
727       int i;
728 
729       /* 'str' is translated, so we cannot use directly
730        * option_enum_set_str(). */
731       for (i = 0; i < strvec_size(widget->data.vector); i++) {
732         if (!strcmp(strvec_get(widget->data.vector, i), widget->string_utf8->text)) {
733           (void) option_enum_set_int(poption, i);
734           break;
735         }
736       }
737     }
738     break;
739 
740   case OT_VIDEO_MODE:
741     {
742       struct video_mode mode;
743 
744       if (string_to_video_mode(widget->string_utf8->text, &mode)) {
745         option_video_mode_set(poption, mode);
746       } else {
747         /* Always fails. */
748         fc_assert(string_to_video_mode(widget->string_utf8->text, &mode));
749       }
750     }
751     break;
752 
753   case OT_BITWISE:
754   case OT_FONT:
755   case OT_COLOR:
756     log_error("Option type %s (%d) not supported yet.",
757               option_type_name(option_type(poption)),
758               option_type(poption));
759     break;
760   }
761 }
762 
763 /****************************************************************************
764   Return a new option dialog.
765 ****************************************************************************/
option_dialog_new(void)766 static struct option_dialog *option_dialog_new(void)
767 {
768   struct option_dialog *pdialog = fc_calloc(1, sizeof(*pdialog));
769   struct widget *window, *close_button, *widget;
770   utf8_str *str;
771 
772   pdialog->mode = ODM_MAIN;
773 
774   /* Create window widget. */
775   str = create_utf8_from_char(_("Options"), adj_font(12));
776   str->style |= TTF_STYLE_BOLD;
777 
778   window = create_window_skeleton(NULL, str, 0);
779   window->action = main_optiondlg_callback;
780 
781   set_wstate(window, FC_WS_NORMAL);
782   add_to_gui_list(ID_OPTIONS_WINDOW, window);
783   pdialog->end_widget_list = window;
784 
785   /* Create close button widget. */
786   close_button = create_themeicon(current_theme->Small_CANCEL_Icon, window->dst,
787                                   WF_WIDGET_HAS_INFO_LABEL
788                                   | WF_RESTORE_BACKGROUND);
789   close_button->info_label = create_utf8_from_char(_("Close Dialog (Esc)"),
790                                                    adj_font(12));
791   close_button->action = back_callback;
792   set_wstate(close_button, FC_WS_NORMAL);
793   close_button->key = SDLK_ESCAPE;
794   add_to_gui_list(ID_OPTIONS_BACK_BUTTON, close_button);
795   pdialog->core_widget_list = close_button;
796 
797   /* Create client options button widget. */
798   widget = create_icon_button_from_chars(NULL, window->dst,
799                                          _("Local options"),
800                                          adj_font(12), 0);
801   widget->action = client_options_callback;
802   set_wstate(widget, FC_WS_NORMAL);
803   widget_resize(widget, widget->size.w, widget->size.h + adj_size(4));
804   add_to_gui_list(ID_OPTIONS_CLIENT_BUTTON, widget);
805 
806   /* Create server options button widget. */
807   widget = create_icon_button_from_chars(NULL, window->dst,
808                                          _("Server options"),
809                                          adj_font(12), 0);
810   widget->action = server_options_callback;
811   if (client.conn.established) {
812     set_wstate(widget, FC_WS_NORMAL);
813   }
814   widget_resize(widget, widget->size.w, widget->size.h + adj_size(4));
815   add_to_gui_list(ID_OPTIONS_SERVER_BUTTON, widget);
816 
817   /* Create global worklists button widget. */
818   widget = create_icon_button_from_chars(NULL, window->dst,
819                                          _("Worklists"), adj_font(12), 0);
820   widget->action = work_lists_callback;
821   if (C_S_RUNNING == client_state()) {
822     set_wstate(widget, FC_WS_NORMAL);
823   }
824   widget_resize(widget, widget->size.w, widget->size.h + adj_size(4));
825   add_to_gui_list(ID_OPTIONS_WORKLIST_BUTTON, widget);
826 
827   /* Create save game button widget. */
828   widget = create_icon_button_from_chars(NULL, window->dst,
829                                          _("Save Local Options"),
830                                          adj_font(12), 0);
831   widget->action = save_client_options_callback;
832   set_wstate(widget, FC_WS_NORMAL);
833   widget_resize(widget, widget->size.w, widget->size.h + adj_size(4));
834   add_to_gui_list(ID_OPTIONS_SAVE_BUTTON, widget);
835 
836   /* Create save game button widget. */
837   widget = create_icon_button_from_chars(NULL, window->dst,
838                                          _("Save Game"), adj_font(12), 0);
839   widget->action = save_game_callback;
840   if (C_S_RUNNING == client_state()) {
841     set_wstate(widget, FC_WS_NORMAL);
842   }
843   widget_resize(widget, widget->size.w, widget->size.h + adj_size(4));
844   add_to_gui_list(ID_OPTIONS_SAVE_GAME_BUTTON, widget);
845 
846   /* Create help browser button widget. */
847   widget = create_icon_button_from_chars(NULL, window->dst,
848                                          _("Help Browser"), adj_font(12), 0);
849   widget->action = help_browser_callback;
850   widget->key = SDLK_h;
851   if (client.conn.established) {
852     set_wstate(widget, FC_WS_NORMAL);
853   }
854   widget_resize(widget, widget->size.w, widget->size.h + adj_size(4));
855   add_to_gui_list(ID_OPTIONS_HELP_BROWSER_BUTTON, widget);
856 
857   /* Create leave game button widget. */
858   widget = create_icon_button_from_chars(NULL, window->dst,
859                                          _("Leave Game"), adj_font(12), 0);
860   widget->action = disconnect_callback;
861   widget->key = SDLK_q;
862   if (client.conn.established) {
863     set_wstate(widget, FC_WS_NORMAL);
864   }
865   widget_resize(widget, widget->size.w, widget->size.h + adj_size(4));
866   add_to_gui_list(ID_OPTIONS_DISC_BUTTON, widget);
867 
868   /* Create quit widget button. */
869   widget = create_icon_button_from_chars(NULL, window->dst,
870                                          _("Quit"), adj_font(12), 0);
871   widget->action = exit_callback;
872   widget->key = SDLK_q;
873   set_wstate(widget, FC_WS_NORMAL);
874   widget_resize(widget, widget->size.w, widget->size.h + adj_size(4));
875   add_to_gui_list(ID_OPTIONS_EXIT_BUTTON, widget);
876 
877   pdialog->begin_widget_list = widget;
878   pdialog->main_widget_list = widget;
879 
880   arrange_widgets(window, 1, -1, widget, pdialog->core_widget_list,
881                   pdialog->core_widget_list, NULL);
882 
883   return pdialog;
884 }
885 
886 /****************************************************************************
887   Destroys an option dialog.
888 ****************************************************************************/
option_dialog_destroy(struct option_dialog * pdialog)889 static void option_dialog_destroy(struct option_dialog *pdialog)
890 {
891   fc_assert_ret(NULL != pdialog);
892 
893   if (ODM_OPTSET == pdialog->mode && -1 != pdialog->optset.category) {
894     options_iterate(pdialog->optset.poptset, poption) {
895       if (pdialog->optset.category == option_category(poption)) {
896         option_set_gui_data(poption, NULL);
897       }
898     } options_iterate_end;
899   }
900 
901   if (NULL != pdialog->advanced) {
902     free(pdialog->advanced->pScroll);
903     free(pdialog->advanced);
904   }
905 
906   popdown_window_group_dialog(pdialog->begin_widget_list,
907                               pdialog->end_widget_list);
908 
909   free(pdialog);
910 }
911 
912 /****************************************************************************
913   Return the number of options of the category.
914 ****************************************************************************/
optset_category_option_count(const struct option_set * poptset,int category)915 static int optset_category_option_count(const struct option_set *poptset,
916                                         int category)
917 {
918   int count = 0;
919 
920   options_iterate(poptset, poption) {
921     if (category == option_category(poption)) {
922       count++;
923     }
924   } options_iterate_end;
925 
926   return count;
927 }
928 
929 /****************************************************************************
930   Initialize a option set page.
931 ****************************************************************************/
option_dialog_optset(struct option_dialog * pdialog,const struct option_set * poptset)932 static void option_dialog_optset(struct option_dialog *pdialog,
933                                  const struct option_set *poptset)
934 {
935   struct option_dialog_optset *poptset_dialog;
936   struct widget *window;
937   struct widget *widget = NULL;
938   int i,  category_num;
939 
940   fc_assert_ret(NULL != pdialog);
941   fc_assert_ret(NULL != poptset);
942   category_num = optset_category_number(poptset);
943   fc_assert_ret(0 < category_num);
944 
945   poptset_dialog = &pdialog->optset;
946   pdialog->mode = ODM_OPTSET;
947   poptset_dialog->poptset = poptset;
948   poptset_dialog->category = -1;
949 
950   window = pdialog->end_widget_list;
951 
952   /* Hide ODM_MAIN widget group. */
953   hide_group(pdialog->main_widget_list, pdialog->core_widget_list->prev);
954 
955   /* Otherwise we don't enter next loop at all, and widget will remain NULL */
956   fc_assert(category_num > 0);
957 
958   /* Make the category buttons. */
959   for (i = 0; i < category_num; i++) {
960     if (0 == optset_category_option_count(poptset, i)) {
961       continue;
962     }
963 
964     widget = create_icon_button_from_chars(NULL, window->dst,
965                                            optset_category_name(poptset, i),
966                                            adj_font(12), 0);
967     widget->action = option_category_callback;
968     set_wstate(widget, FC_WS_NORMAL);
969     widget_resize(widget, widget->size.w, widget->size.h + adj_size(4));
970     add_to_gui_list(MAX_ID - i, widget);
971   }
972 
973   poptset_dialog->widget_list = widget;
974   pdialog->begin_widget_list = widget;
975 
976   arrange_widgets(window, 1, -1, widget, pdialog->main_widget_list,
977                   pdialog->core_widget_list, NULL);
978 }
979 
980 /****************************************************************************
981   Initialize a option set category page.
982 ****************************************************************************/
option_dialog_optset_category(struct option_dialog * pdialog,int category)983 static void option_dialog_optset_category(struct option_dialog *pdialog,
984                                           int category)
985 {
986   struct option_dialog_optset *poptset_dialog;
987   const struct option_set *poptset;
988   struct widget *window, *widget = NULL, *apply_button;
989   const int MAX_SHOWN = 10;
990   SDL_Rect area;
991   int i;
992 
993   fc_assert_ret(NULL != pdialog);
994   fc_assert_ret(ODM_OPTSET == pdialog->mode);
995   fc_assert_ret(NULL == pdialog->advanced);
996   poptset_dialog = &pdialog->optset;
997   poptset = poptset_dialog->poptset;
998   fc_assert_ret(0 < optset_category_option_count(poptset, category));
999 
1000   /* Hide ODM_OPTSET widget group. */
1001   hide_group(poptset_dialog->widget_list, pdialog->main_widget_list->prev);
1002 
1003   poptset_dialog->category = category;
1004   window = pdialog->end_widget_list;
1005 
1006   /* Create the apply button. */
1007   apply_button = create_themeicon(current_theme->Small_OK_Icon, window->dst,
1008                                   WF_WIDGET_HAS_INFO_LABEL
1009                                   | WF_RESTORE_BACKGROUND);
1010   apply_button->info_label = create_utf8_from_char(_("Apply changes"),
1011                                                    adj_font(12));
1012   apply_button->action = apply_callback;
1013   set_wstate(apply_button, FC_WS_NORMAL);
1014   add_to_gui_list(ID_OPTIONS_APPLY_BUTTON, apply_button);
1015 
1016   /* Create the option widgets. */
1017   i = 0;
1018   options_iterate(poptset, poption) {
1019     if (category != option_category(poption)) {
1020       continue;
1021     }
1022 
1023     widget = option_widget_new(poption, window, i >= MAX_SHOWN);
1024     i++;
1025   } options_iterate_end;
1026 
1027   /* Scrollbar. */
1028   pdialog->advanced = fc_calloc(1, sizeof(*pdialog->advanced));
1029   pdialog->advanced->pEndWidgetList = pdialog->end_widget_list;
1030   pdialog->advanced->pEndActiveWidgetList = apply_button->prev;
1031   pdialog->advanced->pBeginWidgetList = widget;
1032   pdialog->advanced->pBeginActiveWidgetList = widget;
1033 
1034   create_vertical_scrollbar(pdialog->advanced, 2, MAX_SHOWN, TRUE, TRUE);
1035 
1036   if (i >= MAX_SHOWN) {
1037     pdialog->advanced->pActiveWidgetList =
1038         pdialog->advanced->pEndActiveWidgetList;
1039   } else {
1040     hide_scrollbar(pdialog->advanced->pScroll);
1041   }
1042 
1043   pdialog->begin_widget_list = pdialog->advanced->pBeginWidgetList;
1044 
1045   arrange_widgets(window, 2, MAX_SHOWN,
1046                   pdialog->advanced->pBeginActiveWidgetList,
1047                   apply_button, pdialog->core_widget_list,
1048                   apply_button, NULL);
1049 
1050   area = window->area;
1051   setup_vertical_scrollbar_area(pdialog->advanced->pScroll,
1052                                 area.x + area.w - 1, area.y + 1,
1053                                 area.h - adj_size(32), TRUE);
1054 
1055   redraw_group(pdialog->begin_widget_list,
1056                pdialog->advanced->pActiveWidgetList, 0);
1057   widget_flush(window);
1058 }
1059 
1060 
1061 /****************************************************************************
1062   Clicked on a global worklist name.
1063 ****************************************************************************/
edit_worklist_callback(struct widget * widget)1064 static int edit_worklist_callback(struct widget *widget)
1065 {
1066   struct global_worklist *pgwl = global_worklist_by_id(MAX_ID - widget->ID);
1067 
1068   if (NULL == option_dialog
1069       || ODM_WORKLIST != option_dialog->mode
1070       || NULL == pgwl) {
1071     return -1;
1072   }
1073 
1074   if (Main.event.type == SDL_MOUSEBUTTONDOWN) {
1075     switch (Main.event.button.button) {
1076     case SDL_BUTTON_LEFT:
1077       /* Edit. */
1078       option_dialog->worklist.edited_name = widget;
1079       popup_worklist_editor(NULL, pgwl);
1080       break;
1081 
1082     case SDL_BUTTON_RIGHT:
1083       {
1084         /* Delete. */
1085         struct ADVANCED_DLG *advanced = option_dialog->advanced;
1086         bool scroll = (NULL != advanced->pActiveWidgetList);
1087 
1088         global_worklist_destroy(pgwl);
1089         del_widget_from_vertical_scroll_widget_list(advanced, widget);
1090 
1091         /* Find if there was scrollbar hide. */
1092         if (scroll && advanced->pActiveWidgetList == NULL) {
1093           int len = advanced->pScroll->pUp_Left_Button->size.w;
1094 
1095           widget = advanced->pEndActiveWidgetList->next;
1096           do {
1097             widget = widget->prev;
1098             widget->size.w += len;
1099             FREESURFACE(widget->gfx);
1100           } while (widget != advanced->pBeginActiveWidgetList);
1101         }
1102 
1103         redraw_group(option_dialog->begin_widget_list,
1104                      option_dialog->end_widget_list, 0);
1105         widget_mark_dirty(option_dialog->end_widget_list);
1106         flush_dirty();
1107       }
1108       break;
1109     }
1110   } else if (PRESSED_EVENT(Main.event)) {
1111     /* Edit. */
1112     option_dialog->worklist.edited_name = widget;
1113     popup_worklist_editor(NULL, pgwl);
1114   }
1115 
1116   return -1;
1117 }
1118 
1119 
1120 /****************************************************************************
1121   Callback to append a global worklist.
1122 ****************************************************************************/
add_new_worklist_callback(struct widget * widget)1123 static int add_new_worklist_callback(struct widget *widget)
1124 {
1125   if (PRESSED_EVENT(Main.event)) {
1126     struct widget *new_worklist_widget = NULL;
1127     struct widget *window = option_dialog->end_widget_list;
1128     struct global_worklist *pgwl = global_worklist_new(_("empty worklist"));
1129     struct ADVANCED_DLG *advanced = option_dialog->advanced;
1130     bool scroll = advanced->pActiveWidgetList == NULL;
1131     bool redraw_all = FALSE;
1132 
1133     set_wstate(widget, FC_WS_NORMAL);
1134     selected_widget = NULL;
1135 
1136     /* Create list element. */
1137     new_worklist_widget =
1138       create_iconlabel_from_chars(NULL, widget->dst,
1139                                   global_worklist_name(pgwl),
1140                                   adj_font(12), WF_RESTORE_BACKGROUND);
1141     new_worklist_widget->ID = MAX_ID - global_worklist_id(pgwl);
1142     new_worklist_widget->string_utf8->style |= SF_CENTER;
1143     set_wstate(new_worklist_widget, FC_WS_NORMAL);
1144     new_worklist_widget->size.w = widget->size.w;
1145     new_worklist_widget->action = edit_worklist_callback;
1146 
1147     /* Add to widget list. */
1148     redraw_all = add_widget_to_vertical_scroll_widget_list(advanced,
1149                      new_worklist_widget, widget, TRUE,
1150                      window->area.x + adj_size(17),
1151                      window->area.y + adj_size(17));
1152 
1153     /* Find if there was scrollbar shown. */
1154     if (scroll && advanced->pActiveWidgetList != NULL) {
1155       int len = advanced->pScroll->pUp_Left_Button->size.w;
1156 
1157       window = advanced->pEndActiveWidgetList->next;
1158       do {
1159         window = window->prev;
1160         window->size.w -= len;
1161         window->area.w -= len;
1162         FREESURFACE(window->gfx);
1163       } while (window != advanced->pBeginActiveWidgetList);
1164     }
1165 
1166     if (redraw_all) {
1167       redraw_group(option_dialog->begin_widget_list,
1168                    option_dialog->end_widget_list, 0);
1169       widget_mark_dirty(option_dialog->end_widget_list);
1170     } else {
1171       /* Redraw only new widget and dock widget. */
1172       if (!widget->gfx && (get_wflags(widget) & WF_RESTORE_BACKGROUND)) {
1173         refresh_widget_background(widget);
1174       }
1175       widget_redraw(widget);
1176       widget_mark_dirty(widget);
1177 
1178       if (!new_worklist_widget->gfx &&
1179           (get_wflags(new_worklist_widget) & WF_RESTORE_BACKGROUND)) {
1180         refresh_widget_background(new_worklist_widget);
1181       }
1182       widget_redraw(new_worklist_widget);
1183       widget_mark_dirty(new_worklist_widget);
1184     }
1185     flush_dirty();
1186   }
1187 
1188   return -1;
1189 }
1190 
1191 /****************************************************************************
1192   The Worklist Report part of Options dialog shows all the global worklists
1193   that the player has defined.
1194 ****************************************************************************/
option_dialog_worklist(struct option_dialog * pdialog)1195 static void option_dialog_worklist(struct option_dialog *pdialog)
1196 {
1197   SDL_Color bg_color = {255, 255, 255, 128};
1198   struct widget *widget, *window, *background;
1199   int count = 0, scrollbar_width = 0, longest = 0;
1200   SDL_Rect area;
1201 
1202   pdialog->mode = ODM_WORKLIST;
1203   pdialog->worklist.edited_name = NULL;
1204   window = pdialog->end_widget_list;
1205 
1206   /* Hide main widget group. */
1207   hide_group(pdialog->main_widget_list, pdialog->core_widget_list->prev);
1208 
1209   /* Create white background. */
1210   background = create_iconlabel(NULL, window->dst, NULL, WF_FREE_THEME);
1211   add_to_gui_list(ID_LABEL, background);
1212 
1213   /* Build the global worklists list. */
1214   global_worklists_iterate(pgwl) {
1215     widget = create_iconlabel_from_chars(NULL, window->dst,
1216                                          global_worklist_name(pgwl),
1217                                          adj_font(12),
1218                                          WF_RESTORE_BACKGROUND);
1219     set_wstate(widget, FC_WS_NORMAL);
1220     add_to_gui_list(MAX_ID - global_worklist_id(pgwl), widget);
1221     widget->action = edit_worklist_callback;
1222     widget->string_utf8->style |= SF_CENTER;
1223     longest = MAX(longest, widget->size.w);
1224     count++;
1225 
1226     if (count > 13) {
1227       set_wflag(widget, WF_HIDDEN);
1228     }
1229   } global_worklists_iterate_end;
1230 
1231   /* Create the adding item. */
1232   widget = create_iconlabel_from_chars(NULL, window->dst,
1233                                        _("Add new worklist"), adj_font(12),
1234                                        WF_RESTORE_BACKGROUND);
1235   set_wstate(widget, FC_WS_NORMAL);
1236   add_to_gui_list(ID_ADD_NEW_WORKLIST, widget);
1237   widget->action = add_new_worklist_callback;
1238   widget->string_utf8->style |= SF_CENTER;
1239   longest = MAX(longest, widget->size.w);
1240   count++;
1241 
1242   if (count > 13) {
1243     set_wflag(widget, WF_HIDDEN);
1244   }
1245 
1246   /* Advanced dialog. */
1247   pdialog->advanced = fc_calloc(1, sizeof(*pdialog->advanced));
1248   pdialog->advanced->pEndWidgetList = pdialog->end_widget_list;
1249   pdialog->advanced->pEndActiveWidgetList =
1250       pdialog->main_widget_list->prev->prev;
1251   pdialog->advanced->pBeginWidgetList = widget;
1252   pdialog->advanced->pBeginActiveWidgetList = widget;
1253 
1254   /* Clear former area. */
1255   area = window->area;
1256   area.w += window->size.x;
1257   area.h += window->size.y;
1258   dirty_sdl_rect(&area);
1259 
1260   /* Resize window. */
1261   resize_window(window, NULL, NULL,
1262                 adj_size(longest + 40), window->size.h);
1263   area = window->area;
1264 
1265   /* Move close button. */
1266   widget = pdialog->core_widget_list;
1267   widget_set_position(widget, area.x + area.w - widget->size.w - 1,
1268                       window->size.y + adj_size(2));
1269 
1270   /* Resize white background. */
1271   area.x += adj_size(12);
1272   area.y += adj_size(12);
1273   area.w -= adj_size(12) + adj_size(12);
1274   area.h -= adj_size(12) + adj_size(12);
1275   background->theme = create_surf(area.w, area.h, SDL_SWSURFACE);
1276   widget_set_area(background, area);
1277   widget_set_position(background, area.x, area.y);
1278   SDL_FillRect(background->theme, NULL,
1279                map_rgba(background->theme->format, bg_color));
1280 
1281   create_frame(background->theme,
1282                0, 0, background->theme->w - 1, background->theme->h - 1,
1283                get_theme_color(COLOR_THEME_OPTIONDLG_WORKLISTLIST_FRAME));
1284 
1285   /* Create the Scrollbar. */
1286   scrollbar_width = create_vertical_scrollbar(pdialog->advanced,
1287                                               1, 13, TRUE, TRUE);
1288   setup_vertical_scrollbar_area(pdialog->advanced->pScroll,
1289                                 area.x + area.w - 1, area.y + 1,
1290                                 area.h - adj_size(32), TRUE);
1291 
1292   if (count > 13) {
1293     pdialog->advanced->pActiveWidgetList =
1294         pdialog->advanced->pEndActiveWidgetList;
1295   } else {
1296     hide_scrollbar(pdialog->advanced->pScroll);
1297     scrollbar_width = 0;
1298   }
1299 
1300   /* Draw! */
1301   setup_vertical_widgets_position(1, area.x + adj_size(5),
1302                                   area.y + adj_size(5),
1303                                   area.w - adj_size(10) - scrollbar_width, 0,
1304                                   pdialog->advanced->pBeginActiveWidgetList,
1305                                   pdialog->advanced->pEndActiveWidgetList);
1306 
1307   pdialog->begin_widget_list = pdialog->advanced->pBeginWidgetList;
1308 
1309   redraw_group(pdialog->begin_widget_list, pdialog->end_widget_list, 0);
1310   widget_flush(window);
1311 }
1312 
1313 /**************************************************************************
1314   User interacted with the option dialog button.
1315 **************************************************************************/
optiondlg_callback(struct widget * pbutton)1316 int optiondlg_callback(struct widget *pbutton)
1317 {
1318   if (PRESSED_EVENT(Main.event)) {
1319     set_wstate(pbutton, FC_WS_DISABLED);
1320     clear_surface(pbutton->dst->surface, &pbutton->size);
1321     widget_redraw(pbutton);
1322     widget_flush(pbutton);
1323 
1324     popup_optiondlg();
1325   }
1326 
1327   return -1;
1328 }
1329 
1330 /* ===================================================================== */
1331 /* =================================== Public ========================== */
1332 /* ===================================================================== */
1333 
1334 /**************************************************************************
1335   Enable button to open option dialog.
1336 **************************************************************************/
enable_options_button(void)1337 void enable_options_button(void)
1338 {
1339   set_wstate(pOptions_Button, FC_WS_NORMAL);
1340 }
1341 
1342 /**************************************************************************
1343   Disable button to open option dialog.
1344 **************************************************************************/
disable_options_button(void)1345 void disable_options_button(void)
1346 {
1347   set_wstate(pOptions_Button, FC_WS_DISABLED);
1348 }
1349 
1350 /**************************************************************************
1351   Create button to open option dialog.
1352 **************************************************************************/
init_options_button(void)1353 void init_options_button(void)
1354 {
1355   char buf[256];
1356 
1357   pOptions_Button = create_themeicon(current_theme->Options_Icon, Main.gui,
1358                                      WF_WIDGET_HAS_INFO_LABEL
1359                                      | WF_RESTORE_BACKGROUND);
1360   pOptions_Button->action = optiondlg_callback;
1361   fc_snprintf(buf, sizeof(buf), "%s (%s)", _("Options"), "Esc");
1362   pOptions_Button->info_label = create_utf8_from_char(buf, adj_font(12));
1363   pOptions_Button->key = SDLK_ESCAPE;
1364   set_wflag(pOptions_Button, WF_HIDDEN);
1365   widget_set_position(pOptions_Button, adj_size(5), adj_size(5));
1366 
1367 #ifndef SMALL_SCREEN
1368   add_to_gui_list(ID_CLIENT_OPTIONS, pOptions_Button);
1369 #endif
1370 
1371   enable_options_button();
1372 }
1373 
1374 /**************************************************************************
1375   If the Options Dlg is open, force Worklist List contents to be updated.
1376   This function is call by exiting worklist editor to update changed
1377   worklist name in global worklist report ( Options Dlg )
1378 **************************************************************************/
update_worklist_report_dialog(void)1379 void update_worklist_report_dialog(void)
1380 {
1381   struct global_worklist *pgwl;
1382 
1383   if (NULL != option_dialog && ODM_WORKLIST == option_dialog->mode) {
1384     pgwl = global_worklist_by_id(MAX_ID
1385                                  - option_dialog->worklist.edited_name->ID);
1386 
1387     if (NULL != pgwl) {
1388       copy_chars_to_utf8_str(option_dialog->worklist.edited_name->string_utf8,
1389                              global_worklist_name(pgwl));
1390       option_dialog->worklist.edited_name = NULL;
1391     }
1392 
1393     redraw_group(option_dialog->begin_widget_list,
1394                  option_dialog->end_widget_list, 0);
1395     widget_mark_dirty(option_dialog->end_widget_list);
1396   }
1397 }
1398 
1399 /****************************************************************************
1400   Popup the main option menu dialog.
1401 ****************************************************************************/
popup_optiondlg(void)1402 void popup_optiondlg(void)
1403 {
1404   if (NULL != option_dialog) {
1405     return;
1406   }
1407 
1408   restore_meswin_dialog = meswin_dialog_is_open();
1409   popdown_all_game_dialogs();
1410   flush_dirty();
1411 
1412   option_dialog = option_dialog_new();
1413 
1414   disable_main_widgets();
1415   flush_dirty();
1416 }
1417 
1418 /**************************************************************************
1419   Close option dialog.
1420 **************************************************************************/
popdown_optiondlg(bool leave_game)1421 void popdown_optiondlg(bool leave_game)
1422 {
1423   if (NULL == option_dialog) {
1424     return;
1425   }
1426 
1427   option_dialog_destroy(option_dialog);
1428   option_dialog = NULL;
1429 
1430   if (!leave_game) {
1431     enable_main_widgets();
1432   }
1433 
1434   if (restore_meswin_dialog) {
1435     meswin_dialog_popup(TRUE);
1436   }
1437 }
1438 
1439 /****************************************************************************
1440   Popup the option dialog for the option set.
1441 ****************************************************************************/
option_dialog_popup(const char * name,const struct option_set * poptset)1442 void option_dialog_popup(const char *name, const struct option_set *poptset)
1443 {
1444   if (NULL == option_dialog) {
1445     popup_optiondlg();
1446   } else if (ODM_OPTSET == option_dialog->mode
1447              && poptset == option_dialog->optset.poptset) {
1448     /* Already in use. */
1449     return;
1450   } else {
1451     while (ODM_MAIN != option_dialog->mode) {
1452       back_callback(NULL);
1453     }
1454   }
1455 
1456   option_dialog_optset(option_dialog, poptset);
1457 }
1458 
1459 /****************************************************************************
1460   Popdown the option dialog for the option set.
1461 ****************************************************************************/
option_dialog_popdown(const struct option_set * poptset)1462 void option_dialog_popdown(const struct option_set *poptset)
1463 {
1464   while (NULL != option_dialog
1465          && ODM_OPTSET == option_dialog->mode
1466          && poptset == option_dialog->optset.poptset) {
1467     back_callback(NULL);
1468   }
1469 }
1470 
1471 /****************************************************************************
1472   Update the GUI for the option.
1473 ****************************************************************************/
option_gui_update(struct option * poption)1474 void option_gui_update(struct option *poption)
1475 {
1476   if (NULL != option_dialog
1477       && ODM_OPTSET == option_dialog->mode
1478       && option_optset(poption) == option_dialog->optset.poptset
1479       && option_category(poption) == option_dialog->optset.category) {
1480     option_widget_update(poption);
1481   }
1482 
1483   if (!strcmp(option_name(poption), "nationset")) {
1484     nationset_changed();
1485   }
1486 }
1487 
1488 /****************************************************************************
1489   Add the GUI for the option.
1490 ****************************************************************************/
option_gui_add(struct option * poption)1491 void option_gui_add(struct option *poption)
1492 {
1493   if (NULL != option_dialog
1494       && ODM_OPTSET == option_dialog->mode
1495       && option_optset(poption) == option_dialog->optset.poptset
1496       && option_category(poption) == option_dialog->optset.category) {
1497     back_callback(NULL);
1498     option_dialog_optset_category(option_dialog, option_category(poption));
1499   }
1500 }
1501 
1502 /****************************************************************************
1503   Remove the GUI for the option.
1504 ****************************************************************************/
option_gui_remove(struct option * poption)1505 void option_gui_remove(struct option *poption)
1506 {
1507   if (NULL != option_dialog
1508       && ODM_OPTSET == option_dialog->mode
1509       && option_optset(poption) == option_dialog->optset.poptset
1510       && option_category(poption) == option_dialog->optset.category) {
1511     back_callback(NULL);
1512     option_dialog_optset_category(option_dialog, option_category(poption));
1513   }
1514 }
1515