When mixer is not available, recommend SDL2_mixer instead of SDL1.2 mixer
[freeciv.git] / client / gui-sdl / dialogs.c
blobec4c8eb6ca3366f6c2b8ec1dc61dc0cedef6a7b0
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 /* SDL */
27 #include <SDL/SDL.h>
29 /* utility */
30 #include "bitvector.h"
31 #include "fcintl.h"
32 #include "log.h"
33 #include "rand.h"
35 /* common */
36 #include "combat.h"
37 #include "game.h"
38 #include "government.h"
39 #include "movement.h"
40 #include "unitlist.h"
42 /* client */
43 #include "client_main.h"
44 #include "climap.h" /* for client_tile_get_known() */
45 #include "goto.h"
46 #include "helpdata.h" /* for helptext_nation() */
47 #include "packhand.h"
48 #include "text.h"
50 /* gui-sdl */
51 #include "chatline.h"
52 #include "citydlg.h"
53 #include "cityrep.h"
54 #include "cma_fe.h"
55 #include "colors.h"
56 #include "finddlg.h"
57 #include "gotodlg.h"
58 #include "graphics.h"
59 #include "gui_iconv.h"
60 #include "gui_id.h"
61 #include "gui_main.h"
62 #include "gui_tilespec.h"
63 #include "helpdlg.h"
64 #include "inteldlg.h"
65 #include "mapctrl.h"
66 #include "mapview.h"
67 #include "menu.h"
68 #include "messagewin.h"
69 #include "optiondlg.h"
70 #include "plrdlg.h"
71 #include "ratesdlg.h"
72 #include "repodlgs.h"
73 #include "sprite.h"
74 #include "themespec.h"
75 #include "widget.h"
76 #include "wldlg.h"
78 #include "dialogs.h"
80 struct player *races_player;
82 extern bool is_unit_move_blocked;
83 extern void popdown_diplomat_dialog(void);
84 extern void popdown_incite_dialog(void);
85 extern void popdown_bribe_dialog(void);
87 void popdown_advanced_terrain_dialog(void);
88 int advanced_terrain_window_dlg_callback(struct widget *pWindow);
89 int exit_advanced_terrain_dlg_callback(struct widget *pWidget);
91 static char *pLeaderName = NULL;
93 static void unit_select_dialog_popdown(void);
94 static void popdown_terrain_info_dialog(void);
95 static void popdown_pillage_dialog(void);
96 static void popdown_connect_dialog(void);
97 static void popdown_revolution_dialog(void);
98 static void popdown_unit_upgrade_dlg(void);
99 static void popdown_unit_disband_dlg(void);
101 /**********************************************************************
102 Place window near given tile on screen.
103 ***********************************************************************/
104 void put_window_near_map_tile(struct widget *pWindow,
105 int window_width, int window_height,
106 struct tile *ptile)
108 float canvas_x, canvas_y;
109 int window_x = 0, window_y = 0;
111 if (tile_to_canvas_pos(&canvas_x, &canvas_y, ptile)) {
112 if (canvas_x + tileset_tile_width(tileset) + window_width >= Main.screen->w) {
113 if (canvas_x - window_width < 0) {
114 window_x = (Main.screen->w - window_width) / 2;
115 } else {
116 window_x = canvas_x - window_width;
118 } else {
119 window_x = canvas_x + tileset_tile_width(tileset);
122 canvas_y += (tileset_tile_height(tileset) - window_height) / 2;
123 if (canvas_y + window_height >= Main.screen->h)
125 window_y = Main.screen->h - window_height - 1;
126 } else {
127 if (canvas_y < 0)
129 window_y = 0;
130 } else {
131 window_y = canvas_y;
134 } else {
135 window_x = (Main.screen->w - window_width) / 2;
136 window_y = (Main.screen->h - window_height) / 2;
139 widget_set_position(pWindow, window_x, window_y);
143 /**********************************************************************
144 This function is called when the client disconnects or the game is
145 over. It should close all dialog windows for that game.
146 ***********************************************************************/
147 void popdown_all_game_dialogs(void)
149 unit_select_dialog_popdown();
150 popdown_advanced_terrain_dialog();
151 popdown_terrain_info_dialog();
152 popdown_newcity_dialog();
153 popdown_optiondlg(TRUE);
154 undraw_order_widgets();
155 popdown_diplomat_dialog();
156 popdown_pillage_dialog();
157 popdown_incite_dialog();
158 popdown_connect_dialog();
159 popdown_bribe_dialog();
160 popdown_find_dialog();
161 popdown_revolution_dialog();
162 science_report_dialogs_popdown_all();
163 meswin_dialog_popdown();
164 popdown_worklist_editor();
165 popdown_all_city_dialogs();
166 city_report_dialog_popdown();
167 economy_report_dialog_popdown();
168 units_report_dialog_popdown();
169 popdown_intel_dialogs();
170 popdown_players_nations_dialog();
171 popdown_players_dialog();
172 popdown_goto_airlift_dialog();
173 popdown_unit_upgrade_dlg();
174 popdown_unit_disband_dlg();
175 popdown_help_dialog();
176 popdown_notify_goto_dialog();
178 /* clear gui buffer */
179 if (C_S_PREPARING == client_state()) {
180 clear_surface(Main.gui->surface, NULL);
184 /* ======================================================================= */
186 /**************************************************************************
187 Find the my unit's (focus) chance of success at attacking/defending the
188 given enemy unit. Return FALSE if the values cannot be determined (e.g., no
189 units given).
190 **************************************************************************/
191 static bool sdl_get_chance_to_win(int *att_chance, int *def_chance,
192 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;
209 /**************************************************************************
210 Notify goto dialog.
211 **************************************************************************/
212 struct notify_goto_data {
213 char *headline;
214 char *lines;
215 struct tile *ptile;
218 #define SPECLIST_TAG notify_goto
219 #define SPECLIST_TYPE struct notify_goto_data
220 #include "speclist.h"
222 struct notify_goto_dialog {
223 struct widget *window;
224 struct widget *close_button;
225 struct widget *label;
226 struct notify_goto_list *datas;
229 static struct notify_goto_dialog *notify_goto_dialog = NULL;
231 static void notify_goto_dialog_advance(struct notify_goto_dialog *pdialog);
233 /**************************************************************************
234 Create a notify goto data.
235 **************************************************************************/
236 static struct notify_goto_data *notify_goto_data_new(const char *headline,
237 const char *lines,
238 struct tile *ptile)
240 struct notify_goto_data *pdata = fc_malloc(sizeof(*pdata));
242 pdata->headline = fc_strdup(headline);
243 pdata->lines = fc_strdup(lines);
244 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);
258 /**************************************************************************
259 Move the notify dialog.
260 **************************************************************************/
261 static int notify_goto_dialog_callback(struct widget *widget)
263 struct notify_goto_dialog *pdialog =
264 (struct notify_goto_dialog *) widget->data.ptr;
266 if (Main.event.button.button == SDL_BUTTON_LEFT) {
267 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);
283 return -1;
286 /**************************************************************************
287 Goto callback.
288 **************************************************************************/
289 static int notify_goto_dialog_goto_callback(struct widget *widget)
291 struct notify_goto_dialog *pdialog =
292 (struct notify_goto_dialog *) widget->data.ptr;
293 const struct notify_goto_data *pdata = notify_goto_list_get(pdialog->datas,
296 if (Main.event.button.button == SDL_BUTTON_LEFT) {
297 if (NULL != pdata->ptile) {
298 center_tile_mapcanvas(pdata->ptile);
300 } else if (Main.event.button.button == SDL_BUTTON_RIGHT) {
301 struct city *pcity;
303 if (NULL != pdata->ptile && (pcity = tile_city(pdata->ptile))) {
304 popup_city_dialog(pcity);
308 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 SDL_String16 *str;
320 /* Window. */
321 str = create_str16_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_str16_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_string16(pdialog->window->string16, 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.screen->w - pdialog->window->size.w) / 2,
402 (Main.screen->h - 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();
444 fc_assert(NULL != notify_goto_dialog);
446 notify_goto_list_prepend(notify_goto_dialog->datas,
447 notify_goto_data_new(headline, lines, ptile));
448 notify_goto_dialog_update(notify_goto_dialog);
451 /**************************************************************************
452 Popdown the notify goto dialog.
453 **************************************************************************/
454 void popdown_notify_goto_dialog(void)
456 if (NULL != notify_goto_dialog) {
457 notify_goto_dialog_destroy(notify_goto_dialog);
458 notify_goto_dialog = NULL;
462 /**************************************************************************
463 Popup a dialog to display connection message from server.
464 **************************************************************************/
465 void popup_connect_msg(const char *headline, const char *message)
467 log_error("popup_connect_msg() PORT ME");
470 /* ----------------------------------------------------------------------- */
471 struct ADVANCED_DLG *pNotifyDlg = NULL;
473 /**************************************************************************
474 User interacted with generic notify dialog.
475 **************************************************************************/
476 static int notify_dialog_window_callback(struct widget *pWindow)
478 if (Main.event.button.button == SDL_BUTTON_LEFT) {
479 move_window_group(pNotifyDlg->pBeginWidgetList, pWindow);
481 return -1;
484 /**************************************************************************
485 User interacted with notify dialog close button.
486 **************************************************************************/
487 static int exit_notify_dialog_callback(struct widget *pWidget)
489 if (Main.event.button.button == SDL_BUTTON_LEFT) {
490 if(pNotifyDlg) {
491 popdown_window_group_dialog(pNotifyDlg->pBeginWidgetList,
492 pNotifyDlg->pEndWidgetList);
493 FC_FREE(pNotifyDlg->pScroll);
494 FC_FREE(pNotifyDlg);
495 flush_dirty();
498 return -1;
501 /**************************************************************************
502 Popup a generic dialog to display some generic information.
503 **************************************************************************/
504 void popup_notify_dialog(const char *caption, const char *headline,
505 const char *lines)
507 struct widget *pBuf, *pWindow;
508 SDL_String16 *pStr;
509 SDL_Surface *pHeadline, *pLines;
510 SDL_Rect dst;
511 SDL_Rect area;
513 if (pNotifyDlg) {
514 return;
517 pNotifyDlg = fc_calloc(1, sizeof(struct ADVANCED_DLG));
519 pStr = create_str16_from_char(caption, adj_font(12));
520 pStr->style |= TTF_STYLE_BOLD;
522 pWindow = create_window_skeleton(NULL, pStr, 0);
524 pWindow->action = notify_dialog_window_callback;
525 set_wstate(pWindow, FC_WS_NORMAL);
527 add_to_gui_list(ID_WINDOW, pWindow);
528 pNotifyDlg->pEndWidgetList = pWindow;
530 area = pWindow->area;
532 /* ---------- */
533 /* create exit button */
534 pBuf = create_themeicon(current_theme->Small_CANCEL_Icon, pWindow->dst,
535 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
536 pBuf->info_label = create_str16_from_char(_("Close Dialog (Esc)"),
537 adj_font(12));
538 pBuf->action = exit_notify_dialog_callback;
539 set_wstate(pBuf, FC_WS_NORMAL);
540 pBuf->key = SDLK_ESCAPE;
541 area.w += (pBuf->size.w + adj_size(10));
543 add_to_gui_list(ID_BUTTON, pBuf);
544 pNotifyDlg->pBeginWidgetList = pBuf;
546 pStr = create_str16_from_char(headline, adj_font(16));
547 pStr->style |= TTF_STYLE_BOLD;
549 pHeadline = create_text_surf_from_str16(pStr);
551 if(lines && *lines != '\0') {
552 change_ptsize16(pStr, adj_font(12));
553 pStr->style &= ~TTF_STYLE_BOLD;
554 copy_chars_to_string16(pStr, lines);
555 pLines = create_text_surf_from_str16(pStr);
556 } else {
557 pLines = NULL;
560 FREESTRING16(pStr);
562 area.w = MAX(area.w, pHeadline->w);
563 if(pLines) {
564 area.w = MAX(area.w, pLines->w);
566 area.w += adj_size(60);
567 area.h = MAX(area.h, adj_size(10) + pHeadline->h + adj_size(10));
568 if(pLines) {
569 area.h += pLines->h + adj_size(10);
572 resize_window(pWindow, NULL, get_theme_color(COLOR_THEME_BACKGROUND),
573 (pWindow->size.w - pWindow->area.w) + area.w,
574 (pWindow->size.h - pWindow->area.h) + area.h);
576 area = pWindow->area;
578 widget_set_position(pWindow,
579 (Main.screen->w - pWindow->size.w) / 2,
580 (Main.screen->h - pWindow->size.h) / 2);
582 dst.x = area.x + (area.w - pHeadline->w) / 2;
583 dst.y = area.y + adj_size(10);
585 alphablit(pHeadline, NULL, pWindow->theme, &dst);
586 if(pLines) {
587 dst.y += pHeadline->h + adj_size(10);
588 if(pHeadline->w < pLines->w) {
589 dst.x = area.x + (area.w - pLines->w) / 2;
592 alphablit(pLines, NULL, pWindow->theme, &dst);
595 FREESURFACE(pHeadline);
596 FREESURFACE(pLines);
598 /* exit button */
599 pBuf = pWindow->prev;
600 pBuf->size.x = area.x + area.w - pBuf->size.w - 1;
601 pBuf->size.y = pWindow->size.y + adj_size(2);
603 /* redraw */
604 redraw_group(pNotifyDlg->pBeginWidgetList, pWindow, 0);
605 widget_flush(pWindow);
608 /* =======================================================================*/
609 /* ========================= UNIT UPGRADE DIALOG =========================*/
610 /* =======================================================================*/
611 static struct SMALL_DLG *pUnit_Upgrade_Dlg = NULL;
613 /****************************************************************
614 User interacted with upgrade unit widget.
615 *****************************************************************/
616 static int upgrade_unit_window_callback(struct widget *pWindow)
618 if (Main.event.button.button == SDL_BUTTON_LEFT) {
619 move_window_group(pUnit_Upgrade_Dlg->pBeginWidgetList, pWindow);
621 return -1;
624 /****************************************************************
625 User interacted with upgrade unit dialog cancel -button
626 *****************************************************************/
627 static int cancel_upgrade_unit_callback(struct widget *pWidget)
629 if (Main.event.button.button == SDL_BUTTON_LEFT) {
630 popdown_unit_upgrade_dlg();
631 /* enable city dlg */
632 enable_city_dlg_widgets();
633 flush_dirty();
635 return -1;
638 /****************************************************************
639 User interacted with unit upgrade dialog "Upgrade" -button.
640 *****************************************************************/
641 static int ok_upgrade_unit_window_callback(struct widget *pWidget)
643 if (Main.event.button.button == SDL_BUTTON_LEFT) {
644 struct unit *pUnit = pWidget->data.unit;
645 popdown_unit_upgrade_dlg();
646 /* enable city dlg */
647 enable_city_dlg_widgets();
648 free_city_units_lists();
649 request_unit_upgrade(pUnit);
650 flush_dirty();
652 return -1;
655 /****************************************************************
656 Open unit upgrade dialog.
657 *****************************************************************/
658 void popup_unit_upgrade_dlg(struct unit *pUnit, bool city)
660 char cBuf[128];
661 struct widget *pBuf = NULL, *pWindow;
662 SDL_String16 *pStr;
663 SDL_Surface *pText;
664 SDL_Rect dst;
665 int window_x = 0, window_y = 0;
666 enum unit_upgrade_result unit_upgrade_result;
667 SDL_Rect area;
669 if (pUnit_Upgrade_Dlg) {
670 /* just in case */
671 flush_dirty();
672 return;
675 pUnit_Upgrade_Dlg = fc_calloc(1, sizeof(struct SMALL_DLG));
677 unit_upgrade_result = unit_upgrade_info(pUnit, cBuf, sizeof(cBuf));
679 pStr = create_str16_from_char(_("Upgrade Obsolete Units"), adj_font(12));
680 pStr->style |= TTF_STYLE_BOLD;
682 pWindow = create_window_skeleton(NULL, pStr, 0);
684 pWindow->action = upgrade_unit_window_callback;
685 set_wstate(pWindow, FC_WS_NORMAL);
687 pUnit_Upgrade_Dlg->pEndWidgetList = pWindow;
689 add_to_gui_list(ID_WINDOW, pWindow);
691 area = pWindow->area;
693 /* ============================================================= */
695 /* create text label */
696 pStr = create_str16_from_char(cBuf, adj_font(10));
697 pStr->style |= (TTF_STYLE_BOLD|SF_CENTER);
698 pStr->fgcol = *get_theme_color(COLOR_THEME_UNITUPGRADE_TEXT);
700 pText = create_text_surf_from_str16(pStr);
701 FREESTRING16(pStr);
703 area.w = MAX(area.w, pText->w + adj_size(20));
704 area.h += (pText->h + adj_size(10));
706 /* cancel button */
707 pBuf = create_themeicon_button_from_chars(current_theme->CANCEL_Icon,
708 pWindow->dst, _("Cancel"), adj_font(12), 0);
710 pBuf->action = cancel_upgrade_unit_callback;
711 set_wstate(pBuf, FC_WS_NORMAL);
713 area.h += (pBuf->size.h + adj_size(20));
715 add_to_gui_list(ID_BUTTON, pBuf);
717 if (UU_OK == unit_upgrade_result) {
718 pBuf = create_themeicon_button_from_chars(current_theme->OK_Icon, pWindow->dst,
719 _("Upgrade"), adj_font(12), 0);
721 pBuf->action = ok_upgrade_unit_window_callback;
722 set_wstate(pBuf, FC_WS_NORMAL);
723 pBuf->data.unit = pUnit;
724 add_to_gui_list(ID_BUTTON, pBuf);
725 pBuf->size.w = MAX(pBuf->size.w, pBuf->next->size.w);
726 pBuf->next->size.w = pBuf->size.w;
727 area.w = MAX(area.w, adj_size(30) + pBuf->size.w * 2);
728 } else {
729 area.w = MAX(area.w, pBuf->size.w + adj_size(20));
731 /* ============================================ */
733 pUnit_Upgrade_Dlg->pBeginWidgetList = pBuf;
735 resize_window(pWindow, NULL, get_theme_color(COLOR_THEME_BACKGROUND),
736 (pWindow->size.w - pWindow->area.w) + area.w,
737 (pWindow->size.h - pWindow->area.h) + area.h);
739 area = pWindow->area;
741 if(city) {
742 window_x = Main.event.motion.x;
743 window_y = Main.event.motion.y;
744 } else {
745 put_window_near_map_tile(pWindow, pWindow->size.w, pWindow->size.h,
746 unit_tile(pUnit));
749 widget_set_position(pWindow, window_x, window_y);
751 /* setup rest of widgets */
752 /* label */
753 dst.x = area.x + (area.w - pText->w) / 2;
754 dst.y = area.y + adj_size(10);
755 alphablit(pText, NULL, pWindow->theme, &dst);
756 FREESURFACE(pText);
758 /* cancel button */
759 pBuf = pWindow->prev;
760 pBuf->size.y = area.y + area.h - pBuf->size.h - adj_size(7);
762 if (UU_OK == unit_upgrade_result) {
763 /* upgrade button */
764 pBuf = pBuf->prev;
765 pBuf->size.x = area.x + (area.w - (2 * pBuf->size.w + adj_size(10))) / 2;
766 pBuf->size.y = pBuf->next->size.y;
768 /* cancel button */
769 pBuf->next->size.x = pBuf->size.x + pBuf->size.w + adj_size(10);
770 } else {
771 /* x position of cancel button */
772 pBuf->size.x = area.x + area.w - pBuf->size.w - adj_size(10);
776 /* ================================================== */
777 /* redraw */
778 redraw_group(pUnit_Upgrade_Dlg->pBeginWidgetList, pWindow, 0);
780 widget_mark_dirty(pWindow);
781 flush_dirty();
785 /****************************************************************
786 Close unit upgrade dialog.
787 *****************************************************************/
788 static void popdown_unit_upgrade_dlg(void)
790 if (pUnit_Upgrade_Dlg) {
791 popdown_window_group_dialog(pUnit_Upgrade_Dlg->pBeginWidgetList,
792 pUnit_Upgrade_Dlg->pEndWidgetList);
793 FC_FREE(pUnit_Upgrade_Dlg);
797 /* =======================================================================*/
798 /* ========================= UNIT DISBAND DIALOG =========================*/
799 /* =======================================================================*/
800 static struct SMALL_DLG *pUnit_Disband_Dlg = NULL;
802 /****************************************************************
803 User interacted with disband unit widget.
804 *****************************************************************/
805 static int disband_unit_window_callback(struct widget *pWindow)
807 if (Main.event.button.button == SDL_BUTTON_LEFT) {
808 move_window_group(pUnit_Disband_Dlg->pBeginWidgetList, pWindow);
810 return -1;
813 /****************************************************************
814 User interacted with disband unit dialog cancel -button
815 *****************************************************************/
816 static int cancel_disband_unit_callback(struct widget *pWidget)
818 if (Main.event.button.button == SDL_BUTTON_LEFT) {
819 popdown_unit_disband_dlg();
820 /* enable city dlg */
821 enable_city_dlg_widgets();
822 flush_dirty();
824 return -1;
827 /****************************************************************
828 User interacted with unit disband dialog "Disband" -button.
829 *****************************************************************/
830 static int ok_disband_unit_window_callback(struct widget *pWidget)
832 if (Main.event.button.button == SDL_BUTTON_LEFT) {
833 struct unit *pUnit = pWidget->data.unit;
834 popdown_unit_disband_dlg();
835 /* enable city dlg */
836 enable_city_dlg_widgets();
837 free_city_units_lists();
838 request_unit_disband(pUnit);
839 flush_dirty();
841 return -1;
844 /****************************************************************
845 Open unit disband dialog.
846 *****************************************************************/
847 void popup_unit_disband_dlg(struct unit *pUnit, bool city)
849 char cBuf[128];
850 struct widget *pBuf = NULL, *pWindow;
851 SDL_String16 *pStr;
852 SDL_Surface *pText;
853 SDL_Rect dst;
854 int window_x = 0, window_y = 0;
855 bool unit_disband_result;
856 SDL_Rect area;
858 if (pUnit_Disband_Dlg) {
859 /* just in case */
860 flush_dirty();
861 return;
864 pUnit_Disband_Dlg = fc_calloc(1, sizeof(struct SMALL_DLG));
867 struct unit_list *pUnits = unit_list_new();
868 unit_list_append(pUnits, pUnit);
869 unit_disband_result = get_units_disband_info(cBuf, sizeof(cBuf), pUnits);
870 unit_list_destroy(pUnits);
873 pStr = create_str16_from_char(_("Disband Units"), adj_font(12));
874 pStr->style |= TTF_STYLE_BOLD;
876 pWindow = create_window_skeleton(NULL, pStr, 0);
878 pWindow->action = disband_unit_window_callback;
879 set_wstate(pWindow, FC_WS_NORMAL);
881 pUnit_Disband_Dlg->pEndWidgetList = pWindow;
883 add_to_gui_list(ID_WINDOW, pWindow);
885 area = pWindow->area;
887 /* ============================================================= */
889 /* create text label */
890 pStr = create_str16_from_char(cBuf, adj_font(10));
891 pStr->style |= (TTF_STYLE_BOLD|SF_CENTER);
892 pStr->fgcol = *get_theme_color(COLOR_THEME_UNITDISBAND_TEXT);
894 pText = create_text_surf_from_str16(pStr);
895 FREESTRING16(pStr);
897 area.w = MAX(area.w, pText->w + adj_size(20));
898 area.h += (pText->h + adj_size(10));
900 /* cancel button */
901 pBuf = create_themeicon_button_from_chars(current_theme->CANCEL_Icon,
902 pWindow->dst, _("Cancel"),
903 adj_font(12), 0);
905 pBuf->action = cancel_disband_unit_callback;
906 set_wstate(pBuf, FC_WS_NORMAL);
908 area.h += (pBuf->size.h + adj_size(20));
910 add_to_gui_list(ID_BUTTON, pBuf);
912 if (unit_disband_result) {
913 pBuf = create_themeicon_button_from_chars(current_theme->OK_Icon, pWindow->dst,
914 _("Disband"), adj_font(12), 0);
916 pBuf->action = ok_disband_unit_window_callback;
917 set_wstate(pBuf, FC_WS_NORMAL);
918 pBuf->data.unit = pUnit;
919 add_to_gui_list(ID_BUTTON, pBuf);
920 pBuf->size.w = MAX(pBuf->size.w, pBuf->next->size.w);
921 pBuf->next->size.w = pBuf->size.w;
922 area.w = MAX(area.w, adj_size(30) + pBuf->size.w * 2);
923 } else {
924 area.w = MAX(area.w, pBuf->size.w + adj_size(20));
926 /* ============================================ */
928 pUnit_Disband_Dlg->pBeginWidgetList = pBuf;
930 resize_window(pWindow, NULL, get_theme_color(COLOR_THEME_BACKGROUND),
931 (pWindow->size.w - pWindow->area.w) + area.w,
932 (pWindow->size.h - pWindow->area.h) + area.h);
934 area = pWindow->area;
936 if(city) {
937 window_x = Main.event.motion.x;
938 window_y = Main.event.motion.y;
939 } else {
940 put_window_near_map_tile(pWindow, pWindow->size.w, pWindow->size.h,
941 unit_tile(pUnit));
944 widget_set_position(pWindow, window_x, window_y);
946 /* setup rest of widgets */
947 /* label */
948 dst.x = area.x + (area.w - pText->w) / 2;
949 dst.y = area.y + adj_size(10);
950 alphablit(pText, NULL, pWindow->theme, &dst);
951 FREESURFACE(pText);
953 /* cancel button */
954 pBuf = pWindow->prev;
955 pBuf->size.y = area.y + area.h - pBuf->size.h - adj_size(7);
957 if (unit_disband_result) {
958 /* disband button */
959 pBuf = pBuf->prev;
960 pBuf->size.x = area.x + (area.w - (2 * pBuf->size.w + adj_size(10))) / 2;
961 pBuf->size.y = pBuf->next->size.y;
963 /* cancel button */
964 pBuf->next->size.x = pBuf->size.x + pBuf->size.w + adj_size(10);
965 } else {
966 /* x position of cancel button */
967 pBuf->size.x = area.x + area.w - pBuf->size.w - adj_size(10);
971 /* ================================================== */
972 /* redraw */
973 redraw_group(pUnit_Disband_Dlg->pBeginWidgetList, pWindow, 0);
975 widget_mark_dirty(pWindow);
976 flush_dirty();
980 /****************************************************************
981 Close unit disband dialog.
982 *****************************************************************/
983 static void popdown_unit_disband_dlg(void)
985 if (pUnit_Disband_Dlg) {
986 popdown_window_group_dialog(pUnit_Disband_Dlg->pBeginWidgetList,
987 pUnit_Disband_Dlg->pEndWidgetList);
988 FC_FREE(pUnit_Disband_Dlg);
992 /* =======================================================================*/
993 /* ======================== UNIT SELECTION DIALOG ========================*/
994 /* =======================================================================*/
995 static struct ADVANCED_DLG *pUnit_Select_Dlg = NULL;
997 /**************************************************************************
998 User interacted with unit selection window.
999 **************************************************************************/
1000 static int unit_select_window_callback(struct widget *pWindow)
1002 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1003 move_window_group(pUnit_Select_Dlg->pBeginWidgetList, pWindow);
1005 return -1;
1008 /**************************************************************************
1009 User requested unit select window to be closed.
1010 **************************************************************************/
1011 static int exit_unit_select_callback( struct widget *pWidget )
1013 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1014 unit_select_dialog_popdown();
1015 is_unit_move_blocked = FALSE;
1017 return -1;
1020 /**************************************************************************
1021 User selected unit from unit select window.
1022 **************************************************************************/
1023 static int unit_select_callback( struct widget *pWidget )
1025 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1026 struct unit *pUnit =
1027 player_unit_by_number(client_player(), MAX_ID - pWidget->ID);
1029 unit_select_dialog_popdown();
1030 if (pUnit) {
1031 request_new_unit_activity(pUnit, ACTIVITY_IDLE);
1032 unit_focus_set(pUnit);
1035 return -1;
1038 /**************************************************************************
1039 Popdown a dialog window to select units on a particular tile.
1040 **************************************************************************/
1041 static void unit_select_dialog_popdown(void)
1043 if (pUnit_Select_Dlg) {
1044 is_unit_move_blocked = FALSE;
1045 popdown_window_group_dialog(pUnit_Select_Dlg->pBeginWidgetList,
1046 pUnit_Select_Dlg->pEndWidgetList);
1048 FC_FREE(pUnit_Select_Dlg->pScroll);
1049 FC_FREE(pUnit_Select_Dlg);
1050 flush_dirty();
1054 /**************************************************************************
1055 Popup a dialog window to select units on a particular tile.
1056 **************************************************************************/
1057 void unit_select_dialog_popup(struct tile *ptile)
1059 struct widget *pBuf = NULL, *pWindow;
1060 SDL_String16 *pStr;
1061 struct unit *pUnit = NULL, *pFocus = head_of_units_in_focus();
1062 struct unit_type *pUnitType;
1063 char cBuf[255];
1064 int i, w = 0, n;
1065 SDL_Rect area;
1067 #define NUM_SEEN 20
1069 n = unit_list_size(ptile->units);
1071 if (!n || pUnit_Select_Dlg) {
1072 return;
1075 is_unit_move_blocked = TRUE;
1076 pUnit_Select_Dlg = fc_calloc(1, sizeof(struct ADVANCED_DLG));
1078 fc_snprintf(cBuf , sizeof(cBuf),"%s (%d)", _("Unit selection") , n);
1079 pStr = create_str16_from_char(cBuf , adj_font(12));
1080 pStr->style |= TTF_STYLE_BOLD;
1082 pWindow = create_window_skeleton(NULL, pStr, 0);
1084 pWindow->action = unit_select_window_callback;
1085 set_wstate(pWindow, FC_WS_NORMAL);
1087 add_to_gui_list(ID_UNIT_SELLECT_DLG_WINDOW, pWindow);
1088 pUnit_Select_Dlg->pEndWidgetList = pWindow;
1090 area = pWindow->area;
1092 /* ---------- */
1093 /* create exit button */
1094 pBuf = create_themeicon(current_theme->Small_CANCEL_Icon, pWindow->dst,
1095 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
1096 pBuf->info_label = create_str16_from_char(_("Close Dialog (Esc)"),
1097 adj_font(12));
1098 pBuf->action = exit_unit_select_callback;
1099 set_wstate(pBuf, FC_WS_NORMAL);
1100 pBuf->key = SDLK_ESCAPE;
1101 area.w += (pBuf->size.w + adj_size(10));
1103 add_to_gui_list(ID_UNIT_SELLECT_DLG_EXIT_BUTTON, pBuf);
1105 /* ---------- */
1107 for (i = 0; i < n; i++) {
1108 const char *vetname;
1110 pUnit = unit_list_get(ptile->units, i);
1111 pUnitType = unit_type_get(pUnit);
1112 vetname = utype_veteran_name_translation(pUnitType, pUnit->veteran);
1114 if (unit_owner(pUnit) == client.conn.playing) {
1115 fc_snprintf(cBuf , sizeof(cBuf), _("Contact %s (%d / %d) %s(%d,%d,%s) %s"),
1116 (vetname != NULL ? vetname : ""),
1117 pUnit->hp, pUnitType->hp,
1118 utype_name_translation(pUnitType),
1119 pUnitType->attack_strength,
1120 pUnitType->defense_strength,
1121 move_points_text(pUnitType->move_rate, FALSE),
1122 unit_activity_text(pUnit));
1123 } else {
1124 int att_chance, def_chance;
1126 fc_snprintf(cBuf , sizeof(cBuf), _("%s %s %s(A:%d D:%d M:%s FP:%d) HP:%d%%"),
1127 nation_adjective_for_player(unit_owner(pUnit)),
1128 (vetname != NULL ? vetname : ""),
1129 utype_name_translation(pUnitType),
1130 pUnitType->attack_strength,
1131 pUnitType->defense_strength,
1132 move_points_text(pUnitType->move_rate, FALSE),
1133 pUnitType->firepower,
1134 (pUnit->hp * 100 / pUnitType->hp + 9) / 10);
1136 /* calculate chance to win */
1137 if (sdl_get_chance_to_win(&att_chance, &def_chance, pUnit, pFocus)) {
1138 /* TRANS: "CtW" = "Chance to Win" */
1139 cat_snprintf(cBuf, sizeof(cBuf), _(" CtW: Att:%d%% Def:%d%%"),
1140 att_chance, def_chance);
1144 create_active_iconlabel(pBuf, pWindow->dst,
1145 pStr, cBuf, unit_select_callback);
1147 add_to_gui_list(MAX_ID - pUnit->id , pBuf);
1149 area.w = MAX(area.w, pBuf->size.w);
1150 area.h += pBuf->size.h;
1151 if (unit_owner(pUnit) == client.conn.playing) {
1152 set_wstate(pBuf, FC_WS_NORMAL);
1155 if (i > NUM_SEEN - 1)
1157 set_wflag(pBuf , WF_HIDDEN);
1161 pUnit_Select_Dlg->pBeginWidgetList = pBuf;
1162 pUnit_Select_Dlg->pBeginActiveWidgetList = pUnit_Select_Dlg->pBeginWidgetList;
1163 pUnit_Select_Dlg->pEndActiveWidgetList = pWindow->prev->prev;
1164 pUnit_Select_Dlg->pActiveWidgetList = pUnit_Select_Dlg->pEndActiveWidgetList;
1166 area.w += adj_size(2);
1167 if (n > NUM_SEEN)
1169 n = create_vertical_scrollbar(pUnit_Select_Dlg, 1, NUM_SEEN, TRUE, TRUE);
1170 area.w += n;
1172 /* ------- window ------- */
1173 area.h = NUM_SEEN * pWindow->prev->prev->size.h;
1176 resize_window(pWindow, NULL, NULL,
1177 (pWindow->size.w - pWindow->area.w) + area.w,
1178 (pWindow->size.h - pWindow->area.h) + area.h);
1180 area = pWindow->area;
1182 put_window_near_map_tile(pWindow, pWindow->size.w, pWindow->size.h,
1183 unit_tile(pUnit));
1185 w = area.w;
1187 if(pUnit_Select_Dlg->pScroll) {
1188 w -= n;
1191 /* exit button */
1192 pBuf = pWindow->prev;
1193 pBuf->size.x = area.x + area.w - pBuf->size.w - 1;
1194 pBuf->size.y = pWindow->size.y + adj_size(2);
1195 pBuf = pBuf->prev;
1197 setup_vertical_widgets_position(1, area.x + 1, area.y, w, 0,
1198 pUnit_Select_Dlg->pBeginActiveWidgetList, pBuf);
1200 if(pUnit_Select_Dlg->pScroll) {
1201 setup_vertical_scrollbar_area(pUnit_Select_Dlg->pScroll,
1202 area.x + area.w, area.y,
1203 area.h, TRUE);
1206 /* ==================================================== */
1207 /* redraw */
1208 redraw_group(pUnit_Select_Dlg->pBeginWidgetList, pWindow, 0);
1210 widget_flush(pWindow);
1213 /**************************************************************************
1214 Update the dialog window to select units on a particular tile.
1215 **************************************************************************/
1216 void unit_select_dialog_update_real(void)
1218 /* PORTME */
1221 /* ====================================================================== */
1222 /* ============================ TERRAIN INFO ============================ */
1223 /* ====================================================================== */
1224 static struct SMALL_DLG *pTerrain_Info_Dlg = NULL;
1227 /**************************************************************************
1228 Popdown terrain information dialog.
1229 **************************************************************************/
1230 static int terrain_info_window_dlg_callback(struct widget *pWindow)
1232 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1233 move_window_group(pTerrain_Info_Dlg->pBeginWidgetList, pWindow);
1235 return -1;
1238 /**************************************************************************
1239 Popdown terrain information dialog.
1240 **************************************************************************/
1241 static void popdown_terrain_info_dialog(void)
1243 if (pTerrain_Info_Dlg) {
1244 popdown_window_group_dialog(pTerrain_Info_Dlg->pBeginWidgetList,
1245 pTerrain_Info_Dlg->pEndWidgetList);
1246 FC_FREE(pTerrain_Info_Dlg);
1247 flush_dirty();
1251 /**************************************************************************
1252 Popdown terrain information dialog.
1253 **************************************************************************/
1254 static int exit_terrain_info_dialog_callback(struct widget *pButton)
1256 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1257 popdown_terrain_info_dialog();
1259 return -1;
1262 /**************************************************************************
1263 Return a (static) string with terrain defense bonus.
1264 This does not include bonuses some units may get out of bases.
1265 **************************************************************************/
1266 const char *sdl_get_tile_defense_info_text(struct tile *ptile)
1268 static char buffer[64];
1269 int bonus = (tile_terrain(ptile)->defense_bonus - 10) * 10;
1271 extra_type_iterate(pextra) {
1272 if (tile_has_extra(ptile, pextra)
1273 && pextra->category == ECAT_NATURAL) {
1274 bonus += pextra->defense_bonus;
1276 } extra_type_iterate_end;
1278 fc_snprintf(buffer, sizeof(buffer), _("Terrain Defense Bonus: +%d%% "), bonus);
1280 return buffer;
1283 /**************************************************************************
1284 Popup terrain information dialog.
1285 **************************************************************************/
1286 static void popup_terrain_info_dialog(SDL_Surface *pDest, struct tile *ptile)
1288 SDL_Surface *pSurf;
1289 struct widget *pBuf, *pWindow;
1290 SDL_String16 *pStr;
1291 char cBuf[256];
1292 SDL_Rect area;
1294 if (pTerrain_Info_Dlg) {
1295 flush_dirty();
1296 return;
1299 pSurf = get_terrain_surface(ptile);
1300 pTerrain_Info_Dlg = fc_calloc(1, sizeof(struct SMALL_DLG));
1302 /* ----------- */
1303 fc_snprintf(cBuf, sizeof(cBuf), "%s [%d,%d]", _("Terrain Info"),
1304 TILE_XY(ptile));
1306 pWindow = create_window_skeleton(NULL, create_str16_from_char(cBuf , adj_font(12)), 0);
1307 pWindow->string16->style |= TTF_STYLE_BOLD;
1309 pWindow->action = terrain_info_window_dlg_callback;
1310 set_wstate(pWindow, FC_WS_NORMAL);
1312 add_to_gui_list(ID_TERRAIN_INFO_DLG_WINDOW, pWindow);
1313 pTerrain_Info_Dlg->pEndWidgetList = pWindow;
1315 area = pWindow->area;
1317 /* ---------- */
1318 pStr = create_str16_from_char(popup_info_text(ptile), adj_font(12));
1319 pStr->style |= SF_CENTER;
1320 pBuf = create_iconlabel(pSurf, pWindow->dst, pStr, 0);
1322 pBuf->size.h += tileset_tile_height(tileset) / 2;
1324 add_to_gui_list(ID_LABEL, pBuf);
1326 /* ------ window ---------- */
1327 area.w = MAX(area.w, pBuf->size.w + adj_size(20));
1328 area.h = MAX(area.h, pBuf->size.h);
1330 resize_window(pWindow, NULL, get_theme_color(COLOR_THEME_BACKGROUND),
1331 (pWindow->size.w - pWindow->area.w) + area.w,
1332 (pWindow->size.h - pWindow->area.h) + area.h);
1334 area = pWindow->area;
1336 put_window_near_map_tile(pWindow, pWindow->size.w, pWindow->size.h, ptile);
1338 /* ------------------------ */
1340 pBuf->size.x = area.x + adj_size(10);
1341 pBuf->size.y = area.y;
1343 /* exit icon */
1344 pBuf = create_themeicon(current_theme->Small_CANCEL_Icon, pWindow->dst,
1345 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
1346 pBuf->info_label = create_str16_from_char(_("Close Dialog (Esc)"),
1347 adj_font(12));
1348 pBuf->size.x = area.x + area.w - pBuf->size.w - 1;
1349 pBuf->size.y = pWindow->size.y + adj_size(2);
1350 pBuf->action = exit_terrain_info_dialog_callback;
1351 set_wstate(pBuf, FC_WS_NORMAL);
1352 pBuf->key = SDLK_ESCAPE;
1354 add_to_gui_list(ID_TERRAIN_INFO_DLG_EXIT_BUTTON, pBuf);
1356 pTerrain_Info_Dlg->pBeginWidgetList = pBuf;
1357 /* --------------------------------- */
1358 /* redraw */
1359 redraw_group(pTerrain_Info_Dlg->pBeginWidgetList, pWindow, 0);
1360 widget_mark_dirty(pWindow);
1361 flush_dirty();
1363 /* ====================================================================== */
1364 /* ========================= ADVANCED_TERRAIN_MENU ====================== */
1365 /* ====================================================================== */
1366 struct ADVANCED_DLG *pAdvanced_Terrain_Dlg = NULL;
1368 /**************************************************************************
1369 Popdown a generic dialog to display some generic information about
1370 terrain : tile, units , cities, etc.
1371 **************************************************************************/
1372 void popdown_advanced_terrain_dialog(void)
1374 if (pAdvanced_Terrain_Dlg) {
1375 is_unit_move_blocked = FALSE;
1376 popdown_window_group_dialog(pAdvanced_Terrain_Dlg->pBeginWidgetList,
1377 pAdvanced_Terrain_Dlg->pEndWidgetList);
1379 FC_FREE(pAdvanced_Terrain_Dlg->pScroll);
1380 FC_FREE(pAdvanced_Terrain_Dlg);
1384 /**************************************************************************
1385 User selected "Advanced Menu"
1386 **************************************************************************/
1387 int advanced_terrain_window_dlg_callback(struct widget *pWindow)
1389 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1390 move_window_group(pAdvanced_Terrain_Dlg->pBeginWidgetList, pWindow);
1392 return -1;
1395 /**************************************************************************
1396 User requested closing of advanced terrain dialog.
1397 **************************************************************************/
1398 int exit_advanced_terrain_dlg_callback(struct widget *pWidget)
1400 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1401 popdown_advanced_terrain_dialog();
1402 flush_dirty();
1404 return -1;
1407 /**************************************************************************
1408 User requested terrain info.
1409 **************************************************************************/
1410 static int terrain_info_callback(struct widget *pWidget)
1412 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1413 int x = pWidget->data.cont->id0;
1414 int y = pWidget->data.cont->id1;
1416 popdown_advanced_terrain_dialog();
1418 popup_terrain_info_dialog(NULL, map_pos_to_tile(x , y));
1420 return -1;
1423 /**************************************************************************
1424 User requested zoom to city.
1425 **************************************************************************/
1426 static int zoom_to_city_callback(struct widget *pWidget)
1428 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1429 struct city *pCity = pWidget->data.city;
1431 popdown_advanced_terrain_dialog();
1433 popup_city_dialog(pCity);
1435 return -1;
1438 /**************************************************************************
1439 User requested production change.
1440 **************************************************************************/
1441 static int change_production_callback(struct widget *pWidget)
1443 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1444 struct city *pCity = pWidget->data.city;
1445 popdown_advanced_terrain_dialog();
1446 popup_worklist_editor(pCity, NULL);
1448 return -1;
1451 /**************************************************************************
1452 User requested hurry production.
1453 **************************************************************************/
1454 static int hurry_production_callback(struct widget *pWidget)
1456 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1457 struct city *pCity = pWidget->data.city;
1459 popdown_advanced_terrain_dialog();
1461 popup_hurry_production_dialog(pCity, NULL);
1463 return -1;
1466 /**************************************************************************
1467 User requested opening of cma settings.
1468 **************************************************************************/
1469 static int cma_callback(struct widget *pWidget)
1471 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1472 struct city *pCity = pWidget->data.city;
1473 popdown_advanced_terrain_dialog();
1474 popup_city_cma_dialog(pCity);
1476 return -1;
1479 /**************************************************************************
1480 User selected unit.
1481 **************************************************************************/
1482 static int adv_unit_select_callback(struct widget *pWidget)
1484 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1485 struct unit *pUnit = pWidget->data.unit;
1487 popdown_advanced_terrain_dialog();
1489 if (pUnit) {
1490 request_new_unit_activity(pUnit, ACTIVITY_IDLE);
1491 unit_focus_set(pUnit);
1494 return -1;
1497 /**************************************************************************
1498 User selected all units from tile.
1499 **************************************************************************/
1500 static int adv_unit_select_all_callback(struct widget *pWidget)
1502 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1503 struct unit *pUnit = pWidget->data.unit;
1505 popdown_advanced_terrain_dialog();
1507 if (pUnit) {
1508 activate_all_units(unit_tile(pUnit));
1511 return -1;
1514 /**************************************************************************
1515 Sentry unit widget contains.
1516 **************************************************************************/
1517 static int adv_unit_sentry_idle_callback(struct widget *pWidget)
1519 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1520 struct unit *pUnit = pWidget->data.unit;
1522 popdown_advanced_terrain_dialog();
1524 if (pUnit) {
1525 struct tile *ptile = unit_tile(pUnit);
1526 unit_list_iterate(ptile->units, punit) {
1527 if (unit_owner(punit) == client.conn.playing
1528 && ACTIVITY_IDLE == punit->activity
1529 && !punit->ai_controlled
1530 && can_unit_do_activity(punit, ACTIVITY_SENTRY)) {
1531 request_new_unit_activity(punit, ACTIVITY_SENTRY);
1533 } unit_list_iterate_end;
1536 return -1;
1539 /**************************************************************************
1540 Initiate goto to selected tile.
1541 **************************************************************************/
1542 static int goto_here_callback(struct widget *pWidget)
1544 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1545 int x = pWidget->data.cont->id0;
1546 int y = pWidget->data.cont->id1;
1548 popdown_advanced_terrain_dialog();
1550 /* may not work */
1551 send_goto_tile(head_of_units_in_focus(), map_pos_to_tile(x, y));
1553 return -1;
1556 /**************************************************************************
1557 Initiate patrol to selected tile.
1558 **************************************************************************/
1559 static int patrol_here_callback(struct widget *pWidget)
1561 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1563 /* FIXME */
1564 #if 0
1565 int x = pWidget->data.cont->id0;
1566 int y = pWidget->data.cont->id1;
1567 struct unit *pUnit = head_of_units_in_focus();
1568 #endif
1570 popdown_advanced_terrain_dialog();
1572 #if 0
1573 if(pUnit) {
1574 enter_goto_state(pUnit);
1575 /* may not work */
1576 do_unit_patrol_to(pUnit, map_pos_to_tile(x, y));
1577 exit_goto_state();
1579 #endif /* 0 */
1581 return -1;
1584 /**************************************************************************
1585 Initiate paradrop to selected tile.
1586 **************************************************************************/
1587 static int paradrop_here_callback(struct widget *pWidget)
1589 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1590 /* FIXME */
1591 #if 0
1592 int x = pWidget->data.cont->id0;
1593 int y = pWidget->data.cont->id1;
1594 #endif
1596 popdown_advanced_terrain_dialog();
1598 #if 0
1599 /* may not work */
1600 do_unit_paradrop_to(get_unit_in_focus(), map_pos_to_tile(x, y));
1601 #endif
1603 return -1;
1606 /**************************************************************************
1607 Show help about unit type.
1608 **************************************************************************/
1609 static int unit_help_callback(struct widget *pWidget)
1611 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1612 Unit_type_id unit_id = MAX_ID - pWidget->ID;
1614 popdown_advanced_terrain_dialog();
1615 popup_unit_info(unit_id);
1617 return -1;
1620 /**************************************************************************
1621 Popup a generic dialog to display some generic information about
1622 terrain : tile, units , cities, etc.
1623 **************************************************************************/
1624 void popup_advanced_terrain_dialog(struct tile *ptile, Uint16 pos_x, Uint16 pos_y)
1626 struct widget *pWindow = NULL, *pBuf = NULL;
1627 struct city *pCity;
1628 struct unit *pFocus_Unit;
1629 SDL_String16 *pStr;
1630 SDL_Rect area2;
1631 struct CONTAINER *pCont;
1632 char cBuf[255];
1633 int n, w = 0, h, units_h = 0;
1634 SDL_Rect area;
1636 if (pAdvanced_Terrain_Dlg) {
1637 return;
1640 pCity = tile_city(ptile);
1641 n = unit_list_size(ptile->units);
1642 pFocus_Unit = head_of_units_in_focus();
1644 if (!n && !pCity && !pFocus_Unit)
1646 popup_terrain_info_dialog(NULL, ptile);
1647 return;
1650 area.h = adj_size(2);
1651 is_unit_move_blocked = TRUE;
1653 pAdvanced_Terrain_Dlg = fc_calloc(1, sizeof(struct ADVANCED_DLG));
1655 pCont = fc_calloc(1, sizeof(struct CONTAINER));
1656 pCont->id0 = index_to_map_pos_x(tile_index(ptile));
1657 pCont->id1 = index_to_map_pos_y(tile_index(ptile));
1659 pStr = create_str16_from_char(_("Advanced Menu") , adj_font(12));
1660 pStr->style |= TTF_STYLE_BOLD;
1662 pWindow = create_window_skeleton(NULL, pStr, 0);
1664 pWindow->action = advanced_terrain_window_dlg_callback;
1665 set_wstate(pWindow , FC_WS_NORMAL);
1667 add_to_gui_list(ID_TERRAIN_ADV_DLG_WINDOW, pWindow);
1668 pAdvanced_Terrain_Dlg->pEndWidgetList = pWindow;
1670 area = pWindow->area;
1672 /* ---------- */
1673 /* exit button */
1674 pBuf = create_themeicon(current_theme->Small_CANCEL_Icon, pWindow->dst,
1675 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
1676 pBuf->info_label = create_str16_from_char(_("Close Dialog (Esc)"),
1677 adj_font(12));
1678 area.w += pBuf->size.w + adj_size(10);
1679 pBuf->action = exit_advanced_terrain_dlg_callback;
1680 set_wstate(pBuf, FC_WS_NORMAL);
1681 pBuf->key = SDLK_ESCAPE;
1683 add_to_gui_list(ID_TERRAIN_ADV_DLG_EXIT_BUTTON, pBuf);
1684 /* ---------- */
1686 pStr = create_str16_from_char(_("Terrain Info") , adj_font(10));
1687 pStr->style |= TTF_STYLE_BOLD;
1689 pBuf = create_iconlabel(NULL, pWindow->dst, pStr ,
1690 (WF_RESTORE_BACKGROUND|WF_DRAW_TEXT_LABEL_WITH_SPACE|WF_FREE_DATA));
1692 pBuf->string16->bgcol = (SDL_Color) {0, 0, 0, 0};
1694 pBuf->data.cont = pCont;
1696 pBuf->action = terrain_info_callback;
1697 set_wstate(pBuf, FC_WS_NORMAL);
1699 add_to_gui_list(ID_LABEL, pBuf);
1701 area.w = MAX(area.w, pBuf->size.w);
1702 area.h += pBuf->size.h;
1704 /* ---------- */
1705 if (pCity && city_owner(pCity) == client.conn.playing)
1707 /* separator */
1708 pBuf = create_iconlabel(NULL, pWindow->dst, NULL, WF_FREE_THEME);
1710 add_to_gui_list(ID_SEPARATOR, pBuf);
1711 area.h += pBuf->next->size.h;
1712 /* ------------------ */
1714 fc_snprintf(cBuf, sizeof(cBuf), _("Zoom to : %s"), city_name_get(pCity));
1716 create_active_iconlabel(pBuf, pWindow->dst,
1717 pStr, cBuf, zoom_to_city_callback);
1718 pBuf->data.city = pCity;
1719 set_wstate(pBuf, FC_WS_NORMAL);
1721 add_to_gui_list(ID_LABEL, pBuf);
1723 area.w = MAX(area.w, pBuf->size.w);
1724 area.h += pBuf->size.h;
1725 /* ----------- */
1727 create_active_iconlabel(pBuf, pWindow->dst, pStr,
1728 _("Change Production"), change_production_callback);
1730 pBuf->data.city = pCity;
1731 set_wstate(pBuf, FC_WS_NORMAL);
1733 add_to_gui_list(ID_LABEL, pBuf);
1735 area.w = MAX(area.w, pBuf->size.w);
1736 area.h += pBuf->size.h;
1737 /* -------------- */
1739 create_active_iconlabel(pBuf, pWindow->dst, pStr,
1740 _("Hurry production"), hurry_production_callback);
1742 pBuf->data.city = pCity;
1743 set_wstate(pBuf, FC_WS_NORMAL);
1745 add_to_gui_list(ID_LABEL, pBuf);
1747 area.w = MAX(area.w, pBuf->size.w);
1748 area.h += pBuf->size.h;
1749 /* ----------- */
1751 create_active_iconlabel(pBuf, pWindow->dst, pStr,
1752 _("Change City Governor settings"), cma_callback);
1754 pBuf->data.city = pCity;
1755 set_wstate(pBuf, FC_WS_NORMAL);
1757 add_to_gui_list(ID_LABEL, pBuf);
1759 area.w = MAX(area.w, pBuf->size.w);
1760 area.h += pBuf->size.h;
1763 /* ---------- */
1765 if(pFocus_Unit
1766 && (tile_index(unit_tile(pFocus_Unit)) != tile_index(ptile))) {
1767 /* separator */
1768 pBuf = create_iconlabel(NULL, pWindow->dst, NULL, WF_FREE_THEME);
1770 add_to_gui_list(ID_SEPARATOR, pBuf);
1771 area.h += pBuf->next->size.h;
1772 /* ------------------ */
1774 create_active_iconlabel(pBuf, pWindow->dst, pStr, _("Goto here"),
1775 goto_here_callback);
1776 pBuf->data.cont = pCont;
1777 set_wstate(pBuf, FC_WS_NORMAL);
1779 add_to_gui_list(MAX_ID - 1000 - pFocus_Unit->id, pBuf);
1781 area.w = MAX(area.w, pBuf->size.w);
1782 area.h += pBuf->size.h;
1783 /* ----------- */
1785 create_active_iconlabel(pBuf, pWindow->dst, pStr, _("Patrol here"),
1786 patrol_here_callback);
1787 pBuf->data.cont = pCont;
1788 set_wstate(pBuf, FC_WS_NORMAL);
1790 add_to_gui_list(MAX_ID - 1000 - pFocus_Unit->id, pBuf);
1792 area.w = MAX(area.w, pBuf->size.w);
1793 area.h += pBuf->size.h;
1794 /* ----------- */
1796 #if 0 /* FIXME: specific connect buttons */
1797 if(unit_has_type_flag(pFocus_Unit, F_SETTLERS)) {
1798 create_active_iconlabel(pBuf, pWindow->dst->surface, pStr, _("Connect here"),
1799 connect_here_callback);
1800 pBuf->data.cont = pCont;
1801 set_wstate(pBuf, FC_WS_NORMAL);
1803 add_to_gui_list(ID_LABEL, pBuf);
1805 area.w = MAX(area.w, pBuf->size.w);
1806 area.h += pBuf->size.h;
1809 #endif /* 0 */
1811 /* FIXME: This logic seems to try to mirror do_paradrop() why? */
1812 if(can_unit_paradrop(pFocus_Unit) && client_tile_get_known(ptile) &&
1813 !(((pCity && pplayers_non_attack(client.conn.playing, city_owner(pCity)))
1814 || is_non_attack_unit_tile(ptile, client.conn.playing))) &&
1815 (unit_type_get(pFocus_Unit)->paratroopers_range >=
1816 real_map_distance(unit_tile(pFocus_Unit), ptile))) {
1818 create_active_iconlabel(pBuf, pWindow->dst, pStr, _("Paradrop here"),
1819 paradrop_here_callback);
1820 pBuf->data.cont = pCont;
1821 set_wstate(pBuf, FC_WS_NORMAL);
1823 add_to_gui_list(ID_LABEL, pBuf);
1825 area.w = MAX(area.w, pBuf->size.w);
1826 area.h += pBuf->size.h;
1831 pAdvanced_Terrain_Dlg->pBeginWidgetList = pBuf;
1833 /* ---------- */
1834 if (n)
1836 int i;
1837 struct unit *pUnit;
1838 struct unit_type *pUnitType = NULL;
1839 units_h = 0;
1840 /* separator */
1841 pBuf = create_iconlabel(NULL, pWindow->dst, NULL, WF_FREE_THEME);
1843 add_to_gui_list(ID_SEPARATOR, pBuf);
1844 area.h += pBuf->next->size.h;
1845 /* ---------- */
1846 if (n > 1)
1848 struct unit *pDefender, *pAttacker;
1849 struct widget *pLast = pBuf;
1850 bool reset = FALSE;
1851 int my_units = 0;
1852 const char *vetname;
1854 #define ADV_NUM_SEEN 15
1856 pDefender = (pFocus_Unit ? get_defender(pFocus_Unit, ptile) : NULL);
1857 pAttacker = (pFocus_Unit ? get_attacker(pFocus_Unit, ptile) : NULL);
1858 for (i = 0; i < n; i++) {
1859 pUnit = unit_list_get(ptile->units, i);
1860 if (pUnit == pFocus_Unit) {
1861 continue;
1863 pUnitType = unit_type_get(pUnit);
1864 vetname = utype_veteran_name_translation(pUnitType, pUnit->veteran);
1866 if (unit_owner(pUnit) == client.conn.playing) {
1867 fc_snprintf(cBuf, sizeof(cBuf),
1868 _("Activate %s (%d / %d) %s (%d,%d,%s) %s"),
1869 (vetname != NULL ? vetname : ""),
1870 pUnit->hp, pUnitType->hp,
1871 utype_name_translation(pUnitType),
1872 pUnitType->attack_strength,
1873 pUnitType->defense_strength,
1874 move_points_text(pUnitType->move_rate, FALSE),
1875 unit_activity_text(pUnit));
1877 create_active_iconlabel(pBuf, pWindow->dst, pStr,
1878 cBuf, adv_unit_select_callback);
1879 pBuf->data.unit = pUnit;
1880 set_wstate(pBuf, FC_WS_NORMAL);
1881 add_to_gui_list(ID_LABEL, pBuf);
1882 my_units++;
1883 } else {
1884 int att_chance, def_chance;
1886 fc_snprintf(cBuf, sizeof(cBuf), _("%s %s %s (A:%d D:%d M:%s FP:%d) HP:%d%%"),
1887 nation_adjective_for_player(unit_owner(pUnit)),
1888 (vetname != NULL ? vetname : ""),
1889 utype_name_translation(pUnitType),
1890 pUnitType->attack_strength,
1891 pUnitType->defense_strength,
1892 move_points_text(pUnitType->move_rate, FALSE),
1893 pUnitType->firepower,
1894 ((pUnit->hp * 100) / pUnitType->hp));
1896 /* calculate chance to win */
1897 if (sdl_get_chance_to_win(&att_chance, &def_chance, pUnit, pFocus_Unit)) {
1898 /* TRANS: "CtW" = "Chance to Win" */
1899 cat_snprintf(cBuf, sizeof(cBuf), _(" CtW: Att:%d%% Def:%d%%"),
1900 att_chance, def_chance);
1903 if (pAttacker && pAttacker == pUnit) {
1904 pStr->fgcol = *(get_game_color(COLOR_OVERVIEW_ENEMY_UNIT));
1905 reset = TRUE;
1906 } else {
1907 if (pDefender && pDefender == pUnit) {
1908 pStr->fgcol = *(get_game_color(COLOR_OVERVIEW_MY_UNIT));
1909 reset = TRUE;
1913 create_active_iconlabel(pBuf, pWindow->dst, pStr, cBuf, NULL);
1915 if (reset) {
1916 pStr->fgcol = *get_theme_color(COLOR_THEME_ADVANCEDTERRAINDLG_TEXT);
1917 reset = FALSE;
1920 add_to_gui_list(ID_LABEL, pBuf);
1923 area.w = MAX(area.w, pBuf->size.w);
1924 units_h += pBuf->size.h;
1926 if (i > ADV_NUM_SEEN - 1)
1928 set_wflag(pBuf, WF_HIDDEN);
1933 pAdvanced_Terrain_Dlg->pEndActiveWidgetList = pLast->prev;
1934 pAdvanced_Terrain_Dlg->pActiveWidgetList = pAdvanced_Terrain_Dlg->pEndActiveWidgetList;
1935 pAdvanced_Terrain_Dlg->pBeginWidgetList = pBuf;
1936 pAdvanced_Terrain_Dlg->pBeginActiveWidgetList = pAdvanced_Terrain_Dlg->pBeginWidgetList;
1938 if(n > ADV_NUM_SEEN)
1940 units_h = ADV_NUM_SEEN * pBuf->size.h;
1941 n = create_vertical_scrollbar(pAdvanced_Terrain_Dlg,
1942 1, ADV_NUM_SEEN, TRUE, TRUE);
1943 area.w += n;
1946 if (my_units > 1) {
1948 fc_snprintf(cBuf, sizeof(cBuf), "%s (%d)", _("Ready all"), my_units);
1949 create_active_iconlabel(pBuf, pWindow->dst, pStr,
1950 cBuf, adv_unit_select_all_callback);
1951 pBuf->data.unit = pAdvanced_Terrain_Dlg->pEndActiveWidgetList->data.unit;
1952 set_wstate(pBuf, FC_WS_NORMAL);
1953 pBuf->ID = ID_LABEL;
1954 DownAdd(pBuf, pLast);
1955 area.h += pBuf->size.h;
1957 fc_snprintf(cBuf, sizeof(cBuf), "%s (%d)", _("Sentry idle"), my_units);
1958 create_active_iconlabel(pBuf, pWindow->dst, pStr,
1959 cBuf, adv_unit_sentry_idle_callback);
1960 pBuf->data.unit = pAdvanced_Terrain_Dlg->pEndActiveWidgetList->data.unit;
1961 set_wstate(pBuf, FC_WS_NORMAL);
1962 pBuf->ID = ID_LABEL;
1963 DownAdd(pBuf, pLast->prev);
1964 area.h += pBuf->size.h;
1966 /* separator */
1967 pBuf = create_iconlabel(NULL, pWindow->dst, NULL, WF_FREE_THEME);
1968 pBuf->ID = ID_SEPARATOR;
1969 DownAdd(pBuf, pLast->prev->prev);
1970 area.h += pBuf->next->size.h;
1973 #undef ADV_NUM_SEEN
1975 else
1976 { /* n == 1 */
1977 /* one unit - give orders */
1978 pUnit = unit_list_get(ptile->units, 0);
1979 pUnitType = unit_type_get(pUnit);
1980 if (pUnit != pFocus_Unit) {
1981 const char *vetname;
1983 vetname = utype_veteran_name_translation(pUnitType, pUnit->veteran);
1984 if ((pCity && city_owner(pCity) == client.conn.playing)
1985 || (unit_owner(pUnit) == client.conn.playing)) {
1986 fc_snprintf(cBuf, sizeof(cBuf),
1987 _("Activate %s (%d / %d) %s (%d,%d,%s) %s"),
1988 (vetname != NULL ? vetname : ""),
1989 pUnit->hp, pUnitType->hp,
1990 utype_name_translation(pUnitType),
1991 pUnitType->attack_strength,
1992 pUnitType->defense_strength,
1993 move_points_text(pUnitType->move_rate, FALSE),
1994 unit_activity_text(pUnit));
1996 create_active_iconlabel(pBuf, pWindow->dst, pStr,
1997 cBuf, adv_unit_select_callback);
1998 pBuf->data.unit = pUnit;
1999 set_wstate(pBuf, FC_WS_NORMAL);
2001 add_to_gui_list(ID_LABEL, pBuf);
2003 area.w = MAX(area.w, pBuf->size.w);
2004 units_h += pBuf->size.h;
2005 /* ---------------- */
2006 /* separator */
2007 pBuf = create_iconlabel(NULL, pWindow->dst, NULL, WF_FREE_THEME);
2009 add_to_gui_list(ID_SEPARATOR, pBuf);
2010 area.h += pBuf->next->size.h;
2011 } else {
2012 int att_chance, def_chance;
2014 fc_snprintf(cBuf, sizeof(cBuf), _("%s %s %s (A:%d D:%d M:%s FP:%d) HP:%d%%"),
2015 nation_adjective_for_player(unit_owner(pUnit)),
2016 (vetname != NULL ? vetname : ""),
2017 utype_name_translation(pUnitType),
2018 pUnitType->attack_strength,
2019 pUnitType->defense_strength,
2020 move_points_text(pUnitType->move_rate, FALSE),
2021 pUnitType->firepower,
2022 ((pUnit->hp * 100) / pUnitType->hp));
2024 /* calculate chance to win */
2025 if (sdl_get_chance_to_win(&att_chance, &def_chance, pUnit, pFocus_Unit)) {
2026 cat_snprintf(cBuf, sizeof(cBuf), _(" CtW: Att:%d%% Def:%d%%"),
2027 att_chance, def_chance);
2029 create_active_iconlabel(pBuf, pWindow->dst, pStr, cBuf, NULL);
2030 add_to_gui_list(ID_LABEL, pBuf);
2031 area.w = MAX(area.w, pBuf->size.w);
2032 units_h += pBuf->size.h;
2033 /* ---------------- */
2035 /* separator */
2036 pBuf = create_iconlabel(NULL, pWindow->dst, NULL, WF_FREE_THEME);
2038 add_to_gui_list(ID_SEPARATOR, pBuf);
2039 area.h += pBuf->next->size.h;
2043 /* ---------------- */
2044 fc_snprintf(cBuf, sizeof(cBuf),
2045 _("Look up \"%s\" in the Help Browser"),
2046 utype_name_translation(pUnitType));
2047 create_active_iconlabel(pBuf, pWindow->dst, pStr,
2048 cBuf, unit_help_callback);
2049 set_wstate(pBuf , FC_WS_NORMAL);
2050 add_to_gui_list(MAX_ID - utype_number(pUnitType), pBuf);
2052 area.w = MAX(area.w, pBuf->size.w);
2053 units_h += pBuf->size.h;
2054 /* ---------------- */
2055 pAdvanced_Terrain_Dlg->pBeginWidgetList = pBuf;
2059 /* ---------- */
2061 area.w += adj_size(2);
2062 area.h += units_h;
2064 resize_window(pWindow, NULL, NULL,
2065 (pWindow->size.w - pWindow->area.w) + area.w,
2066 (pWindow->size.h - pWindow->area.h) + area.h);
2068 area = pWindow->area;
2070 widget_set_position(pWindow, pos_x, pos_y);
2072 w = area.w - adj_size(2);
2074 if (pAdvanced_Terrain_Dlg->pScroll) {
2075 units_h = n;
2076 } else {
2077 units_h = 0;
2080 /* exit button */
2081 pBuf = pWindow->prev;
2083 pBuf->size.x = area.x + area.w - pBuf->size.w - 1;
2084 pBuf->size.y = pWindow->size.y + adj_size(2);
2086 /* terrain info */
2087 pBuf = pBuf->prev;
2089 pBuf->size.x = area.x + 1;
2090 pBuf->size.y = area.y + 1;
2091 pBuf->size.w = w;
2092 h = pBuf->size.h;
2094 area2.x = adj_size(10);
2095 area2.h = adj_size(2);
2097 pBuf = pBuf->prev;
2098 while(pBuf)
2101 if (pBuf == pAdvanced_Terrain_Dlg->pEndActiveWidgetList)
2103 w -= units_h;
2106 pBuf->size.w = w;
2107 pBuf->size.x = pBuf->next->size.x;
2108 pBuf->size.y = pBuf->next->size.y + pBuf->next->size.h;
2110 if (pBuf->ID == ID_SEPARATOR)
2112 FREESURFACE(pBuf->theme);
2113 pBuf->size.h = h;
2114 pBuf->theme = create_surf_alpha(w , h , SDL_SWSURFACE);
2116 area2.y = pBuf->size.h / 2 - 1;
2117 area2.w = pBuf->size.w - adj_size(20);
2119 SDL_FillRect(pBuf->theme, &area2, map_rgba(pBuf->theme->format,
2120 *get_theme_color(COLOR_THEME_ADVANCEDTERRAINDLG_TEXT)));
2123 if(pBuf == pAdvanced_Terrain_Dlg->pBeginWidgetList ||
2124 pBuf == pAdvanced_Terrain_Dlg->pBeginActiveWidgetList) {
2125 break;
2127 pBuf = pBuf->prev;
2130 if (pAdvanced_Terrain_Dlg->pScroll)
2132 setup_vertical_scrollbar_area(pAdvanced_Terrain_Dlg->pScroll,
2133 area.x + area.w,
2134 pAdvanced_Terrain_Dlg->pEndActiveWidgetList->size.y,
2135 area.y - pAdvanced_Terrain_Dlg->pEndActiveWidgetList->size.y + area.h,
2136 TRUE);
2139 /* -------------------- */
2140 /* redraw */
2141 redraw_group(pAdvanced_Terrain_Dlg->pBeginWidgetList, pWindow, 0);
2143 widget_flush(pWindow);
2146 /* ====================================================================== */
2147 /* ============================ PILLAGE DIALOG ========================== */
2148 /* ====================================================================== */
2149 static struct SMALL_DLG *pPillage_Dlg = NULL;
2151 /**************************************************************************
2152 User interacted with pillage dialog.
2153 **************************************************************************/
2154 static int pillage_window_callback(struct widget *pWindow)
2156 if (Main.event.button.button == SDL_BUTTON_LEFT) {
2157 move_window_group(pPillage_Dlg->pBeginWidgetList, pWindow);
2159 return -1;
2162 /**************************************************************************
2163 User selected what to pillage.
2164 **************************************************************************/
2165 static int pillage_callback(struct widget *pWidget)
2167 if (Main.event.button.button == SDL_BUTTON_LEFT) {
2168 struct unit *pUnit = pWidget->data.unit;
2169 int what = MAX_ID - pWidget->ID;
2171 popdown_pillage_dialog();
2173 if (pUnit)
2175 struct extra_type *target = extra_by_number(what);
2177 request_new_unit_activity_targeted(pUnit, ACTIVITY_PILLAGE, target);
2180 return -1;
2183 /**************************************************************************
2184 User requested closing of pillage dialog.
2185 **************************************************************************/
2186 static int exit_pillage_dlg_callback(struct widget *pWidget)
2188 if (Main.event.button.button == SDL_BUTTON_LEFT) {
2189 popdown_pillage_dialog();
2191 return -1;
2194 /**************************************************************************
2195 Popdown a dialog asking the unit which improvement they would like to
2196 pillage.
2197 **************************************************************************/
2198 static void popdown_pillage_dialog(void)
2200 if (pPillage_Dlg) {
2201 is_unit_move_blocked = FALSE;
2202 popdown_window_group_dialog(pPillage_Dlg->pBeginWidgetList,
2203 pPillage_Dlg->pEndWidgetList);
2204 FC_FREE(pPillage_Dlg);
2205 flush_dirty();
2209 /**************************************************************************
2210 Popup a dialog asking the unit which improvement they would like to
2211 pillage.
2212 **************************************************************************/
2213 void popup_pillage_dialog(struct unit *pUnit, bv_extras extras)
2215 struct widget *pWindow = NULL, *pBuf = NULL;
2216 SDL_String16 *pStr;
2217 SDL_Rect area;
2218 struct extra_type *tgt;
2220 if (pPillage_Dlg) {
2221 return;
2224 is_unit_move_blocked = TRUE;
2225 pPillage_Dlg = fc_calloc(1, sizeof(struct SMALL_DLG));
2227 /* window */
2228 pStr = create_str16_from_char(_("What To Pillage") , adj_font(12));
2229 pStr->style |= TTF_STYLE_BOLD;
2231 pWindow = create_window_skeleton(NULL, pStr, 0);
2233 pWindow->action = pillage_window_callback;
2234 set_wstate(pWindow, FC_WS_NORMAL);
2236 add_to_gui_list(ID_PILLAGE_DLG_WINDOW, pWindow);
2237 pPillage_Dlg->pEndWidgetList = pWindow;
2239 area = pWindow->area;
2241 area.h = MAX(area.h, adj_size(2));
2243 /* ---------- */
2244 /* exit button */
2245 pBuf = create_themeicon(current_theme->Small_CANCEL_Icon, pWindow->dst,
2246 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
2247 pBuf->info_label = create_str16_from_char(_("Close Dialog (Esc)"),
2248 adj_font(12));
2249 area.w += pBuf->size.w + adj_size(10);
2250 pBuf->action = exit_pillage_dlg_callback;
2251 set_wstate(pBuf, FC_WS_NORMAL);
2252 pBuf->key = SDLK_ESCAPE;
2254 add_to_gui_list(ID_PILLAGE_DLG_EXIT_BUTTON, pBuf);
2255 /* ---------- */
2257 while ((tgt = get_preferred_pillage(extras))) {
2258 const char *name = NULL;
2259 int what;
2261 BV_CLR(extras, extra_index(tgt));
2262 name = extra_name_translation(tgt);
2263 what = extra_index(tgt);
2265 fc_assert(name != NULL);
2267 create_active_iconlabel(pBuf, pWindow->dst, pStr,
2268 (char *) name, pillage_callback);
2270 pBuf->data.unit = pUnit;
2271 set_wstate(pBuf, FC_WS_NORMAL);
2273 add_to_gui_list(MAX_ID - what, pBuf);
2275 area.w = MAX(area.w, pBuf->size.w);
2276 area.h += pBuf->size.h;
2278 pPillage_Dlg->pBeginWidgetList = pBuf;
2280 /* setup window size and start position */
2282 resize_window(pWindow, NULL, NULL,
2283 (pWindow->size.w - pWindow->area.w) + area.w,
2284 (pWindow->size.h - pWindow->area.h) + area.h);
2286 area = pWindow->area;
2288 put_window_near_map_tile(pWindow, pWindow->size.w, pWindow->size.h,
2289 unit_tile(pUnit));
2291 /* setup widget size and start position */
2293 /* exit button */
2294 pBuf = pWindow->prev;
2295 pBuf->size.x = area.x + area.w - pBuf->size.w - 1;
2296 pBuf->size.y = pWindow->size.y + adj_size(2);
2298 /* first special to pillage */
2299 pBuf = pBuf->prev;
2300 setup_vertical_widgets_position(1,
2301 area.x, area.y + 1, area.w, 0,
2302 pPillage_Dlg->pBeginWidgetList, pBuf);
2304 /* --------------------- */
2305 /* redraw */
2306 redraw_group(pPillage_Dlg->pBeginWidgetList, pWindow, 0);
2308 widget_flush(pWindow);
2311 /* ======================================================================= */
2312 /* =========================== CONNECT DIALOG ============================ */
2313 /* ======================================================================= */
2314 static struct SMALL_DLG *pConnect_Dlg = NULL;
2316 /**************************************************************************
2317 Popdown a dialog asking the unit how they want to "connect" their
2318 location to the destination.
2319 **************************************************************************/
2320 static void popdown_connect_dialog(void)
2322 if (pConnect_Dlg) {
2323 is_unit_move_blocked = FALSE;
2324 popdown_window_group_dialog(pConnect_Dlg->pBeginWidgetList,
2325 pConnect_Dlg->pEndWidgetList);
2326 FC_FREE(pConnect_Dlg);
2330 /**************************************************************************
2331 Revolutions
2332 **************************************************************************/
2333 static struct SMALL_DLG *pRevolutionDlg = NULL;
2335 /**************************************************************************
2336 User confirmed revolution.
2337 **************************************************************************/
2338 static int revolution_dlg_ok_callback(struct widget *pButton)
2340 if (Main.event.button.button == SDL_BUTTON_LEFT) {
2341 start_revolution();
2343 popdown_revolution_dialog();
2345 flush_dirty();
2347 return (-1);
2350 /**************************************************************************
2351 User cancelled revolution.
2352 **************************************************************************/
2353 static int revolution_dlg_cancel_callback(struct widget *pCancel_Button)
2355 if (Main.event.button.button == SDL_BUTTON_LEFT) {
2356 popdown_revolution_dialog();
2357 flush_dirty();
2359 return (-1);
2362 /**************************************************************************
2363 User requested move of revolution dialog.
2364 **************************************************************************/
2365 static int move_revolution_dlg_callback(struct widget *pWindow)
2367 if (Main.event.button.button == SDL_BUTTON_LEFT) {
2368 move_window_group(pRevolutionDlg->pBeginWidgetList, pWindow);
2370 return -1;
2373 /**************************************************************************
2374 Close the revolution dialog.
2375 **************************************************************************/
2376 static void popdown_revolution_dialog(void)
2378 if(pRevolutionDlg) {
2379 popdown_window_group_dialog(pRevolutionDlg->pBeginWidgetList,
2380 pRevolutionDlg->pEndWidgetList);
2381 FC_FREE(pRevolutionDlg);
2382 enable_and_redraw_revolution_button();
2386 /* ==================== Public ========================= */
2388 /**************************************************************************
2389 Sellect Goverment Type
2390 **************************************************************************/
2391 static struct SMALL_DLG *pGov_Dlg = NULL;
2393 /**************************************************************************
2394 Close the government dialog.
2395 **************************************************************************/
2396 static void popdown_government_dialog(void)
2398 if(pGov_Dlg) {
2399 popdown_window_group_dialog(pGov_Dlg->pBeginWidgetList,
2400 pGov_Dlg->pEndWidgetList);
2401 FC_FREE(pGov_Dlg);
2402 enable_and_redraw_revolution_button();
2406 /**************************************************************************
2407 User selected government button.
2408 **************************************************************************/
2409 static int government_dlg_callback(struct widget *pGov_Button)
2411 if (Main.event.button.button == SDL_BUTTON_LEFT) {
2412 set_government_choice(government_by_number(MAX_ID - pGov_Button->ID));
2414 popdown_government_dialog();
2416 return (-1);
2419 /**************************************************************************
2420 User requested move of government dialog.
2421 **************************************************************************/
2422 static int move_government_dlg_callback(struct widget *pWindow)
2424 if (Main.event.button.button == SDL_BUTTON_LEFT) {
2425 move_window_group(pGov_Dlg->pBeginWidgetList, pWindow);
2427 return -1;
2430 /**************************************************************************
2431 Public -
2433 Popup a dialog asking the player what government to switch to (this
2434 happens after a revolution completes).
2435 **************************************************************************/
2436 static void popup_government_dialog(void)
2438 SDL_Surface *pLogo = NULL;
2439 struct SDL_String16 *pStr = NULL;
2440 struct widget *pGov_Button = NULL;
2441 struct widget *pWindow = NULL;
2442 int j;
2443 Uint16 max_w = 0, max_h = 0;
2444 SDL_Rect area;
2446 if (pGov_Dlg) {
2447 return;
2450 pGov_Dlg = fc_calloc(1, sizeof(struct SMALL_DLG));
2452 /* create window */
2453 pStr = create_str16_from_char(_("Choose Your New Government"), adj_font(12));
2454 pStr->style |= TTF_STYLE_BOLD;
2455 /* this win. size is temp. */
2456 pWindow = create_window_skeleton(NULL, pStr, 0);
2457 pWindow->action = move_government_dlg_callback;
2458 add_to_gui_list(ID_GOVERNMENT_DLG_WINDOW, pWindow);
2460 pGov_Dlg->pEndWidgetList = pWindow;
2462 area = pWindow->area;
2464 /* create gov. buttons */
2465 j = 0;
2466 governments_iterate(pGov) {
2468 if (pGov == game.government_during_revolution) {
2469 continue;
2472 if (can_change_to_government(client.conn.playing, pGov)) {
2474 pStr = create_str16_from_char(government_name_translation(pGov), adj_font(12));
2475 pGov_Button =
2476 create_icon_button(get_government_surface(pGov), pWindow->dst, pStr, 0);
2477 pGov_Button->action = government_dlg_callback;
2479 max_w = MAX(max_w, pGov_Button->size.w);
2480 max_h = MAX(max_h, pGov_Button->size.h);
2482 /* ugly hack */
2483 add_to_gui_list((MAX_ID - government_number(pGov)), pGov_Button);
2484 j++;
2487 } governments_iterate_end;
2489 pGov_Dlg->pBeginWidgetList = pGov_Button;
2491 max_w += adj_size(10);
2492 max_h += adj_size(4);
2494 area.w = MAX(area.w, max_w + adj_size(20));
2495 area.h = MAX(area.h, j * (max_h + adj_size(10)) + adj_size(5));
2497 /* create window background */
2498 pLogo = theme_get_background(theme, BACKGROUND_CHOOSEGOVERNMENTDLG);
2499 if (resize_window(pWindow, pLogo, NULL,
2500 (pWindow->size.w - pWindow->area.w) + area.w,
2501 (pWindow->size.h - pWindow->area.h) + area.h)) {
2502 FREESURFACE(pLogo);
2505 area = pWindow->area;
2507 /* set window start positions */
2508 widget_set_position(pWindow,
2509 (Main.screen->w - pWindow->size.w) / 2,
2510 (Main.screen->h - pWindow->size.h) / 2);
2512 /* set buttons start positions and size */
2513 j = 1;
2514 while (pGov_Button != pGov_Dlg->pEndWidgetList) {
2515 pGov_Button->size.w = max_w;
2516 pGov_Button->size.h = max_h;
2517 pGov_Button->size.x = area.x + adj_size(10);
2518 pGov_Button->size.y = area.y + area.h - (j++) * (max_h + adj_size(10));
2519 set_wstate(pGov_Button, FC_WS_NORMAL);
2521 pGov_Button = pGov_Button->next;
2524 set_wstate(pWindow, FC_WS_NORMAL);
2526 /* redraw */
2527 redraw_group(pGov_Dlg->pBeginWidgetList, pWindow, 0);
2529 widget_flush(pWindow);
2532 /**************************************************************************
2533 Popup a dialog asking if the player wants to start a revolution.
2534 **************************************************************************/
2535 void popup_revolution_dialog(void)
2537 SDL_Surface *pLogo;
2538 struct SDL_String16 *pStr = NULL;
2539 struct widget *pLabel = NULL;
2540 struct widget *pWindow = NULL;
2541 struct widget *pCancel_Button = NULL;
2542 struct widget *pOK_Button = NULL;
2543 SDL_Rect area;
2545 if(pRevolutionDlg) {
2546 return;
2549 if (0 <= client.conn.playing->revolution_finishes) {
2550 popup_government_dialog();
2551 return;
2554 pRevolutionDlg = fc_calloc(1, sizeof(struct SMALL_DLG));
2556 pStr = create_str16_from_char(_("REVOLUTION!"), adj_font(12));
2557 pStr->style |= TTF_STYLE_BOLD;
2559 pWindow = create_window_skeleton(NULL, pStr, 0);
2560 pWindow->action = move_revolution_dlg_callback;
2561 set_wstate(pWindow, FC_WS_NORMAL);
2562 add_to_gui_list(ID_REVOLUTION_DLG_WINDOW, pWindow);
2563 pRevolutionDlg->pEndWidgetList = pWindow;
2565 area = pWindow->area;
2567 /* create text label */
2568 pStr = create_str16_from_char(_("You say you wanna revolution?"), adj_font(10));
2569 pStr->style |= (TTF_STYLE_BOLD|SF_CENTER);
2570 pStr->fgcol = *get_theme_color(COLOR_THEME_REVOLUTIONDLG_TEXT);
2571 pLabel = create_iconlabel(NULL, pWindow->dst, pStr, 0);
2572 add_to_gui_list(ID_REVOLUTION_DLG_LABEL, pLabel);
2575 /* create cancel button */
2576 pCancel_Button =
2577 create_themeicon_button_from_chars(current_theme->Small_CANCEL_Icon,
2578 pWindow->dst, _("Cancel"), adj_font(10), 0);
2579 pCancel_Button->action = revolution_dlg_cancel_callback;
2580 pCancel_Button->size.w += adj_size(6);
2581 set_wstate(pCancel_Button, FC_WS_NORMAL);
2582 add_to_gui_list(ID_REVOLUTION_DLG_CANCEL_BUTTON, pCancel_Button);
2584 /* create ok button */
2585 pOK_Button =
2586 create_themeicon_button_from_chars(current_theme->Small_OK_Icon,
2587 pWindow->dst, _("Revolution!"),
2588 adj_font(10), 0);
2589 pOK_Button->action = revolution_dlg_ok_callback;
2590 pOK_Button->key = SDLK_RETURN;
2591 set_wstate(pOK_Button, FC_WS_NORMAL);
2592 add_to_gui_list(ID_REVOLUTION_DLG_OK_BUTTON, pOK_Button);
2594 pRevolutionDlg->pBeginWidgetList = pOK_Button;
2596 if ((pOK_Button->size.w + pCancel_Button->size.w + adj_size(30)) >
2597 pLabel->size.w + adj_size(20)) {
2598 area.w = MAX(area.w, pOK_Button->size.w + pCancel_Button->size.w + adj_size(30));
2599 } else {
2600 area.w = MAX(area.w, pLabel->size.w + adj_size(20));
2603 area.h = MAX(area.h, pOK_Button->size.h + pLabel->size.h + adj_size(24));
2605 /* create window background */
2606 pLogo = theme_get_background(theme, BACKGROUND_REVOLUTIONDLG);
2607 if (resize_window(pWindow, pLogo, NULL,
2608 (pWindow->size.w - pWindow->area.w) + area.w,
2609 (pWindow->size.h - pWindow->area.h) + area.h)) {
2610 FREESURFACE(pLogo);
2613 area = pWindow->area;
2615 /* set start positions */
2616 widget_set_position(pWindow,
2617 (Main.screen->w - pWindow->size.w) / 2,
2618 (Main.screen->h - pWindow->size.h) / 2);
2620 pOK_Button->size.x = area.x + adj_size(10);
2621 pOK_Button->size.y = area.y + area.h - pOK_Button->size.h - adj_size(10);
2623 pCancel_Button->size.y = pOK_Button->size.y;
2624 pCancel_Button->size.x = area.x + area.w - pCancel_Button->size.w - adj_size(10);
2626 pLabel->size.x = area.x;
2627 pLabel->size.y = area.y + adj_size(4);
2628 pLabel->size.w = area.w;
2630 /* redraw */
2631 redraw_group(pOK_Button, pWindow, 0);
2632 widget_mark_dirty(pWindow);
2633 flush_dirty();
2636 /**************************************************************************
2637 Nation Wizard
2638 **************************************************************************/
2639 static struct ADVANCED_DLG *pNationDlg = NULL;
2640 static struct SMALL_DLG *pHelpDlg = NULL;
2642 struct NAT {
2643 unsigned char nation_style; /* selected style */
2644 unsigned char selected_leader; /* if not unique -> selected leader */
2645 Nation_type_id nation; /* selected nation */
2646 bool leader_sex; /* selected leader sex */
2647 struct nation_set *set;
2648 struct widget *pChange_Sex;
2649 struct widget *pName_Edit;
2650 struct widget *pName_Next;
2651 struct widget *pName_Prev;
2652 struct widget *pset_name;
2653 struct widget *pset_next;
2654 struct widget *pset_prev;
2657 static int next_set_callback(struct widget *next_button);
2658 static int prev_set_callback(struct widget *prev_button);
2659 static int nations_dialog_callback(struct widget *pWindow);
2660 static int nation_button_callback(struct widget *pNation);
2661 static int races_dialog_ok_callback(struct widget *pStart_Button);
2662 static int races_dialog_cancel_callback(struct widget *pButton);
2663 static int next_name_callback(struct widget *pNext_Button);
2664 static int prev_name_callback(struct widget *pPrev_Button);
2665 static int change_sex_callback(struct widget *pSex);
2666 static void select_random_leader(Nation_type_id nation);
2667 static void change_nation_label(void);
2669 /**************************************************************************
2670 User interaceted with nations dialog.
2671 **************************************************************************/
2672 static int nations_dialog_callback(struct widget *pWindow)
2674 if (Main.event.button.button == SDL_BUTTON_LEFT) {
2675 if(sellect_window_group_dialog(pNationDlg->pBeginWidgetList, pWindow)) {
2676 widget_flush(pWindow);
2679 return -1;
2682 /**************************************************************************
2683 User accepted nation.
2684 **************************************************************************/
2685 static int races_dialog_ok_callback(struct widget *pStart_Button)
2687 if (Main.event.button.button == SDL_BUTTON_LEFT) {
2688 struct NAT *pSetup = (struct NAT *)(pNationDlg->pEndWidgetList->data.ptr);
2689 char *pStr = convert_to_chars(pSetup->pName_Edit->string16->text);
2691 /* perform a minimum of sanity test on the name */
2692 if (strlen(pStr) == 0) {
2693 output_window_append(ftc_client, _("You must type a legal name."));
2694 pSellected_Widget = pStart_Button;
2695 set_wstate(pStart_Button, FC_WS_SELLECTED);
2696 widget_redraw(pStart_Button);
2697 widget_flush(pStart_Button);
2698 return (-1);
2701 dsend_packet_nation_select_req(&client.conn, player_number(races_player),
2702 pSetup->nation,
2703 pSetup->leader_sex, pStr,
2704 pSetup->nation_style);
2705 FC_FREE(pStr);
2707 popdown_races_dialog();
2708 flush_dirty();
2710 return -1;
2713 /**************************************************************************
2714 User requested leader gender change.
2715 **************************************************************************/
2716 static int change_sex_callback(struct widget *pSex)
2718 if (Main.event.button.button == SDL_BUTTON_LEFT) {
2719 struct NAT *pSetup = (struct NAT *)(pNationDlg->pEndWidgetList->data.ptr);
2721 if (pSetup->leader_sex) {
2722 copy_chars_to_string16(pSetup->pChange_Sex->string16, _("Female"));
2723 } else {
2724 copy_chars_to_string16(pSetup->pChange_Sex->string16, _("Male"));
2726 pSetup->leader_sex = !pSetup->leader_sex;
2728 if (pSex) {
2729 pSellected_Widget = pSex;
2730 set_wstate(pSex, FC_WS_SELLECTED);
2732 widget_redraw(pSex);
2733 widget_flush(pSex);
2736 return -1;
2739 /**************************************************************************
2740 User requested next leader name.
2741 **************************************************************************/
2742 static int next_name_callback(struct widget *pNext)
2744 if (Main.event.button.button == SDL_BUTTON_LEFT) {
2745 struct NAT *pSetup = (struct NAT *)(pNationDlg->pEndWidgetList->data.ptr);
2746 const struct nation_leader_list *leaders =
2747 nation_leaders(nation_by_number(pSetup->nation));
2748 const struct nation_leader *pleader;
2750 pSetup->selected_leader++;
2751 pleader = nation_leader_list_get(leaders, pSetup->selected_leader);
2753 /* change leadaer sex */
2754 if (pSetup->leader_sex != nation_leader_is_male(pleader)) {
2755 change_sex_callback(NULL);
2758 /* change leadaer name */
2759 copy_chars_to_string16(pSetup->pName_Edit->string16,
2760 nation_leader_name(pleader));
2762 FC_FREE(pLeaderName);
2763 pLeaderName = fc_strdup(nation_leader_name(pleader));
2765 if (nation_leader_list_size(leaders) - 1 == pSetup->selected_leader) {
2766 set_wstate(pSetup->pName_Next, FC_WS_DISABLED);
2769 if (get_wstate(pSetup->pName_Prev) == FC_WS_DISABLED) {
2770 set_wstate(pSetup->pName_Prev, FC_WS_NORMAL);
2773 if (!(get_wstate(pSetup->pName_Next) == FC_WS_DISABLED)) {
2774 pSellected_Widget = pSetup->pName_Next;
2775 set_wstate(pSetup->pName_Next, FC_WS_SELLECTED);
2778 widget_redraw(pSetup->pName_Edit);
2779 widget_redraw(pSetup->pName_Prev);
2780 widget_redraw(pSetup->pName_Next);
2781 widget_mark_dirty(pSetup->pName_Edit);
2782 widget_mark_dirty(pSetup->pName_Prev);
2783 widget_mark_dirty(pSetup->pName_Next);
2785 widget_redraw(pSetup->pChange_Sex);
2786 widget_mark_dirty(pSetup->pChange_Sex);
2788 flush_dirty();
2790 return -1;
2793 /**************************************************************************
2794 User requested previous leader name.
2795 **************************************************************************/
2796 static int prev_name_callback(struct widget *pPrev)
2798 if (Main.event.button.button == SDL_BUTTON_LEFT) {
2799 struct NAT *pSetup = (struct NAT *)(pNationDlg->pEndWidgetList->data.ptr);
2800 const struct nation_leader_list *leaders =
2801 nation_leaders(nation_by_number(pSetup->nation));
2802 const struct nation_leader *pleader;
2804 pSetup->selected_leader--;
2805 pleader = nation_leader_list_get(leaders, pSetup->selected_leader);
2807 /* change leadaer sex */
2808 if (pSetup->leader_sex != nation_leader_is_male(pleader)) {
2809 change_sex_callback(NULL);
2812 /* change leadaer name */
2813 copy_chars_to_string16(pSetup->pName_Edit->string16,
2814 nation_leader_name(pleader));
2816 FC_FREE(pLeaderName);
2817 pLeaderName = fc_strdup(nation_leader_name(pleader));
2819 if (!pSetup->selected_leader) {
2820 set_wstate(pSetup->pName_Prev, FC_WS_DISABLED);
2823 if (get_wstate(pSetup->pName_Next) == FC_WS_DISABLED) {
2824 set_wstate(pSetup->pName_Next, FC_WS_NORMAL);
2827 if (!(get_wstate(pSetup->pName_Prev) == FC_WS_DISABLED)) {
2828 pSellected_Widget = pSetup->pName_Prev;
2829 set_wstate(pSetup->pName_Prev, FC_WS_SELLECTED);
2832 widget_redraw(pSetup->pName_Edit);
2833 widget_redraw(pSetup->pName_Prev);
2834 widget_redraw(pSetup->pName_Next);
2835 widget_mark_dirty(pSetup->pName_Edit);
2836 widget_mark_dirty(pSetup->pName_Prev);
2837 widget_mark_dirty(pSetup->pName_Next);
2839 widget_redraw(pSetup->pChange_Sex);
2840 widget_mark_dirty(pSetup->pChange_Sex);
2842 flush_dirty();
2844 return -1;
2847 /**************************************************************************
2848 User requested next nationset
2849 **************************************************************************/
2850 static int next_set_callback(struct widget *next_button)
2852 if (Main.event.button.button == SDL_BUTTON_LEFT) {
2853 struct NAT *pSetup = (struct NAT *)(pNationDlg->pEndWidgetList->data.ptr);
2854 struct option *poption = optset_option_by_name(server_optset, "nationset");
2856 fc_assert(pSetup->set != NULL
2857 && nation_set_index(pSetup->set) < nation_set_count() - 1);
2859 pSetup->set = nation_set_by_number(nation_set_index(pSetup->set) + 1);
2861 option_str_set(poption, nation_set_rule_name(pSetup->set));
2864 return -1;
2867 /**************************************************************************
2868 User requested prev nationset
2869 **************************************************************************/
2870 static int prev_set_callback(struct widget *prev_button)
2872 if (Main.event.button.button == SDL_BUTTON_LEFT) {
2873 struct NAT *pSetup = (struct NAT *)(pNationDlg->pEndWidgetList->data.ptr);
2874 struct option *poption = optset_option_by_name(server_optset, "nationset");
2876 fc_assert(pSetup->set != NULL && nation_set_index(pSetup->set) > 0);
2878 pSetup->set = nation_set_by_number(nation_set_index(pSetup->set) - 1);
2880 option_str_set(poption, nation_set_rule_name(pSetup->set));
2883 return -1;
2886 /**************************************************************************
2887 User cancelled nations dialog.
2888 **************************************************************************/
2889 static int races_dialog_cancel_callback(struct widget *pButton)
2891 if (Main.event.button.button == SDL_BUTTON_LEFT) {
2892 popdown_races_dialog();
2893 flush_dirty();
2895 return -1;
2898 /**************************************************************************
2899 User interacted with style widget.
2900 **************************************************************************/
2901 static int style_callback(struct widget *pWidget)
2903 if (Main.event.button.button == SDL_BUTTON_LEFT) {
2904 struct NAT *pSetup = (struct NAT *)(pNationDlg->pEndWidgetList->data.ptr);
2905 struct widget *pGUI = get_widget_pointer_form_main_list(MAX_ID - 1000 -
2906 pSetup->nation_style);
2908 set_wstate(pGUI, FC_WS_NORMAL);
2909 widget_redraw(pGUI);
2910 widget_mark_dirty(pGUI);
2912 set_wstate(pWidget, FC_WS_DISABLED);
2913 widget_redraw(pWidget);
2914 widget_mark_dirty(pWidget);
2916 pSetup->nation_style = MAX_ID - 1000 - pWidget->ID;
2918 flush_dirty();
2919 pSellected_Widget = NULL;
2921 return -1;
2924 /**************************************************************************
2925 User interacted with help dialog.
2926 **************************************************************************/
2927 static int help_dlg_callback(struct widget *pWindow)
2929 return -1;
2932 /**************************************************************************
2933 User requested closing of help dialog.
2934 **************************************************************************/
2935 static int cancel_help_dlg_callback(struct widget *pWidget)
2937 if (Main.event.button.button == SDL_BUTTON_LEFT) {
2938 if (pHelpDlg) {
2939 popdown_window_group_dialog(pHelpDlg->pBeginWidgetList,
2940 pHelpDlg->pEndWidgetList);
2941 FC_FREE(pHelpDlg);
2942 if (pWidget) {
2943 flush_dirty();
2947 return -1;
2950 /**************************************************************************
2951 User selected nation.
2952 **************************************************************************/
2953 static int nation_button_callback(struct widget *pNationButton)
2955 set_wstate(pNationButton, FC_WS_SELLECTED);
2956 pSellected_Widget = pNationButton;
2958 if (Main.event.button.button == SDL_BUTTON_LEFT) {
2959 struct NAT *pSetup = (struct NAT *)(pNationDlg->pEndWidgetList->data.ptr);
2961 if (pSetup->nation == MAX_ID - pNationButton->ID) {
2962 widget_redraw(pNationButton);
2963 widget_flush(pNationButton);
2964 return -1;
2967 pSetup->nation = MAX_ID - pNationButton->ID;
2969 change_nation_label();
2971 enable(MAX_ID - 1000 - pSetup->nation_style);
2972 pSetup->nation_style = style_number(style_of_nation(nation_by_number(pSetup->nation)));
2973 disable(MAX_ID - 1000 - pSetup->nation_style);
2975 select_random_leader(pSetup->nation);
2977 redraw_group(pNationDlg->pBeginWidgetList, pNationDlg->pEndWidgetList, 0);
2978 widget_flush(pNationDlg->pEndWidgetList);
2979 } else {
2980 /* pop up nation description */
2981 struct widget *pWindow, *pOK_Button;
2982 SDL_String16 *pStr;
2983 SDL_Surface *pText;
2984 SDL_Rect area, area2;
2985 struct nation_type *pNation = nation_by_number(MAX_ID - pNationButton->ID);
2987 widget_redraw(pNationButton);
2988 widget_mark_dirty(pNationButton);
2990 if (!pHelpDlg) {
2992 pHelpDlg = fc_calloc(1, sizeof(struct SMALL_DLG));
2994 pStr = create_str16_from_char(nation_plural_translation(pNation),
2995 adj_font(12));
2996 pStr->style |= TTF_STYLE_BOLD;
2998 pWindow = create_window_skeleton(NULL, pStr, 0);
2999 pWindow->action = help_dlg_callback;
3001 set_wstate(pWindow, FC_WS_NORMAL);
3003 pHelpDlg->pEndWidgetList = pWindow;
3004 add_to_gui_list(ID_WINDOW, pWindow);
3006 pOK_Button = create_themeicon_button_from_chars(current_theme->OK_Icon,
3007 pWindow->dst, _("OK"),
3008 adj_font(14), 0);
3009 pOK_Button->action = cancel_help_dlg_callback;
3010 set_wstate(pOK_Button, FC_WS_NORMAL);
3011 pOK_Button->key = SDLK_ESCAPE;
3012 add_to_gui_list(ID_BUTTON, pOK_Button);
3013 pHelpDlg->pBeginWidgetList = pOK_Button;
3014 } else {
3015 pWindow = pHelpDlg->pEndWidgetList;
3016 pOK_Button = pHelpDlg->pBeginWidgetList;
3017 /* undraw window */
3018 widget_undraw(pWindow);
3019 widget_mark_dirty(pWindow);
3022 area = pWindow->area;
3025 char info[4096];
3026 helptext_nation(info, sizeof(info), pNation, NULL);
3027 pStr = create_str16_from_char(info, adj_font(12));
3030 pStr->fgcol = *get_theme_color(COLOR_THEME_NATIONDLG_LEGEND);
3031 pText = create_text_surf_smaller_that_w(pStr, Main.screen->w - adj_size(20));
3033 FREESTRING16(pStr);
3035 /* create window background */
3036 area.w = MAX(area.w, pText->w + adj_size(20));
3037 area.w = MAX(area.w, pOK_Button->size.w + adj_size(20));
3038 area.h = MAX(area.h, adj_size(9) + pText->h
3039 + adj_size(10) + pOK_Button->size.h + adj_size(10));
3041 resize_window(pWindow, NULL, get_theme_color(COLOR_THEME_BACKGROUND),
3042 (pWindow->size.w - pWindow->area.w) + area.w,
3043 (pWindow->size.h - pWindow->area.h) + area.h);
3045 widget_set_position(pWindow,
3046 (Main.screen->w - pWindow->size.w) / 2,
3047 (Main.screen->h - pWindow->size.h) / 2);
3049 area2.x = area.x + adj_size(7);
3050 area2.y = area.y + adj_size(6);
3051 alphablit(pText, NULL, pWindow->theme, &area2);
3052 FREESURFACE(pText);
3054 pOK_Button->size.x = area.x + (area.w - pOK_Button->size.w) / 2;
3055 pOK_Button->size.y = area.y + area.h - pOK_Button->size.h - adj_size(10);
3057 /* redraw */
3058 redraw_group(pOK_Button, pWindow, 0);
3060 widget_mark_dirty(pWindow);
3062 flush_dirty();
3065 return -1;
3068 /**************************************************************************
3069 User interacted with leader name edit widget.
3070 **************************************************************************/
3071 static int leader_name_edit_callback(struct widget *pEdit)
3073 if (Main.event.button.button == SDL_BUTTON_LEFT) {
3074 char *name = convert_to_chars(pEdit->string16->text);
3076 if (name) {
3077 FC_FREE(name);
3078 } else {
3079 /* empty input -> restore previous content */
3080 copy_chars_to_string16(pEdit->string16, pLeaderName);
3081 widget_redraw(pEdit);
3082 widget_mark_dirty(pEdit);
3083 flush_dirty();
3086 return -1;
3088 /* =========================================================== */
3090 /**************************************************************************
3091 Update nation label.
3092 **************************************************************************/
3093 static void change_nation_label(void)
3095 SDL_Surface *pTmp_Surf, *pTmp_Surf_zoomed;
3096 struct widget *pWindow = pNationDlg->pEndWidgetList;
3097 struct NAT *pSetup = (struct NAT *)(pWindow->data.ptr);
3098 struct widget *pLabel = pSetup->pName_Edit->next;
3099 struct nation_type *pNation = nation_by_number(pSetup->nation);
3101 pTmp_Surf = get_nation_flag_surface(pNation);
3102 pTmp_Surf_zoomed = zoomSurface(pTmp_Surf, DEFAULT_ZOOM * 1.0, DEFAULT_ZOOM * 1.0, 1);
3104 FREESURFACE(pLabel->theme);
3105 pLabel->theme = pTmp_Surf_zoomed;
3107 copy_chars_to_string16(pLabel->string16, nation_plural_translation(pNation));
3109 remake_label_size(pLabel);
3111 pLabel->size.x = pWindow->size.x + pWindow->size.w / 2 +
3112 (pWindow->size.w/2 - pLabel->size.w) / 2;
3116 /**************************************************************************
3117 Selectes a leader and the appropriate sex. Updates the gui elements
3118 and the selected_* variables.
3119 **************************************************************************/
3120 static void select_random_leader(Nation_type_id nation)
3122 struct NAT *pSetup = (struct NAT *)(pNationDlg->pEndWidgetList->data.ptr);
3123 const struct nation_leader_list *leaders =
3124 nation_leaders(nation_by_number(pSetup->nation));
3125 const struct nation_leader *pleader;
3127 pSetup->selected_leader = fc_rand(nation_leader_list_size(leaders));
3128 pleader = nation_leader_list_get(leaders, pSetup->selected_leader);
3129 copy_chars_to_string16(pSetup->pName_Edit->string16,
3130 nation_leader_name(pleader));
3132 FC_FREE(pLeaderName);
3133 pLeaderName = fc_strdup(nation_leader_name(pleader));
3135 /* initialize leader sex */
3136 pSetup->leader_sex = nation_leader_is_male(pleader);
3138 if (pSetup->leader_sex) {
3139 copy_chars_to_string16(pSetup->pChange_Sex->string16, _("Male"));
3140 } else {
3141 copy_chars_to_string16(pSetup->pChange_Sex->string16, _("Female"));
3144 /* disable navigation buttons */
3145 set_wstate(pSetup->pName_Prev, FC_WS_DISABLED);
3146 set_wstate(pSetup->pName_Next, FC_WS_DISABLED);
3148 if (1 < nation_leader_list_size(leaders)) {
3149 /* if selected leader is not the first leader, enable "previous leader" button */
3150 if (pSetup->selected_leader > 0) {
3151 set_wstate(pSetup->pName_Prev, FC_WS_NORMAL);
3154 /* if selected leader is not the last leader, enable "next leader" button */
3155 if (pSetup->selected_leader < (nation_leader_list_size(leaders) - 1)) {
3156 set_wstate(pSetup->pName_Next, FC_WS_NORMAL);
3162 /**************************************************************************
3163 Count available playable nations.
3164 **************************************************************************/
3165 static int get_playable_nation_count(void)
3167 int playable_nation_count = 0;
3169 nations_iterate(pnation) {
3170 if (is_nation_playable(pnation) && !pnation->player
3171 && is_nation_pickable(pnation))
3172 ++playable_nation_count;
3173 } nations_iterate_end;
3175 return playable_nation_count;
3179 /**************************************************************************
3180 Popup the nation selection dialog.
3181 **************************************************************************/
3182 void popup_races_dialog(struct player *pplayer)
3184 SDL_Color bg_color = {255,255,255,128};
3186 struct widget *pWindow, *pWidget = NULL, *pBuf, *pLast_City_Style;
3187 SDL_String16 *pStr;
3188 int len = 0;
3189 int w = adj_size(10), h = adj_size(10);
3190 SDL_Surface *pTmp_Surf, *pTmp_Surf_zoomed = NULL;
3191 SDL_Surface *pMain_Bg, *pText_Name, *pText_Class;
3192 SDL_Rect dst;
3193 float zoom;
3194 struct NAT *pSetup;
3195 SDL_Rect area;
3196 int i;
3197 struct nation_type *pnat;
3198 struct widget *nationsets = NULL;
3199 int natinfo_y, natinfo_h;
3201 #define TARGETS_ROW 5
3202 #define TARGETS_COL 1
3204 if (pNationDlg) {
3205 return;
3208 races_player = pplayer;
3210 pNationDlg = fc_calloc(1, sizeof(struct ADVANCED_DLG));
3212 /* create window widget */
3213 pStr = create_str16_from_char(_("What nation will you be?"), adj_font(12));
3214 pStr->style |= TTF_STYLE_BOLD;
3216 pWindow = create_window(NULL, pStr, w, h, WF_FREE_DATA);
3217 pWindow->action = nations_dialog_callback;
3218 set_wstate(pWindow, FC_WS_NORMAL);
3219 pSetup = fc_calloc(1, sizeof(struct NAT));
3220 pWindow->data.ptr = (void *)pSetup;
3222 pNationDlg->pEndWidgetList = pWindow;
3223 add_to_gui_list(ID_NATION_WIZARD_WINDOW, pWindow);
3224 /* --------------------------------------------------------- */
3225 /* create nations list */
3227 /* Create Imprv Background Icon */
3228 pMain_Bg = create_surf_alpha(adj_size(96*2), adj_size(64), SDL_SWSURFACE);
3230 SDL_FillRect(pMain_Bg, NULL, map_rgba(pMain_Bg->format, bg_color));
3231 putframe(pMain_Bg,
3232 0, 0, pMain_Bg->w - 1, pMain_Bg->h - 1,
3233 get_theme_color(COLOR_THEME_NATIONDLG_FRAME));
3235 pStr = create_string16(NULL, 0, adj_font(12));
3236 pStr->style |= (SF_CENTER|TTF_STYLE_BOLD);
3237 pStr->bgcol = (SDL_Color) {0, 0, 0, 0};
3239 /* fill list */
3240 pText_Class = NULL;
3242 nations_iterate(pNation) {
3244 if (!is_nation_playable(pNation) || !is_nation_pickable(pNation)) {
3245 continue;
3248 pTmp_Surf_zoomed = adj_surf(get_nation_flag_surface(pNation));
3250 pTmp_Surf = crop_rect_from_surface(pMain_Bg, NULL);
3252 copy_chars_to_string16(pStr, nation_plural_translation(pNation));
3253 change_ptsize16(pStr, adj_font(12));
3254 pText_Name = create_text_surf_smaller_that_w(pStr, pTmp_Surf->w - adj_size(4));
3256 #if 0
3257 if (pNation->legend && *(pNation->legend) != '\0') {
3258 copy_chars_to_string16(pStr, pNation->legend);
3259 change_ptsize16(pStr, adj_font(10));
3260 pText_Class = create_text_surf_smaller_that_w(pStr, pTmp_Surf->w - adj_size(4));
3262 #endif /* 0 */
3264 dst.x = (pTmp_Surf->w - pTmp_Surf_zoomed->w) / 2;
3265 len = pTmp_Surf_zoomed->h +
3266 adj_size(10) + pText_Name->h + (pText_Class ? pText_Class->h : 0);
3267 dst.y = (pTmp_Surf->h - len) / 2;
3268 alphablit(pTmp_Surf_zoomed, NULL, pTmp_Surf, &dst);
3269 dst.y += (pTmp_Surf_zoomed->h + adj_size(10));
3271 dst.x = (pTmp_Surf->w - pText_Name->w) / 2;
3272 alphablit(pText_Name, NULL, pTmp_Surf, &dst);
3273 dst.y += pText_Name->h;
3274 FREESURFACE(pText_Name);
3276 if (pText_Class) {
3277 dst.x = (pTmp_Surf->w - pText_Class->w) / 2;
3278 alphablit(pText_Class, NULL, pTmp_Surf, &dst);
3279 FREESURFACE(pText_Class);
3282 pWidget = create_icon2(pTmp_Surf, pWindow->dst,
3283 (WF_RESTORE_BACKGROUND|WF_FREE_THEME));
3285 set_wstate(pWidget, FC_WS_NORMAL);
3287 pWidget->action = nation_button_callback;
3289 w = MAX(w, pWidget->size.w);
3290 h = MAX(h, pWidget->size.h);
3292 add_to_gui_list(MAX_ID - nation_index(pNation), pWidget);
3294 if (nation_index(pNation) > (TARGETS_ROW * TARGETS_COL - 1)) {
3295 set_wflag(pWidget, WF_HIDDEN);
3298 } nations_iterate_end;
3300 FREESURFACE(pMain_Bg);
3302 pNationDlg->pEndActiveWidgetList = pWindow->prev;
3303 pNationDlg->pBeginWidgetList = pWidget;
3304 pNationDlg->pBeginActiveWidgetList = pNationDlg->pBeginWidgetList;
3306 if(get_playable_nation_count() > TARGETS_ROW * TARGETS_COL) {
3307 pNationDlg->pActiveWidgetList = pNationDlg->pEndActiveWidgetList;
3308 create_vertical_scrollbar(pNationDlg,
3309 TARGETS_COL, TARGETS_ROW, TRUE, TRUE);
3312 /* ----------------------------------------------------------------- */
3314 /* nation set selection */
3315 if (nation_set_count() > 1) {
3316 SDL_String16 *natset_str;
3317 struct option *poption;
3319 natset_str = create_str16_from_char(_("Nation set"), adj_font(12));
3320 change_ptsize16(natset_str, adj_font(24));
3321 nationsets = create_iconlabel(NULL, pWindow->dst, natset_str, 0);
3322 add_to_gui_list(ID_LABEL, nationsets);
3324 /* create nation set name label */
3325 poption = optset_option_by_name(server_optset, "nationset");
3326 pSetup->set = nation_set_by_setting_value(option_str_get(poption));
3328 natset_str = create_str16_from_char(nation_set_name_translation(pSetup->set),
3329 adj_font(12));
3330 change_ptsize16(natset_str, adj_font(24));
3332 pWidget = create_iconlabel(NULL, pWindow->dst, natset_str, 0);
3334 add_to_gui_list(ID_LABEL, pWidget);
3335 pSetup->pset_name = pWidget;
3337 /* create next nationset button */
3338 pWidget = create_themeicon_button(current_theme->R_ARROW_Icon,
3339 pWindow->dst, NULL, 0);
3340 pWidget->action = next_set_callback;
3341 if (nation_set_index(pSetup->set) < nation_set_count() - 1) {
3342 set_wstate(pWidget, FC_WS_NORMAL);
3344 add_to_gui_list(ID_NATION_NEXT_NATIONSET_BUTTON, pWidget);
3345 pWidget->size.h = pWidget->next->size.h;
3346 pSetup->pset_next = pWidget;
3348 /* create prev nationset button */
3349 pWidget = create_themeicon_button(current_theme->L_ARROW_Icon,
3350 pWindow->dst, NULL, 0);
3351 pWidget->action = prev_set_callback;
3352 if (nation_set_index(pSetup->set) > 0) {
3353 set_wstate(pWidget, FC_WS_NORMAL);
3355 add_to_gui_list(ID_NATION_PREV_NATIONSET_BUTTON, pWidget);
3356 pWidget->size.h = pWidget->next->size.h;
3357 pSetup->pset_prev = pWidget;
3360 /* nation name */
3361 pSetup->nation = fc_rand(get_playable_nation_count());
3362 pnat = nation_by_number(pSetup->nation);
3363 pSetup->nation_style = style_number(style_of_nation(pnat));
3365 copy_chars_to_string16(pStr, nation_plural_translation(pnat));
3366 change_ptsize16(pStr, adj_font(24));
3367 pStr->render = 2;
3368 pStr->fgcol = *get_theme_color(COLOR_THEME_NATIONDLG_TEXT);
3370 pTmp_Surf_zoomed = adj_surf(get_nation_flag_surface(pnat));
3372 pWidget = create_iconlabel(pTmp_Surf_zoomed, pWindow->dst, pStr,
3373 (WF_ICON_ABOVE_TEXT|WF_ICON_CENTER|WF_FREE_GFX));
3374 if (nationsets == NULL) {
3375 pBuf = pWidget;
3376 } else {
3377 pBuf = nationsets;
3380 add_to_gui_list(ID_LABEL, pWidget);
3382 /* create leader name edit */
3383 pWidget = create_edit_from_unichars(NULL, pWindow->dst,
3384 NULL, 0, adj_font(16), adj_size(200), 0);
3385 pWidget->size.h = adj_size(24);
3387 set_wstate(pWidget, FC_WS_NORMAL);
3388 pWidget->action = leader_name_edit_callback;
3389 add_to_gui_list(ID_NATION_WIZARD_LEADER_NAME_EDIT, pWidget);
3390 pSetup->pName_Edit = pWidget;
3392 /* create next leader name button */
3393 pWidget = create_themeicon_button(current_theme->R_ARROW_Icon,
3394 pWindow->dst, NULL, 0);
3395 pWidget->action = next_name_callback;
3396 add_to_gui_list(ID_NATION_WIZARD_NEXT_LEADER_NAME_BUTTON, pWidget);
3397 pWidget->size.h = pWidget->next->size.h;
3398 pSetup->pName_Next = pWidget;
3400 /* create prev leader name button */
3401 pWidget = create_themeicon_button(current_theme->L_ARROW_Icon,
3402 pWindow->dst, NULL, 0);
3403 pWidget->action = prev_name_callback;
3404 add_to_gui_list(ID_NATION_WIZARD_PREV_LEADER_NAME_BUTTON, pWidget);
3405 pWidget->size.h = pWidget->next->size.h;
3406 pSetup->pName_Prev = pWidget;
3408 /* change sex button */
3409 pWidget = create_icon_button_from_chars(NULL, pWindow->dst, _("Male"), adj_font(14), 0);
3410 pWidget->action = change_sex_callback;
3411 pWidget->size.w = adj_size(100);
3412 pWidget->size.h = adj_size(22);
3413 set_wstate(pWidget, FC_WS_NORMAL);
3414 pSetup->pChange_Sex = pWidget;
3416 /* add to main widget list */
3417 add_to_gui_list(ID_NATION_WIZARD_CHANGE_SEX_BUTTON, pWidget);
3419 /* ---------------------------------------------------------- */
3420 i = 0;
3421 zoom = DEFAULT_ZOOM * 1.0;
3423 len = 0;
3424 styles_iterate(pstyle) {
3425 i = basic_city_style_for_style(pstyle);
3427 pTmp_Surf = get_sample_city_surface(i);
3429 if (pTmp_Surf->w > 48) {
3430 zoom = DEFAULT_ZOOM * (48.0 / pTmp_Surf->w);
3433 pTmp_Surf_zoomed = zoomSurface(get_sample_city_surface(i), zoom, zoom, 0);
3435 pWidget = create_icon2(pTmp_Surf_zoomed, pWindow->dst, WF_RESTORE_BACKGROUND);
3436 pWidget->action = style_callback;
3437 if (i != pSetup->nation_style) {
3438 set_wstate(pWidget, FC_WS_NORMAL);
3440 len += pWidget->size.w;
3441 add_to_gui_list(MAX_ID - 1000 - i, pWidget);
3442 } styles_iterate_end;
3444 pLast_City_Style = pWidget;
3445 /* ---------------------------------------------------------- */
3447 /* create Cancel button */
3448 pWidget = create_themeicon_button_from_chars(current_theme->CANCEL_Icon,
3449 pWindow->dst, _("Cancel"),
3450 adj_font(12), 0);
3451 pWidget->action = races_dialog_cancel_callback;
3452 set_wstate(pWidget, FC_WS_NORMAL);
3454 add_to_gui_list(ID_NATION_WIZARD_DISCONNECT_BUTTON, pWidget);
3456 /* create OK button */
3457 pWidget =
3458 create_themeicon_button_from_chars(current_theme->OK_Icon, pWindow->dst,
3459 _("OK"), adj_font(12), 0);
3460 pWidget->action = races_dialog_ok_callback;
3462 set_wstate(pWidget, FC_WS_NORMAL);
3463 add_to_gui_list(ID_NATION_WIZARD_START_BUTTON, pWidget);
3464 pWidget->size.w = MAX(pWidget->size.w, pWidget->next->size.w);
3465 pWidget->next->size.w = pWidget->size.w;
3467 pNationDlg->pBeginWidgetList = pWidget;
3468 /* ---------------------------------------------------------- */
3470 pMain_Bg = theme_get_background(theme, BACKGROUND_NATIONDLG);
3471 if(resize_window(pWindow, pMain_Bg, NULL, adj_size(640), adj_size(480))) {
3472 FREESURFACE(pMain_Bg);
3475 area = pWindow->area;
3477 widget_set_position(pWindow,
3478 (Main.screen->w - pWindow->size.w) / 2,
3479 (Main.screen->h - pWindow->size.h) / 2);
3481 /* nations */
3483 h = pNationDlg->pEndActiveWidgetList->size.h * TARGETS_ROW;
3484 i = (area.h - adj_size(43) - h) / 2;
3485 setup_vertical_widgets_position(TARGETS_COL,
3486 area.x + adj_size(10),
3487 area.y + i - adj_size(4),
3488 0, 0, pNationDlg->pBeginActiveWidgetList,
3489 pNationDlg->pEndActiveWidgetList);
3491 if(pNationDlg->pScroll) {
3492 SDL_Rect area2;
3494 w = pNationDlg->pEndActiveWidgetList->size.w * TARGETS_COL;
3495 setup_vertical_scrollbar_area(pNationDlg->pScroll,
3496 area.x + w + adj_size(12),
3497 area.y + i - adj_size(4), h, FALSE);
3499 area2.x = area.x + w + adj_size(11);
3500 area2.y = area.y + i - adj_size(4);
3501 area2.w = pNationDlg->pScroll->pUp_Left_Button->size.w + adj_size(2);
3502 area2.h = h;
3503 SDL_FillRectAlpha(pWindow->theme, &area2, &bg_color);
3504 putframe(pWindow->theme,
3505 area2.x, area2.y - 1, area2.x + area2.w, area2.y + area2.h,
3506 get_theme_color(COLOR_THEME_NATIONDLG_FRAME));
3509 if (nationsets != NULL) {
3510 /* Nationsets header */
3511 pBuf->size.x = area.x + area.w / 2 + (area.w / 2 - pBuf->size.w) / 2;
3512 pBuf->size.y = area.y + adj_size(46);
3514 natinfo_y = pBuf->size.y;
3515 natinfo_h = area.h -= pBuf->size.y;
3517 /* Nationset name */
3518 pBuf = pBuf->prev;
3519 pBuf->size.x = area.x + area.w / 2 + (area.w / 2 - pBuf->size.w) / 2;
3520 pBuf->size.y = natinfo_y + adj_size(46);
3522 natinfo_y += adj_size(46);
3523 natinfo_h -= adj_size(46);
3525 /* Next Nationset Button */
3526 pBuf = pBuf->prev;
3527 pBuf->size.x = pBuf->next->size.x + pBuf->next->size.w;
3528 pBuf->size.y = pBuf->next->size.y;
3530 /* Prev Nationset Button */
3531 pBuf = pBuf->prev;
3532 pBuf->size.x = pBuf->next->next->size.x - pBuf->size.w;
3533 pBuf->size.y = pBuf->next->size.y;
3535 pBuf = pBuf->prev;
3536 } else {
3537 natinfo_y = area.y;
3538 natinfo_h = area.h;
3541 /* Selected Nation Name */
3542 pBuf->size.x = area.x + area.w / 2 + (area.w / 2 - pBuf->size.w) / 2;
3543 pBuf->size.y = natinfo_y + adj_size(46);
3545 /* Leader Name Edit */
3546 pBuf = pBuf->prev;
3547 pBuf->size.x = area.x + area.w / 2 + (area.w/2 - pBuf->size.w) / 2;
3548 pBuf->size.y = natinfo_y + (natinfo_h - pBuf->size.h) / 2 - adj_size(30);
3550 /* Next Leader Name Button */
3551 pBuf = pBuf->prev;
3552 pBuf->size.x = pBuf->next->size.x + pBuf->next->size.w;
3553 pBuf->size.y = pBuf->next->size.y;
3555 /* Prev Leader Name Button */
3556 pBuf = pBuf->prev;
3557 pBuf->size.x = pBuf->next->next->size.x - pBuf->size.w;
3558 pBuf->size.y = pBuf->next->size.y;
3560 /* Change Leader Sex Button */
3561 pBuf = pBuf->prev;
3562 pBuf->size.x = area.x + area.w / 2 + (area.w/2 - pBuf->size.w) / 2;
3563 pBuf->size.y = pBuf->next->size.y + pBuf->next->size.h + adj_size(20);
3565 /* First Style Button */
3566 pBuf = pBuf->prev;
3567 pBuf->size.x = area.x + area.w / 2 + (area.w/2 - len) / 2 - adj_size(20);
3568 pBuf->size.y = pBuf->next->size.y + pBuf->next->size.h + adj_size(20);
3570 /* Rest Style Buttons */
3571 while (pBuf != pLast_City_Style) {
3572 pBuf = pBuf->prev;
3573 pBuf->size.x = pBuf->next->size.x + pBuf->next->size.w + adj_size(3);
3574 pBuf->size.y = pBuf->next->size.y;
3577 putline(pWindow->theme,
3578 area.x,
3579 natinfo_y + natinfo_h - adj_size(7) - pBuf->prev->size.h - adj_size(10),
3580 area.w - 1,
3581 natinfo_y + natinfo_h - adj_size(7) - pBuf->prev->size.h - adj_size(10),
3582 get_theme_color(COLOR_THEME_NATIONDLG_FRAME));
3584 /* Disconnect Button */
3585 pBuf = pBuf->prev;
3586 pBuf->size.x = area.x + adj_size(10);
3587 pBuf->size.y = natinfo_y + natinfo_h - adj_size(7) - pBuf->size.h;
3589 /* Start Button */
3590 pBuf = pBuf->prev;
3591 pBuf->size.x = area.w - adj_size(10) - pBuf->size.w;
3592 pBuf->size.y = pBuf->next->size.y;
3594 /* -------------------------------------------------------------------- */
3596 select_random_leader(pSetup->nation);
3598 redraw_group(pNationDlg->pBeginWidgetList, pWindow, 0);
3600 widget_flush(pWindow);
3603 /**************************************************************************
3604 Close the nation selection dialog. This should allow the user to
3605 (at least) select a unit to activate.
3606 **************************************************************************/
3607 void popdown_races_dialog(void)
3609 if (pNationDlg) {
3610 popdown_window_group_dialog(pNationDlg->pBeginWidgetList,
3611 pNationDlg->pEndWidgetList);
3613 cancel_help_dlg_callback(NULL);
3615 FC_FREE(pLeaderName);
3617 FC_FREE(pNationDlg->pScroll);
3618 FC_FREE(pNationDlg);
3622 /**************************************************************************
3623 The server has changed the set of selectable nations.
3624 **************************************************************************/
3625 void races_update_pickable(bool nationset_change)
3627 /* If this is because of nationset change, update will take
3628 * place later when the new option value is received */
3629 if (pNationDlg != NULL && !nationset_change) {
3630 popdown_races_dialog();
3631 popup_races_dialog(client.conn.playing);
3635 /**************************************************************************
3636 Nationset selection update
3637 **************************************************************************/
3638 void nationset_changed(void)
3640 if (pNationDlg != NULL) {
3641 popdown_races_dialog();
3642 popup_races_dialog(client.conn.playing);
3646 /**************************************************************************
3647 In the nation selection dialog, make already-taken nations unavailable.
3648 This information is contained in the packet_nations_used packet.
3649 **************************************************************************/
3650 void races_toggles_set_sensitive()
3652 struct NAT *pSetup;
3653 bool change = FALSE;
3654 struct widget *pNat;
3656 if (!pNationDlg) {
3657 return;
3660 pSetup = (struct NAT *)(pNationDlg->pEndWidgetList->data.ptr);
3662 nations_iterate(nation) {
3664 if (!is_nation_pickable(nation) || nation->player) {
3665 log_debug(" [%d]: %d = %s", nation_index(nation),
3666 (!is_nation_pickable(nation) || nation->player),
3667 nation_rule_name(nation));
3669 pNat = get_widget_pointer_form_main_list(MAX_ID - nation_index(nation));
3670 set_wstate(pNat, FC_WS_DISABLED);
3672 if (nation_index(nation) == pSetup->nation) {
3673 change = TRUE;
3676 } nations_iterate_end;
3678 if (change) {
3679 do {
3680 pSetup->nation = fc_rand(get_playable_nation_count());
3681 pNat = get_widget_pointer_form_main_list(MAX_ID - pSetup->nation);
3682 } while(get_wstate(pNat) == FC_WS_DISABLED);
3683 if (get_wstate(pSetup->pName_Edit) == FC_WS_PRESSED) {
3684 force_exit_from_event_loop();
3685 set_wstate(pSetup->pName_Edit, FC_WS_NORMAL);
3687 change_nation_label();
3688 enable(MAX_ID - 1000 - pSetup->nation_style);
3689 pSetup->nation_style = style_number(style_of_nation(nation_by_number(pSetup->nation)));
3690 disable(MAX_ID - 1000 - pSetup->nation_style);
3691 select_random_leader(pSetup->nation);
3693 redraw_group(pNationDlg->pBeginWidgetList, pNationDlg->pEndWidgetList, 0);
3694 widget_flush(pNationDlg->pEndWidgetList);
3697 /**************************************************************************
3698 Ruleset (modpack) has suggested loading certain tileset. Confirm from
3699 user and load.
3700 **************************************************************************/
3701 void popup_tileset_suggestion_dialog(void)
3705 /****************************************************************
3706 Ruleset (modpack) has suggested loading certain soundset. Confirm from
3707 user and load.
3708 *****************************************************************/
3709 void popup_soundset_suggestion_dialog(void)
3713 /****************************************************************
3714 Ruleset (modpack) has suggested loading certain muicset. Confirm from
3715 user and load.
3716 *****************************************************************/
3717 void popup_musicset_suggestion_dialog(void)
3721 /**************************************************************************
3722 Tileset (modpack) has suggested loading certain theme. Confirm from
3723 user and load.
3724 **************************************************************************/
3725 bool popup_theme_suggestion_dialog(const char *theme_name)
3727 /* Don't load */
3728 return FALSE;
3731 /****************************************************************
3732 Player has gained a new tech.
3733 *****************************************************************/
3734 void show_tech_gained_dialog(Tech_type_id tech)
3736 /* PORTME */
3739 /****************************************************************
3740 Show tileset error dialog.
3741 *****************************************************************/
3742 void show_tileset_error(const char *msg)
3744 /* PORTME */
3747 /****************************************************************
3748 Give a warning when user is about to edit scenario with manually
3749 set properties.
3750 *****************************************************************/
3751 bool handmade_scenario_warning(void)
3753 /* Just tell the client common code to handle this. */
3754 return FALSE;
3757 /****************************************************************
3758 Update multipliers (policies) dialog.
3759 *****************************************************************/
3760 void real_multipliers_dialog_update(void)
3762 /* PORTME */
3765 /****************************************************************
3766 Unit wants to get into some transport on given tile.
3767 *****************************************************************/
3768 bool request_transport(struct unit *pcargo, struct tile *ptile)
3770 return FALSE; /* Unit was not handled here. */