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