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