webperimental: Mountain vision bonus.
[freeciv.git] / client / gui-sdl2 / dialogs.c
blob8dae75802d748ec4f767311a35b19d8e004b3e4d
1 /***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12 ***********************************************************************/
14 /***********************************************************************
15 dialogs.c - description
16 -------------------
17 begin : Wed Jul 24 2002
18 copyright : (C) 2002 by Rafał Bursig
19 email : Rafał Bursig <bursig@poczta.fm>
20 ***********************************************************************/
22 #ifdef HAVE_CONFIG_H
23 #include <fc_config.h>
24 #endif
26 /* SDL2 */
27 #ifdef SDL2_PLAIN_INCLUDE
28 #include <SDL.h>
29 #else /* SDL2_PLAIN_INCLUDE */
30 #include <SDL2/SDL.h>
31 #endif /* SDL2_PLAIN_INCLUDE */
33 /* utility */
34 #include "bitvector.h"
35 #include "fcintl.h"
36 #include "log.h"
37 #include "rand.h"
39 /* common */
40 #include "combat.h"
41 #include "game.h"
42 #include "government.h"
43 #include "movement.h"
44 #include "unitlist.h"
46 /* client */
47 #include "client_main.h"
48 #include "climap.h" /* for client_tile_get_known() */
49 #include "goto.h"
50 #include "helpdata.h" /* for helptext_nation() */
51 #include "packhand.h"
52 #include "text.h"
54 /* gui-sdl2 */
55 #include "chatline.h"
56 #include "citydlg.h"
57 #include "cityrep.h"
58 #include "cma_fe.h"
59 #include "colors.h"
60 #include "finddlg.h"
61 #include "gotodlg.h"
62 #include "graphics.h"
63 #include "gui_iconv.h"
64 #include "gui_id.h"
65 #include "gui_main.h"
66 #include "gui_tilespec.h"
67 #include "helpdlg.h"
68 #include "inteldlg.h"
69 #include "mapctrl.h"
70 #include "mapview.h"
71 #include "menu.h"
72 #include "messagewin.h"
73 #include "optiondlg.h"
74 #include "plrdlg.h"
75 #include "ratesdlg.h"
76 #include "repodlgs.h"
77 #include "sprite.h"
78 #include "themespec.h"
79 #include "widget.h"
80 #include "wldlg.h"
82 #include "dialogs.h"
84 struct player *races_player;
86 extern bool is_unit_move_blocked;
87 extern void popdown_diplomat_dialog(void);
88 extern void popdown_incite_dialog(void);
89 extern void popdown_bribe_dialog(void);
91 void popdown_advanced_terrain_dialog(void);
92 int advanced_terrain_window_dlg_callback(struct widget *pWindow);
93 int exit_advanced_terrain_dlg_callback(struct widget *pWidget);
95 static char *pLeaderName = NULL;
97 static void unit_select_dialog_popdown(void);
98 static void popdown_terrain_info_dialog(void);
99 static void popdown_pillage_dialog(void);
100 static void popdown_connect_dialog(void);
101 static void popdown_revolution_dialog(void);
102 static void popdown_unit_upgrade_dlg(void);
103 static void popdown_unit_disband_dlg(void);
105 /**********************************************************************
106 Place window near given tile on screen.
107 ***********************************************************************/
108 void put_window_near_map_tile(struct widget *pWindow,
109 int window_width, int window_height,
110 struct tile *ptile)
112 float canvas_x, canvas_y;
113 int window_x = 0, window_y = 0;
115 if (tile_to_canvas_pos(&canvas_x, &canvas_y, ptile)) {
116 if (canvas_x + tileset_tile_width(tileset) + window_width >= main_window_width()) {
117 if (canvas_x - window_width < 0) {
118 window_x = (main_window_width() - window_width) / 2;
119 } else {
120 window_x = canvas_x - window_width;
122 } else {
123 window_x = canvas_x + tileset_tile_width(tileset);
126 canvas_y += (tileset_tile_height(tileset) - window_height) / 2;
127 if (canvas_y + window_height >= main_window_height()) {
128 window_y = main_window_height() - window_height - 1;
129 } else {
130 if (canvas_y < 0) {
131 window_y = 0;
132 } else {
133 window_y = canvas_y;
136 } else {
137 window_x = (main_window_width() - window_width) / 2;
138 window_y = (main_window_height() - window_height) / 2;
141 widget_set_position(pWindow, window_x, window_y);
144 /**********************************************************************
145 This function is called when the client disconnects or the game is
146 over. It should close all dialog windows for that game.
147 ***********************************************************************/
148 void popdown_all_game_dialogs(void)
150 unit_select_dialog_popdown();
151 popdown_advanced_terrain_dialog();
152 popdown_terrain_info_dialog();
153 popdown_newcity_dialog();
154 popdown_optiondlg(TRUE);
155 undraw_order_widgets();
156 popdown_diplomat_dialog();
157 popdown_pillage_dialog();
158 popdown_incite_dialog();
159 popdown_connect_dialog();
160 popdown_bribe_dialog();
161 popdown_find_dialog();
162 popdown_revolution_dialog();
163 science_report_dialogs_popdown_all();
164 meswin_dialog_popdown();
165 popdown_worklist_editor();
166 popdown_all_city_dialogs();
167 city_report_dialog_popdown();
168 economy_report_dialog_popdown();
169 units_report_dialog_popdown();
170 popdown_intel_dialogs();
171 popdown_players_nations_dialog();
172 popdown_players_dialog();
173 popdown_goto_airlift_dialog();
174 popdown_unit_upgrade_dlg();
175 popdown_unit_disband_dlg();
176 popdown_help_dialog();
177 popdown_notify_goto_dialog();
179 /* clear gui buffer */
180 if (C_S_PREPARING == client_state()) {
181 clear_surface(Main.gui->surface, NULL);
185 /* ======================================================================= */
187 /**************************************************************************
188 Find the my unit's (focus) chance of success at attacking/defending the
189 given enemy unit. Return FALSE if the values cannot be determined (e.g., no
190 units given).
191 **************************************************************************/
192 static bool sdl_get_chance_to_win(int *att_chance, int *def_chance,
193 struct unit *enemy_unit, struct unit *my_unit)
195 if (!my_unit || !enemy_unit) {
196 return FALSE;
199 /* chance to win when active unit is attacking the selected unit */
200 *att_chance = unit_win_chance(my_unit, enemy_unit) * 100;
202 /* chance to win when selected unit is attacking the active unit */
203 *def_chance = (1.0 - unit_win_chance(enemy_unit, my_unit)) * 100;
205 return TRUE;
208 /**************************************************************************
209 Notify goto dialog.
210 **************************************************************************/
211 struct notify_goto_data {
212 char *headline;
213 char *lines;
214 struct tile *ptile;
217 #define SPECLIST_TAG notify_goto
218 #define SPECLIST_TYPE struct notify_goto_data
219 #include "speclist.h"
221 struct notify_goto_dialog {
222 struct widget *window;
223 struct widget *close_button;
224 struct widget *label;
225 struct notify_goto_list *datas;
228 static struct notify_goto_dialog *notify_goto_dialog = NULL;
230 static void notify_goto_dialog_advance(struct notify_goto_dialog *pdialog);
232 /**************************************************************************
233 Create a notify goto data.
234 **************************************************************************/
235 static struct notify_goto_data *notify_goto_data_new(const char *headline,
236 const char *lines,
237 struct tile *ptile)
239 struct notify_goto_data *pdata = fc_malloc(sizeof(*pdata));
241 pdata->headline = fc_strdup(headline);
242 pdata->lines = fc_strdup(lines);
243 pdata->ptile = ptile;
245 return pdata;
248 /**************************************************************************
249 Destroy a notify goto data.
250 **************************************************************************/
251 static void notify_goto_data_destroy(struct notify_goto_data *pdata)
253 free(pdata->headline);
254 free(pdata->lines);
257 /**************************************************************************
258 Move the notify dialog.
259 **************************************************************************/
260 static int notify_goto_dialog_callback(struct widget *widget)
262 struct notify_goto_dialog *pdialog =
263 (struct notify_goto_dialog *) widget->data.ptr;
265 if (Main.event.button.button == SDL_BUTTON_LEFT) {
266 move_window_group(pdialog->label, pdialog->window);
269 return -1;
272 /**************************************************************************
273 Close the notify dialog.
274 **************************************************************************/
275 static int notify_goto_dialog_close_callback(struct widget *widget)
277 struct notify_goto_dialog *pdialog =
278 (struct notify_goto_dialog *) widget->data.ptr;
280 if (Main.event.button.button == SDL_BUTTON_LEFT) {
281 notify_goto_dialog_advance(pdialog);
284 return -1;
287 /**************************************************************************
288 Goto callback.
289 **************************************************************************/
290 static int notify_goto_dialog_goto_callback(struct widget *widget)
292 struct notify_goto_dialog *pdialog =
293 (struct notify_goto_dialog *) widget->data.ptr;
294 const struct notify_goto_data *pdata = notify_goto_list_get(pdialog->datas,
297 if (Main.event.button.button == SDL_BUTTON_LEFT) {
298 if (NULL != pdata->ptile) {
299 center_tile_mapcanvas(pdata->ptile);
301 } else if (Main.event.button.button == SDL_BUTTON_RIGHT) {
302 struct city *pcity;
304 if (NULL != pdata->ptile && (pcity = tile_city(pdata->ptile))) {
305 popup_city_dialog(pcity);
309 return -1;
312 /**************************************************************************
313 Create a notify dialog.
314 **************************************************************************/
315 static struct notify_goto_dialog *notify_goto_dialog_new(void)
317 struct notify_goto_dialog *pdialog = fc_malloc(sizeof(*pdialog));
318 utf8_str *str;
320 /* Window. */
321 str = create_utf8_from_char("", adj_font(12));
322 str->style |= TTF_STYLE_BOLD;
324 pdialog->window = create_window_skeleton(NULL, str, 0);
325 pdialog->window->action = notify_goto_dialog_callback;
326 pdialog->window->data.ptr = pdialog;
327 set_wstate(pdialog->window, FC_WS_NORMAL);
328 add_to_gui_list(ID_WINDOW, pdialog->window);
330 /* Close button. */
331 pdialog->close_button = create_themeicon(current_theme->Small_CANCEL_Icon,
332 pdialog->window->dst,
333 WF_WIDGET_HAS_INFO_LABEL
334 | WF_RESTORE_BACKGROUND);
335 pdialog->close_button->info_label =
336 create_utf8_from_char(_("Close Dialog (Esc)"), adj_font(12));
337 pdialog->close_button->action = notify_goto_dialog_close_callback;
338 pdialog->close_button->data.ptr = pdialog;
339 set_wstate(pdialog->close_button, FC_WS_NORMAL);
340 pdialog->close_button->key = SDLK_ESCAPE;
341 add_to_gui_list(ID_BUTTON, pdialog->close_button);
343 pdialog->label = NULL;
345 /* Data list. */
346 pdialog->datas = notify_goto_list_new_full(notify_goto_data_destroy);
348 return pdialog;
351 /**************************************************************************
352 Destroy a notify dialog.
353 **************************************************************************/
354 static void notify_goto_dialog_destroy(struct notify_goto_dialog *pdialog)
356 widget_undraw(pdialog->window);
357 widget_mark_dirty(pdialog->window);
358 remove_gui_layer(pdialog->window->dst);
360 del_widget_pointer_from_gui_list(pdialog->window);
361 del_widget_pointer_from_gui_list(pdialog->close_button);
362 if (NULL != pdialog->label) {
363 del_widget_pointer_from_gui_list(pdialog->label);
366 notify_goto_list_destroy(pdialog->datas);
367 free(pdialog);
370 /**************************************************************************
371 Update a notify dialog.
372 **************************************************************************/
373 static void notify_goto_dialog_update(struct notify_goto_dialog *pdialog)
375 const struct notify_goto_data *pdata = notify_goto_list_get(pdialog->datas,
378 if (NULL == pdata) {
379 return;
382 widget_undraw(pdialog->window);
383 widget_mark_dirty(pdialog->window);
385 copy_chars_to_utf8_str(pdialog->window->string_utf8, pdata->headline);
386 if (NULL != pdialog->label) {
387 del_widget_pointer_from_gui_list(pdialog->label);
389 pdialog->label = create_iconlabel_from_chars(NULL, pdialog->window->dst,
390 pdata->lines, adj_font(12),
391 WF_RESTORE_BACKGROUND);
392 pdialog->label->action = notify_goto_dialog_goto_callback;
393 pdialog->label->data.ptr = pdialog;
394 set_wstate(pdialog->label, FC_WS_NORMAL);
395 add_to_gui_list(ID_LABEL, pdialog->label);
397 resize_window(pdialog->window, NULL, NULL,
398 adj_size(pdialog->label->size.w + 40),
399 adj_size(pdialog->label->size.h + 60));
400 widget_set_position(pdialog->window,
401 (main_window_width() - pdialog->window->size.w) / 2,
402 (main_window_height() - pdialog->window->size.h) / 2);
403 widget_set_position(pdialog->close_button, pdialog->window->size.w
404 - pdialog->close_button->size.w - 1,
405 pdialog->window->size.y + adj_size(2));
406 widget_set_position(pdialog->label, adj_size(20), adj_size(40));
408 widget_redraw(pdialog->window);
409 widget_redraw(pdialog->close_button);
410 widget_redraw(pdialog->label);
411 widget_mark_dirty(pdialog->window);
412 flush_all();
415 /**************************************************************************
416 Update a notify dialog.
417 **************************************************************************/
418 static void notify_goto_dialog_advance(struct notify_goto_dialog *pdialog)
420 if (1 < notify_goto_list_size(pdialog->datas)) {
421 notify_goto_list_remove(pdialog->datas,
422 notify_goto_list_get(pdialog->datas, 0));
423 notify_goto_dialog_update(pdialog);
424 } else {
425 notify_goto_dialog_destroy(pdialog);
426 if (pdialog == notify_goto_dialog) {
427 notify_goto_dialog = NULL;
432 /**************************************************************************
433 Popup a dialog to display information about an event that has a
434 specific location. The user should be given the option to goto that
435 location.
436 **************************************************************************/
437 void popup_notify_goto_dialog(const char *headline, const char *lines,
438 const struct text_tag_list *tags,
439 struct tile *ptile)
441 if (NULL == notify_goto_dialog) {
442 notify_goto_dialog = notify_goto_dialog_new();
445 fc_assert(NULL != notify_goto_dialog);
447 notify_goto_list_prepend(notify_goto_dialog->datas,
448 notify_goto_data_new(headline, lines, ptile));
449 notify_goto_dialog_update(notify_goto_dialog);
452 /**************************************************************************
453 Popdown the notify goto dialog.
454 **************************************************************************/
455 void popdown_notify_goto_dialog(void)
457 if (NULL != notify_goto_dialog) {
458 notify_goto_dialog_destroy(notify_goto_dialog);
459 notify_goto_dialog = NULL;
463 /**************************************************************************
464 Popup a dialog to display connection message from server.
465 **************************************************************************/
466 void popup_connect_msg(const char *headline, const char *message)
468 log_error("popup_connect_msg() PORT ME");
471 /* ----------------------------------------------------------------------- */
472 struct ADVANCED_DLG *pNotifyDlg = NULL;
474 /**************************************************************************
475 User interacted with generic notify dialog.
476 **************************************************************************/
477 static int notify_dialog_window_callback(struct widget *pWindow)
479 if (Main.event.button.button == SDL_BUTTON_LEFT) {
480 move_window_group(pNotifyDlg->pBeginWidgetList, pWindow);
483 return -1;
486 /**************************************************************************
487 User interacted with notify dialog close button.
488 **************************************************************************/
489 static int exit_notify_dialog_callback(struct widget *pWidget)
491 if (Main.event.type == SDL_KEYDOWN
492 || (Main.event.type == SDL_MOUSEBUTTONDOWN
493 && Main.event.button.button == SDL_BUTTON_LEFT)) {
494 if (pNotifyDlg) {
495 popdown_window_group_dialog(pNotifyDlg->pBeginWidgetList,
496 pNotifyDlg->pEndWidgetList);
497 FC_FREE(pNotifyDlg->pScroll);
498 FC_FREE(pNotifyDlg);
499 flush_dirty();
502 return -1;
505 /**************************************************************************
506 Popup a generic dialog to display some generic information.
507 **************************************************************************/
508 void popup_notify_dialog(const char *caption, const char *headline,
509 const char *lines)
511 struct widget *pBuf, *pWindow;
512 utf8_str *pstr;
513 SDL_Surface *pHeadline, *pLines;
514 SDL_Rect dst;
515 SDL_Rect area;
517 if (pNotifyDlg) {
518 return;
521 pNotifyDlg = fc_calloc(1, sizeof(struct ADVANCED_DLG));
523 pstr = create_utf8_from_char(caption, adj_font(12));
524 pstr->style |= TTF_STYLE_BOLD;
526 pWindow = create_window_skeleton(NULL, pstr, 0);
528 pWindow->action = notify_dialog_window_callback;
529 set_wstate(pWindow, FC_WS_NORMAL);
531 add_to_gui_list(ID_WINDOW, pWindow);
532 pNotifyDlg->pEndWidgetList = pWindow;
534 area = pWindow->area;
536 /* ---------- */
537 /* create exit button */
538 pBuf = create_themeicon(current_theme->Small_CANCEL_Icon, pWindow->dst,
539 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
540 pBuf->info_label = create_utf8_from_char(_("Close Dialog (Esc)"),
541 adj_font(12));
542 pBuf->action = exit_notify_dialog_callback;
543 set_wstate(pBuf, FC_WS_NORMAL);
544 pBuf->key = SDLK_ESCAPE;
545 area.w += (pBuf->size.w + adj_size(10));
547 add_to_gui_list(ID_BUTTON, pBuf);
548 pNotifyDlg->pBeginWidgetList = pBuf;
550 pstr = create_utf8_from_char(headline, adj_font(16));
551 pstr->style |= TTF_STYLE_BOLD;
553 pHeadline = create_text_surf_from_utf8(pstr);
555 if (lines && *lines != '\0') {
556 change_ptsize_utf8(pstr, adj_font(12));
557 pstr->style &= ~TTF_STYLE_BOLD;
558 copy_chars_to_utf8_str(pstr, lines);
559 pLines = create_text_surf_from_utf8(pstr);
560 } else {
561 pLines = NULL;
564 FREEUTF8STR(pstr);
566 area.w = MAX(area.w, pHeadline->w);
567 if (pLines) {
568 area.w = MAX(area.w, pLines->w);
570 area.w += adj_size(60);
571 area.h = MAX(area.h, adj_size(10) + pHeadline->h + adj_size(10));
572 if (pLines) {
573 area.h += pLines->h + adj_size(10);
576 resize_window(pWindow, NULL, get_theme_color(COLOR_THEME_BACKGROUND),
577 (pWindow->size.w - pWindow->area.w) + area.w,
578 (pWindow->size.h - pWindow->area.h) + area.h);
580 area = pWindow->area;
582 widget_set_position(pWindow,
583 (main_window_width() - pWindow->size.w) / 2,
584 (main_window_height() - pWindow->size.h) / 2);
586 dst.x = area.x + (area.w - pHeadline->w) / 2;
587 dst.y = area.y + adj_size(10);
589 alphablit(pHeadline, NULL, pWindow->theme, &dst, 255);
590 if (pLines) {
591 dst.y += pHeadline->h + adj_size(10);
592 if (pHeadline->w < pLines->w) {
593 dst.x = area.x + (area.w - pLines->w) / 2;
596 alphablit(pLines, NULL, pWindow->theme, &dst, 255);
599 FREESURFACE(pHeadline);
600 FREESURFACE(pLines);
602 /* exit button */
603 pBuf = pWindow->prev;
604 pBuf->size.x = area.x + area.w - pBuf->size.w - 1;
605 pBuf->size.y = pWindow->size.y + adj_size(2);
607 /* redraw */
608 redraw_group(pNotifyDlg->pBeginWidgetList, pWindow, 0);
609 widget_flush(pWindow);
612 /* =======================================================================*/
613 /* ========================= UNIT UPGRADE DIALOG =========================*/
614 /* =======================================================================*/
615 static struct SMALL_DLG *pUnit_Upgrade_Dlg = NULL;
617 /****************************************************************
618 User interacted with upgrade unit widget.
619 *****************************************************************/
620 static int upgrade_unit_window_callback(struct widget *pWindow)
622 if (Main.event.button.button == SDL_BUTTON_LEFT) {
623 move_window_group(pUnit_Upgrade_Dlg->pBeginWidgetList, pWindow);
625 return -1;
628 /****************************************************************
629 User interacted with upgrade unit dialog cancel -button
630 *****************************************************************/
631 static int cancel_upgrade_unit_callback(struct widget *pWidget)
633 if (Main.event.button.button == SDL_BUTTON_LEFT) {
634 popdown_unit_upgrade_dlg();
635 /* enable city dlg */
636 enable_city_dlg_widgets();
637 flush_dirty();
639 return -1;
642 /****************************************************************
643 User interacted with unit upgrade dialog "Upgrade" -button.
644 *****************************************************************/
645 static int ok_upgrade_unit_window_callback(struct widget *pWidget)
647 if (Main.event.button.button == SDL_BUTTON_LEFT) {
648 struct unit *pUnit = pWidget->data.unit;
650 popdown_unit_upgrade_dlg();
651 /* enable city dlg */
652 enable_city_dlg_widgets();
653 free_city_units_lists();
654 request_unit_upgrade(pUnit);
655 flush_dirty();
657 return -1;
660 /****************************************************************
661 Open unit upgrade dialog.
662 *****************************************************************/
663 void popup_unit_upgrade_dlg(struct unit *pUnit, bool city)
665 char cBuf[128];
666 struct widget *pBuf = NULL, *pWindow;
667 utf8_str *pstr;
668 SDL_Surface *pText;
669 SDL_Rect dst;
670 int window_x = 0, window_y = 0;
671 enum unit_upgrade_result unit_upgrade_result;
672 SDL_Rect area;
674 if (pUnit_Upgrade_Dlg) {
675 /* just in case */
676 flush_dirty();
677 return;
680 pUnit_Upgrade_Dlg = fc_calloc(1, sizeof(struct SMALL_DLG));
682 unit_upgrade_result = unit_upgrade_info(pUnit, cBuf, sizeof(cBuf));
684 pstr = create_utf8_from_char(_("Upgrade Obsolete Units"), adj_font(12));
685 pstr->style |= TTF_STYLE_BOLD;
687 pWindow = create_window_skeleton(NULL, pstr, 0);
689 pWindow->action = upgrade_unit_window_callback;
690 set_wstate(pWindow, FC_WS_NORMAL);
692 pUnit_Upgrade_Dlg->pEndWidgetList = pWindow;
694 add_to_gui_list(ID_WINDOW, pWindow);
696 area = pWindow->area;
698 /* ============================================================= */
700 /* create text label */
701 pstr = create_utf8_from_char(cBuf, adj_font(10));
702 pstr->style |= (TTF_STYLE_BOLD|SF_CENTER);
703 pstr->fgcol = *get_theme_color(COLOR_THEME_UNITUPGRADE_TEXT);
705 pText = create_text_surf_from_utf8(pstr);
706 FREEUTF8STR(pstr);
708 area.w = MAX(area.w, pText->w + adj_size(20));
709 area.h += (pText->h + adj_size(10));
711 /* cancel button */
712 pBuf = create_themeicon_button_from_chars(current_theme->CANCEL_Icon,
713 pWindow->dst, _("Cancel"),
714 adj_font(12), 0);
716 pBuf->action = cancel_upgrade_unit_callback;
717 set_wstate(pBuf, FC_WS_NORMAL);
719 area.h += (pBuf->size.h + adj_size(20));
721 add_to_gui_list(ID_BUTTON, pBuf);
723 if (UU_OK == unit_upgrade_result) {
724 pBuf = create_themeicon_button_from_chars(current_theme->OK_Icon, pWindow->dst,
725 _("Upgrade"), adj_font(12), 0);
727 pBuf->action = ok_upgrade_unit_window_callback;
728 set_wstate(pBuf, FC_WS_NORMAL);
729 pBuf->data.unit = pUnit;
730 add_to_gui_list(ID_BUTTON, pBuf);
731 pBuf->size.w = MAX(pBuf->size.w, pBuf->next->size.w);
732 pBuf->next->size.w = pBuf->size.w;
733 area.w = MAX(area.w, adj_size(30) + pBuf->size.w * 2);
734 } else {
735 area.w = MAX(area.w, pBuf->size.w + adj_size(20));
737 /* ============================================ */
739 pUnit_Upgrade_Dlg->pBeginWidgetList = pBuf;
741 resize_window(pWindow, NULL, get_theme_color(COLOR_THEME_BACKGROUND),
742 (pWindow->size.w - pWindow->area.w) + area.w,
743 (pWindow->size.h - pWindow->area.h) + area.h);
745 area = pWindow->area;
747 if (city) {
748 window_x = Main.event.motion.x;
749 window_y = Main.event.motion.y;
750 } else {
751 put_window_near_map_tile(pWindow, pWindow->size.w, pWindow->size.h,
752 unit_tile(pUnit));
755 widget_set_position(pWindow, window_x, window_y);
757 /* setup rest of widgets */
758 /* label */
759 dst.x = area.x + (area.w - pText->w) / 2;
760 dst.y = area.y + adj_size(10);
761 alphablit(pText, NULL, pWindow->theme, &dst, 255);
762 FREESURFACE(pText);
764 /* cancel button */
765 pBuf = pWindow->prev;
766 pBuf->size.y = area.y + area.h - pBuf->size.h - adj_size(7);
768 if (UU_OK == unit_upgrade_result) {
769 /* upgrade button */
770 pBuf = pBuf->prev;
771 pBuf->size.x = area.x + (area.w - (2 * pBuf->size.w + adj_size(10))) / 2;
772 pBuf->size.y = pBuf->next->size.y;
774 /* cancel button */
775 pBuf->next->size.x = pBuf->size.x + pBuf->size.w + adj_size(10);
776 } else {
777 /* x position of cancel button */
778 pBuf->size.x = area.x + area.w - pBuf->size.w - adj_size(10);
781 /* ================================================== */
782 /* redraw */
783 redraw_group(pUnit_Upgrade_Dlg->pBeginWidgetList, pWindow, 0);
785 widget_mark_dirty(pWindow);
786 flush_dirty();
789 /****************************************************************
790 Close unit upgrade dialog.
791 *****************************************************************/
792 static void popdown_unit_upgrade_dlg(void)
794 if (pUnit_Upgrade_Dlg) {
795 popdown_window_group_dialog(pUnit_Upgrade_Dlg->pBeginWidgetList,
796 pUnit_Upgrade_Dlg->pEndWidgetList);
797 FC_FREE(pUnit_Upgrade_Dlg);
801 /* =======================================================================*/
802 /* ========================= UNIT DISBAND DIALOG =========================*/
803 /* =======================================================================*/
804 static struct SMALL_DLG *pUnit_Disband_Dlg = NULL;
806 /****************************************************************
807 User interacted with disband unit widget.
808 *****************************************************************/
809 static int disband_unit_window_callback(struct widget *pWindow)
811 if (Main.event.button.button == SDL_BUTTON_LEFT) {
812 move_window_group(pUnit_Disband_Dlg->pBeginWidgetList, pWindow);
815 return -1;
818 /****************************************************************
819 User interacted with disband unit dialog cancel -button
820 *****************************************************************/
821 static int cancel_disband_unit_callback(struct widget *pWidget)
823 if (Main.event.button.button == SDL_BUTTON_LEFT) {
824 popdown_unit_disband_dlg();
825 /* enable city dlg */
826 enable_city_dlg_widgets();
827 flush_dirty();
829 return -1;
832 /****************************************************************
833 User interacted with unit disband dialog "Disband" -button.
834 *****************************************************************/
835 static int ok_disband_unit_window_callback(struct widget *pWidget)
837 if (Main.event.button.button == SDL_BUTTON_LEFT) {
838 struct unit *pUnit = pWidget->data.unit;
840 popdown_unit_disband_dlg();
841 /* enable city dlg */
842 enable_city_dlg_widgets();
843 free_city_units_lists();
844 request_unit_disband(pUnit);
845 flush_dirty();
847 return -1;
850 /****************************************************************
851 Open unit disband dialog.
852 *****************************************************************/
853 void popup_unit_disband_dlg(struct unit *pUnit, bool city)
855 char cBuf[128];
856 struct widget *pBuf = NULL, *pWindow;
857 utf8_str *pstr;
858 SDL_Surface *pText;
859 SDL_Rect dst;
860 int window_x = 0, window_y = 0;
861 bool unit_disband_result;
862 SDL_Rect area;
864 if (pUnit_Disband_Dlg) {
865 /* just in case */
866 flush_dirty();
867 return;
870 pUnit_Disband_Dlg = fc_calloc(1, sizeof(struct SMALL_DLG));
873 struct unit_list *pUnits = unit_list_new();
875 unit_list_append(pUnits, pUnit);
876 unit_disband_result = get_units_disband_info(cBuf, sizeof(cBuf), pUnits);
877 unit_list_destroy(pUnits);
880 pstr = create_utf8_from_char(_("Disband Units"), adj_font(12));
881 pstr->style |= TTF_STYLE_BOLD;
883 pWindow = create_window_skeleton(NULL, pstr, 0);
885 pWindow->action = disband_unit_window_callback;
886 set_wstate(pWindow, FC_WS_NORMAL);
888 pUnit_Disband_Dlg->pEndWidgetList = pWindow;
890 add_to_gui_list(ID_WINDOW, pWindow);
892 area = pWindow->area;
894 /* ============================================================= */
896 /* create text label */
897 pstr = create_utf8_from_char(cBuf, adj_font(10));
898 pstr->style |= (TTF_STYLE_BOLD|SF_CENTER);
899 pstr->fgcol = *get_theme_color(COLOR_THEME_UNITDISBAND_TEXT);
901 pText = create_text_surf_from_utf8(pstr);
902 FREEUTF8STR(pstr);
904 area.w = MAX(area.w, pText->w + adj_size(20));
905 area.h += (pText->h + adj_size(10));
907 /* cancel button */
908 pBuf = create_themeicon_button_from_chars(current_theme->CANCEL_Icon,
909 pWindow->dst, _("Cancel"),
910 adj_font(12), 0);
912 pBuf->action = cancel_disband_unit_callback;
913 set_wstate(pBuf, FC_WS_NORMAL);
915 area.h += (pBuf->size.h + adj_size(20));
917 add_to_gui_list(ID_BUTTON, pBuf);
919 if (unit_disband_result) {
920 pBuf = create_themeicon_button_from_chars(current_theme->OK_Icon, pWindow->dst,
921 _("Disband"), adj_font(12), 0);
923 pBuf->action = ok_disband_unit_window_callback;
924 set_wstate(pBuf, FC_WS_NORMAL);
925 pBuf->data.unit = pUnit;
926 add_to_gui_list(ID_BUTTON, pBuf);
927 pBuf->size.w = MAX(pBuf->size.w, pBuf->next->size.w);
928 pBuf->next->size.w = pBuf->size.w;
929 area.w = MAX(area.w, adj_size(30) + pBuf->size.w * 2);
930 } else {
931 area.w = MAX(area.w, pBuf->size.w + adj_size(20));
933 /* ============================================ */
935 pUnit_Disband_Dlg->pBeginWidgetList = pBuf;
937 resize_window(pWindow, NULL, get_theme_color(COLOR_THEME_BACKGROUND),
938 (pWindow->size.w - pWindow->area.w) + area.w,
939 (pWindow->size.h - pWindow->area.h) + area.h);
941 area = pWindow->area;
943 if (city) {
944 window_x = Main.event.motion.x;
945 window_y = Main.event.motion.y;
946 } else {
947 put_window_near_map_tile(pWindow, pWindow->size.w, pWindow->size.h,
948 unit_tile(pUnit));
951 widget_set_position(pWindow, window_x, window_y);
953 /* setup rest of widgets */
954 /* label */
955 dst.x = area.x + (area.w - pText->w) / 2;
956 dst.y = area.y + adj_size(10);
957 alphablit(pText, NULL, pWindow->theme, &dst, 255);
958 FREESURFACE(pText);
960 /* cancel button */
961 pBuf = pWindow->prev;
962 pBuf->size.y = area.y + area.h - pBuf->size.h - adj_size(7);
964 if (unit_disband_result) {
965 /* disband button */
966 pBuf = pBuf->prev;
967 pBuf->size.x = area.x + (area.w - (2 * pBuf->size.w + adj_size(10))) / 2;
968 pBuf->size.y = pBuf->next->size.y;
970 /* cancel button */
971 pBuf->next->size.x = pBuf->size.x + pBuf->size.w + adj_size(10);
972 } else {
973 /* x position of cancel button */
974 pBuf->size.x = area.x + area.w - pBuf->size.w - adj_size(10);
977 /* ================================================== */
978 /* redraw */
979 redraw_group(pUnit_Disband_Dlg->pBeginWidgetList, pWindow, 0);
981 widget_mark_dirty(pWindow);
982 flush_dirty();
985 /****************************************************************
986 Close unit disband dialog.
987 *****************************************************************/
988 static void popdown_unit_disband_dlg(void)
990 if (pUnit_Disband_Dlg) {
991 popdown_window_group_dialog(pUnit_Disband_Dlg->pBeginWidgetList,
992 pUnit_Disband_Dlg->pEndWidgetList);
993 FC_FREE(pUnit_Disband_Dlg);
997 /* =======================================================================*/
998 /* ======================== UNIT SELECTION DIALOG ========================*/
999 /* =======================================================================*/
1000 static struct ADVANCED_DLG *pUnit_Select_Dlg = NULL;
1002 /**************************************************************************
1003 User interacted with unit selection window.
1004 **************************************************************************/
1005 static int unit_select_window_callback(struct widget *pWindow)
1007 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1008 move_window_group(pUnit_Select_Dlg->pBeginWidgetList, pWindow);
1011 return -1;
1014 /**************************************************************************
1015 User requested unit select window to be closed.
1016 **************************************************************************/
1017 static int exit_unit_select_callback(struct widget *pWidget)
1019 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1020 unit_select_dialog_popdown();
1021 is_unit_move_blocked = FALSE;
1024 return -1;
1027 /**************************************************************************
1028 User selected unit from unit select window.
1029 **************************************************************************/
1030 static int unit_select_callback(struct widget *pWidget)
1032 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1033 struct unit *pUnit =
1034 player_unit_by_number(client_player(), MAX_ID - pWidget->ID);
1036 unit_select_dialog_popdown();
1037 if (pUnit) {
1038 request_new_unit_activity(pUnit, ACTIVITY_IDLE);
1039 unit_focus_set(pUnit);
1042 return -1;
1045 /**************************************************************************
1046 Popdown a dialog window to select units on a particular tile.
1047 **************************************************************************/
1048 static void unit_select_dialog_popdown(void)
1050 if (pUnit_Select_Dlg) {
1051 is_unit_move_blocked = FALSE;
1052 popdown_window_group_dialog(pUnit_Select_Dlg->pBeginWidgetList,
1053 pUnit_Select_Dlg->pEndWidgetList);
1055 FC_FREE(pUnit_Select_Dlg->pScroll);
1056 FC_FREE(pUnit_Select_Dlg);
1057 flush_dirty();
1061 /**************************************************************************
1062 Popup a dialog window to select units on a particular tile.
1063 **************************************************************************/
1064 void unit_select_dialog_popup(struct tile *ptile)
1066 struct widget *pBuf = NULL, *pWindow;
1067 utf8_str *pstr;
1068 struct unit *pUnit = NULL, *pFocus = head_of_units_in_focus();
1069 struct unit_type *pUnitType;
1070 char cBuf[255];
1071 int i, w = 0, n;
1072 SDL_Rect area;
1074 #define NUM_SEEN 20
1076 n = unit_list_size(ptile->units);
1078 if (!n || pUnit_Select_Dlg) {
1079 return;
1082 is_unit_move_blocked = TRUE;
1083 pUnit_Select_Dlg = fc_calloc(1, sizeof(struct ADVANCED_DLG));
1085 fc_snprintf(cBuf , sizeof(cBuf),"%s (%d)", _("Unit selection") , n);
1086 pstr = create_utf8_from_char(cBuf , adj_font(12));
1087 pstr->style |= TTF_STYLE_BOLD;
1089 pWindow = create_window_skeleton(NULL, pstr, 0);
1091 pWindow->action = unit_select_window_callback;
1092 set_wstate(pWindow, FC_WS_NORMAL);
1094 add_to_gui_list(ID_UNIT_SELECT_DLG_WINDOW, pWindow);
1095 pUnit_Select_Dlg->pEndWidgetList = pWindow;
1097 area = pWindow->area;
1099 /* ---------- */
1100 /* create exit button */
1101 pBuf = create_themeicon(current_theme->Small_CANCEL_Icon, pWindow->dst,
1102 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
1103 pBuf->info_label = create_utf8_from_char(_("Close Dialog (Esc)"),
1104 adj_font(12));
1105 pBuf->action = exit_unit_select_callback;
1106 set_wstate(pBuf, FC_WS_NORMAL);
1107 pBuf->key = SDLK_ESCAPE;
1108 area.w += (pBuf->size.w + adj_size(10));
1110 add_to_gui_list(ID_UNIT_SELECT_DLG_EXIT_BUTTON, pBuf);
1112 /* ---------- */
1114 for (i = 0; i < n; i++) {
1115 const char *vetname;
1117 pUnit = unit_list_get(ptile->units, i);
1118 pUnitType = unit_type_get(pUnit);
1119 vetname = utype_veteran_name_translation(pUnitType, pUnit->veteran);
1121 if (unit_owner(pUnit) == client.conn.playing) {
1122 fc_snprintf(cBuf , sizeof(cBuf), _("Contact %s (%d / %d) %s(%d,%d,%s) %s"),
1123 (vetname != NULL ? vetname : ""),
1124 pUnit->hp, pUnitType->hp,
1125 utype_name_translation(pUnitType),
1126 pUnitType->attack_strength,
1127 pUnitType->defense_strength,
1128 move_points_text(pUnitType->move_rate, FALSE),
1129 unit_activity_text(pUnit));
1130 } else {
1131 int att_chance, def_chance;
1133 fc_snprintf(cBuf , sizeof(cBuf), _("%s %s %s(A:%d D:%d M:%s FP:%d) HP:%d%%"),
1134 nation_adjective_for_player(unit_owner(pUnit)),
1135 (vetname != NULL ? vetname : ""),
1136 utype_name_translation(pUnitType),
1137 pUnitType->attack_strength,
1138 pUnitType->defense_strength,
1139 move_points_text(pUnitType->move_rate, FALSE),
1140 pUnitType->firepower,
1141 (pUnit->hp * 100 / pUnitType->hp + 9) / 10);
1143 /* calculate chance to win */
1144 if (sdl_get_chance_to_win(&att_chance, &def_chance, pUnit, pFocus)) {
1145 /* TRANS: "CtW" = "Chance to Win" */
1146 cat_snprintf(cBuf, sizeof(cBuf), _(" CtW: Att:%d%% Def:%d%%"),
1147 att_chance, def_chance);
1151 create_active_iconlabel(pBuf, pWindow->dst, pstr, cBuf,
1152 unit_select_callback);
1154 add_to_gui_list(MAX_ID - pUnit->id , pBuf);
1156 area.w = MAX(area.w, pBuf->size.w);
1157 area.h += pBuf->size.h;
1158 if (unit_owner(pUnit) == client.conn.playing) {
1159 set_wstate(pBuf, FC_WS_NORMAL);
1162 if (i > NUM_SEEN - 1) {
1163 set_wflag(pBuf , WF_HIDDEN);
1167 pUnit_Select_Dlg->pBeginWidgetList = pBuf;
1168 pUnit_Select_Dlg->pBeginActiveWidgetList = pUnit_Select_Dlg->pBeginWidgetList;
1169 pUnit_Select_Dlg->pEndActiveWidgetList = pWindow->prev->prev;
1170 pUnit_Select_Dlg->pActiveWidgetList = pUnit_Select_Dlg->pEndActiveWidgetList;
1172 area.w += adj_size(2);
1173 if (n > NUM_SEEN) {
1174 n = create_vertical_scrollbar(pUnit_Select_Dlg, 1, NUM_SEEN, TRUE, TRUE);
1175 area.w += n;
1177 /* ------- window ------- */
1178 area.h = NUM_SEEN * pWindow->prev->prev->size.h;
1181 resize_window(pWindow, NULL, NULL,
1182 (pWindow->size.w - pWindow->area.w) + area.w,
1183 (pWindow->size.h - pWindow->area.h) + area.h);
1185 area = pWindow->area;
1187 put_window_near_map_tile(pWindow, pWindow->size.w, pWindow->size.h,
1188 unit_tile(pUnit));
1190 w = area.w;
1192 if (pUnit_Select_Dlg->pScroll) {
1193 w -= n;
1196 /* exit button */
1197 pBuf = pWindow->prev;
1198 pBuf->size.x = area.x + area.w - pBuf->size.w - 1;
1199 pBuf->size.y = pWindow->size.y + adj_size(2);
1200 pBuf = pBuf->prev;
1202 setup_vertical_widgets_position(1, area.x + 1, area.y, w, 0,
1203 pUnit_Select_Dlg->pBeginActiveWidgetList,
1204 pBuf);
1206 if (pUnit_Select_Dlg->pScroll) {
1207 setup_vertical_scrollbar_area(pUnit_Select_Dlg->pScroll,
1208 area.x + area.w, area.y,
1209 area.h, TRUE);
1212 /* ==================================================== */
1213 /* redraw */
1214 redraw_group(pUnit_Select_Dlg->pBeginWidgetList, pWindow, 0);
1216 widget_flush(pWindow);
1219 /**************************************************************************
1220 Update the dialog window to select units on a particular tile.
1221 **************************************************************************/
1222 void unit_select_dialog_update_real(void)
1224 /* PORTME */
1227 /* ====================================================================== */
1228 /* ============================ TERRAIN INFO ============================ */
1229 /* ====================================================================== */
1230 static struct SMALL_DLG *pTerrain_Info_Dlg = NULL;
1233 /**************************************************************************
1234 Popdown terrain information dialog.
1235 **************************************************************************/
1236 static int terrain_info_window_dlg_callback(struct widget *pWindow)
1238 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1239 move_window_group(pTerrain_Info_Dlg->pBeginWidgetList, pWindow);
1241 return -1;
1244 /**************************************************************************
1245 Popdown terrain information dialog.
1246 **************************************************************************/
1247 static void popdown_terrain_info_dialog(void)
1249 if (pTerrain_Info_Dlg) {
1250 popdown_window_group_dialog(pTerrain_Info_Dlg->pBeginWidgetList,
1251 pTerrain_Info_Dlg->pEndWidgetList);
1252 FC_FREE(pTerrain_Info_Dlg);
1253 flush_dirty();
1257 /**************************************************************************
1258 Popdown terrain information dialog.
1259 **************************************************************************/
1260 static int exit_terrain_info_dialog_callback(struct widget *pButton)
1262 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1263 popdown_terrain_info_dialog();
1265 return -1;
1268 /**************************************************************************
1269 Return a (static) string with terrain defense bonus.
1270 This does not include bonuses some units may get out of bases.
1271 **************************************************************************/
1272 const char *sdl_get_tile_defense_info_text(struct tile *ptile)
1274 static char buffer[64];
1275 int bonus = (tile_terrain(ptile)->defense_bonus - 10) * 10;
1277 extra_type_iterate(pextra) {
1278 if (tile_has_extra(ptile, pextra)
1279 && pextra->category == ECAT_NATURAL) {
1280 bonus += pextra->defense_bonus;
1282 } extra_type_iterate_end;
1284 fc_snprintf(buffer, sizeof(buffer), _("Terrain Defense Bonus: +%d%% "), bonus);
1286 return buffer;
1289 /**************************************************************************
1290 Popup terrain information dialog.
1291 **************************************************************************/
1292 static void popup_terrain_info_dialog(SDL_Surface *pDest, struct tile *ptile)
1294 SDL_Surface *pSurf;
1295 struct widget *pBuf, *pWindow;
1296 utf8_str *pstr;
1297 char cBuf[256];
1298 SDL_Rect area;
1300 if (pTerrain_Info_Dlg) {
1301 flush_dirty();
1302 return;
1305 pSurf = get_terrain_surface(ptile);
1306 pTerrain_Info_Dlg = fc_calloc(1, sizeof(struct SMALL_DLG));
1308 /* ----------- */
1309 fc_snprintf(cBuf, sizeof(cBuf), "%s [%d,%d]", _("Terrain Info"),
1310 TILE_XY(ptile));
1312 pWindow = create_window_skeleton(NULL, create_utf8_from_char(cBuf , adj_font(12)), 0);
1313 pWindow->string_utf8->style |= TTF_STYLE_BOLD;
1315 pWindow->action = terrain_info_window_dlg_callback;
1316 set_wstate(pWindow, FC_WS_NORMAL);
1318 add_to_gui_list(ID_TERRAIN_INFO_DLG_WINDOW, pWindow);
1319 pTerrain_Info_Dlg->pEndWidgetList = pWindow;
1321 area = pWindow->area;
1323 /* ---------- */
1324 pstr = create_utf8_from_char(popup_info_text(ptile), adj_font(12));
1325 pstr->style |= SF_CENTER;
1326 pBuf = create_iconlabel(pSurf, pWindow->dst, pstr, 0);
1328 pBuf->size.h += tileset_tile_height(tileset) / 2;
1330 add_to_gui_list(ID_LABEL, pBuf);
1332 /* ------ window ---------- */
1333 area.w = MAX(area.w, pBuf->size.w + adj_size(20));
1334 area.h = MAX(area.h, pBuf->size.h);
1336 resize_window(pWindow, NULL, get_theme_color(COLOR_THEME_BACKGROUND),
1337 (pWindow->size.w - pWindow->area.w) + area.w,
1338 (pWindow->size.h - pWindow->area.h) + area.h);
1340 area = pWindow->area;
1342 put_window_near_map_tile(pWindow, pWindow->size.w, pWindow->size.h, ptile);
1344 /* ------------------------ */
1346 pBuf->size.x = area.x + adj_size(10);
1347 pBuf->size.y = area.y;
1349 /* exit icon */
1350 pBuf = create_themeicon(current_theme->Small_CANCEL_Icon, pWindow->dst,
1351 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
1352 pBuf->info_label = create_utf8_from_char(_("Close Dialog (Esc)"),
1353 adj_font(12));
1354 pBuf->size.x = area.x + area.w - pBuf->size.w - 1;
1355 pBuf->size.y = pWindow->size.y + adj_size(2);
1356 pBuf->action = exit_terrain_info_dialog_callback;
1357 set_wstate(pBuf, FC_WS_NORMAL);
1358 pBuf->key = SDLK_ESCAPE;
1360 add_to_gui_list(ID_TERRAIN_INFO_DLG_EXIT_BUTTON, pBuf);
1362 pTerrain_Info_Dlg->pBeginWidgetList = pBuf;
1363 /* --------------------------------- */
1364 /* redraw */
1365 redraw_group(pTerrain_Info_Dlg->pBeginWidgetList, pWindow, 0);
1366 widget_mark_dirty(pWindow);
1367 flush_dirty();
1370 /* ====================================================================== */
1371 /* ========================= ADVANCED_TERRAIN_MENU ====================== */
1372 /* ====================================================================== */
1373 struct ADVANCED_DLG *pAdvanced_Terrain_Dlg = NULL;
1375 /**************************************************************************
1376 Popdown a generic dialog to display some generic information about
1377 terrain : tile, units , cities, etc.
1378 **************************************************************************/
1379 void popdown_advanced_terrain_dialog(void)
1381 if (pAdvanced_Terrain_Dlg) {
1382 is_unit_move_blocked = FALSE;
1383 popdown_window_group_dialog(pAdvanced_Terrain_Dlg->pBeginWidgetList,
1384 pAdvanced_Terrain_Dlg->pEndWidgetList);
1386 FC_FREE(pAdvanced_Terrain_Dlg->pScroll);
1387 FC_FREE(pAdvanced_Terrain_Dlg);
1391 /**************************************************************************
1392 User selected "Advanced Menu"
1393 **************************************************************************/
1394 int advanced_terrain_window_dlg_callback(struct widget *pWindow)
1396 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1397 move_window_group(pAdvanced_Terrain_Dlg->pBeginWidgetList, pWindow);
1399 return -1;
1402 /**************************************************************************
1403 User requested closing of advanced terrain dialog.
1404 **************************************************************************/
1405 int exit_advanced_terrain_dlg_callback(struct widget *pWidget)
1407 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1408 popdown_advanced_terrain_dialog();
1409 flush_dirty();
1411 return -1;
1414 /**************************************************************************
1415 User requested terrain info.
1416 **************************************************************************/
1417 static int terrain_info_callback(struct widget *pWidget)
1419 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1420 int x = pWidget->data.cont->id0;
1421 int y = pWidget->data.cont->id1;
1423 popdown_advanced_terrain_dialog();
1425 popup_terrain_info_dialog(NULL, map_pos_to_tile(x , y));
1427 return -1;
1430 /**************************************************************************
1431 User requested zoom to city.
1432 **************************************************************************/
1433 static int zoom_to_city_callback(struct widget *pWidget)
1435 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1436 struct city *pCity = pWidget->data.city;
1438 popdown_advanced_terrain_dialog();
1440 popup_city_dialog(pCity);
1442 return -1;
1445 /**************************************************************************
1446 User requested production change.
1447 **************************************************************************/
1448 static int change_production_callback(struct widget *pWidget)
1450 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1451 struct city *pCity = pWidget->data.city;
1453 popdown_advanced_terrain_dialog();
1454 popup_worklist_editor(pCity, NULL);
1456 return -1;
1459 /**************************************************************************
1460 User requested hurry production.
1461 **************************************************************************/
1462 static int hurry_production_callback(struct widget *pWidget)
1464 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1465 struct city *pCity = pWidget->data.city;
1467 popdown_advanced_terrain_dialog();
1469 popup_hurry_production_dialog(pCity, NULL);
1471 return -1;
1474 /**************************************************************************
1475 User requested opening of cma settings.
1476 **************************************************************************/
1477 static int cma_callback(struct widget *pWidget)
1479 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1480 struct city *pCity = pWidget->data.city;
1482 popdown_advanced_terrain_dialog();
1483 popup_city_cma_dialog(pCity);
1485 return -1;
1488 /**************************************************************************
1489 User selected unit.
1490 **************************************************************************/
1491 static int adv_unit_select_callback(struct widget *pWidget)
1493 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1494 struct unit *pUnit = pWidget->data.unit;
1496 popdown_advanced_terrain_dialog();
1498 if (pUnit) {
1499 request_new_unit_activity(pUnit, ACTIVITY_IDLE);
1500 unit_focus_set(pUnit);
1503 return -1;
1506 /**************************************************************************
1507 User selected all units from tile.
1508 **************************************************************************/
1509 static int adv_unit_select_all_callback(struct widget *pWidget)
1511 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1512 struct unit *pUnit = pWidget->data.unit;
1514 popdown_advanced_terrain_dialog();
1516 if (pUnit) {
1517 activate_all_units(unit_tile(pUnit));
1520 return -1;
1523 /**************************************************************************
1524 Sentry unit widget contains.
1525 **************************************************************************/
1526 static int adv_unit_sentry_idle_callback(struct widget *pWidget)
1528 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1529 struct unit *pUnit = pWidget->data.unit;
1531 popdown_advanced_terrain_dialog();
1533 if (pUnit) {
1534 struct tile *ptile = unit_tile(pUnit);
1536 unit_list_iterate(ptile->units, punit) {
1537 if (unit_owner(punit) == client.conn.playing
1538 && ACTIVITY_IDLE == punit->activity
1539 && !punit->ai_controlled
1540 && can_unit_do_activity(punit, ACTIVITY_SENTRY)) {
1541 request_new_unit_activity(punit, ACTIVITY_SENTRY);
1543 } unit_list_iterate_end;
1546 return -1;
1549 /**************************************************************************
1550 Initiate goto to selected tile.
1551 **************************************************************************/
1552 static int goto_here_callback(struct widget *pWidget)
1554 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1555 int x = pWidget->data.cont->id0;
1556 int y = pWidget->data.cont->id1;
1558 popdown_advanced_terrain_dialog();
1560 /* may not work */
1561 send_goto_tile(head_of_units_in_focus(), map_pos_to_tile(x, y));
1563 return -1;
1566 /**************************************************************************
1567 Initiate patrol to selected tile.
1568 **************************************************************************/
1569 static int patrol_here_callback(struct widget *pWidget)
1571 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1573 /* FIXME */
1574 #if 0
1575 int x = pWidget->data.cont->id0;
1576 int y = pWidget->data.cont->id1;
1577 struct unit *pUnit = head_of_units_in_focus();
1578 #endif
1580 popdown_advanced_terrain_dialog();
1582 #if 0
1583 if (pUnit) {
1584 enter_goto_state(pUnit);
1585 /* may not work */
1586 do_unit_patrol_to(pUnit, map_pos_to_tile(x, y));
1587 exit_goto_state();
1589 #endif /* 0 */
1591 return -1;
1594 /**************************************************************************
1595 Initiate paradrop to selected tile.
1596 **************************************************************************/
1597 static int paradrop_here_callback(struct widget *pWidget)
1599 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1600 /* FIXME */
1601 #if 0
1602 int x = pWidget->data.cont->id0;
1603 int y = pWidget->data.cont->id1;
1604 #endif
1606 popdown_advanced_terrain_dialog();
1608 #if 0
1609 /* may not work */
1610 do_unit_paradrop_to(get_unit_in_focus(), map_pos_to_tile(x, y));
1611 #endif
1613 return -1;
1616 /**************************************************************************
1617 Show help about unit type.
1618 **************************************************************************/
1619 static int unit_help_callback(struct widget *pWidget)
1621 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1622 Unit_type_id unit_id = MAX_ID - pWidget->ID;
1624 popdown_advanced_terrain_dialog();
1625 popup_unit_info(unit_id);
1627 return -1;
1630 /**************************************************************************
1631 Popup a generic dialog to display some generic information about
1632 terrain : tile, units , cities, etc.
1633 **************************************************************************/
1634 void popup_advanced_terrain_dialog(struct tile *ptile, Uint16 pos_x, Uint16 pos_y)
1636 struct widget *pWindow = NULL, *pBuf = NULL;
1637 struct city *pCity;
1638 struct unit *pFocus_Unit;
1639 utf8_str *pstr;
1640 SDL_Rect area2;
1641 struct CONTAINER *pCont;
1642 char cBuf[255];
1643 int n, w = 0, h, units_h = 0;
1644 SDL_Rect area;
1646 if (pAdvanced_Terrain_Dlg) {
1647 return;
1650 pCity = tile_city(ptile);
1651 n = unit_list_size(ptile->units);
1652 pFocus_Unit = head_of_units_in_focus();
1654 if (!n && !pCity && !pFocus_Unit) {
1655 popup_terrain_info_dialog(NULL, ptile);
1657 return;
1660 area.h = adj_size(2);
1661 is_unit_move_blocked = TRUE;
1663 pAdvanced_Terrain_Dlg = fc_calloc(1, sizeof(struct ADVANCED_DLG));
1665 pCont = fc_calloc(1, sizeof(struct CONTAINER));
1666 pCont->id0 = index_to_map_pos_x(tile_index(ptile));
1667 pCont->id1 = index_to_map_pos_y(tile_index(ptile));
1669 pstr = create_utf8_from_char(_("Advanced Menu") , adj_font(12));
1670 pstr->style |= TTF_STYLE_BOLD;
1672 pWindow = create_window_skeleton(NULL, pstr, 0);
1674 pWindow->action = advanced_terrain_window_dlg_callback;
1675 set_wstate(pWindow , FC_WS_NORMAL);
1677 add_to_gui_list(ID_TERRAIN_ADV_DLG_WINDOW, pWindow);
1678 pAdvanced_Terrain_Dlg->pEndWidgetList = pWindow;
1680 area = pWindow->area;
1682 /* ---------- */
1683 /* exit button */
1684 pBuf = create_themeicon(current_theme->Small_CANCEL_Icon, pWindow->dst,
1685 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
1686 pBuf->info_label = create_utf8_from_char(_("Close Dialog (Esc)"),
1687 adj_font(12));
1688 area.w += pBuf->size.w + adj_size(10);
1689 pBuf->action = exit_advanced_terrain_dlg_callback;
1690 set_wstate(pBuf, FC_WS_NORMAL);
1691 pBuf->key = SDLK_ESCAPE;
1693 add_to_gui_list(ID_TERRAIN_ADV_DLG_EXIT_BUTTON, pBuf);
1694 /* ---------- */
1696 pstr = create_utf8_from_char(_("Terrain Info") , adj_font(10));
1697 pstr->style |= TTF_STYLE_BOLD;
1699 pBuf = create_iconlabel(NULL, pWindow->dst, pstr,
1700 (WF_RESTORE_BACKGROUND|WF_DRAW_TEXT_LABEL_WITH_SPACE|WF_FREE_DATA));
1702 pBuf->string_utf8->bgcol = (SDL_Color) {0, 0, 0, 0};
1704 pBuf->data.cont = pCont;
1706 pBuf->action = terrain_info_callback;
1707 set_wstate(pBuf, FC_WS_NORMAL);
1709 add_to_gui_list(ID_LABEL, pBuf);
1711 area.w = MAX(area.w, pBuf->size.w);
1712 area.h += pBuf->size.h;
1714 /* ---------- */
1715 if (pCity && city_owner(pCity) == client.conn.playing) {
1716 /* separator */
1717 pBuf = create_iconlabel(NULL, pWindow->dst, NULL, WF_FREE_THEME);
1719 add_to_gui_list(ID_SEPARATOR, pBuf);
1720 area.h += pBuf->next->size.h;
1721 /* ------------------ */
1723 fc_snprintf(cBuf, sizeof(cBuf), _("Zoom to : %s"), city_name_get(pCity));
1725 create_active_iconlabel(pBuf, pWindow->dst,
1726 pstr, cBuf, zoom_to_city_callback);
1727 pBuf->data.city = pCity;
1728 set_wstate(pBuf, FC_WS_NORMAL);
1730 add_to_gui_list(ID_LABEL, pBuf);
1732 area.w = MAX(area.w, pBuf->size.w);
1733 area.h += pBuf->size.h;
1734 /* ----------- */
1736 create_active_iconlabel(pBuf, pWindow->dst, pstr,
1737 _("Change Production"), change_production_callback);
1739 pBuf->data.city = pCity;
1740 set_wstate(pBuf, FC_WS_NORMAL);
1742 add_to_gui_list(ID_LABEL, pBuf);
1744 area.w = MAX(area.w, pBuf->size.w);
1745 area.h += pBuf->size.h;
1746 /* -------------- */
1748 create_active_iconlabel(pBuf, pWindow->dst, pstr,
1749 _("Hurry production"), hurry_production_callback);
1751 pBuf->data.city = pCity;
1752 set_wstate(pBuf, FC_WS_NORMAL);
1754 add_to_gui_list(ID_LABEL, pBuf);
1756 area.w = MAX(area.w, pBuf->size.w);
1757 area.h += pBuf->size.h;
1758 /* ----------- */
1760 create_active_iconlabel(pBuf, pWindow->dst, pstr,
1761 _("Change City Governor settings"), cma_callback);
1763 pBuf->data.city = pCity;
1764 set_wstate(pBuf, FC_WS_NORMAL);
1766 add_to_gui_list(ID_LABEL, pBuf);
1768 area.w = MAX(area.w, pBuf->size.w);
1769 area.h += pBuf->size.h;
1771 /* ---------- */
1773 if (pFocus_Unit
1774 && (tile_index(unit_tile(pFocus_Unit)) != tile_index(ptile))) {
1775 /* separator */
1776 pBuf = create_iconlabel(NULL, pWindow->dst, NULL, WF_FREE_THEME);
1778 add_to_gui_list(ID_SEPARATOR, pBuf);
1779 area.h += pBuf->next->size.h;
1780 /* ------------------ */
1782 create_active_iconlabel(pBuf, pWindow->dst, pstr, _("Goto here"),
1783 goto_here_callback);
1784 pBuf->data.cont = pCont;
1785 set_wstate(pBuf, FC_WS_NORMAL);
1787 add_to_gui_list(MAX_ID - 1000 - pFocus_Unit->id, pBuf);
1789 area.w = MAX(area.w, pBuf->size.w);
1790 area.h += pBuf->size.h;
1791 /* ----------- */
1793 create_active_iconlabel(pBuf, pWindow->dst, pstr, _("Patrol here"),
1794 patrol_here_callback);
1795 pBuf->data.cont = pCont;
1796 set_wstate(pBuf, FC_WS_NORMAL);
1798 add_to_gui_list(MAX_ID - 1000 - pFocus_Unit->id, pBuf);
1800 area.w = MAX(area.w, pBuf->size.w);
1801 area.h += pBuf->size.h;
1802 /* ----------- */
1804 #if 0 /* FIXME: specific connect buttons */
1805 if (unit_has_type_flag(pFocus_Unit, F_SETTLERS)) {
1806 create_active_iconlabel(pBuf, pWindow->dst->surface, pstr, _("Connect here"),
1807 connect_here_callback);
1808 pBuf->data.cont = pCont;
1809 set_wstate(pBuf, FC_WS_NORMAL);
1811 add_to_gui_list(ID_LABEL, pBuf);
1813 area.w = MAX(area.w, pBuf->size.w);
1814 area.h += pBuf->size.h;
1816 #endif /* 0 */
1818 /* FIXME: This logic seems to try to mirror do_paradrop() why? */
1819 if (can_unit_paradrop(pFocus_Unit) && client_tile_get_known(ptile)
1820 && !(((pCity && pplayers_non_attack(client.conn.playing, city_owner(pCity)))
1821 || is_non_attack_unit_tile(ptile, client.conn.playing)))
1822 && (unit_type_get(pFocus_Unit)->paratroopers_range >=
1823 real_map_distance(unit_tile(pFocus_Unit), ptile))) {
1825 create_active_iconlabel(pBuf, pWindow->dst, pstr, _("Paradrop here"),
1826 paradrop_here_callback);
1827 pBuf->data.cont = pCont;
1828 set_wstate(pBuf, FC_WS_NORMAL);
1830 add_to_gui_list(ID_LABEL, pBuf);
1832 area.w = MAX(area.w, pBuf->size.w);
1833 area.h += pBuf->size.h;
1837 pAdvanced_Terrain_Dlg->pBeginWidgetList = pBuf;
1839 /* ---------- */
1840 if (n) {
1841 int i;
1842 struct unit *pUnit;
1843 struct unit_type *pUnitType = NULL;
1845 units_h = 0;
1846 /* separator */
1847 pBuf = create_iconlabel(NULL, pWindow->dst, NULL, WF_FREE_THEME);
1849 add_to_gui_list(ID_SEPARATOR, pBuf);
1850 area.h += pBuf->next->size.h;
1851 /* ---------- */
1852 if (n > 1) {
1853 struct unit *pDefender, *pAttacker;
1854 struct widget *pLast = pBuf;
1855 bool reset = FALSE;
1856 int my_units = 0;
1857 const char *vetname;
1859 #define ADV_NUM_SEEN 15
1861 pDefender = (pFocus_Unit ? get_defender(pFocus_Unit, ptile) : NULL);
1862 pAttacker = (pFocus_Unit ? get_attacker(pFocus_Unit, ptile) : NULL);
1863 for (i = 0; i < n; i++) {
1864 pUnit = unit_list_get(ptile->units, i);
1865 if (pUnit == pFocus_Unit) {
1866 continue;
1868 pUnitType = unit_type_get(pUnit);
1869 vetname = utype_veteran_name_translation(pUnitType, pUnit->veteran);
1871 if (unit_owner(pUnit) == client.conn.playing) {
1872 fc_snprintf(cBuf, sizeof(cBuf),
1873 _("Activate %s (%d / %d) %s (%d,%d,%s) %s"),
1874 (vetname != NULL ? vetname : ""),
1875 pUnit->hp, pUnitType->hp,
1876 utype_name_translation(pUnitType),
1877 pUnitType->attack_strength,
1878 pUnitType->defense_strength,
1879 move_points_text(pUnitType->move_rate, FALSE),
1880 unit_activity_text(pUnit));
1882 create_active_iconlabel(pBuf, pWindow->dst, pstr,
1883 cBuf, adv_unit_select_callback);
1884 pBuf->data.unit = pUnit;
1885 set_wstate(pBuf, FC_WS_NORMAL);
1886 add_to_gui_list(ID_LABEL, pBuf);
1887 my_units++;
1888 } else {
1889 int att_chance, def_chance;
1891 fc_snprintf(cBuf, sizeof(cBuf), _("%s %s %s (A:%d D:%d M:%s FP:%d) HP:%d%%"),
1892 nation_adjective_for_player(unit_owner(pUnit)),
1893 (vetname != NULL ? vetname : ""),
1894 utype_name_translation(pUnitType),
1895 pUnitType->attack_strength,
1896 pUnitType->defense_strength,
1897 move_points_text(pUnitType->move_rate, FALSE),
1898 pUnitType->firepower,
1899 ((pUnit->hp * 100) / pUnitType->hp));
1901 /* calculate chance to win */
1902 if (sdl_get_chance_to_win(&att_chance, &def_chance, pUnit, pFocus_Unit)) {
1903 /* TRANS: "CtW" = "Chance to Win" */
1904 cat_snprintf(cBuf, sizeof(cBuf), _(" CtW: Att:%d%% Def:%d%%"),
1905 att_chance, def_chance);
1908 if (pAttacker && pAttacker == pUnit) {
1909 pstr->fgcol = *(get_game_color(COLOR_OVERVIEW_ENEMY_UNIT));
1910 reset = TRUE;
1911 } else {
1912 if (pDefender && pDefender == pUnit) {
1913 pstr->fgcol = *(get_game_color(COLOR_OVERVIEW_MY_UNIT));
1914 reset = TRUE;
1918 create_active_iconlabel(pBuf, pWindow->dst, pstr, cBuf, NULL);
1920 if (reset) {
1921 pstr->fgcol = *get_theme_color(COLOR_THEME_ADVANCEDTERRAINDLG_TEXT);
1922 reset = FALSE;
1925 add_to_gui_list(ID_LABEL, pBuf);
1928 area.w = MAX(area.w, pBuf->size.w);
1929 units_h += pBuf->size.h;
1931 if (i > ADV_NUM_SEEN - 1) {
1932 set_wflag(pBuf, WF_HIDDEN);
1936 pAdvanced_Terrain_Dlg->pEndActiveWidgetList = pLast->prev;
1937 pAdvanced_Terrain_Dlg->pActiveWidgetList = pAdvanced_Terrain_Dlg->pEndActiveWidgetList;
1938 pAdvanced_Terrain_Dlg->pBeginWidgetList = pBuf;
1939 pAdvanced_Terrain_Dlg->pBeginActiveWidgetList = pAdvanced_Terrain_Dlg->pBeginWidgetList;
1941 if (n > ADV_NUM_SEEN) {
1942 units_h = ADV_NUM_SEEN * pBuf->size.h;
1943 n = create_vertical_scrollbar(pAdvanced_Terrain_Dlg,
1944 1, ADV_NUM_SEEN, TRUE, TRUE);
1945 area.w += n;
1948 if (my_units > 1) {
1949 fc_snprintf(cBuf, sizeof(cBuf), "%s (%d)", _("Ready all"), my_units);
1950 create_active_iconlabel(pBuf, pWindow->dst, pstr,
1951 cBuf, adv_unit_select_all_callback);
1952 pBuf->data.unit = pAdvanced_Terrain_Dlg->pEndActiveWidgetList->data.unit;
1953 set_wstate(pBuf, FC_WS_NORMAL);
1954 pBuf->ID = ID_LABEL;
1955 DownAdd(pBuf, pLast);
1956 area.h += pBuf->size.h;
1958 fc_snprintf(cBuf, sizeof(cBuf), "%s (%d)", _("Sentry idle"), my_units);
1959 create_active_iconlabel(pBuf, pWindow->dst, pstr,
1960 cBuf, adv_unit_sentry_idle_callback);
1961 pBuf->data.unit = pAdvanced_Terrain_Dlg->pEndActiveWidgetList->data.unit;
1962 set_wstate(pBuf, FC_WS_NORMAL);
1963 pBuf->ID = ID_LABEL;
1964 DownAdd(pBuf, pLast->prev);
1965 area.h += pBuf->size.h;
1967 /* separator */
1968 pBuf = create_iconlabel(NULL, pWindow->dst, NULL, WF_FREE_THEME);
1969 pBuf->ID = ID_SEPARATOR;
1970 DownAdd(pBuf, pLast->prev->prev);
1971 area.h += pBuf->next->size.h;
1973 #undef ADV_NUM_SEEN
1974 } else { /* n == 1 */
1975 /* one unit - give orders */
1976 pUnit = unit_list_get(ptile->units, 0);
1977 pUnitType = unit_type_get(pUnit);
1978 if (pUnit != pFocus_Unit) {
1979 const char *vetname;
1981 vetname = utype_veteran_name_translation(pUnitType, pUnit->veteran);
1982 if ((pCity && city_owner(pCity) == client.conn.playing)
1983 || (unit_owner(pUnit) == client.conn.playing)) {
1984 fc_snprintf(cBuf, sizeof(cBuf),
1985 _("Activate %s (%d / %d) %s (%d,%d,%s) %s"),
1986 (vetname != NULL ? vetname : ""),
1987 pUnit->hp, pUnitType->hp,
1988 utype_name_translation(pUnitType),
1989 pUnitType->attack_strength,
1990 pUnitType->defense_strength,
1991 move_points_text(pUnitType->move_rate, FALSE),
1992 unit_activity_text(pUnit));
1994 create_active_iconlabel(pBuf, pWindow->dst, pstr,
1995 cBuf, adv_unit_select_callback);
1996 pBuf->data.unit = pUnit;
1997 set_wstate(pBuf, FC_WS_NORMAL);
1999 add_to_gui_list(ID_LABEL, pBuf);
2001 area.w = MAX(area.w, pBuf->size.w);
2002 units_h += pBuf->size.h;
2003 /* ---------------- */
2004 /* separator */
2005 pBuf = create_iconlabel(NULL, pWindow->dst, NULL, WF_FREE_THEME);
2007 add_to_gui_list(ID_SEPARATOR, pBuf);
2008 area.h += pBuf->next->size.h;
2009 } else {
2010 int att_chance, def_chance;
2012 fc_snprintf(cBuf, sizeof(cBuf), _("%s %s %s (A:%d D:%d M:%s FP:%d) HP:%d%%"),
2013 nation_adjective_for_player(unit_owner(pUnit)),
2014 (vetname != NULL ? vetname : ""),
2015 utype_name_translation(pUnitType),
2016 pUnitType->attack_strength,
2017 pUnitType->defense_strength,
2018 move_points_text(pUnitType->move_rate, FALSE),
2019 pUnitType->firepower,
2020 ((pUnit->hp * 100) / pUnitType->hp));
2022 /* calculate chance to win */
2023 if (sdl_get_chance_to_win(&att_chance, &def_chance, pUnit, pFocus_Unit)) {
2024 cat_snprintf(cBuf, sizeof(cBuf), _(" CtW: Att:%d%% Def:%d%%"),
2025 att_chance, def_chance);
2027 create_active_iconlabel(pBuf, pWindow->dst, pstr, cBuf, NULL);
2028 add_to_gui_list(ID_LABEL, pBuf);
2029 area.w = MAX(area.w, pBuf->size.w);
2030 units_h += pBuf->size.h;
2031 /* ---------------- */
2033 /* separator */
2034 pBuf = create_iconlabel(NULL, pWindow->dst, NULL, WF_FREE_THEME);
2036 add_to_gui_list(ID_SEPARATOR, pBuf);
2037 area.h += pBuf->next->size.h;
2040 /* ---------------- */
2041 fc_snprintf(cBuf, sizeof(cBuf),
2042 _("Look up \"%s\" in the Help Browser"),
2043 utype_name_translation(pUnitType));
2044 create_active_iconlabel(pBuf, pWindow->dst, pstr,
2045 cBuf, unit_help_callback);
2046 set_wstate(pBuf , FC_WS_NORMAL);
2047 add_to_gui_list(MAX_ID - utype_number(pUnitType), pBuf);
2049 area.w = MAX(area.w, pBuf->size.w);
2050 units_h += pBuf->size.h;
2051 /* ---------------- */
2052 pAdvanced_Terrain_Dlg->pBeginWidgetList = pBuf;
2056 /* ---------- */
2058 area.w += adj_size(2);
2059 area.h += units_h;
2061 resize_window(pWindow, NULL, NULL,
2062 (pWindow->size.w - pWindow->area.w) + area.w,
2063 (pWindow->size.h - pWindow->area.h) + area.h);
2065 area = pWindow->area;
2067 widget_set_position(pWindow, pos_x, pos_y);
2069 w = area.w - adj_size(2);
2071 if (pAdvanced_Terrain_Dlg->pScroll) {
2072 units_h = n;
2073 } else {
2074 units_h = 0;
2077 /* exit button */
2078 pBuf = pWindow->prev;
2080 pBuf->size.x = area.x + area.w - pBuf->size.w - 1;
2081 pBuf->size.y = pWindow->size.y + adj_size(2);
2083 /* terrain info */
2084 pBuf = pBuf->prev;
2086 pBuf->size.x = area.x + 1;
2087 pBuf->size.y = area.y + 1;
2088 pBuf->size.w = w;
2089 h = pBuf->size.h;
2091 area2.x = adj_size(10);
2092 area2.h = adj_size(2);
2094 pBuf = pBuf->prev;
2095 while (pBuf) {
2096 if (pBuf == pAdvanced_Terrain_Dlg->pEndActiveWidgetList) {
2097 w -= units_h;
2100 pBuf->size.w = w;
2101 pBuf->size.x = pBuf->next->size.x;
2102 pBuf->size.y = pBuf->next->size.y + pBuf->next->size.h;
2104 if (pBuf->ID == ID_SEPARATOR) {
2105 FREESURFACE(pBuf->theme);
2106 pBuf->size.h = h;
2107 pBuf->theme = create_surf(w , h , SDL_SWSURFACE);
2109 area2.y = pBuf->size.h / 2 - 1;
2110 area2.w = pBuf->size.w - adj_size(20);
2112 SDL_FillRect(pBuf->theme, &area2, map_rgba(pBuf->theme->format,
2113 *get_theme_color(COLOR_THEME_ADVANCEDTERRAINDLG_TEXT)));
2116 if (pBuf == pAdvanced_Terrain_Dlg->pBeginWidgetList
2117 || pBuf == pAdvanced_Terrain_Dlg->pBeginActiveWidgetList) {
2118 break;
2120 pBuf = pBuf->prev;
2123 if (pAdvanced_Terrain_Dlg->pScroll) {
2124 setup_vertical_scrollbar_area(pAdvanced_Terrain_Dlg->pScroll,
2125 area.x + area.w,
2126 pAdvanced_Terrain_Dlg->pEndActiveWidgetList->size.y,
2127 area.y - pAdvanced_Terrain_Dlg->pEndActiveWidgetList->size.y + area.h,
2128 TRUE);
2131 /* -------------------- */
2132 /* redraw */
2133 redraw_group(pAdvanced_Terrain_Dlg->pBeginWidgetList, pWindow, 0);
2135 widget_flush(pWindow);
2138 /* ====================================================================== */
2139 /* ============================ PILLAGE DIALOG ========================== */
2140 /* ====================================================================== */
2141 static struct SMALL_DLG *pPillage_Dlg = NULL;
2143 /**************************************************************************
2144 User interacted with pillage dialog.
2145 **************************************************************************/
2146 static int pillage_window_callback(struct widget *pWindow)
2148 if (Main.event.button.button == SDL_BUTTON_LEFT) {
2149 move_window_group(pPillage_Dlg->pBeginWidgetList, pWindow);
2151 return -1;
2154 /**************************************************************************
2155 User selected what to pillage.
2156 **************************************************************************/
2157 static int pillage_callback(struct widget *pWidget)
2159 if (Main.event.button.button == SDL_BUTTON_LEFT) {
2160 struct unit *pUnit = pWidget->data.unit;
2161 int what = MAX_ID - pWidget->ID;
2163 popdown_pillage_dialog();
2165 if (pUnit) {
2166 struct extra_type *target = extra_by_number(what);
2168 request_new_unit_activity_targeted(pUnit, ACTIVITY_PILLAGE, target);
2171 return -1;
2174 /**************************************************************************
2175 User requested closing of pillage dialog.
2176 **************************************************************************/
2177 static int exit_pillage_dlg_callback(struct widget *pWidget)
2179 if (Main.event.button.button == SDL_BUTTON_LEFT) {
2180 popdown_pillage_dialog();
2182 return -1;
2185 /**************************************************************************
2186 Popdown a dialog asking the unit which improvement they would like to
2187 pillage.
2188 **************************************************************************/
2189 static void popdown_pillage_dialog(void)
2191 if (pPillage_Dlg) {
2192 is_unit_move_blocked = FALSE;
2193 popdown_window_group_dialog(pPillage_Dlg->pBeginWidgetList,
2194 pPillage_Dlg->pEndWidgetList);
2195 FC_FREE(pPillage_Dlg);
2196 flush_dirty();
2200 /**************************************************************************
2201 Popup a dialog asking the unit which improvement they would like to
2202 pillage.
2203 **************************************************************************/
2204 void popup_pillage_dialog(struct unit *pUnit, bv_extras extras)
2206 struct widget *pWindow = NULL, *pBuf = NULL;
2207 utf8_str *pstr;
2208 SDL_Rect area;
2209 struct extra_type *tgt;
2211 if (pPillage_Dlg) {
2212 return;
2215 is_unit_move_blocked = TRUE;
2216 pPillage_Dlg = fc_calloc(1, sizeof(struct SMALL_DLG));
2218 /* window */
2219 pstr = create_utf8_from_char(_("What To Pillage") , adj_font(12));
2220 pstr->style |= TTF_STYLE_BOLD;
2222 pWindow = create_window_skeleton(NULL, pstr, 0);
2224 pWindow->action = pillage_window_callback;
2225 set_wstate(pWindow, FC_WS_NORMAL);
2227 add_to_gui_list(ID_PILLAGE_DLG_WINDOW, pWindow);
2228 pPillage_Dlg->pEndWidgetList = pWindow;
2230 area = pWindow->area;
2232 area.h = MAX(area.h, adj_size(2));
2234 /* ---------- */
2235 /* exit button */
2236 pBuf = create_themeicon(current_theme->Small_CANCEL_Icon, pWindow->dst,
2237 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
2238 pBuf->info_label = create_utf8_from_char(_("Close Dialog (Esc)"),
2239 adj_font(12));
2240 area.w += pBuf->size.w + adj_size(10);
2241 pBuf->action = exit_pillage_dlg_callback;
2242 set_wstate(pBuf, FC_WS_NORMAL);
2243 pBuf->key = SDLK_ESCAPE;
2245 add_to_gui_list(ID_PILLAGE_DLG_EXIT_BUTTON, pBuf);
2246 /* ---------- */
2248 while ((tgt = get_preferred_pillage(extras))) {
2249 const char *name = NULL;
2250 int what;
2252 BV_CLR(extras, extra_index(tgt));
2253 name = extra_name_translation(tgt);
2254 what = extra_index(tgt);
2256 fc_assert(name != NULL);
2258 create_active_iconlabel(pBuf, pWindow->dst, pstr,
2259 (char *) name, pillage_callback);
2261 pBuf->data.unit = pUnit;
2262 set_wstate(pBuf, FC_WS_NORMAL);
2264 add_to_gui_list(MAX_ID - what, pBuf);
2266 area.w = MAX(area.w, pBuf->size.w);
2267 area.h += pBuf->size.h;
2269 pPillage_Dlg->pBeginWidgetList = pBuf;
2271 /* setup window size and start position */
2273 resize_window(pWindow, NULL, NULL,
2274 (pWindow->size.w - pWindow->area.w) + area.w,
2275 (pWindow->size.h - pWindow->area.h) + area.h);
2277 area = pWindow->area;
2279 put_window_near_map_tile(pWindow, pWindow->size.w, pWindow->size.h,
2280 unit_tile(pUnit));
2282 /* setup widget size and start position */
2284 /* exit button */
2285 pBuf = pWindow->prev;
2286 pBuf->size.x = area.x + area.w - pBuf->size.w - 1;
2287 pBuf->size.y = pWindow->size.y + adj_size(2);
2289 /* first special to pillage */
2290 pBuf = pBuf->prev;
2291 setup_vertical_widgets_position(1,
2292 area.x, area.y + 1, area.w, 0,
2293 pPillage_Dlg->pBeginWidgetList, pBuf);
2295 /* --------------------- */
2296 /* redraw */
2297 redraw_group(pPillage_Dlg->pBeginWidgetList, pWindow, 0);
2299 widget_flush(pWindow);
2302 /* ======================================================================= */
2303 /* =========================== CONNECT DIALOG ============================ */
2304 /* ======================================================================= */
2305 static struct SMALL_DLG *pConnect_Dlg = NULL;
2307 /**************************************************************************
2308 Popdown a dialog asking the unit how they want to "connect" their
2309 location to the destination.
2310 **************************************************************************/
2311 static void popdown_connect_dialog(void)
2313 if (pConnect_Dlg) {
2314 is_unit_move_blocked = FALSE;
2315 popdown_window_group_dialog(pConnect_Dlg->pBeginWidgetList,
2316 pConnect_Dlg->pEndWidgetList);
2317 FC_FREE(pConnect_Dlg);
2321 /**************************************************************************
2322 Revolutions
2323 **************************************************************************/
2324 static struct SMALL_DLG *pRevolutionDlg = NULL;
2326 /**************************************************************************
2327 User confirmed revolution.
2328 **************************************************************************/
2329 static int revolution_dlg_ok_callback(struct widget *pButton)
2331 if (Main.event.button.button == SDL_BUTTON_LEFT) {
2332 start_revolution();
2334 popdown_revolution_dialog();
2336 flush_dirty();
2338 return (-1);
2341 /**************************************************************************
2342 User cancelled revolution.
2343 **************************************************************************/
2344 static int revolution_dlg_cancel_callback(struct widget *pCancel_Button)
2346 if (Main.event.button.button == SDL_BUTTON_LEFT) {
2347 popdown_revolution_dialog();
2348 flush_dirty();
2350 return (-1);
2353 /**************************************************************************
2354 User requested move of revolution dialog.
2355 **************************************************************************/
2356 static int move_revolution_dlg_callback(struct widget *pWindow)
2358 if (Main.event.button.button == SDL_BUTTON_LEFT) {
2359 move_window_group(pRevolutionDlg->pBeginWidgetList, pWindow);
2361 return -1;
2364 /**************************************************************************
2365 Close the revolution dialog.
2366 **************************************************************************/
2367 static void popdown_revolution_dialog(void)
2369 if (pRevolutionDlg) {
2370 popdown_window_group_dialog(pRevolutionDlg->pBeginWidgetList,
2371 pRevolutionDlg->pEndWidgetList);
2372 FC_FREE(pRevolutionDlg);
2373 enable_and_redraw_revolution_button();
2377 /* ==================== Public ========================= */
2379 /**************************************************************************
2380 Select Goverment Type
2381 **************************************************************************/
2382 static struct SMALL_DLG *pGov_Dlg = NULL;
2384 /**************************************************************************
2385 Close the government dialog.
2386 **************************************************************************/
2387 static void popdown_government_dialog(void)
2389 if (pGov_Dlg) {
2390 popdown_window_group_dialog(pGov_Dlg->pBeginWidgetList,
2391 pGov_Dlg->pEndWidgetList);
2392 FC_FREE(pGov_Dlg);
2393 enable_and_redraw_revolution_button();
2397 /**************************************************************************
2398 User selected government button.
2399 **************************************************************************/
2400 static int government_dlg_callback(struct widget *pGov_Button)
2402 if (Main.event.button.button == SDL_BUTTON_LEFT) {
2403 set_government_choice(government_by_number(MAX_ID - pGov_Button->ID));
2405 popdown_government_dialog();
2407 return (-1);
2410 /**************************************************************************
2411 User requested move of government dialog.
2412 **************************************************************************/
2413 static int move_government_dlg_callback(struct widget *pWindow)
2415 if (Main.event.button.button == SDL_BUTTON_LEFT) {
2416 move_window_group(pGov_Dlg->pBeginWidgetList, pWindow);
2418 return -1;
2421 /**************************************************************************
2422 Public -
2424 Popup a dialog asking the player what government to switch to (this
2425 happens after a revolution completes).
2426 **************************************************************************/
2427 static void popup_government_dialog(void)
2429 SDL_Surface *pLogo = NULL;
2430 struct utf8_str *pstr = NULL;
2431 struct widget *pGov_Button = NULL;
2432 struct widget *pWindow = NULL;
2433 int j;
2434 Uint16 max_w = 0, max_h = 0;
2435 SDL_Rect area;
2437 if (pGov_Dlg) {
2438 return;
2441 pGov_Dlg = fc_calloc(1, sizeof(struct SMALL_DLG));
2443 /* create window */
2444 pstr = create_utf8_from_char(_("Choose Your New Government"), adj_font(12));
2445 pstr->style |= TTF_STYLE_BOLD;
2446 /* this win. size is temp. */
2447 pWindow = create_window_skeleton(NULL, pstr, 0);
2448 pWindow->action = move_government_dlg_callback;
2449 add_to_gui_list(ID_GOVERNMENT_DLG_WINDOW, pWindow);
2451 pGov_Dlg->pEndWidgetList = pWindow;
2453 area = pWindow->area;
2455 /* create gov. buttons */
2456 j = 0;
2457 governments_iterate(pGov) {
2458 if (pGov == game.government_during_revolution) {
2459 continue;
2462 if (can_change_to_government(client.conn.playing, pGov)) {
2463 pstr = create_utf8_from_char(government_name_translation(pGov), adj_font(12));
2464 pGov_Button =
2465 create_icon_button(get_government_surface(pGov), pWindow->dst, pstr, 0);
2466 pGov_Button->action = government_dlg_callback;
2468 max_w = MAX(max_w, pGov_Button->size.w);
2469 max_h = MAX(max_h, pGov_Button->size.h);
2471 /* ugly hack */
2472 add_to_gui_list((MAX_ID - government_number(pGov)), pGov_Button);
2473 j++;
2476 } governments_iterate_end;
2478 pGov_Dlg->pBeginWidgetList = pGov_Button;
2480 max_w += adj_size(10);
2481 max_h += adj_size(4);
2483 area.w = MAX(area.w, max_w + adj_size(20));
2484 area.h = MAX(area.h, j * (max_h + adj_size(10)) + adj_size(5));
2486 /* create window background */
2487 pLogo = theme_get_background(theme, BACKGROUND_CHOOSEGOVERNMENTDLG);
2488 if (resize_window(pWindow, pLogo, NULL,
2489 (pWindow->size.w - pWindow->area.w) + area.w,
2490 (pWindow->size.h - pWindow->area.h) + area.h)) {
2491 FREESURFACE(pLogo);
2494 area = pWindow->area;
2496 /* set window start positions */
2497 widget_set_position(pWindow,
2498 (main_window_width() - pWindow->size.w) / 2,
2499 (main_window_height() - pWindow->size.h) / 2);
2501 /* set buttons start positions and size */
2502 j = 1;
2503 while (pGov_Button != pGov_Dlg->pEndWidgetList) {
2504 pGov_Button->size.w = max_w;
2505 pGov_Button->size.h = max_h;
2506 pGov_Button->size.x = area.x + adj_size(10);
2507 pGov_Button->size.y = area.y + area.h - (j++) * (max_h + adj_size(10));
2508 set_wstate(pGov_Button, FC_WS_NORMAL);
2510 pGov_Button = pGov_Button->next;
2513 set_wstate(pWindow, FC_WS_NORMAL);
2515 /* redraw */
2516 redraw_group(pGov_Dlg->pBeginWidgetList, pWindow, 0);
2518 widget_flush(pWindow);
2521 /**************************************************************************
2522 Popup a dialog asking if the player wants to start a revolution.
2523 **************************************************************************/
2524 void popup_revolution_dialog(void)
2526 SDL_Surface *pLogo;
2527 utf8_str *pstr = NULL;
2528 struct widget *pLabel = NULL;
2529 struct widget *pWindow = NULL;
2530 struct widget *pCancel_Button = NULL;
2531 struct widget *pOK_Button = NULL;
2532 SDL_Rect area;
2534 if (pRevolutionDlg) {
2535 return;
2538 if (0 <= client.conn.playing->revolution_finishes) {
2539 popup_government_dialog();
2540 return;
2543 pRevolutionDlg = fc_calloc(1, sizeof(struct SMALL_DLG));
2545 pstr = create_utf8_from_char(_("REVOLUTION!"), adj_font(12));
2546 pstr->style |= TTF_STYLE_BOLD;
2548 pWindow = create_window_skeleton(NULL, pstr, 0);
2549 pWindow->action = move_revolution_dlg_callback;
2550 set_wstate(pWindow, FC_WS_NORMAL);
2551 add_to_gui_list(ID_REVOLUTION_DLG_WINDOW, pWindow);
2552 pRevolutionDlg->pEndWidgetList = pWindow;
2554 area = pWindow->area;
2556 /* create text label */
2557 pstr = create_utf8_from_char(_("You say you wanna revolution?"), adj_font(10));
2558 pstr->style |= (TTF_STYLE_BOLD|SF_CENTER);
2559 pstr->fgcol = *get_theme_color(COLOR_THEME_REVOLUTIONDLG_TEXT);
2560 pLabel = create_iconlabel(NULL, pWindow->dst, pstr, 0);
2561 add_to_gui_list(ID_REVOLUTION_DLG_LABEL, pLabel);
2563 /* create cancel button */
2564 pCancel_Button =
2565 create_themeicon_button_from_chars(current_theme->Small_CANCEL_Icon,
2566 pWindow->dst, _("Cancel"), adj_font(10), 0);
2567 pCancel_Button->action = revolution_dlg_cancel_callback;
2568 pCancel_Button->size.w += adj_size(6);
2569 set_wstate(pCancel_Button, FC_WS_NORMAL);
2570 add_to_gui_list(ID_REVOLUTION_DLG_CANCEL_BUTTON, pCancel_Button);
2572 /* create ok button */
2573 pOK_Button =
2574 create_themeicon_button_from_chars(current_theme->Small_OK_Icon,
2575 pWindow->dst, _("Revolution!"),
2576 adj_font(10), 0);
2577 pOK_Button->action = revolution_dlg_ok_callback;
2578 pOK_Button->key = SDLK_RETURN;
2579 set_wstate(pOK_Button, FC_WS_NORMAL);
2580 add_to_gui_list(ID_REVOLUTION_DLG_OK_BUTTON, pOK_Button);
2582 pRevolutionDlg->pBeginWidgetList = pOK_Button;
2584 if ((pOK_Button->size.w + pCancel_Button->size.w + adj_size(30)) >
2585 pLabel->size.w + adj_size(20)) {
2586 area.w = MAX(area.w, pOK_Button->size.w + pCancel_Button->size.w + adj_size(30));
2587 } else {
2588 area.w = MAX(area.w, pLabel->size.w + adj_size(20));
2591 area.h = MAX(area.h, pOK_Button->size.h + pLabel->size.h + adj_size(24));
2593 /* create window background */
2594 pLogo = theme_get_background(theme, BACKGROUND_REVOLUTIONDLG);
2595 if (resize_window(pWindow, pLogo, NULL,
2596 (pWindow->size.w - pWindow->area.w) + area.w,
2597 (pWindow->size.h - pWindow->area.h) + area.h)) {
2598 FREESURFACE(pLogo);
2601 area = pWindow->area;
2603 /* set start positions */
2604 widget_set_position(pWindow,
2605 (main_window_width() - pWindow->size.w) / 2,
2606 (main_window_height() - pWindow->size.h) / 2);
2608 pOK_Button->size.x = area.x + adj_size(10);
2609 pOK_Button->size.y = area.y + area.h - pOK_Button->size.h - adj_size(10);
2611 pCancel_Button->size.y = pOK_Button->size.y;
2612 pCancel_Button->size.x = area.x + area.w - pCancel_Button->size.w - adj_size(10);
2614 pLabel->size.x = area.x;
2615 pLabel->size.y = area.y + adj_size(4);
2616 pLabel->size.w = area.w;
2618 /* redraw */
2619 redraw_group(pOK_Button, pWindow, 0);
2620 widget_mark_dirty(pWindow);
2621 flush_dirty();
2624 /**************************************************************************
2625 Nation Wizard
2626 **************************************************************************/
2627 static struct ADVANCED_DLG *pNationDlg = NULL;
2628 static struct SMALL_DLG *pHelpDlg = NULL;
2630 struct NAT {
2631 unsigned char nation_style; /* selected style */
2632 unsigned char selected_leader; /* if not unique -> selected leader */
2633 Nation_type_id nation; /* selected nation */
2634 bool leader_sex; /* selected leader sex */
2635 struct nation_set *set;
2636 struct widget *pChange_Sex;
2637 struct widget *pName_Edit;
2638 struct widget *pName_Next;
2639 struct widget *pName_Prev;
2640 struct widget *pset_name;
2641 struct widget *pset_next;
2642 struct widget *pset_prev;
2645 static int next_set_callback(struct widget *next_button);
2646 static int prev_set_callback(struct widget *prev_button);
2647 static int nations_dialog_callback(struct widget *pWindow);
2648 static int nation_button_callback(struct widget *pNation);
2649 static int races_dialog_ok_callback(struct widget *pStart_Button);
2650 static int races_dialog_cancel_callback(struct widget *pButton);
2651 static int next_name_callback(struct widget *pNext_Button);
2652 static int prev_name_callback(struct widget *pPrev_Button);
2653 static int change_sex_callback(struct widget *pSex);
2654 static void select_random_leader(Nation_type_id nation);
2655 static void change_nation_label(void);
2657 /**************************************************************************
2658 User interacted with nations dialog.
2659 **************************************************************************/
2660 static int nations_dialog_callback(struct widget *pWindow)
2662 if (Main.event.button.button == SDL_BUTTON_LEFT) {
2663 if (select_window_group_dialog(pNationDlg->pBeginWidgetList, pWindow)) {
2664 widget_flush(pWindow);
2667 return -1;
2670 /**************************************************************************
2671 User accepted nation.
2672 **************************************************************************/
2673 static int races_dialog_ok_callback(struct widget *pStart_Button)
2675 if (Main.event.button.button == SDL_BUTTON_LEFT) {
2676 struct NAT *pSetup = (struct NAT *)(pNationDlg->pEndWidgetList->data.ptr);
2677 char *pstr = pSetup->pName_Edit->string_utf8->text;
2679 /* perform a minimum of sanity test on the name */
2680 if (strlen(pstr) == 0) {
2681 output_window_append(ftc_client, _("You must type a legal name."));
2682 selected_widget = pStart_Button;
2683 set_wstate(pStart_Button, FC_WS_SELECTED);
2684 widget_redraw(pStart_Button);
2685 widget_flush(pStart_Button);
2687 return (-1);
2690 dsend_packet_nation_select_req(&client.conn, player_number(races_player),
2691 pSetup->nation,
2692 pSetup->leader_sex, pstr,
2693 pSetup->nation_style);
2695 popdown_races_dialog();
2696 flush_dirty();
2699 return -1;
2702 /**************************************************************************
2703 User requested leader gender change.
2704 **************************************************************************/
2705 static int change_sex_callback(struct widget *pSex)
2707 if (Main.event.button.button == SDL_BUTTON_LEFT) {
2708 struct NAT *pSetup = (struct NAT *)(pNationDlg->pEndWidgetList->data.ptr);
2710 if (pSetup->leader_sex) {
2711 copy_chars_to_utf8_str(pSetup->pChange_Sex->string_utf8, _("Female"));
2712 } else {
2713 copy_chars_to_utf8_str(pSetup->pChange_Sex->string_utf8, _("Male"));
2715 pSetup->leader_sex = !pSetup->leader_sex;
2717 if (pSex) {
2718 selected_widget = pSex;
2719 set_wstate(pSex, FC_WS_SELECTED);
2721 widget_redraw(pSex);
2722 widget_flush(pSex);
2725 return -1;
2728 /**************************************************************************
2729 User requested next leader name.
2730 **************************************************************************/
2731 static int next_name_callback(struct widget *pNext)
2733 if (Main.event.button.button == SDL_BUTTON_LEFT) {
2734 struct NAT *pSetup = (struct NAT *)(pNationDlg->pEndWidgetList->data.ptr);
2735 const struct nation_leader_list *leaders =
2736 nation_leaders(nation_by_number(pSetup->nation));
2737 const struct nation_leader *pleader;
2739 pSetup->selected_leader++;
2740 pleader = nation_leader_list_get(leaders, pSetup->selected_leader);
2742 /* change leader sex */
2743 if (pSetup->leader_sex != nation_leader_is_male(pleader)) {
2744 change_sex_callback(NULL);
2747 /* change leader name */
2748 copy_chars_to_utf8_str(pSetup->pName_Edit->string_utf8,
2749 nation_leader_name(pleader));
2751 FC_FREE(pLeaderName);
2752 pLeaderName = fc_strdup(nation_leader_name(pleader));
2754 if (nation_leader_list_size(leaders) - 1 == pSetup->selected_leader) {
2755 set_wstate(pSetup->pName_Next, FC_WS_DISABLED);
2758 if (get_wstate(pSetup->pName_Prev) == FC_WS_DISABLED) {
2759 set_wstate(pSetup->pName_Prev, FC_WS_NORMAL);
2762 if (!(get_wstate(pSetup->pName_Next) == FC_WS_DISABLED)) {
2763 selected_widget = pSetup->pName_Next;
2764 set_wstate(pSetup->pName_Next, FC_WS_SELECTED);
2767 widget_redraw(pSetup->pName_Edit);
2768 widget_redraw(pSetup->pName_Prev);
2769 widget_redraw(pSetup->pName_Next);
2770 widget_mark_dirty(pSetup->pName_Edit);
2771 widget_mark_dirty(pSetup->pName_Prev);
2772 widget_mark_dirty(pSetup->pName_Next);
2774 widget_redraw(pSetup->pChange_Sex);
2775 widget_mark_dirty(pSetup->pChange_Sex);
2777 flush_dirty();
2779 return -1;
2782 /**************************************************************************
2783 User requested previous leader name.
2784 **************************************************************************/
2785 static int prev_name_callback(struct widget *pPrev)
2787 if (Main.event.button.button == SDL_BUTTON_LEFT) {
2788 struct NAT *pSetup = (struct NAT *)(pNationDlg->pEndWidgetList->data.ptr);
2789 const struct nation_leader_list *leaders =
2790 nation_leaders(nation_by_number(pSetup->nation));
2791 const struct nation_leader *pleader;
2793 pSetup->selected_leader--;
2794 pleader = nation_leader_list_get(leaders, pSetup->selected_leader);
2796 /* change leader sex */
2797 if (pSetup->leader_sex != nation_leader_is_male(pleader)) {
2798 change_sex_callback(NULL);
2801 /* change leader name */
2802 copy_chars_to_utf8_str(pSetup->pName_Edit->string_utf8,
2803 nation_leader_name(pleader));
2805 FC_FREE(pLeaderName);
2806 pLeaderName = fc_strdup(nation_leader_name(pleader));
2808 if (!pSetup->selected_leader) {
2809 set_wstate(pSetup->pName_Prev, FC_WS_DISABLED);
2812 if (get_wstate(pSetup->pName_Next) == FC_WS_DISABLED) {
2813 set_wstate(pSetup->pName_Next, FC_WS_NORMAL);
2816 if (!(get_wstate(pSetup->pName_Prev) == FC_WS_DISABLED)) {
2817 selected_widget = pSetup->pName_Prev;
2818 set_wstate(pSetup->pName_Prev, FC_WS_SELECTED);
2821 widget_redraw(pSetup->pName_Edit);
2822 widget_redraw(pSetup->pName_Prev);
2823 widget_redraw(pSetup->pName_Next);
2824 widget_mark_dirty(pSetup->pName_Edit);
2825 widget_mark_dirty(pSetup->pName_Prev);
2826 widget_mark_dirty(pSetup->pName_Next);
2828 widget_redraw(pSetup->pChange_Sex);
2829 widget_mark_dirty(pSetup->pChange_Sex);
2831 flush_dirty();
2833 return -1;
2836 /**************************************************************************
2837 User requested next nationset
2838 **************************************************************************/
2839 static int next_set_callback(struct widget *next_button)
2841 if (Main.event.button.button == SDL_BUTTON_LEFT) {
2842 struct NAT *pSetup = (struct NAT *)(pNationDlg->pEndWidgetList->data.ptr);
2843 struct option *poption = optset_option_by_name(server_optset, "nationset");
2845 fc_assert(pSetup->set != NULL
2846 && nation_set_index(pSetup->set) < nation_set_count() - 1);
2848 pSetup->set = nation_set_by_number(nation_set_index(pSetup->set) + 1);
2850 option_str_set(poption, nation_set_rule_name(pSetup->set));
2853 return -1;
2856 /**************************************************************************
2857 User requested prev nationset
2858 **************************************************************************/
2859 static int prev_set_callback(struct widget *prev_button)
2861 if (Main.event.button.button == SDL_BUTTON_LEFT) {
2862 struct NAT *pSetup = (struct NAT *)(pNationDlg->pEndWidgetList->data.ptr);
2863 struct option *poption = optset_option_by_name(server_optset, "nationset");
2865 fc_assert(pSetup->set != NULL && nation_set_index(pSetup->set) > 0);
2867 pSetup->set = nation_set_by_number(nation_set_index(pSetup->set) - 1);
2869 option_str_set(poption, nation_set_rule_name(pSetup->set));
2872 return -1;
2875 /**************************************************************************
2876 User cancelled nations dialog.
2877 **************************************************************************/
2878 static int races_dialog_cancel_callback(struct widget *pButton)
2880 if (Main.event.button.button == SDL_BUTTON_LEFT) {
2881 popdown_races_dialog();
2882 flush_dirty();
2884 return -1;
2887 /**************************************************************************
2888 User interacted with style widget.
2889 **************************************************************************/
2890 static int style_callback(struct widget *pWidget)
2892 if (Main.event.button.button == SDL_BUTTON_LEFT) {
2893 struct NAT *pSetup = (struct NAT *)(pNationDlg->pEndWidgetList->data.ptr);
2894 struct widget *pGUI = get_widget_pointer_form_main_list(MAX_ID - 1000 -
2895 pSetup->nation_style);
2897 set_wstate(pGUI, FC_WS_NORMAL);
2898 widget_redraw(pGUI);
2899 widget_mark_dirty(pGUI);
2901 set_wstate(pWidget, FC_WS_DISABLED);
2902 widget_redraw(pWidget);
2903 widget_mark_dirty(pWidget);
2905 pSetup->nation_style = MAX_ID - 1000 - pWidget->ID;
2907 flush_dirty();
2908 selected_widget = NULL;
2910 return -1;
2913 /**************************************************************************
2914 User interacted with help dialog.
2915 **************************************************************************/
2916 static int help_dlg_callback(struct widget *pWindow)
2918 return -1;
2921 /**************************************************************************
2922 User requested closing of help dialog.
2923 **************************************************************************/
2924 static int cancel_help_dlg_callback(struct widget *pWidget)
2926 if (Main.event.button.button == SDL_BUTTON_LEFT) {
2927 if (pHelpDlg) {
2928 popdown_window_group_dialog(pHelpDlg->pBeginWidgetList,
2929 pHelpDlg->pEndWidgetList);
2930 FC_FREE(pHelpDlg);
2931 if (pWidget) {
2932 flush_dirty();
2936 return -1;
2939 /**************************************************************************
2940 User selected nation.
2941 **************************************************************************/
2942 static int nation_button_callback(struct widget *pNationButton)
2944 set_wstate(pNationButton, FC_WS_SELECTED);
2945 selected_widget = pNationButton;
2947 if (Main.event.button.button == SDL_BUTTON_LEFT) {
2948 struct NAT *pSetup = (struct NAT *)(pNationDlg->pEndWidgetList->data.ptr);
2950 if (pSetup->nation == MAX_ID - pNationButton->ID) {
2951 widget_redraw(pNationButton);
2952 widget_flush(pNationButton);
2953 return -1;
2956 pSetup->nation = MAX_ID - pNationButton->ID;
2958 change_nation_label();
2960 enable(MAX_ID - 1000 - pSetup->nation_style);
2961 pSetup->nation_style = style_number(style_of_nation(nation_by_number(pSetup->nation)));
2962 disable(MAX_ID - 1000 - pSetup->nation_style);
2964 select_random_leader(pSetup->nation);
2966 redraw_group(pNationDlg->pBeginWidgetList, pNationDlg->pEndWidgetList, 0);
2967 widget_flush(pNationDlg->pEndWidgetList);
2968 } else {
2969 /* pop up nation description */
2970 struct widget *pWindow, *pOK_Button;
2971 utf8_str *pstr;
2972 SDL_Surface *pText;
2973 SDL_Rect area, area2;
2974 struct nation_type *pNation = nation_by_number(MAX_ID - pNationButton->ID);
2976 widget_redraw(pNationButton);
2977 widget_mark_dirty(pNationButton);
2979 if (!pHelpDlg) {
2980 pHelpDlg = fc_calloc(1, sizeof(struct SMALL_DLG));
2982 pstr = create_utf8_from_char(nation_plural_translation(pNation),
2983 adj_font(12));
2984 pstr->style |= TTF_STYLE_BOLD;
2986 pWindow = create_window_skeleton(NULL, pstr, 0);
2987 pWindow->action = help_dlg_callback;
2989 set_wstate(pWindow, FC_WS_NORMAL);
2991 pHelpDlg->pEndWidgetList = pWindow;
2992 add_to_gui_list(ID_WINDOW, pWindow);
2994 pOK_Button = create_themeicon_button_from_chars(current_theme->OK_Icon,
2995 pWindow->dst, _("OK"), adj_font(14), 0);
2996 pOK_Button->action = cancel_help_dlg_callback;
2997 set_wstate(pOK_Button, FC_WS_NORMAL);
2998 pOK_Button->key = SDLK_ESCAPE;
2999 add_to_gui_list(ID_BUTTON, pOK_Button);
3000 pHelpDlg->pBeginWidgetList = pOK_Button;
3001 } else {
3002 pWindow = pHelpDlg->pEndWidgetList;
3003 pOK_Button = pHelpDlg->pBeginWidgetList;
3004 /* undraw window */
3005 widget_undraw(pWindow);
3006 widget_mark_dirty(pWindow);
3009 area = pWindow->area;
3012 char info[4096];
3014 helptext_nation(info, sizeof(info), pNation, NULL);
3015 pstr = create_utf8_from_char(info, adj_font(12));
3018 pstr->fgcol = *get_theme_color(COLOR_THEME_NATIONDLG_LEGEND);
3019 pText = create_text_surf_smaller_than_w(pstr, main_window_width() - adj_size(20));
3021 FREEUTF8STR(pstr);
3023 /* create window background */
3024 area.w = MAX(area.w, pText->w + adj_size(20));
3025 area.w = MAX(area.w, pOK_Button->size.w + adj_size(20));
3026 area.h = MAX(area.h, adj_size(9) + pText->h
3027 + adj_size(10) + pOK_Button->size.h + adj_size(10));
3029 resize_window(pWindow, NULL, get_theme_color(COLOR_THEME_BACKGROUND),
3030 (pWindow->size.w - pWindow->area.w) + area.w,
3031 (pWindow->size.h - pWindow->area.h) + area.h);
3033 widget_set_position(pWindow,
3034 (main_window_width() - pWindow->size.w) / 2,
3035 (main_window_height() - pWindow->size.h) / 2);
3037 area2.x = area.x + adj_size(7);
3038 area2.y = area.y + adj_size(6);
3039 alphablit(pText, NULL, pWindow->theme, &area2, 255);
3040 FREESURFACE(pText);
3042 pOK_Button->size.x = area.x + (area.w - pOK_Button->size.w) / 2;
3043 pOK_Button->size.y = area.y + area.h - pOK_Button->size.h - adj_size(10);
3045 /* redraw */
3046 redraw_group(pOK_Button, pWindow, 0);
3048 widget_mark_dirty(pWindow);
3050 flush_dirty();
3053 return -1;
3056 /**************************************************************************
3057 User interacted with leader name edit widget.
3058 **************************************************************************/
3059 static int leader_name_edit_callback(struct widget *pEdit)
3061 if (Main.event.button.button == SDL_BUTTON_LEFT) {
3062 if (pEdit->string_utf8->text != NULL) {
3063 /* empty input -> restore previous content */
3064 copy_chars_to_utf8_str(pEdit->string_utf8, pLeaderName);
3065 widget_redraw(pEdit);
3066 widget_mark_dirty(pEdit);
3067 flush_dirty();
3071 return -1;
3073 /* =========================================================== */
3075 /**************************************************************************
3076 Update nation label.
3077 **************************************************************************/
3078 static void change_nation_label(void)
3080 SDL_Surface *pTmp_Surf, *pTmp_Surf_zoomed;
3081 struct widget *pWindow = pNationDlg->pEndWidgetList;
3082 struct NAT *pSetup = (struct NAT *)(pWindow->data.ptr);
3083 struct widget *pLabel = pSetup->pName_Edit->next;
3084 struct nation_type *pNation = nation_by_number(pSetup->nation);
3086 pTmp_Surf = get_nation_flag_surface(pNation);
3087 pTmp_Surf_zoomed = zoomSurface(pTmp_Surf, DEFAULT_ZOOM * 1.0, DEFAULT_ZOOM * 1.0, 1);
3089 FREESURFACE(pLabel->theme);
3090 pLabel->theme = pTmp_Surf_zoomed;
3092 copy_chars_to_utf8_str(pLabel->string_utf8, nation_plural_translation(pNation));
3094 remake_label_size(pLabel);
3096 pLabel->size.x = pWindow->size.x + pWindow->size.w / 2 +
3097 (pWindow->size.w/2 - pLabel->size.w) / 2;
3101 /**************************************************************************
3102 Selectes a leader and the appropriate sex. Updates the gui elements
3103 and the selected_* variables.
3104 **************************************************************************/
3105 static void select_random_leader(Nation_type_id nation)
3107 struct NAT *pSetup = (struct NAT *)(pNationDlg->pEndWidgetList->data.ptr);
3108 const struct nation_leader_list *leaders =
3109 nation_leaders(nation_by_number(pSetup->nation));
3110 const struct nation_leader *pleader;
3112 pSetup->selected_leader = fc_rand(nation_leader_list_size(leaders));
3113 pleader = nation_leader_list_get(leaders, pSetup->selected_leader);
3114 copy_chars_to_utf8_str(pSetup->pName_Edit->string_utf8,
3115 nation_leader_name(pleader));
3117 FC_FREE(pLeaderName);
3118 pLeaderName = fc_strdup(nation_leader_name(pleader));
3120 /* initialize leader sex */
3121 pSetup->leader_sex = nation_leader_is_male(pleader);
3123 if (pSetup->leader_sex) {
3124 copy_chars_to_utf8_str(pSetup->pChange_Sex->string_utf8, _("Male"));
3125 } else {
3126 copy_chars_to_utf8_str(pSetup->pChange_Sex->string_utf8, _("Female"));
3129 /* disable navigation buttons */
3130 set_wstate(pSetup->pName_Prev, FC_WS_DISABLED);
3131 set_wstate(pSetup->pName_Next, FC_WS_DISABLED);
3133 if (1 < nation_leader_list_size(leaders)) {
3134 /* if selected leader is not the first leader, enable "previous leader" button */
3135 if (pSetup->selected_leader > 0) {
3136 set_wstate(pSetup->pName_Prev, FC_WS_NORMAL);
3139 /* if selected leader is not the last leader, enable "next leader" button */
3140 if (pSetup->selected_leader < (nation_leader_list_size(leaders) - 1)) {
3141 set_wstate(pSetup->pName_Next, FC_WS_NORMAL);
3146 /**************************************************************************
3147 Count available playable nations.
3148 **************************************************************************/
3149 static int get_playable_nation_count(void)
3151 int playable_nation_count = 0;
3153 nations_iterate(pnation) {
3154 if (pnation->is_playable && !pnation->player
3155 && is_nation_pickable(pnation))
3156 playable_nation_count++;
3157 } nations_iterate_end;
3159 return playable_nation_count;
3162 /**************************************************************************
3163 Popup the nation selection dialog.
3164 **************************************************************************/
3165 void popup_races_dialog(struct player *pplayer)
3167 SDL_Color bg_color = {255,255,255,128};
3169 struct widget *pWindow, *pWidget = NULL, *pBuf, *pLast_City_Style;
3170 utf8_str *pstr;
3171 int len = 0;
3172 int w = adj_size(10), h = adj_size(10);
3173 SDL_Surface *pTmp_Surf, *pTmp_Surf_zoomed = NULL;
3174 SDL_Surface *pMain_Bg, *pText_Name, *pText_Class;
3175 SDL_Rect dst;
3176 float zoom;
3177 struct NAT *pSetup;
3178 SDL_Rect area;
3179 int i;
3180 struct nation_type *pnat;
3181 struct widget *nationsets = NULL;
3182 int natinfo_y, natinfo_h;
3184 #define TARGETS_ROW 5
3185 #define TARGETS_COL 1
3187 if (pNationDlg) {
3188 return;
3191 races_player = pplayer;
3193 pNationDlg = fc_calloc(1, sizeof(struct ADVANCED_DLG));
3195 /* create window widget */
3196 pstr = create_utf8_from_char(_("What nation will you be?"), adj_font(12));
3197 pstr->style |= TTF_STYLE_BOLD;
3199 pWindow = create_window(NULL, pstr, w, h, WF_FREE_DATA);
3200 pWindow->action = nations_dialog_callback;
3201 set_wstate(pWindow, FC_WS_NORMAL);
3202 pSetup = fc_calloc(1, sizeof(struct NAT));
3203 pWindow->data.ptr = (void *)pSetup;
3205 pNationDlg->pEndWidgetList = pWindow;
3206 add_to_gui_list(ID_NATION_WIZARD_WINDOW, pWindow);
3207 /* --------------------------------------------------------- */
3208 /* create nations list */
3210 /* Create Imprv Background Icon */
3211 pMain_Bg = create_surf(adj_size(96*2), adj_size(64), SDL_SWSURFACE);
3213 SDL_FillRect(pMain_Bg, NULL, map_rgba(pMain_Bg->format, bg_color));
3215 create_frame(pMain_Bg,
3216 0, 0, pMain_Bg->w - 1, pMain_Bg->h - 1,
3217 get_theme_color(COLOR_THEME_NATIONDLG_FRAME));
3219 pstr = create_utf8_str(NULL, 0, adj_font(12));
3220 pstr->style |= (SF_CENTER|TTF_STYLE_BOLD);
3221 pstr->bgcol = (SDL_Color) {0, 0, 0, 0};
3223 /* fill list */
3224 pText_Class = NULL;
3226 nations_iterate(pNation) {
3227 if (!is_nation_playable(pNation) || !is_nation_pickable(pNation)) {
3228 continue;
3231 pTmp_Surf_zoomed = adj_surf(get_nation_flag_surface(pNation));
3233 pTmp_Surf = crop_rect_from_surface(pMain_Bg, NULL);
3235 copy_chars_to_utf8_str(pstr, nation_plural_translation(pNation));
3236 change_ptsize_utf8(pstr, adj_font(12));
3237 pText_Name = create_text_surf_smaller_than_w(pstr, pTmp_Surf->w - adj_size(4));
3239 if (pNation->legend && *(pNation->legend) != '\0') {
3240 copy_chars_to_utf8_str(pstr, pNation->legend);
3241 change_ptsize_utf8(pstr, adj_font(10));
3242 pText_Class = create_text_surf_smaller_than_w(pstr, pTmp_Surf->w - adj_size(4));
3245 dst.x = (pTmp_Surf->w - pTmp_Surf_zoomed->w) / 2;
3246 len = pTmp_Surf_zoomed->h +
3247 adj_size(10) + pText_Name->h + (pText_Class ? pText_Class->h : 0);
3248 dst.y = (pTmp_Surf->h - len) / 2;
3249 alphablit(pTmp_Surf_zoomed, NULL, pTmp_Surf, &dst, 255);
3250 dst.y += (pTmp_Surf_zoomed->h + adj_size(10));
3252 dst.x = (pTmp_Surf->w - pText_Name->w) / 2;
3253 alphablit(pText_Name, NULL, pTmp_Surf, &dst, 255);
3254 dst.y += pText_Name->h;
3255 FREESURFACE(pText_Name);
3257 if (pText_Class) {
3258 dst.x = (pTmp_Surf->w - pText_Class->w) / 2;
3259 alphablit(pText_Class, NULL, pTmp_Surf, &dst, 255);
3260 FREESURFACE(pText_Class);
3263 pWidget = create_icon2(pTmp_Surf, pWindow->dst,
3264 (WF_RESTORE_BACKGROUND|WF_FREE_THEME));
3266 set_wstate(pWidget, FC_WS_NORMAL);
3268 pWidget->action = nation_button_callback;
3270 w = MAX(w, pWidget->size.w);
3271 h = MAX(h, pWidget->size.h);
3273 add_to_gui_list(MAX_ID - nation_index(pNation), pWidget);
3275 if (nation_index(pNation) > (TARGETS_ROW * TARGETS_COL - 1)) {
3276 set_wflag(pWidget, WF_HIDDEN);
3279 } nations_iterate_end;
3281 FREESURFACE(pMain_Bg);
3283 pNationDlg->pEndActiveWidgetList = pWindow->prev;
3284 pNationDlg->pBeginWidgetList = pWidget;
3285 pNationDlg->pBeginActiveWidgetList = pNationDlg->pBeginWidgetList;
3287 if (get_playable_nation_count() > TARGETS_ROW * TARGETS_COL) {
3288 pNationDlg->pActiveWidgetList = pNationDlg->pEndActiveWidgetList;
3289 create_vertical_scrollbar(pNationDlg,
3290 TARGETS_COL, TARGETS_ROW, TRUE, TRUE);
3293 /* ----------------------------------------------------------------- */
3295 /* nation set selection */
3296 if (nation_set_count() > 1) {
3297 utf8_str *natset_str;
3298 struct option *poption;
3300 natset_str = create_utf8_from_char(_("Nation set"), adj_font(12));
3301 change_ptsize_utf8(natset_str, adj_font(24));
3302 nationsets = create_iconlabel(NULL, pWindow->dst, natset_str, 0);
3303 add_to_gui_list(ID_LABEL, nationsets);
3305 /* create nation set name label */
3306 poption = optset_option_by_name(server_optset, "nationset");
3307 pSetup->set = nation_set_by_setting_value(option_str_get(poption));
3309 natset_str = create_utf8_from_char(nation_set_name_translation(pSetup->set),
3310 adj_font(12));
3311 change_ptsize_utf8(natset_str, adj_font(24));
3313 pWidget = create_iconlabel(NULL, pWindow->dst, natset_str, 0);
3315 add_to_gui_list(ID_LABEL, pWidget);
3316 pSetup->pset_name = pWidget;
3318 /* create next nationset button */
3319 pWidget = create_themeicon_button(current_theme->R_ARROW_Icon,
3320 pWindow->dst, NULL, 0);
3321 pWidget->action = next_set_callback;
3322 if (nation_set_index(pSetup->set) < nation_set_count() - 1) {
3323 set_wstate(pWidget, FC_WS_NORMAL);
3325 add_to_gui_list(ID_NATION_NEXT_NATIONSET_BUTTON, pWidget);
3326 pWidget->size.h = pWidget->next->size.h;
3327 pSetup->pset_next = pWidget;
3329 /* create prev nationset button */
3330 pWidget = create_themeicon_button(current_theme->L_ARROW_Icon,
3331 pWindow->dst, NULL, 0);
3332 pWidget->action = prev_set_callback;
3333 if (nation_set_index(pSetup->set) > 0) {
3334 set_wstate(pWidget, FC_WS_NORMAL);
3336 add_to_gui_list(ID_NATION_PREV_NATIONSET_BUTTON, pWidget);
3337 pWidget->size.h = pWidget->next->size.h;
3338 pSetup->pset_prev = pWidget;
3341 /* nation name */
3342 pSetup->nation = fc_rand(get_playable_nation_count());
3343 pnat = nation_by_number(pSetup->nation);
3344 pSetup->nation_style = style_number(style_of_nation(pnat));
3346 copy_chars_to_utf8_str(pstr, nation_plural_translation(pnat));
3347 change_ptsize_utf8(pstr, adj_font(24));
3348 pstr->render = 2;
3349 pstr->fgcol = *get_theme_color(COLOR_THEME_NATIONDLG_TEXT);
3351 pTmp_Surf_zoomed = adj_surf(get_nation_flag_surface(pnat));
3353 pWidget = create_iconlabel(pTmp_Surf_zoomed, pWindow->dst, pstr,
3354 (WF_ICON_ABOVE_TEXT|WF_ICON_CENTER|WF_FREE_GFX));
3355 if (nationsets == NULL) {
3356 pBuf = pWidget;
3357 } else {
3358 pBuf = nationsets;
3361 add_to_gui_list(ID_LABEL, pWidget);
3363 /* create leader name edit */
3364 pWidget = create_edit_from_chars(NULL, pWindow->dst,
3365 NULL, adj_font(16), adj_size(200), 0);
3366 pWidget->size.h = adj_size(24);
3368 set_wstate(pWidget, FC_WS_NORMAL);
3369 pWidget->action = leader_name_edit_callback;
3370 add_to_gui_list(ID_NATION_WIZARD_LEADER_NAME_EDIT, pWidget);
3371 pSetup->pName_Edit = pWidget;
3373 /* create next leader name button */
3374 pWidget = create_themeicon_button(current_theme->R_ARROW_Icon,
3375 pWindow->dst, NULL, 0);
3376 pWidget->action = next_name_callback;
3377 add_to_gui_list(ID_NATION_WIZARD_NEXT_LEADER_NAME_BUTTON, pWidget);
3378 pWidget->size.h = pWidget->next->size.h;
3379 pSetup->pName_Next = pWidget;
3381 /* create prev leader name button */
3382 pWidget = create_themeicon_button(current_theme->L_ARROW_Icon,
3383 pWindow->dst, NULL, 0);
3384 pWidget->action = prev_name_callback;
3385 add_to_gui_list(ID_NATION_WIZARD_PREV_LEADER_NAME_BUTTON, pWidget);
3386 pWidget->size.h = pWidget->next->size.h;
3387 pSetup->pName_Prev = pWidget;
3389 /* change sex button */
3390 pWidget = create_icon_button_from_chars(NULL, pWindow->dst, _("Male"), adj_font(14), 0);
3391 pWidget->action = change_sex_callback;
3392 pWidget->size.w = adj_size(100);
3393 pWidget->size.h = adj_size(22);
3394 set_wstate(pWidget, FC_WS_NORMAL);
3395 pSetup->pChange_Sex = pWidget;
3397 /* add to main widget list */
3398 add_to_gui_list(ID_NATION_WIZARD_CHANGE_SEX_BUTTON, pWidget);
3400 /* ---------------------------------------------------------- */
3401 i = 0;
3402 zoom = DEFAULT_ZOOM * 1.0;
3404 len = 0;
3405 styles_iterate(pstyle) {
3406 i = basic_city_style_for_style(pstyle);
3408 pTmp_Surf = get_sample_city_surface(i);
3410 if (pTmp_Surf->w > 48) {
3411 zoom = DEFAULT_ZOOM * (48.0 / pTmp_Surf->w);
3414 pTmp_Surf_zoomed = zoomSurface(get_sample_city_surface(i), zoom, zoom, 0);
3416 pWidget = create_icon2(pTmp_Surf_zoomed, pWindow->dst, WF_RESTORE_BACKGROUND);
3417 pWidget->action = style_callback;
3418 if (i != pSetup->nation_style) {
3419 set_wstate(pWidget, FC_WS_NORMAL);
3421 len += pWidget->size.w;
3422 add_to_gui_list(MAX_ID - 1000 - i, pWidget);
3423 } styles_iterate_end;
3425 pLast_City_Style = pWidget;
3426 /* ---------------------------------------------------------- */
3428 /* create Cancel button */
3429 pWidget = create_themeicon_button_from_chars(current_theme->CANCEL_Icon,
3430 pWindow->dst, _("Cancel"),
3431 adj_font(12), 0);
3432 pWidget->action = races_dialog_cancel_callback;
3433 set_wstate(pWidget, FC_WS_NORMAL);
3435 add_to_gui_list(ID_NATION_WIZARD_DISCONNECT_BUTTON, pWidget);
3437 /* create OK button */
3438 pWidget =
3439 create_themeicon_button_from_chars(current_theme->OK_Icon, pWindow->dst,
3440 _("OK"), adj_font(12), 0);
3441 pWidget->action = races_dialog_ok_callback;
3443 set_wstate(pWidget, FC_WS_NORMAL);
3444 add_to_gui_list(ID_NATION_WIZARD_START_BUTTON, pWidget);
3445 pWidget->size.w = MAX(pWidget->size.w, pWidget->next->size.w);
3446 pWidget->next->size.w = pWidget->size.w;
3448 pNationDlg->pBeginWidgetList = pWidget;
3449 /* ---------------------------------------------------------- */
3451 pMain_Bg = theme_get_background(theme, BACKGROUND_NATIONDLG);
3452 if (resize_window(pWindow, pMain_Bg, NULL, adj_size(640), adj_size(480))) {
3453 FREESURFACE(pMain_Bg);
3456 area = pWindow->area;
3458 widget_set_position(pWindow,
3459 (main_window_width() - pWindow->size.w) / 2,
3460 (main_window_height() - pWindow->size.h) / 2);
3462 /* nations */
3464 h = pNationDlg->pEndActiveWidgetList->size.h * TARGETS_ROW;
3465 i = (area.h - adj_size(43) - h) / 2;
3466 setup_vertical_widgets_position(TARGETS_COL,
3467 area.x + adj_size(10),
3468 area.y + i - adj_size(4),
3469 0, 0, pNationDlg->pBeginActiveWidgetList,
3470 pNationDlg->pEndActiveWidgetList);
3472 if (pNationDlg->pScroll) {
3473 SDL_Rect area2;
3475 w = pNationDlg->pEndActiveWidgetList->size.w * TARGETS_COL;
3476 setup_vertical_scrollbar_area(pNationDlg->pScroll,
3477 area.x + w + adj_size(12),
3478 area.y + i - adj_size(4), h, FALSE);
3480 area2.x = area.x + w + adj_size(11);
3481 area2.y = area.y + i - adj_size(4);
3482 area2.w = pNationDlg->pScroll->pUp_Left_Button->size.w + adj_size(2);
3483 area2.h = h;
3484 fill_rect_alpha(pWindow->theme, &area2, &bg_color);
3486 create_frame(pWindow->theme,
3487 area2.x, area2.y - 1, area2.w, area2.h + 1,
3488 get_theme_color(COLOR_THEME_NATIONDLG_FRAME));
3491 if (nationsets != NULL) {
3492 /* Nationsets header */
3493 pBuf->size.x = area.x + area.w / 2 + (area.w / 2 - pBuf->size.w) / 2;
3494 pBuf->size.y = area.y + adj_size(46);
3496 natinfo_y = pBuf->size.y;
3497 natinfo_h = area.h -= pBuf->size.y;
3499 /* Nationset name */
3500 pBuf = pBuf->prev;
3501 pBuf->size.x = area.x + area.w / 2 + (area.w / 2 - pBuf->size.w) / 2;
3502 pBuf->size.y = natinfo_y + adj_size(46);
3504 natinfo_y += adj_size(46);
3505 natinfo_h -= adj_size(46);
3507 /* Next Nationset Button */
3508 pBuf = pBuf->prev;
3509 pBuf->size.x = pBuf->next->size.x + pBuf->next->size.w;
3510 pBuf->size.y = pBuf->next->size.y;
3512 /* Prev Nationset Button */
3513 pBuf = pBuf->prev;
3514 pBuf->size.x = pBuf->next->next->size.x - pBuf->size.w;
3515 pBuf->size.y = pBuf->next->size.y;
3517 pBuf = pBuf->prev;
3518 } else {
3519 natinfo_y = area.y;
3520 natinfo_h = area.h;
3523 /* Selected Nation Name */
3524 pBuf->size.x = area.x + area.w / 2 + (area.w / 2 - pBuf->size.w) / 2;
3525 pBuf->size.y = natinfo_y + adj_size(46);
3527 /* Leader Name Edit */
3528 pBuf = pBuf->prev;
3529 pBuf->size.x = area.x + area.w / 2 + (area.w/2 - pBuf->size.w) / 2;
3530 pBuf->size.y = natinfo_y + (natinfo_h - pBuf->size.h) / 2 - adj_size(30);
3532 /* Next Leader Name Button */
3533 pBuf = pBuf->prev;
3534 pBuf->size.x = pBuf->next->size.x + pBuf->next->size.w;
3535 pBuf->size.y = pBuf->next->size.y;
3537 /* Prev Leader Name Button */
3538 pBuf = pBuf->prev;
3539 pBuf->size.x = pBuf->next->next->size.x - pBuf->size.w;
3540 pBuf->size.y = pBuf->next->size.y;
3542 /* Change Leader Sex Button */
3543 pBuf = pBuf->prev;
3544 pBuf->size.x = area.x + area.w / 2 + (area.w/2 - pBuf->size.w) / 2;
3545 pBuf->size.y = pBuf->next->size.y + pBuf->next->size.h + adj_size(20);
3547 /* First Style Button */
3548 pBuf = pBuf->prev;
3549 pBuf->size.x = area.x + area.w / 2 + (area.w/2 - len) / 2 - adj_size(20);
3550 pBuf->size.y = pBuf->next->size.y + pBuf->next->size.h + adj_size(20);
3552 /* Rest Style Buttons */
3553 while (pBuf != pLast_City_Style) {
3554 pBuf = pBuf->prev;
3555 pBuf->size.x = pBuf->next->size.x + pBuf->next->size.w + adj_size(3);
3556 pBuf->size.y = pBuf->next->size.y;
3559 create_line(pWindow->theme,
3560 area.x,
3561 natinfo_y + natinfo_h - adj_size(7) - pBuf->prev->size.h - adj_size(10),
3562 area.w - 1,
3563 natinfo_y + natinfo_h - adj_size(7) - pBuf->prev->size.h - adj_size(10),
3564 get_theme_color(COLOR_THEME_NATIONDLG_FRAME));
3566 /* Disconnect Button */
3567 pBuf = pBuf->prev;
3568 pBuf->size.x = area.x + adj_size(10);
3569 pBuf->size.y = natinfo_y + natinfo_h - adj_size(7) - pBuf->size.h;
3571 /* Start Button */
3572 pBuf = pBuf->prev;
3573 pBuf->size.x = area.w - adj_size(10) - pBuf->size.w;
3574 pBuf->size.y = pBuf->next->size.y;
3576 /* -------------------------------------------------------------------- */
3578 select_random_leader(pSetup->nation);
3580 redraw_group(pNationDlg->pBeginWidgetList, pWindow, 0);
3582 widget_flush(pWindow);
3585 /**************************************************************************
3586 Close the nation selection dialog. This should allow the user to
3587 (at least) select a unit to activate.
3588 **************************************************************************/
3589 void popdown_races_dialog(void)
3591 if (pNationDlg) {
3592 popdown_window_group_dialog(pNationDlg->pBeginWidgetList,
3593 pNationDlg->pEndWidgetList);
3595 cancel_help_dlg_callback(NULL);
3597 FC_FREE(pLeaderName);
3599 FC_FREE(pNationDlg->pScroll);
3600 FC_FREE(pNationDlg);
3604 /**************************************************************************
3605 The server has changed the set of selectable nations.
3606 **************************************************************************/
3607 void races_update_pickable(bool nationset_change)
3609 /* If this is because of nationset change, update will take
3610 * place later when the new option value is received */
3611 if (pNationDlg != NULL && !nationset_change) {
3612 popdown_races_dialog();
3613 popup_races_dialog(client.conn.playing);
3617 /**************************************************************************
3618 Nationset selection update
3619 **************************************************************************/
3620 void nationset_changed(void)
3622 if (pNationDlg != NULL) {
3623 popdown_races_dialog();
3624 popup_races_dialog(client.conn.playing);
3628 /**************************************************************************
3629 In the nation selection dialog, make already-taken nations unavailable.
3630 This information is contained in the packet_nations_used packet.
3631 **************************************************************************/
3632 void races_toggles_set_sensitive()
3634 struct NAT *pSetup;
3635 bool change = FALSE;
3636 struct widget *pNat;
3638 if (!pNationDlg) {
3639 return;
3642 pSetup = (struct NAT *)(pNationDlg->pEndWidgetList->data.ptr);
3644 nations_iterate(nation) {
3645 if (!is_nation_pickable(nation) || nation->player) {
3646 log_debug(" [%d]: %d = %s", nation_index(nation),
3647 (!is_nation_pickable(nation) || nation->player),
3648 nation_rule_name(nation));
3650 pNat = get_widget_pointer_form_main_list(MAX_ID - nation_index(nation));
3651 set_wstate(pNat, FC_WS_DISABLED);
3653 if (nation_index(nation) == pSetup->nation) {
3654 change = TRUE;
3657 } nations_iterate_end;
3659 if (change) {
3660 do {
3661 pSetup->nation = fc_rand(get_playable_nation_count());
3662 pNat = get_widget_pointer_form_main_list(MAX_ID - pSetup->nation);
3663 } while (get_wstate(pNat) == FC_WS_DISABLED);
3665 if (get_wstate(pSetup->pName_Edit) == FC_WS_PRESSED) {
3666 force_exit_from_event_loop();
3667 set_wstate(pSetup->pName_Edit, FC_WS_NORMAL);
3669 change_nation_label();
3670 enable(MAX_ID - 1000 - pSetup->nation_style);
3671 pSetup->nation_style = style_number(style_of_nation(nation_by_number(pSetup->nation)));
3672 disable(MAX_ID - 1000 - pSetup->nation_style);
3673 select_random_leader(pSetup->nation);
3675 redraw_group(pNationDlg->pBeginWidgetList, pNationDlg->pEndWidgetList, 0);
3676 widget_flush(pNationDlg->pEndWidgetList);
3679 /**************************************************************************
3680 Ruleset (modpack) has suggested loading certain tileset. Confirm from
3681 user and load.
3682 **************************************************************************/
3683 void popup_tileset_suggestion_dialog(void)
3687 /****************************************************************
3688 Ruleset (modpack) has suggested loading certain soundset. Confirm from
3689 user and load.
3690 *****************************************************************/
3691 void popup_soundset_suggestion_dialog(void)
3695 /****************************************************************
3696 Ruleset (modpack) has suggested loading certain musicset. Confirm from
3697 user and load.
3698 *****************************************************************/
3699 void popup_musicset_suggestion_dialog(void)
3703 /**************************************************************************
3704 Tileset (modpack) has suggested loading certain theme. Confirm from
3705 user and load.
3706 **************************************************************************/
3707 bool popup_theme_suggestion_dialog(const char *theme_name)
3709 /* Don't load */
3710 return FALSE;
3713 /****************************************************************
3714 Player has gained a new tech.
3715 *****************************************************************/
3716 void show_tech_gained_dialog(Tech_type_id tech)
3718 /* PORTME */
3721 /****************************************************************
3722 Show tileset error dialog.
3723 *****************************************************************/
3724 void show_tileset_error(const char *msg)
3726 /* PORTME */
3729 /****************************************************************
3730 Give a warning when user is about to edit scenario with manually
3731 set properties.
3732 *****************************************************************/
3733 bool handmade_scenario_warning(void)
3735 /* Just tell the client common code to handle this. */
3736 return FALSE;
3739 /****************************************************************
3740 Update multipliers (policies) dialog.
3741 *****************************************************************/
3742 void real_multipliers_dialog_update(void)
3744 /* PORTME */
3747 /****************************************************************
3748 Unit wants to get into some transport on given tile.
3749 *****************************************************************/
3750 bool request_transport(struct unit *pcargo, struct tile *ptile)
3752 return FALSE; /* Unit was not handled here. */
3755 /***************************************************************************
3756 Popup detailed information about battle or save information for
3757 some kind of statistics
3758 ***************************************************************************/
3759 void popup_combat_info(int attacker_unit_id, int defender_unit_id,
3760 int attacker_hp, int defender_hp,
3761 bool make_winner_veteran)