1 /***********************************************************************
2  Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3    This program is free software; you can redistribute it and/or modify
4    it under the terms of the GNU General Public License as published by
5    the Free Software Foundation; either version 2, or (at your option)
6    any later version.
7 
8    This program is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11    GNU General Public License for more details.
12 ***********************************************************************/
13 
14 /***********************************************************************
15                           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 ***********************************************************************/
21 
22 #ifdef HAVE_CONFIG_H
23 #include <fc_config.h>
24 #endif
25 
26 /* SDL2 */
27 #ifdef SDL2_PLAIN_INCLUDE
28 #include <SDL.h>
29 #else  /* SDL2_PLAIN_INCLUDE */
30 #include <SDL2/SDL.h>
31 #endif /* SDL2_PLAIN_INCLUDE */
32 
33 /* utility */
34 #include "bitvector.h"
35 #include "fcintl.h"
36 #include "log.h"
37 #include "rand.h"
38 
39 /* common */
40 #include "combat.h"
41 #include "game.h"
42 #include "government.h"
43 #include "movement.h"
44 #include "unitlist.h"
45 
46 /* client */
47 #include "client_main.h"
48 #include "climap.h" /* for client_tile_get_known() */
49 #include "goto.h"
50 #include "helpdata.h" /* for helptext_nation() */
51 #include "packhand.h"
52 #include "text.h"
53 
54 /* gui-sdl2 */
55 #include "chatline.h"
56 #include "citydlg.h"
57 #include "cityrep.h"
58 #include "cma_fe.h"
59 #include "colors.h"
60 #include "finddlg.h"
61 #include "gotodlg.h"
62 #include "graphics.h"
63 #include "gui_iconv.h"
64 #include "gui_id.h"
65 #include "gui_main.h"
66 #include "gui_tilespec.h"
67 #include "helpdlg.h"
68 #include "inteldlg.h"
69 #include "mapctrl.h"
70 #include "mapview.h"
71 #include "menu.h"
72 #include "messagewin.h"
73 #include "optiondlg.h"
74 #include "plrdlg.h"
75 #include "ratesdlg.h"
76 #include "repodlgs.h"
77 #include "sprite.h"
78 #include "themespec.h"
79 #include "widget.h"
80 #include "wldlg.h"
81 
82 #include "dialogs.h"
83 
84 struct player *races_player;
85 
86 extern bool is_unit_move_blocked;
87 extern void popdown_diplomat_dialog(void);
88 extern void popdown_incite_dialog(void);
89 extern void popdown_bribe_dialog(void);
90 
91 void popdown_advanced_terrain_dialog(void);
92 int advanced_terrain_window_dlg_callback(struct widget *pWindow);
93 int exit_advanced_terrain_dlg_callback(struct widget *pWidget);
94 
95 static char *pLeaderName = NULL;
96 
97 static void unit_select_dialog_popdown(void);
98 static void popdown_terrain_info_dialog(void);
99 static void popdown_pillage_dialog(void);
100 static void popdown_connect_dialog(void);
101 static void popdown_unit_upgrade_dlg(void);
102 static void popdown_unit_disband_dlg(void);
103 
104 /**********************************************************************
105   Place window near given tile on screen.
106 ***********************************************************************/
put_window_near_map_tile(struct widget * pWindow,int window_width,int window_height,struct tile * ptile)107 void put_window_near_map_tile(struct widget *pWindow,
108                               int window_width, int window_height,
109                               struct tile *ptile)
110 {
111   float canvas_x, canvas_y;
112   int window_x = 0, window_y = 0;
113 
114   if (tile_to_canvas_pos(&canvas_x, &canvas_y, ptile)) {
115     if (canvas_x + tileset_tile_width(tileset) + window_width >= main_window_width()) {
116       if (canvas_x - window_width < 0) {
117         window_x = (main_window_width() - window_width) / 2;
118       } else {
119         window_x = canvas_x - window_width;
120       }
121     } else {
122       window_x = canvas_x + tileset_tile_width(tileset);
123     }
124 
125     canvas_y += (tileset_tile_height(tileset) - window_height) / 2;
126     if (canvas_y + window_height >= main_window_height()) {
127       window_y = main_window_height() - window_height - 1;
128     } else {
129       if (canvas_y < 0) {
130         window_y = 0;
131       } else {
132         window_y = canvas_y;
133       }
134     }
135   } else {
136     window_x = (main_window_width() - window_width) / 2;
137     window_y = (main_window_height() - window_height) / 2;
138   }
139 
140   widget_set_position(pWindow, window_x, window_y);
141 }
142 
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 ***********************************************************************/
popdown_all_game_dialogs(void)147 void popdown_all_game_dialogs(void)
148 {
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   science_report_dialogs_popdown_all();
162   meswin_dialog_popdown();
163   popdown_worklist_editor();
164   popdown_all_city_dialogs();
165   city_report_dialog_popdown();
166   economy_report_dialog_popdown();
167   units_report_dialog_popdown();
168   popdown_intel_dialogs();
169   popdown_players_nations_dialog();
170   popdown_players_dialog();
171   popdown_goto_airlift_dialog();
172   popdown_unit_upgrade_dlg();
173   popdown_unit_disband_dlg();
174   popdown_help_dialog();
175   popdown_notify_goto_dialog();
176 
177   /* clear gui buffer */
178   if (C_S_PREPARING == client_state()) {
179     clear_surface(Main.gui->surface, NULL);
180   }
181 }
182 
183 /* ======================================================================= */
184 
185 /**************************************************************************
186   Find the my unit's (focus) chance of success at attacking/defending the
187   given enemy unit.  Return FALSE if the values cannot be determined (e.g., no
188   units given).
189 **************************************************************************/
sdl_get_chance_to_win(int * att_chance,int * def_chance,struct unit * enemy_unit,struct unit * my_unit)190 static bool sdl_get_chance_to_win(int *att_chance, int *def_chance,
191                                   struct unit *enemy_unit, struct unit *my_unit)
192 {
193   if (!my_unit || !enemy_unit) {
194     return FALSE;
195   }
196 
197   /* chance to win when active unit is attacking the selected unit */
198   *att_chance = unit_win_chance(my_unit, enemy_unit) * 100;
199 
200   /* chance to win when selected unit is attacking the active unit */
201   *def_chance = (1.0 - unit_win_chance(enemy_unit, my_unit)) * 100;
202 
203   return TRUE;
204 }
205 
206 /**************************************************************************
207   Notify goto dialog.
208 **************************************************************************/
209 struct notify_goto_data {
210   char *headline;
211   char *lines;
212   struct tile *ptile;
213 };
214 
215 #define SPECLIST_TAG notify_goto
216 #define SPECLIST_TYPE struct notify_goto_data
217 #include "speclist.h"
218 
219 struct notify_goto_dialog {
220   struct widget *window;
221   struct widget *close_button;
222   struct widget *label;
223   struct notify_goto_list *datas;
224 };
225 
226 static struct notify_goto_dialog *notify_goto_dialog = NULL;
227 
228 static void notify_goto_dialog_advance(struct notify_goto_dialog *pdialog);
229 
230 /**************************************************************************
231   Create a notify goto data.
232 **************************************************************************/
notify_goto_data_new(const char * headline,const char * lines,struct tile * ptile)233 static struct notify_goto_data *notify_goto_data_new(const char *headline,
234                                                      const char *lines,
235                                                      struct tile *ptile)
236 {
237   struct notify_goto_data *pdata = fc_malloc(sizeof(*pdata));
238 
239   pdata->headline = fc_strdup(headline);
240   pdata->lines = fc_strdup(lines);
241   pdata->ptile = ptile;
242 
243   return pdata;
244 }
245 
246 /**************************************************************************
247   Destroy a notify goto data.
248 **************************************************************************/
notify_goto_data_destroy(struct notify_goto_data * pdata)249 static void notify_goto_data_destroy(struct notify_goto_data *pdata)
250 {
251   free(pdata->headline);
252   free(pdata->lines);
253 }
254 
255 /**************************************************************************
256   Move the notify dialog.
257 **************************************************************************/
notify_goto_dialog_callback(struct widget * widget)258 static int notify_goto_dialog_callback(struct widget *widget)
259 {
260   struct notify_goto_dialog *pdialog =
261       (struct notify_goto_dialog *) widget->data.ptr;
262 
263   if (PRESSED_EVENT(Main.event)) {
264     move_window_group(pdialog->label, pdialog->window);
265   }
266 
267   return -1;
268 }
269 
270 /**************************************************************************
271   Close the notify dialog.
272 **************************************************************************/
notify_goto_dialog_close_callback(struct widget * widget)273 static int notify_goto_dialog_close_callback(struct widget *widget)
274 {
275   struct notify_goto_dialog *pdialog =
276       (struct notify_goto_dialog *) widget->data.ptr;
277 
278   if (PRESSED_EVENT(Main.event)) {
279     notify_goto_dialog_advance(pdialog);
280   }
281 
282   return -1;
283 }
284 
285 /**************************************************************************
286   Goto callback.
287 **************************************************************************/
notify_goto_dialog_goto_callback(struct widget * widget)288 static int notify_goto_dialog_goto_callback(struct widget *widget)
289 {
290   struct notify_goto_dialog *pdialog =
291       (struct notify_goto_dialog *) widget->data.ptr;
292   const struct notify_goto_data *pdata = notify_goto_list_get(pdialog->datas,
293                                                               0);
294 
295   if (PRESSED_EVENT(Main.event)) {
296     if (NULL != pdata->ptile) {
297       center_tile_mapcanvas(pdata->ptile);
298     }
299   } else if (Main.event.button.button == SDL_BUTTON_RIGHT) {
300      struct city *pcity;
301 
302      if (NULL != pdata->ptile && (pcity = tile_city(pdata->ptile))) {
303        popup_city_dialog(pcity);
304     }
305   }
306 
307   return -1;
308 }
309 
310 /**************************************************************************
311   Create a notify dialog.
312 **************************************************************************/
notify_goto_dialog_new(void)313 static struct notify_goto_dialog *notify_goto_dialog_new(void)
314 {
315   struct notify_goto_dialog *pdialog = fc_malloc(sizeof(*pdialog));
316   utf8_str *str;
317 
318   /* Window. */
319   str = create_utf8_from_char("", adj_font(12));
320   str->style |= TTF_STYLE_BOLD;
321 
322   pdialog->window = create_window_skeleton(NULL, str, 0);
323   pdialog->window->action = notify_goto_dialog_callback;
324   pdialog->window->data.ptr = pdialog;
325   set_wstate(pdialog->window, FC_WS_NORMAL);
326   add_to_gui_list(ID_WINDOW, pdialog->window);
327 
328   /* Close button. */
329   pdialog->close_button = create_themeicon(current_theme->Small_CANCEL_Icon,
330                                            pdialog->window->dst,
331                                            WF_WIDGET_HAS_INFO_LABEL
332                                            | WF_RESTORE_BACKGROUND);
333   pdialog->close_button->info_label =
334       create_utf8_from_char(_("Close Dialog (Esc)"), adj_font(12));
335   pdialog->close_button->action = notify_goto_dialog_close_callback;
336   pdialog->close_button->data.ptr = pdialog;
337   set_wstate(pdialog->close_button, FC_WS_NORMAL);
338   pdialog->close_button->key = SDLK_ESCAPE;
339   add_to_gui_list(ID_BUTTON, pdialog->close_button);
340 
341   pdialog->label = NULL;
342 
343   /* Data list. */
344   pdialog->datas = notify_goto_list_new_full(notify_goto_data_destroy);
345 
346   return pdialog;
347 }
348 
349 /**************************************************************************
350   Destroy a notify dialog.
351 **************************************************************************/
notify_goto_dialog_destroy(struct notify_goto_dialog * pdialog)352 static void notify_goto_dialog_destroy(struct notify_goto_dialog *pdialog)
353 {
354   widget_undraw(pdialog->window);
355   widget_mark_dirty(pdialog->window);
356   remove_gui_layer(pdialog->window->dst);
357 
358   del_widget_pointer_from_gui_list(pdialog->window);
359   del_widget_pointer_from_gui_list(pdialog->close_button);
360   if (NULL != pdialog->label) {
361     del_widget_pointer_from_gui_list(pdialog->label);
362   }
363 
364   notify_goto_list_destroy(pdialog->datas);
365   free(pdialog);
366 }
367 
368 /**************************************************************************
369   Update a notify dialog.
370 **************************************************************************/
notify_goto_dialog_update(struct notify_goto_dialog * pdialog)371 static void notify_goto_dialog_update(struct notify_goto_dialog *pdialog)
372 {
373   const struct notify_goto_data *pdata = notify_goto_list_get(pdialog->datas,
374                                                               0);
375 
376   if (NULL == pdata) {
377     return;
378   }
379 
380   widget_undraw(pdialog->window);
381   widget_mark_dirty(pdialog->window);
382 
383   copy_chars_to_utf8_str(pdialog->window->string_utf8, pdata->headline);
384   if (NULL != pdialog->label) {
385     del_widget_pointer_from_gui_list(pdialog->label);
386   }
387   pdialog->label = create_iconlabel_from_chars(NULL, pdialog->window->dst,
388                                                pdata->lines, adj_font(12),
389                                                WF_RESTORE_BACKGROUND);
390   pdialog->label->action = notify_goto_dialog_goto_callback;
391   pdialog->label->data.ptr = pdialog;
392   set_wstate(pdialog->label, FC_WS_NORMAL);
393   add_to_gui_list(ID_LABEL, pdialog->label);
394 
395   resize_window(pdialog->window, NULL, NULL,
396                 adj_size(pdialog->label->size.w + 40),
397                 adj_size(pdialog->label->size.h + 60));
398   widget_set_position(pdialog->window,
399                       (main_window_width() - pdialog->window->size.w) / 2,
400                       (main_window_height() - pdialog->window->size.h) / 2);
401   widget_set_position(pdialog->close_button, pdialog->window->size.w
402                       - pdialog->close_button->size.w - 1,
403                       pdialog->window->size.y + adj_size(2));
404   widget_set_position(pdialog->label, adj_size(20), adj_size(40));
405 
406   widget_redraw(pdialog->window);
407   widget_redraw(pdialog->close_button);
408   widget_redraw(pdialog->label);
409   widget_mark_dirty(pdialog->window);
410   flush_all();
411 }
412 
413 /**************************************************************************
414   Update a notify dialog.
415 **************************************************************************/
notify_goto_dialog_advance(struct notify_goto_dialog * pdialog)416 static void notify_goto_dialog_advance(struct notify_goto_dialog *pdialog)
417 {
418   if (1 < notify_goto_list_size(pdialog->datas)) {
419     notify_goto_list_remove(pdialog->datas,
420                             notify_goto_list_get(pdialog->datas, 0));
421     notify_goto_dialog_update(pdialog);
422   } else {
423     notify_goto_dialog_destroy(pdialog);
424     if (pdialog == notify_goto_dialog) {
425       notify_goto_dialog = NULL;
426     }
427   }
428 }
429 
430 /**************************************************************************
431   Popup a dialog to display information about an event that has a
432   specific location.  The user should be given the option to goto that
433   location.
434 **************************************************************************/
popup_notify_goto_dialog(const char * headline,const char * lines,const struct text_tag_list * tags,struct tile * ptile)435 void popup_notify_goto_dialog(const char *headline, const char *lines,
436                               const struct text_tag_list *tags,
437                               struct tile *ptile)
438 {
439   if (NULL == notify_goto_dialog) {
440     notify_goto_dialog = notify_goto_dialog_new();
441   }
442 
443   fc_assert(NULL != notify_goto_dialog);
444 
445   notify_goto_list_prepend(notify_goto_dialog->datas,
446                            notify_goto_data_new(headline, lines, ptile));
447   notify_goto_dialog_update(notify_goto_dialog);
448 }
449 
450 /**************************************************************************
451   Popdown the notify goto dialog.
452 **************************************************************************/
popdown_notify_goto_dialog(void)453 void popdown_notify_goto_dialog(void)
454 {
455   if (NULL != notify_goto_dialog) {
456     notify_goto_dialog_destroy(notify_goto_dialog);
457     notify_goto_dialog = NULL;
458   }
459 }
460 
461 /**************************************************************************
462   Popup a dialog to display connection message from server.
463 **************************************************************************/
popup_connect_msg(const char * headline,const char * message)464 void popup_connect_msg(const char *headline, const char *message)
465 {
466   log_error("popup_connect_msg() PORT ME");
467 }
468 
469 /* ----------------------------------------------------------------------- */
470 struct ADVANCED_DLG *pNotifyDlg = NULL;
471 
472 /**************************************************************************
473   User interacted with generic notify dialog.
474 **************************************************************************/
notify_dialog_window_callback(struct widget * pWindow)475 static int notify_dialog_window_callback(struct widget *pWindow)
476 {
477   if (PRESSED_EVENT(Main.event)) {
478     move_window_group(pNotifyDlg->pBeginWidgetList, pWindow);
479   }
480 
481   return -1;
482 }
483 
484 /**************************************************************************
485   User interacted with notify dialog close button.
486 **************************************************************************/
exit_notify_dialog_callback(struct widget * pWidget)487 static int exit_notify_dialog_callback(struct widget *pWidget)
488 {
489   if (PRESSED_EVENT(Main.event)) {
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();
496     }
497   }
498   return -1;
499 }
500 
501 /**************************************************************************
502   Popup a generic dialog to display some generic information.
503 **************************************************************************/
popup_notify_dialog(const char * caption,const char * headline,const char * lines)504 void popup_notify_dialog(const char *caption, const char *headline,
505                          const char *lines)
506 {
507   struct widget *pBuf, *pWindow;
508   utf8_str *pstr;
509   SDL_Surface *pHeadline, *pLines;
510   SDL_Rect dst;
511   SDL_Rect area;
512 
513   if (pNotifyDlg) {
514     return;
515   }
516 
517   pNotifyDlg = fc_calloc(1, sizeof(struct ADVANCED_DLG));
518 
519   pstr = create_utf8_from_char(caption, adj_font(12));
520   pstr->style |= TTF_STYLE_BOLD;
521 
522   pWindow = create_window_skeleton(NULL, pstr, 0);
523 
524   pWindow->action = notify_dialog_window_callback;
525   set_wstate(pWindow, FC_WS_NORMAL);
526 
527   add_to_gui_list(ID_WINDOW, pWindow);
528   pNotifyDlg->pEndWidgetList = pWindow;
529 
530   area = pWindow->area;
531 
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_utf8_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));
542 
543   add_to_gui_list(ID_BUTTON, pBuf);
544   pNotifyDlg->pBeginWidgetList = pBuf;
545 
546   pstr = create_utf8_from_char(headline, adj_font(16));
547   pstr->style |= TTF_STYLE_BOLD;
548 
549   pHeadline = create_text_surf_from_utf8(pstr);
550 
551   if (lines && *lines != '\0') {
552     change_ptsize_utf8(pstr, adj_font(12));
553     pstr->style &= ~TTF_STYLE_BOLD;
554     copy_chars_to_utf8_str(pstr, lines);
555     pLines = create_text_surf_from_utf8(pstr);
556   } else {
557     pLines = NULL;
558   }
559 
560   FREEUTF8STR(pstr);
561 
562   area.w = MAX(area.w, pHeadline->w);
563   if (pLines) {
564     area.w = MAX(area.w, pLines->w);
565   }
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);
570   }
571 
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);
575 
576   area = pWindow->area;
577 
578   widget_set_position(pWindow,
579                       (main_window_width() - pWindow->size.w) / 2,
580                       (main_window_height() - pWindow->size.h) / 2);
581 
582   dst.x = area.x + (area.w - pHeadline->w) / 2;
583   dst.y = area.y + adj_size(10);
584 
585   alphablit(pHeadline, NULL, pWindow->theme, &dst, 255);
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;
590     }
591 
592     alphablit(pLines, NULL, pWindow->theme, &dst, 255);
593   }
594 
595   FREESURFACE(pHeadline);
596   FREESURFACE(pLines);
597 
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);
602 
603   /* redraw */
604   redraw_group(pNotifyDlg->pBeginWidgetList, pWindow, 0);
605   widget_flush(pWindow);
606 }
607 
608 /* =======================================================================*/
609 /* ========================= UNIT UPGRADE DIALOG =========================*/
610 /* =======================================================================*/
611 static struct SMALL_DLG *pUnit_Upgrade_Dlg = NULL;
612 
613 /****************************************************************
614   User interacted with upgrade unit widget.
615 *****************************************************************/
upgrade_unit_window_callback(struct widget * pWindow)616 static int upgrade_unit_window_callback(struct widget *pWindow)
617 {
618   if (PRESSED_EVENT(Main.event)) {
619     move_window_group(pUnit_Upgrade_Dlg->pBeginWidgetList, pWindow);
620   }
621   return -1;
622 }
623 
624 /****************************************************************
625   User interacted with upgrade unit dialog cancel -button
626 *****************************************************************/
cancel_upgrade_unit_callback(struct widget * pWidget)627 static int cancel_upgrade_unit_callback(struct widget *pWidget)
628 {
629   if (PRESSED_EVENT(Main.event)) {
630     popdown_unit_upgrade_dlg();
631     /* enable city dlg */
632     enable_city_dlg_widgets();
633     flush_dirty();
634   }
635   return -1;
636 }
637 
638 /****************************************************************
639   User interacted with unit upgrade dialog "Upgrade" -button.
640 *****************************************************************/
ok_upgrade_unit_window_callback(struct widget * pWidget)641 static int ok_upgrade_unit_window_callback(struct widget *pWidget)
642 {
643   if (PRESSED_EVENT(Main.event)) {
644     struct unit *pUnit = pWidget->data.unit;
645 
646     popdown_unit_upgrade_dlg();
647     /* enable city dlg */
648     enable_city_dlg_widgets();
649     free_city_units_lists();
650     request_unit_upgrade(pUnit);
651     flush_dirty();
652   }
653   return -1;
654 }
655 
656 /****************************************************************
657   Open unit upgrade dialog.
658 *****************************************************************/
popup_unit_upgrade_dlg(struct unit * pUnit,bool city)659 void popup_unit_upgrade_dlg(struct unit *pUnit, bool city)
660 {
661   char cBuf[128];
662   struct widget *pBuf = NULL, *pWindow;
663   utf8_str *pstr;
664   SDL_Surface *pText;
665   SDL_Rect dst;
666   int window_x = 0, window_y = 0;
667   enum unit_upgrade_result unit_upgrade_result;
668   SDL_Rect area;
669 
670   if (pUnit_Upgrade_Dlg) {
671     /* just in case */
672     flush_dirty();
673     return;
674   }
675 
676   pUnit_Upgrade_Dlg = fc_calloc(1, sizeof(struct SMALL_DLG));
677 
678   unit_upgrade_result = unit_upgrade_info(pUnit, cBuf, sizeof(cBuf));
679 
680   pstr = create_utf8_from_char(_("Upgrade Obsolete Units"), adj_font(12));
681   pstr->style |= TTF_STYLE_BOLD;
682 
683   pWindow = create_window_skeleton(NULL, pstr, 0);
684 
685   pWindow->action = upgrade_unit_window_callback;
686   set_wstate(pWindow, FC_WS_NORMAL);
687 
688   pUnit_Upgrade_Dlg->pEndWidgetList = pWindow;
689 
690   add_to_gui_list(ID_WINDOW, pWindow);
691 
692   area = pWindow->area;
693 
694   /* ============================================================= */
695 
696   /* create text label */
697   pstr = create_utf8_from_char(cBuf, adj_font(10));
698   pstr->style |= (TTF_STYLE_BOLD|SF_CENTER);
699   pstr->fgcol = *get_theme_color(COLOR_THEME_UNITUPGRADE_TEXT);
700 
701   pText = create_text_surf_from_utf8(pstr);
702   FREEUTF8STR(pstr);
703 
704   area.w = MAX(area.w, pText->w + adj_size(20));
705   area.h += (pText->h + adj_size(10));
706 
707   /* cancel button */
708   pBuf = create_themeicon_button_from_chars(current_theme->CANCEL_Icon,
709                                             pWindow->dst, _("Cancel"),
710                                             adj_font(12), 0);
711 
712   pBuf->action = cancel_upgrade_unit_callback;
713   set_wstate(pBuf, FC_WS_NORMAL);
714 
715   area.h += (pBuf->size.h + adj_size(20));
716 
717   add_to_gui_list(ID_BUTTON, pBuf);
718 
719   if (UU_OK == unit_upgrade_result) {
720     pBuf = create_themeicon_button_from_chars(current_theme->OK_Icon, pWindow->dst,
721                                               _("Upgrade"), adj_font(12), 0);
722 
723     pBuf->action = ok_upgrade_unit_window_callback;
724     set_wstate(pBuf, FC_WS_NORMAL);
725     pBuf->data.unit = pUnit;
726     add_to_gui_list(ID_BUTTON, pBuf);
727     pBuf->size.w = MAX(pBuf->size.w, pBuf->next->size.w);
728     pBuf->next->size.w = pBuf->size.w;
729     area.w = MAX(area.w, adj_size(30) + pBuf->size.w * 2);
730   } else {
731     area.w = MAX(area.w, pBuf->size.w + adj_size(20));
732   }
733   /* ============================================ */
734 
735   pUnit_Upgrade_Dlg->pBeginWidgetList = pBuf;
736 
737   resize_window(pWindow, NULL, get_theme_color(COLOR_THEME_BACKGROUND),
738                 (pWindow->size.w - pWindow->area.w) + area.w,
739                 (pWindow->size.h - pWindow->area.h) + area.h);
740 
741   area = pWindow->area;
742 
743   if (city) {
744     window_x = Main.event.motion.x;
745     window_y = Main.event.motion.y;
746   } else {
747     put_window_near_map_tile(pWindow, pWindow->size.w, pWindow->size.h,
748                              unit_tile(pUnit));
749   }
750 
751   widget_set_position(pWindow, window_x, window_y);
752 
753   /* setup rest of widgets */
754   /* label */
755   dst.x = area.x + (area.w - pText->w) / 2;
756   dst.y = area.y + adj_size(10);
757   alphablit(pText, NULL, pWindow->theme, &dst, 255);
758   FREESURFACE(pText);
759 
760   /* cancel button */
761   pBuf = pWindow->prev;
762   pBuf->size.y = area.y + area.h - pBuf->size.h - adj_size(7);
763 
764   if (UU_OK == unit_upgrade_result) {
765     /* upgrade button */
766     pBuf = pBuf->prev;
767     pBuf->size.x = area.x + (area.w - (2 * pBuf->size.w + adj_size(10))) / 2;
768     pBuf->size.y = pBuf->next->size.y;
769 
770     /* cancel button */
771     pBuf->next->size.x = pBuf->size.x + pBuf->size.w + adj_size(10);
772   } else {
773     /* x position of cancel button */
774     pBuf->size.x = area.x + area.w - pBuf->size.w - adj_size(10);
775   }
776 
777   /* ================================================== */
778   /* redraw */
779   redraw_group(pUnit_Upgrade_Dlg->pBeginWidgetList, pWindow, 0);
780 
781   widget_mark_dirty(pWindow);
782   flush_dirty();
783 }
784 
785 /****************************************************************
786   Close unit upgrade dialog.
787 *****************************************************************/
popdown_unit_upgrade_dlg(void)788 static void popdown_unit_upgrade_dlg(void)
789 {
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);
794   }
795 }
796 
797 /* =======================================================================*/
798 /* ========================= UNIT DISBAND DIALOG =========================*/
799 /* =======================================================================*/
800 static struct SMALL_DLG *pUnit_Disband_Dlg = NULL;
801 
802 /****************************************************************
803   User interacted with disband unit widget.
804 *****************************************************************/
disband_unit_window_callback(struct widget * pWindow)805 static int disband_unit_window_callback(struct widget *pWindow)
806 {
807   if (PRESSED_EVENT(Main.event)) {
808     move_window_group(pUnit_Disband_Dlg->pBeginWidgetList, pWindow);
809   }
810 
811   return -1;
812 }
813 
814 /****************************************************************
815   User interacted with disband unit dialog cancel -button
816 *****************************************************************/
cancel_disband_unit_callback(struct widget * pWidget)817 static int cancel_disband_unit_callback(struct widget *pWidget)
818 {
819   if (PRESSED_EVENT(Main.event)) {
820     popdown_unit_disband_dlg();
821     /* enable city dlg */
822     enable_city_dlg_widgets();
823     flush_dirty();
824   }
825   return -1;
826 }
827 
828 /****************************************************************
829   User interacted with unit disband dialog "Disband" -button.
830 *****************************************************************/
ok_disband_unit_window_callback(struct widget * pWidget)831 static int ok_disband_unit_window_callback(struct widget *pWidget)
832 {
833   if (PRESSED_EVENT(Main.event)) {
834     struct unit *pUnit = pWidget->data.unit;
835 
836     popdown_unit_disband_dlg();
837     /* enable city dlg */
838     enable_city_dlg_widgets();
839     free_city_units_lists();
840     request_unit_disband(pUnit);
841     flush_dirty();
842   }
843   return -1;
844 }
845 
846 /****************************************************************
847   Open unit disband dialog.
848 *****************************************************************/
popup_unit_disband_dlg(struct unit * pUnit,bool city)849 void popup_unit_disband_dlg(struct unit *pUnit, bool city)
850 {
851   char cBuf[128];
852   struct widget *pBuf = NULL, *pWindow;
853   utf8_str *pstr;
854   SDL_Surface *pText;
855   SDL_Rect dst;
856   int window_x = 0, window_y = 0;
857   bool unit_disband_result;
858   SDL_Rect area;
859 
860   if (pUnit_Disband_Dlg) {
861     /* just in case */
862     flush_dirty();
863     return;
864   }
865 
866   pUnit_Disband_Dlg = fc_calloc(1, sizeof(struct SMALL_DLG));
867 
868   {
869     struct unit_list *pUnits = unit_list_new();
870 
871     unit_list_append(pUnits, pUnit);
872     unit_disband_result = get_units_disband_info(cBuf, sizeof(cBuf), pUnits);
873     unit_list_destroy(pUnits);
874   }
875 
876   pstr = create_utf8_from_char(_("Disband Units"), adj_font(12));
877   pstr->style |= TTF_STYLE_BOLD;
878 
879   pWindow = create_window_skeleton(NULL, pstr, 0);
880 
881   pWindow->action = disband_unit_window_callback;
882   set_wstate(pWindow, FC_WS_NORMAL);
883 
884   pUnit_Disband_Dlg->pEndWidgetList = pWindow;
885 
886   add_to_gui_list(ID_WINDOW, pWindow);
887 
888   area = pWindow->area;
889 
890   /* ============================================================= */
891 
892   /* create text label */
893   pstr = create_utf8_from_char(cBuf, adj_font(10));
894   pstr->style |= (TTF_STYLE_BOLD|SF_CENTER);
895   pstr->fgcol = *get_theme_color(COLOR_THEME_UNITDISBAND_TEXT);
896 
897   pText = create_text_surf_from_utf8(pstr);
898   FREEUTF8STR(pstr);
899 
900   area.w = MAX(area.w, pText->w + adj_size(20));
901   area.h += (pText->h + adj_size(10));
902 
903   /* cancel button */
904   pBuf = create_themeicon_button_from_chars(current_theme->CANCEL_Icon,
905                                             pWindow->dst, _("Cancel"),
906                                             adj_font(12), 0);
907 
908   pBuf->action = cancel_disband_unit_callback;
909   set_wstate(pBuf, FC_WS_NORMAL);
910 
911   area.h += (pBuf->size.h + adj_size(20));
912 
913   add_to_gui_list(ID_BUTTON, pBuf);
914 
915   if (unit_disband_result) {
916     pBuf = create_themeicon_button_from_chars(current_theme->OK_Icon, pWindow->dst,
917                                               _("Disband"), adj_font(12), 0);
918 
919     pBuf->action = ok_disband_unit_window_callback;
920     set_wstate(pBuf, FC_WS_NORMAL);
921     pBuf->data.unit = pUnit;
922     add_to_gui_list(ID_BUTTON, pBuf);
923     pBuf->size.w = MAX(pBuf->size.w, pBuf->next->size.w);
924     pBuf->next->size.w = pBuf->size.w;
925     area.w = MAX(area.w, adj_size(30) + pBuf->size.w * 2);
926   } else {
927     area.w = MAX(area.w, pBuf->size.w + adj_size(20));
928   }
929   /* ============================================ */
930 
931   pUnit_Disband_Dlg->pBeginWidgetList = pBuf;
932 
933   resize_window(pWindow, NULL, get_theme_color(COLOR_THEME_BACKGROUND),
934                 (pWindow->size.w - pWindow->area.w) + area.w,
935                 (pWindow->size.h - pWindow->area.h) + area.h);
936 
937   area = pWindow->area;
938 
939   if (city) {
940     window_x = Main.event.motion.x;
941     window_y = Main.event.motion.y;
942   } else {
943     put_window_near_map_tile(pWindow, pWindow->size.w, pWindow->size.h,
944                              unit_tile(pUnit));
945   }
946 
947   widget_set_position(pWindow, window_x, window_y);
948 
949   /* setup rest of widgets */
950   /* label */
951   dst.x = area.x + (area.w - pText->w) / 2;
952   dst.y = area.y + adj_size(10);
953   alphablit(pText, NULL, pWindow->theme, &dst, 255);
954   FREESURFACE(pText);
955 
956   /* cancel button */
957   pBuf = pWindow->prev;
958   pBuf->size.y = area.y + area.h - pBuf->size.h - adj_size(7);
959 
960   if (unit_disband_result) {
961     /* disband button */
962     pBuf = pBuf->prev;
963     pBuf->size.x = area.x + (area.w - (2 * pBuf->size.w + adj_size(10))) / 2;
964     pBuf->size.y = pBuf->next->size.y;
965 
966     /* cancel button */
967     pBuf->next->size.x = pBuf->size.x + pBuf->size.w + adj_size(10);
968   } else {
969     /* x position of cancel button */
970     pBuf->size.x = area.x + area.w - pBuf->size.w - adj_size(10);
971   }
972 
973   /* ================================================== */
974   /* redraw */
975   redraw_group(pUnit_Disband_Dlg->pBeginWidgetList, pWindow, 0);
976 
977   widget_mark_dirty(pWindow);
978   flush_dirty();
979 }
980 
981 /****************************************************************
982   Close unit disband dialog.
983 *****************************************************************/
popdown_unit_disband_dlg(void)984 static void popdown_unit_disband_dlg(void)
985 {
986   if (pUnit_Disband_Dlg) {
987     popdown_window_group_dialog(pUnit_Disband_Dlg->pBeginWidgetList,
988                                 pUnit_Disband_Dlg->pEndWidgetList);
989     FC_FREE(pUnit_Disband_Dlg);
990   }
991 }
992 
993 /* =======================================================================*/
994 /* ======================== UNIT SELECTION DIALOG ========================*/
995 /* =======================================================================*/
996 static struct ADVANCED_DLG *pUnit_Select_Dlg = NULL;
997 
998 /**************************************************************************
999   User interacted with unit selection window.
1000 **************************************************************************/
unit_select_window_callback(struct widget * pWindow)1001 static int unit_select_window_callback(struct widget *pWindow)
1002 {
1003   if (PRESSED_EVENT(Main.event)) {
1004     move_window_group(pUnit_Select_Dlg->pBeginWidgetList, pWindow);
1005   }
1006 
1007   return -1;
1008 }
1009 
1010 /**************************************************************************
1011   User requested unit select window to be closed.
1012 **************************************************************************/
exit_unit_select_callback(struct widget * pWidget)1013 static int exit_unit_select_callback(struct widget *pWidget)
1014 {
1015   if (PRESSED_EVENT(Main.event)) {
1016     unit_select_dialog_popdown();
1017     is_unit_move_blocked = FALSE;
1018   }
1019 
1020   return -1;
1021 }
1022 
1023 /**************************************************************************
1024   User selected unit from unit select window.
1025 **************************************************************************/
unit_select_callback(struct widget * pWidget)1026 static int unit_select_callback(struct widget *pWidget)
1027 {
1028   if (PRESSED_EVENT(Main.event)) {
1029     struct unit *pUnit =
1030       player_unit_by_number(client_player(), MAX_ID - pWidget->ID);
1031 
1032     unit_select_dialog_popdown();
1033     if (pUnit) {
1034       request_new_unit_activity(pUnit, ACTIVITY_IDLE);
1035       unit_focus_set(pUnit);
1036     }
1037   }
1038   return -1;
1039 }
1040 
1041 /**************************************************************************
1042   Popdown a dialog window to select units on a particular tile.
1043 **************************************************************************/
unit_select_dialog_popdown(void)1044 static void unit_select_dialog_popdown(void)
1045 {
1046   if (pUnit_Select_Dlg) {
1047     is_unit_move_blocked = FALSE;
1048     popdown_window_group_dialog(pUnit_Select_Dlg->pBeginWidgetList,
1049                                 pUnit_Select_Dlg->pEndWidgetList);
1050 
1051     FC_FREE(pUnit_Select_Dlg->pScroll);
1052     FC_FREE(pUnit_Select_Dlg);
1053     flush_dirty();
1054   }
1055 }
1056 
1057 /**************************************************************************
1058   Popup a dialog window to select units on a particular tile.
1059 **************************************************************************/
unit_select_dialog_popup(struct tile * ptile)1060 void unit_select_dialog_popup(struct tile *ptile)
1061 {
1062   struct widget *pBuf = NULL, *pWindow;
1063   utf8_str *pstr;
1064   struct unit *pUnit = NULL, *pFocus = head_of_units_in_focus();
1065   struct unit_type *pUnitType;
1066   char cBuf[255];
1067   int i, w = 0, n;
1068   SDL_Rect area;
1069 
1070 #define NUM_SEEN	20
1071 
1072   n = unit_list_size(ptile->units);
1073 
1074   if (!n || pUnit_Select_Dlg) {
1075     return;
1076   }
1077 
1078   is_unit_move_blocked = TRUE;
1079   pUnit_Select_Dlg = fc_calloc(1, sizeof(struct ADVANCED_DLG));
1080 
1081   fc_snprintf(cBuf , sizeof(cBuf),"%s (%d)", _("Unit selection") , n);
1082   pstr = create_utf8_from_char(cBuf , adj_font(12));
1083   pstr->style |= TTF_STYLE_BOLD;
1084 
1085   pWindow = create_window_skeleton(NULL, pstr, 0);
1086 
1087   pWindow->action = unit_select_window_callback;
1088   set_wstate(pWindow, FC_WS_NORMAL);
1089 
1090   add_to_gui_list(ID_UNIT_SELECT_DLG_WINDOW, pWindow);
1091   pUnit_Select_Dlg->pEndWidgetList = pWindow;
1092 
1093   area = pWindow->area;
1094 
1095   /* ---------- */
1096   /* create exit button */
1097   pBuf = create_themeicon(current_theme->Small_CANCEL_Icon, pWindow->dst,
1098                           WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
1099   pBuf->info_label = create_utf8_from_char(_("Close Dialog (Esc)"),
1100                                            adj_font(12));
1101   pBuf->action = exit_unit_select_callback;
1102   set_wstate(pBuf, FC_WS_NORMAL);
1103   pBuf->key = SDLK_ESCAPE;
1104   area.w += (pBuf->size.w + adj_size(10));
1105 
1106   add_to_gui_list(ID_UNIT_SELECT_DLG_EXIT_BUTTON, pBuf);
1107 
1108   /* ---------- */
1109 
1110   for (i = 0; i < n; i++) {
1111     const char *vetname;
1112 
1113     pUnit = unit_list_get(ptile->units, i);
1114     pUnitType = unit_type_get(pUnit);
1115     vetname = utype_veteran_name_translation(pUnitType, pUnit->veteran);
1116 
1117     if (unit_owner(pUnit) == client.conn.playing) {
1118       fc_snprintf(cBuf , sizeof(cBuf), _("Contact %s (%d / %d) %s(%d,%d,%s) %s"),
1119                   (vetname != NULL ? vetname : ""),
1120                   pUnit->hp, pUnitType->hp,
1121                   utype_name_translation(pUnitType),
1122                   pUnitType->attack_strength,
1123                   pUnitType->defense_strength,
1124                   move_points_text(pUnitType->move_rate, FALSE),
1125                   unit_activity_text(pUnit));
1126     } else {
1127       int att_chance, def_chance;
1128 
1129       fc_snprintf(cBuf , sizeof(cBuf), _("%s %s %s(A:%d D:%d M:%s FP:%d) HP:%d%%"),
1130                   nation_adjective_for_player(unit_owner(pUnit)),
1131                   (vetname != NULL ? vetname : ""),
1132                   utype_name_translation(pUnitType),
1133                   pUnitType->attack_strength,
1134                   pUnitType->defense_strength,
1135                   move_points_text(pUnitType->move_rate, FALSE),
1136                   pUnitType->firepower,
1137                   (pUnit->hp * 100 / pUnitType->hp + 9) / 10);
1138 
1139       /* calculate chance to win */
1140       if (sdl_get_chance_to_win(&att_chance, &def_chance, pUnit, pFocus)) {
1141         /* TRANS: "CtW" = "Chance to Win"; preserve leading space */
1142         cat_snprintf(cBuf, sizeof(cBuf), _(" CtW: Att:%d%% Def:%d%%"),
1143                      att_chance, def_chance);
1144       }
1145     }
1146 
1147     create_active_iconlabel(pBuf, pWindow->dst, pstr, cBuf,
1148                             unit_select_callback);
1149 
1150     add_to_gui_list(MAX_ID - pUnit->id , pBuf);
1151 
1152     area.w = MAX(area.w, pBuf->size.w);
1153     area.h += pBuf->size.h;
1154     if (unit_owner(pUnit) == client.conn.playing) {
1155       set_wstate(pBuf, FC_WS_NORMAL);
1156     }
1157 
1158     if (i > NUM_SEEN - 1) {
1159       set_wflag(pBuf , WF_HIDDEN);
1160     }
1161   }
1162 
1163   pUnit_Select_Dlg->pBeginWidgetList = pBuf;
1164   pUnit_Select_Dlg->pBeginActiveWidgetList = pUnit_Select_Dlg->pBeginWidgetList;
1165   pUnit_Select_Dlg->pEndActiveWidgetList = pWindow->prev->prev;
1166   pUnit_Select_Dlg->pActiveWidgetList = pUnit_Select_Dlg->pEndActiveWidgetList;
1167 
1168   area.w += adj_size(2);
1169   if (n > NUM_SEEN) {
1170     n = create_vertical_scrollbar(pUnit_Select_Dlg, 1, NUM_SEEN, TRUE, TRUE);
1171     area.w += n;
1172 
1173     /* ------- window ------- */
1174     area.h = NUM_SEEN * pWindow->prev->prev->size.h;
1175   }
1176 
1177   resize_window(pWindow, NULL, NULL,
1178                 (pWindow->size.w - pWindow->area.w) + area.w,
1179                 (pWindow->size.h - pWindow->area.h) + area.h);
1180 
1181   area = pWindow->area;
1182 
1183   put_window_near_map_tile(pWindow, pWindow->size.w, pWindow->size.h,
1184                            unit_tile(pUnit));
1185 
1186   w = area.w;
1187 
1188   if (pUnit_Select_Dlg->pScroll) {
1189     w -= n;
1190   }
1191 
1192   /* exit button */
1193   pBuf = pWindow->prev;
1194   pBuf->size.x = area.x + area.w - pBuf->size.w - 1;
1195   pBuf->size.y = pWindow->size.y + adj_size(2);
1196   pBuf = pBuf->prev;
1197 
1198   setup_vertical_widgets_position(1, area.x + 1, area.y, w, 0,
1199                                   pUnit_Select_Dlg->pBeginActiveWidgetList,
1200                                   pBuf);
1201 
1202   if (pUnit_Select_Dlg->pScroll) {
1203     setup_vertical_scrollbar_area(pUnit_Select_Dlg->pScroll,
1204                                   area.x + area.w, area.y,
1205                                   area.h, TRUE);
1206   }
1207 
1208   /* ==================================================== */
1209   /* redraw */
1210   redraw_group(pUnit_Select_Dlg->pBeginWidgetList, pWindow, 0);
1211 
1212   widget_flush(pWindow);
1213 }
1214 
1215 /**************************************************************************
1216   Update the dialog window to select units on a particular tile.
1217 **************************************************************************/
unit_select_dialog_update_real(void * unused)1218 void unit_select_dialog_update_real(void *unused)
1219 {
1220   /* PORTME */
1221 }
1222 
1223 /* ====================================================================== */
1224 /* ============================ TERRAIN INFO ============================ */
1225 /* ====================================================================== */
1226 static struct SMALL_DLG *pTerrain_Info_Dlg = NULL;
1227 
1228 
1229 /**************************************************************************
1230   Popdown terrain information dialog.
1231 **************************************************************************/
terrain_info_window_dlg_callback(struct widget * pWindow)1232 static int terrain_info_window_dlg_callback(struct widget *pWindow)
1233 {
1234   if (PRESSED_EVENT(Main.event)) {
1235     move_window_group(pTerrain_Info_Dlg->pBeginWidgetList, pWindow);
1236   }
1237   return -1;
1238 }
1239 
1240 /**************************************************************************
1241   Popdown terrain information dialog.
1242 **************************************************************************/
popdown_terrain_info_dialog(void)1243 static void popdown_terrain_info_dialog(void)
1244 {
1245   if (pTerrain_Info_Dlg) {
1246     popdown_window_group_dialog(pTerrain_Info_Dlg->pBeginWidgetList,
1247 				pTerrain_Info_Dlg->pEndWidgetList);
1248     FC_FREE(pTerrain_Info_Dlg);
1249     flush_dirty();
1250   }
1251 }
1252 
1253 /**************************************************************************
1254   Popdown terrain information dialog.
1255 **************************************************************************/
exit_terrain_info_dialog_callback(struct widget * pButton)1256 static int exit_terrain_info_dialog_callback(struct widget *pButton)
1257 {
1258   if (PRESSED_EVENT(Main.event)) {
1259     popdown_terrain_info_dialog();
1260   }
1261   return -1;
1262 }
1263 
1264 /**************************************************************************
1265   Return a (static) string with terrain defense bonus.
1266   This does not include bonuses some units may get out of bases.
1267 **************************************************************************/
sdl_get_tile_defense_info_text(struct tile * ptile)1268 const char *sdl_get_tile_defense_info_text(struct tile *ptile)
1269 {
1270   static char buffer[64];
1271   int bonus = (tile_terrain(ptile)->defense_bonus - 10) * 10;
1272 
1273   extra_type_iterate(pextra) {
1274     if (tile_has_extra(ptile, pextra)
1275         && pextra->category == ECAT_NATURAL) {
1276       bonus += pextra->defense_bonus;
1277     }
1278   } extra_type_iterate_end;
1279 
1280   fc_snprintf(buffer, sizeof(buffer), _("Terrain Defense Bonus: +%d%% "), bonus);
1281 
1282   return buffer;
1283 }
1284 
1285 /**************************************************************************
1286   Popup terrain information dialog.
1287 **************************************************************************/
popup_terrain_info_dialog(SDL_Surface * pDest,struct tile * ptile)1288 static void popup_terrain_info_dialog(SDL_Surface *pDest, struct tile *ptile)
1289 {
1290   SDL_Surface *pSurf;
1291   struct widget *pBuf, *pWindow;
1292   utf8_str *pstr;
1293   char cBuf[256];
1294   SDL_Rect area;
1295 
1296   if (pTerrain_Info_Dlg) {
1297     flush_dirty();
1298     return;
1299   }
1300 
1301   pSurf = get_terrain_surface(ptile);
1302   pTerrain_Info_Dlg = fc_calloc(1, sizeof(struct SMALL_DLG));
1303 
1304   /* ----------- */
1305   fc_snprintf(cBuf, sizeof(cBuf), "%s [%d,%d]", _("Terrain Info"),
1306               TILE_XY(ptile));
1307 
1308   pWindow = create_window_skeleton(NULL, create_utf8_from_char(cBuf , adj_font(12)), 0);
1309   pWindow->string_utf8->style |= TTF_STYLE_BOLD;
1310 
1311   pWindow->action = terrain_info_window_dlg_callback;
1312   set_wstate(pWindow, FC_WS_NORMAL);
1313 
1314   add_to_gui_list(ID_TERRAIN_INFO_DLG_WINDOW, pWindow);
1315   pTerrain_Info_Dlg->pEndWidgetList = pWindow;
1316 
1317   area = pWindow->area;
1318 
1319   /* ---------- */
1320   pstr = create_utf8_from_char(popup_info_text(ptile), adj_font(12));
1321   pstr->style |= SF_CENTER;
1322   pBuf = create_iconlabel(pSurf, pWindow->dst, pstr, 0);
1323 
1324   pBuf->size.h += tileset_tile_height(tileset) / 2;
1325 
1326   add_to_gui_list(ID_LABEL, pBuf);
1327 
1328   /* ------ window ---------- */
1329   area.w = MAX(area.w, pBuf->size.w + adj_size(20));
1330   area.h = MAX(area.h, pBuf->size.h);
1331 
1332   resize_window(pWindow, NULL, get_theme_color(COLOR_THEME_BACKGROUND),
1333                 (pWindow->size.w - pWindow->area.w) + area.w,
1334                 (pWindow->size.h - pWindow->area.h) + area.h);
1335 
1336   area = pWindow->area;
1337 
1338   put_window_near_map_tile(pWindow, pWindow->size.w, pWindow->size.h, ptile);
1339 
1340   /* ------------------------ */
1341 
1342   pBuf->size.x = area.x + adj_size(10);
1343   pBuf->size.y = area.y;
1344 
1345   /* exit icon */
1346   pBuf = create_themeicon(current_theme->Small_CANCEL_Icon, pWindow->dst,
1347                           WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
1348   pBuf->info_label = create_utf8_from_char(_("Close Dialog (Esc)"),
1349                                            adj_font(12));
1350   pBuf->size.x = area.x + area.w - pBuf->size.w - 1;
1351   pBuf->size.y = pWindow->size.y + adj_size(2);
1352   pBuf->action = exit_terrain_info_dialog_callback;
1353   set_wstate(pBuf, FC_WS_NORMAL);
1354   pBuf->key = SDLK_ESCAPE;
1355 
1356   add_to_gui_list(ID_TERRAIN_INFO_DLG_EXIT_BUTTON, pBuf);
1357 
1358   pTerrain_Info_Dlg->pBeginWidgetList = pBuf;
1359   /* --------------------------------- */
1360   /* redraw */
1361   redraw_group(pTerrain_Info_Dlg->pBeginWidgetList, pWindow, 0);
1362   widget_mark_dirty(pWindow);
1363   flush_dirty();
1364 }
1365 
1366 /* ====================================================================== */
1367 /* ========================= ADVANCED_TERRAIN_MENU ====================== */
1368 /* ====================================================================== */
1369 struct ADVANCED_DLG  *pAdvanced_Terrain_Dlg = NULL;
1370 
1371 /**************************************************************************
1372   Popdown a generic dialog to display some generic information about
1373   terrain : tile, units , cities, etc.
1374 **************************************************************************/
popdown_advanced_terrain_dialog(void)1375 void popdown_advanced_terrain_dialog(void)
1376 {
1377   if (pAdvanced_Terrain_Dlg) {
1378     is_unit_move_blocked = FALSE;
1379     popdown_window_group_dialog(pAdvanced_Terrain_Dlg->pBeginWidgetList,
1380                                 pAdvanced_Terrain_Dlg->pEndWidgetList);
1381 
1382     FC_FREE(pAdvanced_Terrain_Dlg->pScroll);
1383     FC_FREE(pAdvanced_Terrain_Dlg);
1384   }
1385 }
1386 
1387 /**************************************************************************
1388   User selected "Advanced Menu"
1389 **************************************************************************/
advanced_terrain_window_dlg_callback(struct widget * pWindow)1390 int advanced_terrain_window_dlg_callback(struct widget *pWindow)
1391 {
1392   if (PRESSED_EVENT(Main.event)) {
1393     move_window_group(pAdvanced_Terrain_Dlg->pBeginWidgetList, pWindow);
1394   }
1395   return -1;
1396 }
1397 
1398 /**************************************************************************
1399   User requested closing of advanced terrain dialog.
1400 **************************************************************************/
exit_advanced_terrain_dlg_callback(struct widget * pWidget)1401 int exit_advanced_terrain_dlg_callback(struct widget *pWidget)
1402 {
1403   if (PRESSED_EVENT(Main.event)) {
1404     popdown_advanced_terrain_dialog();
1405     flush_dirty();
1406   }
1407   return -1;
1408 }
1409 
1410 /**************************************************************************
1411   User requested terrain info.
1412 **************************************************************************/
terrain_info_callback(struct widget * pWidget)1413 static int terrain_info_callback(struct widget *pWidget)
1414 {
1415   if (PRESSED_EVENT(Main.event)) {
1416     int x = pWidget->data.cont->id0;
1417     int y = pWidget->data.cont->id1;
1418 
1419     popdown_advanced_terrain_dialog();
1420 
1421     popup_terrain_info_dialog(NULL, map_pos_to_tile(x , y));
1422   }
1423   return -1;
1424 }
1425 
1426 /**************************************************************************
1427   User requested zoom to city.
1428 **************************************************************************/
zoom_to_city_callback(struct widget * pWidget)1429 static int zoom_to_city_callback(struct widget *pWidget)
1430 {
1431   if (PRESSED_EVENT(Main.event)) {
1432     struct city *pCity = pWidget->data.city;
1433 
1434     popdown_advanced_terrain_dialog();
1435 
1436     popup_city_dialog(pCity);
1437   }
1438   return -1;
1439 }
1440 
1441 /**************************************************************************
1442   User requested production change.
1443 **************************************************************************/
change_production_callback(struct widget * pWidget)1444 static int change_production_callback(struct widget *pWidget)
1445 {
1446   if (PRESSED_EVENT(Main.event)) {
1447     struct city *pCity = pWidget->data.city;
1448 
1449     popdown_advanced_terrain_dialog();
1450     popup_worklist_editor(pCity, NULL);
1451   }
1452   return -1;
1453 }
1454 
1455 /**************************************************************************
1456   User requested hurry production.
1457 **************************************************************************/
hurry_production_callback(struct widget * pWidget)1458 static int hurry_production_callback(struct widget *pWidget)
1459 {
1460   if (PRESSED_EVENT(Main.event)) {
1461     struct city *pCity = pWidget->data.city;
1462 
1463     popdown_advanced_terrain_dialog();
1464 
1465     popup_hurry_production_dialog(pCity, NULL);
1466   }
1467   return -1;
1468 }
1469 
1470 /**************************************************************************
1471   User requested opening of cma settings.
1472 **************************************************************************/
cma_callback(struct widget * pWidget)1473 static int cma_callback(struct widget *pWidget)
1474 {
1475   if (PRESSED_EVENT(Main.event)) {
1476     struct city *pCity = pWidget->data.city;
1477 
1478     popdown_advanced_terrain_dialog();
1479     popup_city_cma_dialog(pCity);
1480   }
1481   return -1;
1482 }
1483 
1484 /**************************************************************************
1485   User selected unit.
1486 **************************************************************************/
adv_unit_select_callback(struct widget * pWidget)1487 static int adv_unit_select_callback(struct widget *pWidget)
1488 {
1489   if (PRESSED_EVENT(Main.event)) {
1490     struct unit *pUnit = pWidget->data.unit;
1491 
1492     popdown_advanced_terrain_dialog();
1493 
1494     if (pUnit) {
1495       request_new_unit_activity(pUnit, ACTIVITY_IDLE);
1496       unit_focus_set(pUnit);
1497     }
1498   }
1499   return -1;
1500 }
1501 
1502 /**************************************************************************
1503   User selected all units from tile.
1504 **************************************************************************/
adv_unit_select_all_callback(struct widget * pWidget)1505 static int adv_unit_select_all_callback(struct widget *pWidget)
1506 {
1507   if (PRESSED_EVENT(Main.event)) {
1508     struct unit *pUnit = pWidget->data.unit;
1509 
1510     popdown_advanced_terrain_dialog();
1511 
1512     if (pUnit) {
1513       activate_all_units(unit_tile(pUnit));
1514     }
1515   }
1516   return -1;
1517 }
1518 
1519 /**************************************************************************
1520   Sentry unit widget contains.
1521 **************************************************************************/
adv_unit_sentry_idle_callback(struct widget * pWidget)1522 static int adv_unit_sentry_idle_callback(struct widget *pWidget)
1523 {
1524   if (PRESSED_EVENT(Main.event)) {
1525     struct unit *pUnit = pWidget->data.unit;
1526 
1527     popdown_advanced_terrain_dialog();
1528 
1529     if (pUnit) {
1530       struct tile *ptile = unit_tile(pUnit);
1531 
1532       unit_list_iterate(ptile->units, punit) {
1533         if (unit_owner(punit) == client.conn.playing
1534             && ACTIVITY_IDLE == punit->activity
1535             && !punit->ai_controlled
1536             && can_unit_do_activity(punit, ACTIVITY_SENTRY)) {
1537           request_new_unit_activity(punit, ACTIVITY_SENTRY);
1538         }
1539       } unit_list_iterate_end;
1540     }
1541   }
1542   return -1;
1543 }
1544 
1545 /**************************************************************************
1546   Initiate goto to selected tile.
1547 **************************************************************************/
goto_here_callback(struct widget * pWidget)1548 static int goto_here_callback(struct widget *pWidget)
1549 {
1550   if (PRESSED_EVENT(Main.event)) {
1551     int x = pWidget->data.cont->id0;
1552     int y = pWidget->data.cont->id1;
1553 
1554     popdown_advanced_terrain_dialog();
1555 
1556     /* may not work */
1557     send_goto_tile(head_of_units_in_focus(), map_pos_to_tile(x, y));
1558   }
1559   return -1;
1560 }
1561 
1562 /**************************************************************************
1563   Initiate patrol to selected tile.
1564 **************************************************************************/
patrol_here_callback(struct widget * pWidget)1565 static int patrol_here_callback(struct widget *pWidget)
1566 {
1567   if (PRESSED_EVENT(Main.event)) {
1568 
1569 /* FIXME */
1570 #if 0
1571     int x = pWidget->data.cont->id0;
1572     int y = pWidget->data.cont->id1;
1573     struct unit *pUnit = head_of_units_in_focus();
1574 #endif
1575 
1576     popdown_advanced_terrain_dialog();
1577 
1578 #if 0
1579     if (pUnit) {
1580       enter_goto_state(pUnit);
1581       /* may not work */
1582       do_unit_patrol_to(pUnit, map_pos_to_tile(x, y));
1583       exit_goto_state();
1584     }
1585 #endif /* 0 */
1586   }
1587   return -1;
1588 }
1589 
1590 /**************************************************************************
1591   Initiate paradrop to selected tile.
1592 **************************************************************************/
paradrop_here_callback(struct widget * pWidget)1593 static int paradrop_here_callback(struct widget *pWidget)
1594 {
1595   if (PRESSED_EVENT(Main.event)) {
1596 /* FIXME */
1597 #if 0
1598     int x = pWidget->data.cont->id0;
1599     int y = pWidget->data.cont->id1;
1600 #endif
1601 
1602     popdown_advanced_terrain_dialog();
1603 
1604 #if 0
1605     /* may not work */
1606     do_unit_paradrop_to(get_unit_in_focus(), map_pos_to_tile(x, y));
1607 #endif
1608   }
1609   return -1;
1610 }
1611 
1612 /**************************************************************************
1613   Show help about unit type.
1614 **************************************************************************/
unit_help_callback(struct widget * pWidget)1615 static int unit_help_callback(struct widget *pWidget)
1616 {
1617   if (PRESSED_EVENT(Main.event)) {
1618     Unit_type_id unit_id = MAX_ID - pWidget->ID;
1619 
1620     popdown_advanced_terrain_dialog();
1621     popup_unit_info(unit_id);
1622   }
1623   return -1;
1624 }
1625 
1626 /**************************************************************************
1627   Popup a generic dialog to display some generic information about
1628   terrain : tile, units , cities, etc.
1629 **************************************************************************/
popup_advanced_terrain_dialog(struct tile * ptile,Uint16 pos_x,Uint16 pos_y)1630 void popup_advanced_terrain_dialog(struct tile *ptile, Uint16 pos_x, Uint16 pos_y)
1631 {
1632   struct widget *pWindow = NULL, *pBuf = NULL;
1633   struct city *pCity;
1634   struct unit *pFocus_Unit;
1635   utf8_str *pstr;
1636   SDL_Rect area2;
1637   struct CONTAINER *pCont;
1638   char cBuf[255];
1639   int n, w = 0, h, units_h = 0;
1640   SDL_Rect area;
1641 
1642   if (pAdvanced_Terrain_Dlg) {
1643     return;
1644   }
1645 
1646   pCity = tile_city(ptile);
1647   n = unit_list_size(ptile->units);
1648   pFocus_Unit = head_of_units_in_focus();
1649 
1650   if (!n && !pCity && !pFocus_Unit) {
1651     popup_terrain_info_dialog(NULL, ptile);
1652 
1653     return;
1654   }
1655 
1656   area.h = adj_size(2);
1657   is_unit_move_blocked = TRUE;
1658 
1659   pAdvanced_Terrain_Dlg = fc_calloc(1, sizeof(struct ADVANCED_DLG));
1660 
1661   pCont = fc_calloc(1, sizeof(struct CONTAINER));
1662   pCont->id0 = index_to_map_pos_x(tile_index(ptile));
1663   pCont->id1 = index_to_map_pos_y(tile_index(ptile));
1664 
1665   pstr = create_utf8_from_char(_("Advanced Menu") , adj_font(12));
1666   pstr->style |= TTF_STYLE_BOLD;
1667 
1668   pWindow = create_window_skeleton(NULL, pstr, 0);
1669 
1670   pWindow->action = advanced_terrain_window_dlg_callback;
1671   set_wstate(pWindow , FC_WS_NORMAL);
1672 
1673   add_to_gui_list(ID_TERRAIN_ADV_DLG_WINDOW, pWindow);
1674   pAdvanced_Terrain_Dlg->pEndWidgetList = pWindow;
1675 
1676   area = pWindow->area;
1677 
1678   /* ---------- */
1679   /* exit button */
1680   pBuf = create_themeicon(current_theme->Small_CANCEL_Icon, pWindow->dst,
1681                           WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
1682   pBuf->info_label = create_utf8_from_char(_("Close Dialog (Esc)"),
1683                                            adj_font(12));
1684   area.w += pBuf->size.w + adj_size(10);
1685   pBuf->action = exit_advanced_terrain_dlg_callback;
1686   set_wstate(pBuf, FC_WS_NORMAL);
1687   pBuf->key = SDLK_ESCAPE;
1688 
1689   add_to_gui_list(ID_TERRAIN_ADV_DLG_EXIT_BUTTON, pBuf);
1690   /* ---------- */
1691 
1692   pstr = create_utf8_from_char(_("Terrain Info") , adj_font(10));
1693   pstr->style |= TTF_STYLE_BOLD;
1694 
1695   pBuf = create_iconlabel(NULL, pWindow->dst, pstr,
1696     (WF_RESTORE_BACKGROUND|WF_DRAW_TEXT_LABEL_WITH_SPACE|WF_FREE_DATA));
1697 
1698   pBuf->string_utf8->bgcol = (SDL_Color) {0, 0, 0, 0};
1699 
1700   pBuf->data.cont = pCont;
1701 
1702   pBuf->action = terrain_info_callback;
1703   set_wstate(pBuf, FC_WS_NORMAL);
1704 
1705   add_to_gui_list(ID_LABEL, pBuf);
1706 
1707   area.w = MAX(area.w, pBuf->size.w);
1708   area.h += pBuf->size.h;
1709 
1710   /* ---------- */
1711   if (pCity && city_owner(pCity) == client.conn.playing) {
1712     /* separator */
1713     pBuf = create_iconlabel(NULL, pWindow->dst, NULL, WF_FREE_THEME);
1714 
1715     add_to_gui_list(ID_SEPARATOR, pBuf);
1716     area.h += pBuf->next->size.h;
1717     /* ------------------ */
1718 
1719     fc_snprintf(cBuf, sizeof(cBuf), _("Zoom to : %s"), city_name_get(pCity));
1720 
1721     create_active_iconlabel(pBuf, pWindow->dst,
1722                             pstr, cBuf, zoom_to_city_callback);
1723     pBuf->data.city = pCity;
1724     set_wstate(pBuf, FC_WS_NORMAL);
1725 
1726     add_to_gui_list(ID_LABEL, pBuf);
1727 
1728     area.w = MAX(area.w, pBuf->size.w);
1729     area.h += pBuf->size.h;
1730     /* ----------- */
1731 
1732     create_active_iconlabel(pBuf, pWindow->dst, pstr,
1733                             _("Change Production"), change_production_callback);
1734 
1735     pBuf->data.city = pCity;
1736     set_wstate(pBuf, FC_WS_NORMAL);
1737 
1738     add_to_gui_list(ID_LABEL, pBuf);
1739 
1740     area.w = MAX(area.w, pBuf->size.w);
1741     area.h += pBuf->size.h;
1742     /* -------------- */
1743 
1744     create_active_iconlabel(pBuf, pWindow->dst, pstr,
1745                             _("Hurry production"), hurry_production_callback);
1746 
1747     pBuf->data.city = pCity;
1748     set_wstate(pBuf, FC_WS_NORMAL);
1749 
1750     add_to_gui_list(ID_LABEL, pBuf);
1751 
1752     area.w = MAX(area.w, pBuf->size.w);
1753     area.h += pBuf->size.h;
1754     /* ----------- */
1755 
1756     create_active_iconlabel(pBuf, pWindow->dst, pstr,
1757                             _("Change City Governor settings"), cma_callback);
1758 
1759     pBuf->data.city = pCity;
1760     set_wstate(pBuf, FC_WS_NORMAL);
1761 
1762     add_to_gui_list(ID_LABEL, pBuf);
1763 
1764     area.w = MAX(area.w, pBuf->size.w);
1765     area.h += pBuf->size.h;
1766   }
1767   /* ---------- */
1768 
1769   if (pFocus_Unit
1770       && (tile_index(unit_tile(pFocus_Unit)) != tile_index(ptile))) {
1771     /* separator */
1772     pBuf = create_iconlabel(NULL, pWindow->dst, NULL, WF_FREE_THEME);
1773 
1774     add_to_gui_list(ID_SEPARATOR, pBuf);
1775     area.h += pBuf->next->size.h;
1776     /* ------------------ */
1777 
1778     create_active_iconlabel(pBuf, pWindow->dst, pstr, _("Goto here"),
1779                             goto_here_callback);
1780     pBuf->data.cont = pCont;
1781     set_wstate(pBuf, FC_WS_NORMAL);
1782 
1783     add_to_gui_list(MAX_ID - 1000 - pFocus_Unit->id, pBuf);
1784 
1785     area.w = MAX(area.w, pBuf->size.w);
1786     area.h += pBuf->size.h;
1787     /* ----------- */
1788 
1789     create_active_iconlabel(pBuf, pWindow->dst, pstr, _("Patrol here"),
1790                             patrol_here_callback);
1791     pBuf->data.cont = pCont;
1792     set_wstate(pBuf, FC_WS_NORMAL);
1793 
1794     add_to_gui_list(MAX_ID - 1000 - pFocus_Unit->id, pBuf);
1795 
1796     area.w = MAX(area.w, pBuf->size.w);
1797     area.h += pBuf->size.h;
1798     /* ----------- */
1799 
1800 #if 0 /* FIXME: specific connect buttons */
1801     if (unit_has_type_flag(pFocus_Unit, UTYF_SETTLERS)) {
1802       create_active_iconlabel(pBuf, pWindow->dst->surface, pstr, _("Connect here"),
1803                               connect_here_callback);
1804       pBuf->data.cont = pCont;
1805       set_wstate(pBuf, FC_WS_NORMAL);
1806 
1807       add_to_gui_list(ID_LABEL, pBuf);
1808 
1809       area.w = MAX(area.w, pBuf->size.w);
1810       area.h += pBuf->size.h;
1811     }
1812 #endif /* 0 */
1813 
1814     /* FIXME: This logic seems to try to mirror do_paradrop() why? */
1815     if (can_unit_paradrop(pFocus_Unit) && client_tile_get_known(ptile)
1816         && !(((pCity && pplayers_non_attack(client.conn.playing, city_owner(pCity)))
1817               || is_non_attack_unit_tile(ptile, client.conn.playing)))
1818         && (unit_type_get(pFocus_Unit)->paratroopers_range >=
1819             real_map_distance(unit_tile(pFocus_Unit), ptile))) {
1820 
1821       create_active_iconlabel(pBuf, pWindow->dst, pstr, _("Paradrop here"),
1822                               paradrop_here_callback);
1823       pBuf->data.cont = pCont;
1824       set_wstate(pBuf, FC_WS_NORMAL);
1825 
1826       add_to_gui_list(ID_LABEL, pBuf);
1827 
1828       area.w = MAX(area.w, pBuf->size.w);
1829       area.h += pBuf->size.h;
1830     }
1831 
1832   }
1833   pAdvanced_Terrain_Dlg->pBeginWidgetList = pBuf;
1834 
1835   /* ---------- */
1836   if (n) {
1837     int i;
1838     struct unit *pUnit;
1839     struct unit_type *pUnitType = NULL;
1840 
1841     units_h = 0;
1842     /* separator */
1843     pBuf = create_iconlabel(NULL, pWindow->dst, NULL, WF_FREE_THEME);
1844 
1845     add_to_gui_list(ID_SEPARATOR, pBuf);
1846     area.h += pBuf->next->size.h;
1847     /* ---------- */
1848     if (n > 1) {
1849       struct unit *pDefender, *pAttacker;
1850       struct widget *pLast = pBuf;
1851       bool reset = FALSE;
1852       int my_units = 0;
1853       const char *vetname;
1854 
1855       #define ADV_NUM_SEEN  15
1856 
1857       pDefender = (pFocus_Unit ? get_defender(pFocus_Unit, ptile) : NULL);
1858       pAttacker = (pFocus_Unit ? get_attacker(pFocus_Unit, ptile) : NULL);
1859       for (i = 0; i < n; i++) {
1860         pUnit = unit_list_get(ptile->units, i);
1861         if (pUnit == pFocus_Unit) {
1862           continue;
1863         }
1864         pUnitType = unit_type_get(pUnit);
1865         vetname = utype_veteran_name_translation(pUnitType, pUnit->veteran);
1866 
1867         if (unit_owner(pUnit) == client.conn.playing) {
1868           fc_snprintf(cBuf, sizeof(cBuf),
1869                       _("Activate %s (%d / %d) %s (%d,%d,%s) %s"),
1870                       (vetname != NULL ? vetname : ""),
1871                       pUnit->hp, pUnitType->hp,
1872                       utype_name_translation(pUnitType),
1873                       pUnitType->attack_strength,
1874                       pUnitType->defense_strength,
1875                       move_points_text(pUnitType->move_rate, FALSE),
1876                       unit_activity_text(pUnit));
1877 
1878           create_active_iconlabel(pBuf, pWindow->dst, pstr,
1879                                   cBuf, adv_unit_select_callback);
1880           pBuf->data.unit = pUnit;
1881           set_wstate(pBuf, FC_WS_NORMAL);
1882           add_to_gui_list(ID_LABEL, pBuf);
1883           my_units++;
1884         } else {
1885           int att_chance, def_chance;
1886 
1887           fc_snprintf(cBuf, sizeof(cBuf), _("%s %s %s (A:%d D:%d M:%s FP:%d) HP:%d%%"),
1888                       nation_adjective_for_player(unit_owner(pUnit)),
1889                       (vetname != NULL ? vetname : ""),
1890                       utype_name_translation(pUnitType),
1891                       pUnitType->attack_strength,
1892                       pUnitType->defense_strength,
1893                       move_points_text(pUnitType->move_rate, FALSE),
1894                       pUnitType->firepower,
1895                       ((pUnit->hp * 100) / pUnitType->hp));
1896 
1897           /* calculate chance to win */
1898           if (sdl_get_chance_to_win(&att_chance, &def_chance, pUnit, pFocus_Unit)) {
1899             /* TRANS: "CtW" = "Chance to Win"; preserve leading space */
1900             cat_snprintf(cBuf, sizeof(cBuf), _(" CtW: Att:%d%% Def:%d%%"),
1901                          att_chance, def_chance);
1902           }
1903 
1904           if (pAttacker && pAttacker == pUnit) {
1905             pstr->fgcol = *(get_game_color(COLOR_OVERVIEW_ENEMY_UNIT));
1906             reset = TRUE;
1907           } else {
1908             if (pDefender && pDefender == pUnit) {
1909               pstr->fgcol = *(get_game_color(COLOR_OVERVIEW_MY_UNIT));
1910               reset = TRUE;
1911             }
1912           }
1913 
1914 	  create_active_iconlabel(pBuf, pWindow->dst, pstr, cBuf, NULL);
1915 
1916 	  if (reset) {
1917             pstr->fgcol = *get_theme_color(COLOR_THEME_ADVANCEDTERRAINDLG_TEXT);
1918             reset = FALSE;
1919 	  }
1920 
1921 	  add_to_gui_list(ID_LABEL, pBuf);
1922 	}
1923 
1924         area.w = MAX(area.w, pBuf->size.w);
1925         units_h += pBuf->size.h;
1926 
1927         if (i > ADV_NUM_SEEN - 1) {
1928           set_wflag(pBuf, WF_HIDDEN);
1929         }
1930       }
1931 
1932       pAdvanced_Terrain_Dlg->pEndActiveWidgetList = pLast->prev;
1933       pAdvanced_Terrain_Dlg->pActiveWidgetList = pAdvanced_Terrain_Dlg->pEndActiveWidgetList;
1934       pAdvanced_Terrain_Dlg->pBeginWidgetList = pBuf;
1935       pAdvanced_Terrain_Dlg->pBeginActiveWidgetList = pAdvanced_Terrain_Dlg->pBeginWidgetList;
1936 
1937       if (n > ADV_NUM_SEEN) {
1938         units_h = ADV_NUM_SEEN * pBuf->size.h;
1939         n = create_vertical_scrollbar(pAdvanced_Terrain_Dlg,
1940                                       1, ADV_NUM_SEEN, TRUE, TRUE);
1941         area.w += n;
1942       }
1943 
1944       if (my_units > 1) {
1945         fc_snprintf(cBuf, sizeof(cBuf), "%s (%d)", _("Ready all"), my_units);
1946         create_active_iconlabel(pBuf, pWindow->dst, pstr,
1947                                 cBuf, adv_unit_select_all_callback);
1948         pBuf->data.unit = pAdvanced_Terrain_Dlg->pEndActiveWidgetList->data.unit;
1949         set_wstate(pBuf, FC_WS_NORMAL);
1950         pBuf->ID = ID_LABEL;
1951         DownAdd(pBuf, pLast);
1952         area.h += pBuf->size.h;
1953 
1954         fc_snprintf(cBuf, sizeof(cBuf), "%s (%d)", _("Sentry idle"), my_units);
1955         create_active_iconlabel(pBuf, pWindow->dst, pstr,
1956                                 cBuf, adv_unit_sentry_idle_callback);
1957         pBuf->data.unit = pAdvanced_Terrain_Dlg->pEndActiveWidgetList->data.unit;
1958         set_wstate(pBuf, FC_WS_NORMAL);
1959         pBuf->ID = ID_LABEL;
1960         DownAdd(pBuf, pLast->prev);
1961         area.h += pBuf->size.h;
1962 
1963         /* separator */
1964         pBuf = create_iconlabel(NULL, pWindow->dst, NULL, WF_FREE_THEME);
1965         pBuf->ID = ID_SEPARATOR;
1966         DownAdd(pBuf, pLast->prev->prev);
1967         area.h += pBuf->next->size.h;
1968       }
1969 #undef ADV_NUM_SEEN
1970     } else { /* n == 1 */
1971       /* one unit - give orders */
1972       pUnit = unit_list_get(ptile->units, 0);
1973       pUnitType = unit_type_get(pUnit);
1974       if (pUnit != pFocus_Unit) {
1975         const char *vetname;
1976 
1977         vetname = utype_veteran_name_translation(pUnitType, pUnit->veteran);
1978         if ((pCity && city_owner(pCity) == client.conn.playing)
1979             || (unit_owner(pUnit) == client.conn.playing)) {
1980           fc_snprintf(cBuf, sizeof(cBuf),
1981                       _("Activate %s (%d / %d) %s (%d,%d,%s) %s"),
1982                       (vetname != NULL ? vetname : ""),
1983                       pUnit->hp, pUnitType->hp,
1984                       utype_name_translation(pUnitType),
1985                       pUnitType->attack_strength,
1986                       pUnitType->defense_strength,
1987                       move_points_text(pUnitType->move_rate, FALSE),
1988                       unit_activity_text(pUnit));
1989 
1990           create_active_iconlabel(pBuf, pWindow->dst, pstr,
1991                                   cBuf, adv_unit_select_callback);
1992           pBuf->data.unit = pUnit;
1993           set_wstate(pBuf, FC_WS_NORMAL);
1994 
1995           add_to_gui_list(ID_LABEL, pBuf);
1996 
1997           area.w = MAX(area.w, pBuf->size.w);
1998           units_h += pBuf->size.h;
1999           /* ---------------- */
2000           /* separator */
2001           pBuf = create_iconlabel(NULL, pWindow->dst, NULL, WF_FREE_THEME);
2002 
2003           add_to_gui_list(ID_SEPARATOR, pBuf);
2004           area.h += pBuf->next->size.h;
2005         } else {
2006           int att_chance, def_chance;
2007 
2008           fc_snprintf(cBuf, sizeof(cBuf), _("%s %s %s (A:%d D:%d M:%s FP:%d) HP:%d%%"),
2009                       nation_adjective_for_player(unit_owner(pUnit)),
2010                       (vetname != NULL ? vetname : ""),
2011                       utype_name_translation(pUnitType),
2012                       pUnitType->attack_strength,
2013                       pUnitType->defense_strength,
2014                       move_points_text(pUnitType->move_rate, FALSE),
2015                       pUnitType->firepower,
2016                       ((pUnit->hp * 100) / pUnitType->hp));
2017 
2018           /* calculate chance to win */
2019             if (sdl_get_chance_to_win(&att_chance, &def_chance, pUnit, pFocus_Unit)) {
2020               /* TRANS: preserve leading space */
2021               cat_snprintf(cBuf, sizeof(cBuf), _(" CtW: Att:%d%% Def:%d%%"),
2022                            att_chance, def_chance);
2023             }
2024             create_active_iconlabel(pBuf, pWindow->dst, pstr, cBuf, NULL);
2025             add_to_gui_list(ID_LABEL, pBuf);
2026             area.w = MAX(area.w, pBuf->size.w);
2027             units_h += pBuf->size.h;
2028             /* ---------------- */
2029 
2030             /* separator */
2031             pBuf = create_iconlabel(NULL, pWindow->dst, NULL, WF_FREE_THEME);
2032 
2033             add_to_gui_list(ID_SEPARATOR, pBuf);
2034             area.h += pBuf->next->size.h;
2035         }
2036       }
2037       /* ---------------- */
2038       fc_snprintf(cBuf, sizeof(cBuf),
2039             _("Look up \"%s\" in the Help Browser"),
2040             utype_name_translation(pUnitType));
2041       create_active_iconlabel(pBuf, pWindow->dst, pstr,
2042                               cBuf, unit_help_callback);
2043       set_wstate(pBuf , FC_WS_NORMAL);
2044       add_to_gui_list(MAX_ID - utype_number(pUnitType), pBuf);
2045 
2046       area.w = MAX(area.w, pBuf->size.w);
2047       units_h += pBuf->size.h;
2048       /* ---------------- */
2049       pAdvanced_Terrain_Dlg->pBeginWidgetList = pBuf;
2050     }
2051 
2052   }
2053   /* ---------- */
2054 
2055   area.w += adj_size(2);
2056   area.h += units_h;
2057 
2058   resize_window(pWindow, NULL, NULL,
2059                 (pWindow->size.w - pWindow->area.w) + area.w,
2060                 (pWindow->size.h - pWindow->area.h) + area.h);
2061 
2062   area = pWindow->area;
2063 
2064   widget_set_position(pWindow, pos_x, pos_y);
2065 
2066   w = area.w - adj_size(2);
2067 
2068   if (pAdvanced_Terrain_Dlg->pScroll) {
2069     units_h = n;
2070   } else {
2071     units_h = 0;
2072   }
2073 
2074   /* exit button */
2075   pBuf = pWindow->prev;
2076 
2077   pBuf->size.x = area.x + area.w - pBuf->size.w - 1;
2078   pBuf->size.y = pWindow->size.y + adj_size(2);
2079 
2080   /* terrain info */
2081   pBuf = pBuf->prev;
2082 
2083   pBuf->size.x = area.x + 1;
2084   pBuf->size.y = area.y + 1;
2085   pBuf->size.w = w;
2086   h = pBuf->size.h;
2087 
2088   area2.x = adj_size(10);
2089   area2.h = adj_size(2);
2090 
2091   pBuf = pBuf->prev;
2092   while (pBuf) {
2093     if (pBuf == pAdvanced_Terrain_Dlg->pEndActiveWidgetList) {
2094       w -= units_h;
2095     }
2096 
2097     pBuf->size.w = w;
2098     pBuf->size.x = pBuf->next->size.x;
2099     pBuf->size.y = pBuf->next->size.y + pBuf->next->size.h;
2100 
2101     if (pBuf->ID == ID_SEPARATOR) {
2102       FREESURFACE(pBuf->theme);
2103       pBuf->size.h = h;
2104       pBuf->theme = create_surf(w , h , SDL_SWSURFACE);
2105 
2106       area2.y = pBuf->size.h / 2 - 1;
2107       area2.w = pBuf->size.w - adj_size(20);
2108 
2109       SDL_FillRect(pBuf->theme, &area2, map_rgba(pBuf->theme->format,
2110                                       *get_theme_color(COLOR_THEME_ADVANCEDTERRAINDLG_TEXT)));
2111     }
2112 
2113     if (pBuf == pAdvanced_Terrain_Dlg->pBeginWidgetList
2114         || pBuf == pAdvanced_Terrain_Dlg->pBeginActiveWidgetList) {
2115       break;
2116     }
2117     pBuf = pBuf->prev;
2118   }
2119 
2120   if (pAdvanced_Terrain_Dlg->pScroll) {
2121     setup_vertical_scrollbar_area(pAdvanced_Terrain_Dlg->pScroll,
2122 	area.x + area.w,
2123     	pAdvanced_Terrain_Dlg->pEndActiveWidgetList->size.y,
2124     	area.y - pAdvanced_Terrain_Dlg->pEndActiveWidgetList->size.y + area.h,
2125         TRUE);
2126   }
2127 
2128   /* -------------------- */
2129   /* redraw */
2130   redraw_group(pAdvanced_Terrain_Dlg->pBeginWidgetList, pWindow, 0);
2131 
2132   widget_flush(pWindow);
2133 }
2134 
2135 /* ====================================================================== */
2136 /* ============================ PILLAGE DIALOG ========================== */
2137 /* ====================================================================== */
2138 static struct SMALL_DLG *pPillage_Dlg = NULL;
2139 
2140 /**************************************************************************
2141   User interacted with pillage dialog.
2142 **************************************************************************/
pillage_window_callback(struct widget * pWindow)2143 static int pillage_window_callback(struct widget *pWindow)
2144 {
2145   if (PRESSED_EVENT(Main.event)) {
2146     move_window_group(pPillage_Dlg->pBeginWidgetList, pWindow);
2147   }
2148   return -1;
2149 }
2150 
2151 /**************************************************************************
2152   User selected what to pillage.
2153 **************************************************************************/
pillage_callback(struct widget * pWidget)2154 static int pillage_callback(struct widget *pWidget)
2155 {
2156   if (PRESSED_EVENT(Main.event)) {
2157     struct unit *pUnit = pWidget->data.unit;
2158     int what = MAX_ID - pWidget->ID;
2159 
2160     popdown_pillage_dialog();
2161 
2162     if (pUnit) {
2163       struct extra_type *target = extra_by_number(what);
2164 
2165       request_new_unit_activity_targeted(pUnit, ACTIVITY_PILLAGE, target);
2166     }
2167   }
2168   return -1;
2169 }
2170 
2171 /**************************************************************************
2172   User requested closing of pillage dialog.
2173 **************************************************************************/
exit_pillage_dlg_callback(struct widget * pWidget)2174 static int exit_pillage_dlg_callback(struct widget *pWidget)
2175 {
2176   if (PRESSED_EVENT(Main.event)) {
2177     popdown_pillage_dialog();
2178   }
2179   return -1;
2180 }
2181 
2182 /**************************************************************************
2183   Popdown a dialog asking the unit which improvement they would like to
2184   pillage.
2185 **************************************************************************/
popdown_pillage_dialog(void)2186 static void popdown_pillage_dialog(void)
2187 {
2188   if (pPillage_Dlg) {
2189     is_unit_move_blocked = FALSE;
2190     popdown_window_group_dialog(pPillage_Dlg->pBeginWidgetList,
2191                                 pPillage_Dlg->pEndWidgetList);
2192     FC_FREE(pPillage_Dlg);
2193     flush_dirty();
2194   }
2195 }
2196 
2197 /**************************************************************************
2198   Popup a dialog asking the unit which improvement they would like to
2199   pillage.
2200 **************************************************************************/
popup_pillage_dialog(struct unit * pUnit,bv_extras extras)2201 void popup_pillage_dialog(struct unit *pUnit, bv_extras extras)
2202 {
2203   struct widget *pWindow = NULL, *pBuf = NULL;
2204   utf8_str *pstr;
2205   SDL_Rect area;
2206   struct extra_type *tgt;
2207 
2208   if (pPillage_Dlg) {
2209     return;
2210   }
2211 
2212   is_unit_move_blocked = TRUE;
2213   pPillage_Dlg = fc_calloc(1, sizeof(struct SMALL_DLG));
2214 
2215   /* window */
2216   pstr = create_utf8_from_char(_("What To Pillage") , adj_font(12));
2217   pstr->style |= TTF_STYLE_BOLD;
2218 
2219   pWindow = create_window_skeleton(NULL, pstr, 0);
2220 
2221   pWindow->action = pillage_window_callback;
2222   set_wstate(pWindow, FC_WS_NORMAL);
2223 
2224   add_to_gui_list(ID_PILLAGE_DLG_WINDOW, pWindow);
2225   pPillage_Dlg->pEndWidgetList = pWindow;
2226 
2227   area = pWindow->area;
2228 
2229   area.h = MAX(area.h, adj_size(2));
2230 
2231   /* ---------- */
2232   /* exit button */
2233   pBuf = create_themeicon(current_theme->Small_CANCEL_Icon, pWindow->dst,
2234                           WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
2235   pBuf->info_label = create_utf8_from_char(_("Close Dialog (Esc)"),
2236                                            adj_font(12));
2237   area.w += pBuf->size.w + adj_size(10);
2238   pBuf->action = exit_pillage_dlg_callback;
2239   set_wstate(pBuf, FC_WS_NORMAL);
2240   pBuf->key = SDLK_ESCAPE;
2241 
2242   add_to_gui_list(ID_PILLAGE_DLG_EXIT_BUTTON, pBuf);
2243   /* ---------- */
2244 
2245   while ((tgt = get_preferred_pillage(extras))) {
2246     const char *name = NULL;
2247     int what;
2248 
2249     BV_CLR(extras, extra_index(tgt));
2250     name = extra_name_translation(tgt);
2251     what = extra_index(tgt);
2252 
2253     fc_assert(name != NULL);
2254 
2255     create_active_iconlabel(pBuf, pWindow->dst, pstr,
2256                             (char *) name, pillage_callback);
2257 
2258     pBuf->data.unit = pUnit;
2259     set_wstate(pBuf, FC_WS_NORMAL);
2260 
2261     add_to_gui_list(MAX_ID - what, pBuf);
2262 
2263     area.w = MAX(area.w, pBuf->size.w);
2264     area.h += pBuf->size.h;
2265   }
2266   pPillage_Dlg->pBeginWidgetList = pBuf;
2267 
2268   /* setup window size and start position */
2269 
2270   resize_window(pWindow, NULL, NULL,
2271                 (pWindow->size.w - pWindow->area.w) + area.w,
2272                 (pWindow->size.h - pWindow->area.h) + area.h);
2273 
2274   area = pWindow->area;
2275 
2276   put_window_near_map_tile(pWindow, pWindow->size.w, pWindow->size.h,
2277                            unit_tile(pUnit));
2278 
2279   /* setup widget size and start position */
2280 
2281   /* exit button */
2282   pBuf = pWindow->prev;
2283   pBuf->size.x = area.x + area.w - pBuf->size.w - 1;
2284   pBuf->size.y = pWindow->size.y + adj_size(2);
2285 
2286   /* first special to pillage */
2287   pBuf = pBuf->prev;
2288   setup_vertical_widgets_position(1,
2289 	area.x,	area.y + 1, area.w, 0,
2290 	pPillage_Dlg->pBeginWidgetList, pBuf);
2291 
2292   /* --------------------- */
2293   /* redraw */
2294   redraw_group(pPillage_Dlg->pBeginWidgetList, pWindow, 0);
2295 
2296   widget_flush(pWindow);
2297 }
2298 
2299 /* ======================================================================= */
2300 /* =========================== CONNECT DIALOG ============================ */
2301 /* ======================================================================= */
2302 static struct SMALL_DLG *pConnect_Dlg = NULL;
2303 
2304 /**************************************************************************
2305   Popdown a dialog asking the unit how they want to "connect" their
2306   location to the destination.
2307 **************************************************************************/
popdown_connect_dialog(void)2308 static void popdown_connect_dialog(void)
2309 {
2310   if (pConnect_Dlg) {
2311     is_unit_move_blocked = FALSE;
2312     popdown_window_group_dialog(pConnect_Dlg->pBeginWidgetList,
2313                                 pConnect_Dlg->pEndWidgetList);
2314     FC_FREE(pConnect_Dlg);
2315   }
2316 }
2317 
2318 /* ==================== Public ========================= */
2319 
2320 /**************************************************************************
2321                            Select Goverment Type
2322 **************************************************************************/
2323 static struct SMALL_DLG *pGov_Dlg = NULL;
2324 
2325 /**************************************************************************
2326   Close the government dialog.
2327 **************************************************************************/
popdown_government_dialog(void)2328 static void popdown_government_dialog(void)
2329 {
2330   if (pGov_Dlg) {
2331     popdown_window_group_dialog(pGov_Dlg->pBeginWidgetList,
2332                                 pGov_Dlg->pEndWidgetList);
2333     FC_FREE(pGov_Dlg);
2334     enable_and_redraw_revolution_button();
2335   }
2336 }
2337 
2338 /**************************************************************************
2339   User selected government button.
2340 **************************************************************************/
government_dlg_callback(struct widget * pGov_Button)2341 static int government_dlg_callback(struct widget *pGov_Button)
2342 {
2343   if (PRESSED_EVENT(Main.event)) {
2344     set_government_choice(government_by_number(MAX_ID - pGov_Button->ID));
2345 
2346     popdown_government_dialog();
2347   }
2348   return (-1);
2349 }
2350 
2351 /**************************************************************************
2352   User requested move of government dialog.
2353 **************************************************************************/
move_government_dlg_callback(struct widget * pWindow)2354 static int move_government_dlg_callback(struct widget *pWindow)
2355 {
2356   if (PRESSED_EVENT(Main.event)) {
2357     move_window_group(pGov_Dlg->pBeginWidgetList, pWindow);
2358   }
2359   return -1;
2360 }
2361 
2362 /**************************************************************************
2363   Public -
2364 
2365   Popup a dialog asking the player what government to switch to (this
2366   happens after a revolution completes).
2367 **************************************************************************/
popup_government_dialog(void)2368 void popup_government_dialog(void)
2369 {
2370   SDL_Surface *pLogo = NULL;
2371   struct utf8_str *pstr = NULL;
2372   struct widget *pGov_Button = NULL;
2373   struct widget *pWindow = NULL;
2374   int j;
2375   Uint16 max_w = 0, max_h = 0;
2376   SDL_Rect area;
2377 
2378   if (pGov_Dlg) {
2379     return;
2380   }
2381 
2382   pGov_Dlg = fc_calloc(1, sizeof(struct SMALL_DLG));
2383 
2384   /* create window */
2385   pstr = create_utf8_from_char(_("Choose Your New Government"), adj_font(12));
2386   pstr->style |= TTF_STYLE_BOLD;
2387   /* this win. size is temp. */
2388   pWindow = create_window_skeleton(NULL, pstr, 0);
2389   pWindow->action = move_government_dlg_callback;
2390   add_to_gui_list(ID_GOVERNMENT_DLG_WINDOW, pWindow);
2391 
2392   pGov_Dlg->pEndWidgetList = pWindow;
2393 
2394   area = pWindow->area;
2395 
2396   /* create gov. buttons */
2397   j = 0;
2398   governments_iterate(pGov) {
2399     if (pGov == game.government_during_revolution) {
2400       continue;
2401     }
2402 
2403     if (can_change_to_government(client.conn.playing, pGov)) {
2404       pstr = create_utf8_from_char(government_name_translation(pGov), adj_font(12));
2405       pGov_Button =
2406           create_icon_button(get_government_surface(pGov), pWindow->dst, pstr, 0);
2407       pGov_Button->action = government_dlg_callback;
2408 
2409       max_w = MAX(max_w, pGov_Button->size.w);
2410       max_h = MAX(max_h, pGov_Button->size.h);
2411 
2412       /* ugly hack */
2413       add_to_gui_list((MAX_ID - government_number(pGov)), pGov_Button);
2414       j++;
2415 
2416     }
2417   } governments_iterate_end;
2418 
2419   pGov_Dlg->pBeginWidgetList = pGov_Button;
2420 
2421   max_w += adj_size(10);
2422   max_h += adj_size(4);
2423 
2424   area.w = MAX(area.w, max_w + adj_size(20));
2425   area.h = MAX(area.h, j * (max_h + adj_size(10)) + adj_size(5));
2426 
2427   /* create window background */
2428   pLogo = theme_get_background(theme, BACKGROUND_CHOOSEGOVERNMENTDLG);
2429   if (resize_window(pWindow, pLogo, NULL,
2430                     (pWindow->size.w - pWindow->area.w) + area.w,
2431                     (pWindow->size.h - pWindow->area.h) + area.h)) {
2432     FREESURFACE(pLogo);
2433   }
2434 
2435   area = pWindow->area;
2436 
2437   /* set window start positions */
2438   widget_set_position(pWindow,
2439                       (main_window_width() - pWindow->size.w) / 2,
2440                       (main_window_height() - pWindow->size.h) / 2);
2441 
2442   /* set buttons start positions and size */
2443   j = 1;
2444   while (pGov_Button != pGov_Dlg->pEndWidgetList) {
2445     pGov_Button->size.w = max_w;
2446     pGov_Button->size.h = max_h;
2447     pGov_Button->size.x = area.x + adj_size(10);
2448     pGov_Button->size.y = area.y + area.h - (j++) * (max_h + adj_size(10));
2449     set_wstate(pGov_Button, FC_WS_NORMAL);
2450 
2451     pGov_Button = pGov_Button->next;
2452   }
2453 
2454   set_wstate(pWindow, FC_WS_NORMAL);
2455 
2456   /* redraw */
2457   redraw_group(pGov_Dlg->pBeginWidgetList, pWindow, 0);
2458 
2459   widget_flush(pWindow);
2460 }
2461 
2462 /**************************************************************************
2463                                 Nation Wizard
2464 **************************************************************************/
2465 static struct ADVANCED_DLG *pNationDlg = NULL;
2466 static struct SMALL_DLG *pHelpDlg = NULL;
2467 
2468 struct NAT {
2469   unsigned char nation_style;      /* selected style */
2470   unsigned char selected_leader;   /* if not unique -> selected leader */
2471   Nation_type_id nation;           /* selected nation */
2472   bool leader_sex;                 /* selected leader sex */
2473   struct nation_set *set;
2474   struct widget *pChange_Sex;
2475   struct widget *pName_Edit;
2476   struct widget *pName_Next;
2477   struct widget *pName_Prev;
2478   struct widget *pset_name;
2479   struct widget *pset_next;
2480   struct widget *pset_prev;
2481 };
2482 
2483 static int next_set_callback(struct widget *next_button);
2484 static int prev_set_callback(struct widget *prev_button);
2485 static int nations_dialog_callback(struct widget *pWindow);
2486 static int nation_button_callback(struct widget *pNation);
2487 static int races_dialog_ok_callback(struct widget *pStart_Button);
2488 static int races_dialog_cancel_callback(struct widget *pButton);
2489 static int next_name_callback(struct widget *pNext_Button);
2490 static int prev_name_callback(struct widget *pPrev_Button);
2491 static int change_sex_callback(struct widget *pSex);
2492 static void select_random_leader(Nation_type_id nation);
2493 static void change_nation_label(void);
2494 
2495 /**************************************************************************
2496   User interacted with nations dialog.
2497 **************************************************************************/
nations_dialog_callback(struct widget * pWindow)2498 static int nations_dialog_callback(struct widget *pWindow)
2499 {
2500   if (PRESSED_EVENT(Main.event)) {
2501     if (select_window_group_dialog(pNationDlg->pBeginWidgetList, pWindow)) {
2502       widget_flush(pWindow);
2503     }
2504   }
2505   return -1;
2506 }
2507 
2508 /**************************************************************************
2509   User accepted nation.
2510 **************************************************************************/
races_dialog_ok_callback(struct widget * pStart_Button)2511 static int races_dialog_ok_callback(struct widget *pStart_Button)
2512 {
2513   if (PRESSED_EVENT(Main.event)) {
2514     struct NAT *pSetup = (struct NAT *)(pNationDlg->pEndWidgetList->data.ptr);
2515     char *pstr = pSetup->pName_Edit->string_utf8->text;
2516 
2517     /* perform a minimum of sanity test on the name */
2518     if (strlen(pstr) == 0) {
2519       output_window_append(ftc_client, _("You must type a legal name."));
2520       selected_widget = pStart_Button;
2521       set_wstate(pStart_Button, FC_WS_SELECTED);
2522       widget_redraw(pStart_Button);
2523       widget_flush(pStart_Button);
2524 
2525       return (-1);
2526     }
2527 
2528     dsend_packet_nation_select_req(&client.conn, player_number(races_player),
2529                                    pSetup->nation,
2530                                    pSetup->leader_sex, pstr,
2531                                    pSetup->nation_style);
2532 
2533     popdown_races_dialog();
2534     flush_dirty();
2535   }
2536 
2537   return -1;
2538 }
2539 
2540 /**************************************************************************
2541   User requested leader gender change.
2542 **************************************************************************/
change_sex_callback(struct widget * pSex)2543 static int change_sex_callback(struct widget *pSex)
2544 {
2545   if (PRESSED_EVENT(Main.event)) {
2546     struct NAT *pSetup = (struct NAT *)(pNationDlg->pEndWidgetList->data.ptr);
2547 
2548     if (pSetup->leader_sex) {
2549       copy_chars_to_utf8_str(pSetup->pChange_Sex->string_utf8, _("Female"));
2550     } else {
2551       copy_chars_to_utf8_str(pSetup->pChange_Sex->string_utf8, _("Male"));
2552     }
2553     pSetup->leader_sex = !pSetup->leader_sex;
2554 
2555     if (pSex) {
2556       selected_widget = pSex;
2557       set_wstate(pSex, FC_WS_SELECTED);
2558 
2559       widget_redraw(pSex);
2560       widget_flush(pSex);
2561     }
2562   }
2563   return -1;
2564 }
2565 
2566 /**************************************************************************
2567   User requested next leader name.
2568 **************************************************************************/
next_name_callback(struct widget * pNext)2569 static int next_name_callback(struct widget *pNext)
2570 {
2571   if (PRESSED_EVENT(Main.event)) {
2572     struct NAT *pSetup = (struct NAT *)(pNationDlg->pEndWidgetList->data.ptr);
2573     const struct nation_leader_list *leaders =
2574         nation_leaders(nation_by_number(pSetup->nation));
2575     const struct nation_leader *pleader;
2576 
2577     pSetup->selected_leader++;
2578     pleader = nation_leader_list_get(leaders, pSetup->selected_leader);
2579 
2580     /* change leader sex */
2581     if (pSetup->leader_sex != nation_leader_is_male(pleader)) {
2582       change_sex_callback(NULL);
2583     }
2584 
2585     /* change leader name */
2586     copy_chars_to_utf8_str(pSetup->pName_Edit->string_utf8,
2587                            nation_leader_name(pleader));
2588 
2589     FC_FREE(pLeaderName);
2590     pLeaderName = fc_strdup(nation_leader_name(pleader));
2591 
2592     if (nation_leader_list_size(leaders) - 1 == pSetup->selected_leader) {
2593       set_wstate(pSetup->pName_Next, FC_WS_DISABLED);
2594     }
2595 
2596     if (get_wstate(pSetup->pName_Prev) == FC_WS_DISABLED) {
2597       set_wstate(pSetup->pName_Prev, FC_WS_NORMAL);
2598     }
2599 
2600     if (!(get_wstate(pSetup->pName_Next) == FC_WS_DISABLED)) {
2601       selected_widget = pSetup->pName_Next;
2602       set_wstate(pSetup->pName_Next, FC_WS_SELECTED);
2603     }
2604 
2605     widget_redraw(pSetup->pName_Edit);
2606     widget_redraw(pSetup->pName_Prev);
2607     widget_redraw(pSetup->pName_Next);
2608     widget_mark_dirty(pSetup->pName_Edit);
2609     widget_mark_dirty(pSetup->pName_Prev);
2610     widget_mark_dirty(pSetup->pName_Next);
2611 
2612     widget_redraw(pSetup->pChange_Sex);
2613     widget_mark_dirty(pSetup->pChange_Sex);
2614 
2615     flush_dirty();
2616   }
2617   return -1;
2618 }
2619 
2620 /**************************************************************************
2621   User requested previous leader name.
2622 **************************************************************************/
prev_name_callback(struct widget * pPrev)2623 static int prev_name_callback(struct widget *pPrev)
2624 {
2625   if (PRESSED_EVENT(Main.event)) {
2626     struct NAT *pSetup = (struct NAT *)(pNationDlg->pEndWidgetList->data.ptr);
2627     const struct nation_leader_list *leaders =
2628         nation_leaders(nation_by_number(pSetup->nation));
2629     const struct nation_leader *pleader;
2630 
2631     pSetup->selected_leader--;
2632     pleader = nation_leader_list_get(leaders, pSetup->selected_leader);
2633 
2634     /* change leader sex */
2635     if (pSetup->leader_sex != nation_leader_is_male(pleader)) {
2636       change_sex_callback(NULL);
2637     }
2638 
2639     /* change leader name */
2640     copy_chars_to_utf8_str(pSetup->pName_Edit->string_utf8,
2641                            nation_leader_name(pleader));
2642 
2643     FC_FREE(pLeaderName);
2644     pLeaderName = fc_strdup(nation_leader_name(pleader));
2645 
2646     if (!pSetup->selected_leader) {
2647       set_wstate(pSetup->pName_Prev, FC_WS_DISABLED);
2648     }
2649 
2650     if (get_wstate(pSetup->pName_Next) == FC_WS_DISABLED) {
2651       set_wstate(pSetup->pName_Next, FC_WS_NORMAL);
2652     }
2653 
2654     if (!(get_wstate(pSetup->pName_Prev) == FC_WS_DISABLED)) {
2655       selected_widget = pSetup->pName_Prev;
2656       set_wstate(pSetup->pName_Prev, FC_WS_SELECTED);
2657     }
2658 
2659     widget_redraw(pSetup->pName_Edit);
2660     widget_redraw(pSetup->pName_Prev);
2661     widget_redraw(pSetup->pName_Next);
2662     widget_mark_dirty(pSetup->pName_Edit);
2663     widget_mark_dirty(pSetup->pName_Prev);
2664     widget_mark_dirty(pSetup->pName_Next);
2665 
2666     widget_redraw(pSetup->pChange_Sex);
2667     widget_mark_dirty(pSetup->pChange_Sex);
2668 
2669     flush_dirty();
2670   }
2671   return -1;
2672 }
2673 
2674 /**************************************************************************
2675   User requested next nationset
2676 **************************************************************************/
next_set_callback(struct widget * next_button)2677 static int next_set_callback(struct widget *next_button)
2678 {
2679   if (PRESSED_EVENT(Main.event)) {
2680     struct NAT *pSetup = (struct NAT *)(pNationDlg->pEndWidgetList->data.ptr);
2681     struct option *poption = optset_option_by_name(server_optset, "nationset");
2682 
2683     fc_assert(pSetup->set != NULL
2684               && nation_set_index(pSetup->set) < nation_set_count() - 1);
2685 
2686     pSetup->set = nation_set_by_number(nation_set_index(pSetup->set) + 1);
2687 
2688     option_str_set(poption, nation_set_rule_name(pSetup->set));
2689   }
2690 
2691   return -1;
2692 }
2693 
2694 /**************************************************************************
2695   User requested prev nationset
2696 **************************************************************************/
prev_set_callback(struct widget * prev_button)2697 static int prev_set_callback(struct widget *prev_button)
2698 {
2699   if (PRESSED_EVENT(Main.event)) {
2700     struct NAT *pSetup = (struct NAT *)(pNationDlg->pEndWidgetList->data.ptr);
2701     struct option *poption = optset_option_by_name(server_optset, "nationset");
2702 
2703     fc_assert(pSetup->set != NULL && nation_set_index(pSetup->set) > 0);
2704 
2705     pSetup->set = nation_set_by_number(nation_set_index(pSetup->set) - 1);
2706 
2707     option_str_set(poption, nation_set_rule_name(pSetup->set));
2708   }
2709 
2710   return -1;
2711 }
2712 
2713 /**************************************************************************
2714   User cancelled nations dialog.
2715 **************************************************************************/
races_dialog_cancel_callback(struct widget * pButton)2716 static int races_dialog_cancel_callback(struct widget *pButton)
2717 {
2718   if (PRESSED_EVENT(Main.event)) {
2719     popdown_races_dialog();
2720     flush_dirty();
2721   }
2722   return -1;
2723 }
2724 
2725 /**************************************************************************
2726   User interacted with style widget.
2727 **************************************************************************/
style_callback(struct widget * pWidget)2728 static int style_callback(struct widget *pWidget)
2729 {
2730   if (PRESSED_EVENT(Main.event)) {
2731     struct NAT *pSetup = (struct NAT *)(pNationDlg->pEndWidgetList->data.ptr);
2732     struct widget *pGUI = get_widget_pointer_from_main_list(MAX_ID - 1000 -
2733                                                             pSetup->nation_style);
2734 
2735     set_wstate(pGUI, FC_WS_NORMAL);
2736     widget_redraw(pGUI);
2737     widget_mark_dirty(pGUI);
2738 
2739     set_wstate(pWidget, FC_WS_DISABLED);
2740     widget_redraw(pWidget);
2741     widget_mark_dirty(pWidget);
2742 
2743     pSetup->nation_style = MAX_ID - 1000 - pWidget->ID;
2744 
2745     flush_dirty();
2746     selected_widget = NULL;
2747   }
2748   return -1;
2749 }
2750 
2751 /**************************************************************************
2752   User interacted with help dialog.
2753 **************************************************************************/
help_dlg_callback(struct widget * pWindow)2754 static int help_dlg_callback(struct widget *pWindow)
2755 {
2756   return -1;
2757 }
2758 
2759 /**************************************************************************
2760   User requested closing of help dialog.
2761 **************************************************************************/
cancel_help_dlg_callback(struct widget * pWidget)2762 static int cancel_help_dlg_callback(struct widget *pWidget)
2763 {
2764   if (PRESSED_EVENT(Main.event)) {
2765     if (pHelpDlg) {
2766       popdown_window_group_dialog(pHelpDlg->pBeginWidgetList,
2767                                   pHelpDlg->pEndWidgetList);
2768       FC_FREE(pHelpDlg);
2769       if (pWidget) {
2770         flush_dirty();
2771       }
2772     }
2773   }
2774   return -1;
2775 }
2776 
2777 /**************************************************************************
2778   User selected nation.
2779 **************************************************************************/
nation_button_callback(struct widget * pNationButton)2780 static int nation_button_callback(struct widget *pNationButton)
2781 {
2782   set_wstate(pNationButton, FC_WS_SELECTED);
2783   selected_widget = pNationButton;
2784 
2785   if (PRESSED_EVENT(Main.event)) {
2786     struct NAT *pSetup = (struct NAT *)(pNationDlg->pEndWidgetList->data.ptr);
2787 
2788     if (pSetup->nation == MAX_ID - pNationButton->ID) {
2789       widget_redraw(pNationButton);
2790       widget_flush(pNationButton);
2791       return -1;
2792     }
2793 
2794     pSetup->nation = MAX_ID - pNationButton->ID;
2795 
2796     change_nation_label();
2797 
2798     enable(MAX_ID - 1000 - pSetup->nation_style);
2799     pSetup->nation_style = style_number(style_of_nation(nation_by_number(pSetup->nation)));
2800     disable(MAX_ID - 1000 - pSetup->nation_style);
2801 
2802     select_random_leader(pSetup->nation);
2803 
2804     redraw_group(pNationDlg->pBeginWidgetList, pNationDlg->pEndWidgetList, 0);
2805     widget_flush(pNationDlg->pEndWidgetList);
2806   } else {
2807     /* pop up nation description */
2808     struct widget *pWindow, *pOK_Button;
2809     utf8_str *pstr;
2810     SDL_Surface *pText;
2811     SDL_Rect area, area2;
2812     struct nation_type *pNation = nation_by_number(MAX_ID - pNationButton->ID);
2813 
2814     widget_redraw(pNationButton);
2815     widget_mark_dirty(pNationButton);
2816 
2817     if (!pHelpDlg) {
2818       pHelpDlg = fc_calloc(1, sizeof(struct SMALL_DLG));
2819 
2820       pstr = create_utf8_from_char(nation_plural_translation(pNation),
2821                                    adj_font(12));
2822       pstr->style |= TTF_STYLE_BOLD;
2823 
2824       pWindow = create_window_skeleton(NULL, pstr, 0);
2825       pWindow->action = help_dlg_callback;
2826 
2827       set_wstate(pWindow, FC_WS_NORMAL);
2828 
2829       pHelpDlg->pEndWidgetList = pWindow;
2830       add_to_gui_list(ID_WINDOW, pWindow);
2831 
2832       pOK_Button = create_themeicon_button_from_chars(current_theme->OK_Icon,
2833                                pWindow->dst, _("OK"), adj_font(14), 0);
2834       pOK_Button->action = cancel_help_dlg_callback;
2835       set_wstate(pOK_Button, FC_WS_NORMAL);
2836       pOK_Button->key = SDLK_ESCAPE;
2837       add_to_gui_list(ID_BUTTON, pOK_Button);
2838       pHelpDlg->pBeginWidgetList = pOK_Button;
2839     } else {
2840       pWindow = pHelpDlg->pEndWidgetList;
2841       pOK_Button = pHelpDlg->pBeginWidgetList;
2842       /* undraw window */
2843       widget_undraw(pWindow);
2844       widget_mark_dirty(pWindow);
2845     }
2846 
2847     area = pWindow->area;
2848 
2849     {
2850       char info[4096];
2851 
2852       helptext_nation(info, sizeof(info), pNation, NULL);
2853       pstr = create_utf8_from_char(info, adj_font(12));
2854     }
2855 
2856     pstr->fgcol = *get_theme_color(COLOR_THEME_NATIONDLG_LEGEND);
2857     pText = create_text_surf_smaller_than_w(pstr, main_window_width() - adj_size(20));
2858 
2859     FREEUTF8STR(pstr);
2860 
2861     /* create window background */
2862     area.w = MAX(area.w, pText->w + adj_size(20));
2863     area.w = MAX(area.w, pOK_Button->size.w + adj_size(20));
2864     area.h = MAX(area.h, adj_size(9) + pText->h
2865                          + adj_size(10) + pOK_Button->size.h + adj_size(10));
2866 
2867     resize_window(pWindow, NULL, get_theme_color(COLOR_THEME_BACKGROUND),
2868                   (pWindow->size.w - pWindow->area.w) + area.w,
2869                   (pWindow->size.h - pWindow->area.h) + area.h);
2870 
2871     widget_set_position(pWindow,
2872                         (main_window_width() - pWindow->size.w) / 2,
2873                         (main_window_height() - pWindow->size.h) / 2);
2874 
2875     area2.x = area.x + adj_size(7);
2876     area2.y = area.y + adj_size(6);
2877     alphablit(pText, NULL, pWindow->theme, &area2, 255);
2878     FREESURFACE(pText);
2879 
2880     pOK_Button->size.x = area.x + (area.w - pOK_Button->size.w) / 2;
2881     pOK_Button->size.y = area.y + area.h - pOK_Button->size.h - adj_size(10);
2882 
2883     /* redraw */
2884     redraw_group(pOK_Button, pWindow, 0);
2885 
2886     widget_mark_dirty(pWindow);
2887 
2888     flush_dirty();
2889 
2890   }
2891   return -1;
2892 }
2893 
2894 /**************************************************************************
2895   User interacted with leader name edit widget.
2896 **************************************************************************/
leader_name_edit_callback(struct widget * pEdit)2897 static int leader_name_edit_callback(struct widget *pEdit)
2898 {
2899   if (PRESSED_EVENT(Main.event)) {
2900     if (pEdit->string_utf8->text != NULL) {
2901       /* empty input -> restore previous content */
2902       copy_chars_to_utf8_str(pEdit->string_utf8, pLeaderName);
2903       widget_redraw(pEdit);
2904       widget_mark_dirty(pEdit);
2905       flush_dirty();
2906     }
2907   }
2908 
2909   return -1;
2910 }
2911 /* =========================================================== */
2912 
2913 /**************************************************************************
2914   Update nation label.
2915 **************************************************************************/
change_nation_label(void)2916 static void change_nation_label(void)
2917 {
2918   SDL_Surface *pTmp_Surf, *pTmp_Surf_zoomed;
2919   struct widget *pWindow = pNationDlg->pEndWidgetList;
2920   struct NAT *pSetup = (struct NAT *)(pWindow->data.ptr);
2921   struct widget *pLabel = pSetup->pName_Edit->next;
2922   struct nation_type *pNation = nation_by_number(pSetup->nation);
2923 
2924   pTmp_Surf = get_nation_flag_surface(pNation);
2925   pTmp_Surf_zoomed = zoomSurface(pTmp_Surf, DEFAULT_ZOOM * 1.0, DEFAULT_ZOOM * 1.0, 1);
2926 
2927   FREESURFACE(pLabel->theme);
2928   pLabel->theme = pTmp_Surf_zoomed;
2929 
2930   copy_chars_to_utf8_str(pLabel->string_utf8, nation_plural_translation(pNation));
2931 
2932   remake_label_size(pLabel);
2933 
2934   pLabel->size.x = pWindow->size.x + pWindow->size.w / 2 +
2935   				(pWindow->size.w/2 - pLabel->size.w) / 2;
2936 
2937 }
2938 
2939 /**************************************************************************
2940   Selects a leader and the appropriate sex. Updates the gui elements
2941   and the selected_* variables.
2942 **************************************************************************/
select_random_leader(Nation_type_id nation)2943 static void select_random_leader(Nation_type_id nation)
2944 {
2945   struct NAT *pSetup = (struct NAT *)(pNationDlg->pEndWidgetList->data.ptr);
2946   const struct nation_leader_list *leaders =
2947       nation_leaders(nation_by_number(pSetup->nation));
2948   const struct nation_leader *pleader;
2949 
2950   pSetup->selected_leader = fc_rand(nation_leader_list_size(leaders));
2951   pleader = nation_leader_list_get(leaders, pSetup->selected_leader);
2952   copy_chars_to_utf8_str(pSetup->pName_Edit->string_utf8,
2953                          nation_leader_name(pleader));
2954 
2955   FC_FREE(pLeaderName);
2956   pLeaderName = fc_strdup(nation_leader_name(pleader));
2957 
2958   /* initialize leader sex */
2959   pSetup->leader_sex = nation_leader_is_male(pleader);
2960 
2961   if (pSetup->leader_sex) {
2962     copy_chars_to_utf8_str(pSetup->pChange_Sex->string_utf8, _("Male"));
2963   } else {
2964     copy_chars_to_utf8_str(pSetup->pChange_Sex->string_utf8, _("Female"));
2965   }
2966 
2967   /* disable navigation buttons */
2968   set_wstate(pSetup->pName_Prev, FC_WS_DISABLED);
2969   set_wstate(pSetup->pName_Next, FC_WS_DISABLED);
2970 
2971   if (1 < nation_leader_list_size(leaders)) {
2972     /* if selected leader is not the first leader, enable "previous leader" button */
2973     if (pSetup->selected_leader > 0) {
2974       set_wstate(pSetup->pName_Prev, FC_WS_NORMAL);
2975     }
2976 
2977     /* if selected leader is not the last leader, enable "next leader" button */
2978     if (pSetup->selected_leader < (nation_leader_list_size(leaders) - 1)) {
2979       set_wstate(pSetup->pName_Next, FC_WS_NORMAL);
2980     }
2981   }
2982 }
2983 
2984 /**************************************************************************
2985    Count available playable nations.
2986 **************************************************************************/
get_playable_nation_count(void)2987 static int get_playable_nation_count(void)
2988 {
2989   int playable_nation_count = 0;
2990 
2991   nations_iterate(pnation) {
2992     if (pnation->is_playable && !pnation->player
2993         && is_nation_pickable(pnation))
2994       playable_nation_count++;
2995   } nations_iterate_end;
2996 
2997   return playable_nation_count;
2998 }
2999 
3000 /**************************************************************************
3001   Popup the nation selection dialog.
3002 **************************************************************************/
popup_races_dialog(struct player * pplayer)3003 void popup_races_dialog(struct player *pplayer)
3004 {
3005   SDL_Color bg_color = {255,255,255,128};
3006 
3007   struct widget *pWindow, *pWidget = NULL, *pBuf, *pLast_City_Style;
3008   utf8_str *pstr;
3009   int len = 0;
3010   int w = adj_size(10), h = adj_size(10);
3011   SDL_Surface *pTmp_Surf, *pTmp_Surf_zoomed = NULL;
3012   SDL_Surface *pMain_Bg, *pText_Name;
3013   SDL_Rect dst;
3014   float zoom;
3015   struct NAT *pSetup;
3016   SDL_Rect area;
3017   int i;
3018   struct nation_type *pnat;
3019   struct widget *nationsets = NULL;
3020   int natinfo_y, natinfo_h;
3021 
3022 #define TARGETS_ROW 5
3023 #define TARGETS_COL 1
3024 
3025   if (pNationDlg) {
3026     return;
3027   }
3028 
3029   races_player = pplayer;
3030 
3031   pNationDlg = fc_calloc(1, sizeof(struct ADVANCED_DLG));
3032 
3033   /* create window widget */
3034   pstr = create_utf8_from_char(_("What nation will you be?"), adj_font(12));
3035   pstr->style |= TTF_STYLE_BOLD;
3036 
3037   pWindow = create_window(NULL, pstr, w, h, WF_FREE_DATA);
3038   pWindow->action = nations_dialog_callback;
3039   set_wstate(pWindow, FC_WS_NORMAL);
3040   pSetup = fc_calloc(1, sizeof(struct NAT));
3041   pWindow->data.ptr = (void *)pSetup;
3042 
3043   pNationDlg->pEndWidgetList = pWindow;
3044   add_to_gui_list(ID_NATION_WIZARD_WINDOW, pWindow);
3045   /* --------------------------------------------------------- */
3046   /* create nations list */
3047 
3048   /* Create Imprv Background Icon */
3049   pMain_Bg = create_surf(adj_size(96*2), adj_size(64), SDL_SWSURFACE);
3050 
3051   SDL_FillRect(pMain_Bg, NULL, map_rgba(pMain_Bg->format, bg_color));
3052 
3053   create_frame(pMain_Bg,
3054                0, 0, pMain_Bg->w - 1, pMain_Bg->h - 1,
3055                get_theme_color(COLOR_THEME_NATIONDLG_FRAME));
3056 
3057   pstr = create_utf8_str(NULL, 0, adj_font(12));
3058   pstr->style |= (SF_CENTER|TTF_STYLE_BOLD);
3059   pstr->bgcol = (SDL_Color) {0, 0, 0, 0};
3060 
3061   /* fill list */
3062 
3063   nations_iterate(pNation) {
3064     if (!is_nation_playable(pNation) || !is_nation_pickable(pNation)) {
3065       continue;
3066     }
3067 
3068     pTmp_Surf_zoomed = adj_surf(get_nation_flag_surface(pNation));
3069 
3070     pTmp_Surf = crop_rect_from_surface(pMain_Bg, NULL);
3071 
3072     copy_chars_to_utf8_str(pstr, nation_plural_translation(pNation));
3073     change_ptsize_utf8(pstr, adj_font(12));
3074     pText_Name = create_text_surf_smaller_than_w(pstr, pTmp_Surf->w - adj_size(4));
3075 
3076     dst.x = (pTmp_Surf->w - pTmp_Surf_zoomed->w) / 2;
3077     len = pTmp_Surf_zoomed->h +
3078       adj_size(10) + pText_Name->h;
3079     dst.y = (pTmp_Surf->h - len) / 2;
3080     alphablit(pTmp_Surf_zoomed, NULL, pTmp_Surf, &dst, 255);
3081     dst.y += (pTmp_Surf_zoomed->h + adj_size(10));
3082 
3083     dst.x = (pTmp_Surf->w - pText_Name->w) / 2;
3084     alphablit(pText_Name, NULL, pTmp_Surf, &dst, 255);
3085     dst.y += pText_Name->h;
3086     FREESURFACE(pText_Name);
3087 
3088     pWidget = create_icon2(pTmp_Surf, pWindow->dst,
3089                            (WF_RESTORE_BACKGROUND|WF_FREE_THEME));
3090 
3091     set_wstate(pWidget, FC_WS_NORMAL);
3092 
3093     pWidget->action = nation_button_callback;
3094 
3095     w = MAX(w, pWidget->size.w);
3096     h = MAX(h, pWidget->size.h);
3097 
3098     add_to_gui_list(MAX_ID - nation_index(pNation), pWidget);
3099 
3100     if (nation_index(pNation) > (TARGETS_ROW * TARGETS_COL - 1)) {
3101       set_wflag(pWidget, WF_HIDDEN);
3102     }
3103 
3104   } nations_iterate_end;
3105 
3106   FREESURFACE(pMain_Bg);
3107 
3108   pNationDlg->pEndActiveWidgetList = pWindow->prev;
3109   pNationDlg->pBeginWidgetList = pWidget;
3110   pNationDlg->pBeginActiveWidgetList = pNationDlg->pBeginWidgetList;
3111 
3112   if (get_playable_nation_count() > TARGETS_ROW * TARGETS_COL) {
3113     pNationDlg->pActiveWidgetList = pNationDlg->pEndActiveWidgetList;
3114     create_vertical_scrollbar(pNationDlg,
3115                               TARGETS_COL, TARGETS_ROW, TRUE, TRUE);
3116   }
3117 
3118   /* ----------------------------------------------------------------- */
3119 
3120   /* nation set selection */
3121   if (nation_set_count() > 1) {
3122     utf8_str *natset_str;
3123     struct option *poption;
3124 
3125     natset_str = create_utf8_from_char(_("Nation set"), adj_font(12));
3126     change_ptsize_utf8(natset_str, adj_font(24));
3127     nationsets = create_iconlabel(NULL, pWindow->dst, natset_str, 0);
3128     add_to_gui_list(ID_LABEL, nationsets);
3129 
3130     /* create nation set name label */
3131     poption = optset_option_by_name(server_optset, "nationset");
3132     pSetup->set = nation_set_by_setting_value(option_str_get(poption));
3133 
3134     natset_str = create_utf8_from_char(nation_set_name_translation(pSetup->set),
3135                                        adj_font(12));
3136     change_ptsize_utf8(natset_str, adj_font(24));
3137 
3138     pWidget = create_iconlabel(NULL, pWindow->dst, natset_str, 0);
3139 
3140     add_to_gui_list(ID_LABEL, pWidget);
3141     pSetup->pset_name = pWidget;
3142 
3143     /* create next nationset button */
3144     pWidget = create_themeicon_button(current_theme->R_ARROW_Icon,
3145                                       pWindow->dst, NULL, 0);
3146     pWidget->action = next_set_callback;
3147     if (nation_set_index(pSetup->set) < nation_set_count() - 1) {
3148       set_wstate(pWidget, FC_WS_NORMAL);
3149     }
3150     add_to_gui_list(ID_NATION_NEXT_NATIONSET_BUTTON, pWidget);
3151     pWidget->size.h = pWidget->next->size.h;
3152     pSetup->pset_next = pWidget;
3153 
3154     /* create prev nationset button */
3155     pWidget = create_themeicon_button(current_theme->L_ARROW_Icon,
3156                                       pWindow->dst, NULL, 0);
3157     pWidget->action = prev_set_callback;
3158     if (nation_set_index(pSetup->set) > 0) {
3159       set_wstate(pWidget, FC_WS_NORMAL);
3160     }
3161     add_to_gui_list(ID_NATION_PREV_NATIONSET_BUTTON, pWidget);
3162     pWidget->size.h = pWidget->next->size.h;
3163     pSetup->pset_prev = pWidget;
3164   }
3165 
3166   /* nation name */
3167   pSetup->nation = fc_rand(get_playable_nation_count());
3168   pnat = nation_by_number(pSetup->nation);
3169   pSetup->nation_style = style_number(style_of_nation(pnat));
3170 
3171   copy_chars_to_utf8_str(pstr, nation_plural_translation(pnat));
3172   change_ptsize_utf8(pstr, adj_font(24));
3173   pstr->render = 2;
3174   pstr->fgcol = *get_theme_color(COLOR_THEME_NATIONDLG_TEXT);
3175 
3176   pTmp_Surf_zoomed = adj_surf(get_nation_flag_surface(pnat));
3177 
3178   pWidget = create_iconlabel(pTmp_Surf_zoomed, pWindow->dst, pstr,
3179                              (WF_ICON_ABOVE_TEXT|WF_ICON_CENTER|WF_FREE_GFX));
3180   if (nationsets == NULL) {
3181     pBuf = pWidget;
3182   } else {
3183     pBuf = nationsets;
3184   }
3185 
3186   add_to_gui_list(ID_LABEL, pWidget);
3187 
3188   /* create leader name edit */
3189   pWidget = create_edit_from_chars(NULL, pWindow->dst,
3190                                    NULL, adj_font(16), adj_size(200), 0);
3191   pWidget->size.h = adj_size(24);
3192 
3193   set_wstate(pWidget, FC_WS_NORMAL);
3194   pWidget->action = leader_name_edit_callback;
3195   add_to_gui_list(ID_NATION_WIZARD_LEADER_NAME_EDIT, pWidget);
3196   pSetup->pName_Edit = pWidget;
3197 
3198   /* create next leader name button */
3199   pWidget = create_themeicon_button(current_theme->R_ARROW_Icon,
3200                                     pWindow->dst, NULL, 0);
3201   pWidget->action = next_name_callback;
3202   add_to_gui_list(ID_NATION_WIZARD_NEXT_LEADER_NAME_BUTTON, pWidget);
3203   pWidget->size.h = pWidget->next->size.h;
3204   pSetup->pName_Next = pWidget;
3205 
3206   /* create prev leader name button */
3207   pWidget = create_themeicon_button(current_theme->L_ARROW_Icon,
3208                                     pWindow->dst, NULL, 0);
3209   pWidget->action = prev_name_callback;
3210   add_to_gui_list(ID_NATION_WIZARD_PREV_LEADER_NAME_BUTTON, pWidget);
3211   pWidget->size.h = pWidget->next->size.h;
3212   pSetup->pName_Prev = pWidget;
3213 
3214   /* change sex button */
3215   pWidget = create_icon_button_from_chars(NULL, pWindow->dst, _("Male"), adj_font(14), 0);
3216   pWidget->action = change_sex_callback;
3217   pWidget->size.w = adj_size(100);
3218   pWidget->size.h = adj_size(22);
3219   set_wstate(pWidget, FC_WS_NORMAL);
3220   pSetup->pChange_Sex = pWidget;
3221 
3222   /* add to main widget list */
3223   add_to_gui_list(ID_NATION_WIZARD_CHANGE_SEX_BUTTON, pWidget);
3224 
3225   /* ---------------------------------------------------------- */
3226   i = 0;
3227   zoom = DEFAULT_ZOOM * 1.0;
3228 
3229   len = 0;
3230   styles_iterate(pstyle) {
3231     i = basic_city_style_for_style(pstyle);
3232 
3233     pTmp_Surf = get_sample_city_surface(i);
3234 
3235     if (pTmp_Surf->w > 48) {
3236       zoom = DEFAULT_ZOOM * (48.0 / pTmp_Surf->w);
3237     }
3238 
3239     pTmp_Surf_zoomed = zoomSurface(get_sample_city_surface(i), zoom, zoom, 0);
3240 
3241     pWidget = create_icon2(pTmp_Surf_zoomed, pWindow->dst, WF_RESTORE_BACKGROUND);
3242     pWidget->action = style_callback;
3243     if (i != pSetup->nation_style) {
3244       set_wstate(pWidget, FC_WS_NORMAL);
3245     }
3246     len += pWidget->size.w;
3247     add_to_gui_list(MAX_ID - 1000 - i, pWidget);
3248   } styles_iterate_end;
3249 
3250   pLast_City_Style = pWidget;
3251   /* ---------------------------------------------------------- */
3252 
3253   /* create Cancel button */
3254   pWidget = create_themeicon_button_from_chars(current_theme->CANCEL_Icon,
3255                                                pWindow->dst, _("Cancel"),
3256                                                adj_font(12), 0);
3257   pWidget->action = races_dialog_cancel_callback;
3258   set_wstate(pWidget, FC_WS_NORMAL);
3259 
3260   add_to_gui_list(ID_NATION_WIZARD_DISCONNECT_BUTTON, pWidget);
3261 
3262   /* create OK button */
3263   pWidget =
3264     create_themeicon_button_from_chars(current_theme->OK_Icon, pWindow->dst,
3265                                        _("OK"), adj_font(12), 0);
3266   pWidget->action = races_dialog_ok_callback;
3267 
3268   set_wstate(pWidget, FC_WS_NORMAL);
3269   add_to_gui_list(ID_NATION_WIZARD_START_BUTTON, pWidget);
3270   pWidget->size.w = MAX(pWidget->size.w, pWidget->next->size.w);
3271   pWidget->next->size.w = pWidget->size.w;
3272 
3273   pNationDlg->pBeginWidgetList = pWidget;
3274   /* ---------------------------------------------------------- */
3275 
3276   pMain_Bg = theme_get_background(theme, BACKGROUND_NATIONDLG);
3277   if (resize_window(pWindow, pMain_Bg, NULL, adj_size(640), adj_size(480))) {
3278     FREESURFACE(pMain_Bg);
3279   }
3280 
3281   area = pWindow->area;
3282 
3283   widget_set_position(pWindow,
3284                       (main_window_width() - pWindow->size.w) / 2,
3285                       (main_window_height() - pWindow->size.h) / 2);
3286 
3287   /* nations */
3288 
3289   h = pNationDlg->pEndActiveWidgetList->size.h * TARGETS_ROW;
3290   i = (area.h - adj_size(43) - h) / 2;
3291   setup_vertical_widgets_position(TARGETS_COL,
3292                                   area.x + adj_size(10),
3293                                   area.y + i - adj_size(4),
3294                                   0, 0, pNationDlg->pBeginActiveWidgetList,
3295                                   pNationDlg->pEndActiveWidgetList);
3296 
3297   if (pNationDlg->pScroll) {
3298     SDL_Rect area2;
3299 
3300     w = pNationDlg->pEndActiveWidgetList->size.w * TARGETS_COL;
3301     setup_vertical_scrollbar_area(pNationDlg->pScroll,
3302                                   area.x + w + adj_size(12),
3303                                   area.y + i - adj_size(4), h, FALSE);
3304 
3305     area2.x = area.x + w + adj_size(11);
3306     area2.y = area.y + i - adj_size(4);
3307     area2.w = pNationDlg->pScroll->pUp_Left_Button->size.w + adj_size(2);
3308     area2.h = h;
3309     fill_rect_alpha(pWindow->theme, &area2, &bg_color);
3310 
3311     create_frame(pWindow->theme,
3312                  area2.x, area2.y - 1, area2.w, area2.h + 1,
3313                  get_theme_color(COLOR_THEME_NATIONDLG_FRAME));
3314   }
3315 
3316   if (nationsets != NULL) {
3317     /* Nationsets header */
3318     pBuf->size.x = area.x + area.w / 2 + (area.w / 2 - pBuf->size.w) / 2;
3319     pBuf->size.y = area.y + adj_size(46);
3320 
3321     natinfo_y = pBuf->size.y;
3322     natinfo_h = area.h -= pBuf->size.y;
3323 
3324     /* Nationset name */
3325     pBuf = pBuf->prev;
3326     pBuf->size.x = area.x + area.w / 2 + (area.w / 2 - pBuf->size.w) / 2;
3327     pBuf->size.y = natinfo_y + adj_size(46);
3328 
3329     natinfo_y += adj_size(46);
3330     natinfo_h -= adj_size(46);
3331 
3332     /* Next Nationset Button */
3333     pBuf = pBuf->prev;
3334     pBuf->size.x = pBuf->next->size.x + pBuf->next->size.w;
3335     pBuf->size.y = pBuf->next->size.y;
3336 
3337     /* Prev Nationset Button */
3338     pBuf = pBuf->prev;
3339     pBuf->size.x = pBuf->next->next->size.x - pBuf->size.w;
3340     pBuf->size.y = pBuf->next->size.y;
3341 
3342     pBuf = pBuf->prev;
3343   } else {
3344     natinfo_y = area.y;
3345     natinfo_h = area.h;
3346   }
3347 
3348   /* Selected Nation Name */
3349   pBuf->size.x = area.x + area.w / 2 + (area.w / 2 - pBuf->size.w) / 2;
3350   pBuf->size.y = natinfo_y + adj_size(46);
3351 
3352   /* Leader Name Edit */
3353   pBuf = pBuf->prev;
3354   pBuf->size.x = area.x + area.w / 2 + (area.w/2 - pBuf->size.w) / 2;
3355   pBuf->size.y = natinfo_y + (natinfo_h - pBuf->size.h) / 2 - adj_size(30);
3356 
3357   /* Next Leader Name Button */
3358   pBuf = pBuf->prev;
3359   pBuf->size.x = pBuf->next->size.x + pBuf->next->size.w;
3360   pBuf->size.y = pBuf->next->size.y;
3361 
3362   /* Prev Leader Name Button */
3363   pBuf = pBuf->prev;
3364   pBuf->size.x = pBuf->next->next->size.x - pBuf->size.w;
3365   pBuf->size.y = pBuf->next->size.y;
3366 
3367   /* Change Leader Sex Button */
3368   pBuf = pBuf->prev;
3369   pBuf->size.x = area.x + area.w / 2 + (area.w/2 - pBuf->size.w) / 2;
3370   pBuf->size.y = pBuf->next->size.y + pBuf->next->size.h + adj_size(20);
3371 
3372   /* First Style Button */
3373   pBuf = pBuf->prev;
3374   pBuf->size.x = area.x + area.w / 2 + (area.w/2 - len) / 2 - adj_size(20);
3375   pBuf->size.y = pBuf->next->size.y + pBuf->next->size.h + adj_size(20);
3376 
3377   /* Rest Style Buttons */
3378   while (pBuf != pLast_City_Style) {
3379     pBuf = pBuf->prev;
3380     pBuf->size.x = pBuf->next->size.x + pBuf->next->size.w + adj_size(3);
3381     pBuf->size.y = pBuf->next->size.y;
3382   }
3383 
3384   create_line(pWindow->theme,
3385               area.x,
3386               natinfo_y + natinfo_h - adj_size(7) - pBuf->prev->size.h - adj_size(10),
3387               area.w - 1,
3388               natinfo_y + natinfo_h - adj_size(7) - pBuf->prev->size.h - adj_size(10),
3389               get_theme_color(COLOR_THEME_NATIONDLG_FRAME));
3390 
3391   /* Disconnect Button */
3392   pBuf = pBuf->prev;
3393   pBuf->size.x = area.x + adj_size(10);
3394   pBuf->size.y = natinfo_y + natinfo_h - adj_size(7) - pBuf->size.h;
3395 
3396   /* Start Button */
3397   pBuf = pBuf->prev;
3398   pBuf->size.x = area.w - adj_size(10) - pBuf->size.w;
3399   pBuf->size.y = pBuf->next->size.y;
3400 
3401   /* -------------------------------------------------------------------- */
3402 
3403   select_random_leader(pSetup->nation);
3404 
3405   redraw_group(pNationDlg->pBeginWidgetList, pWindow, 0);
3406 
3407   widget_flush(pWindow);
3408 }
3409 
3410 /**************************************************************************
3411   Close the nation selection dialog.  This should allow the user to
3412   (at least) select a unit to activate.
3413 **************************************************************************/
popdown_races_dialog(void)3414 void popdown_races_dialog(void)
3415 {
3416   if (pNationDlg) {
3417     popdown_window_group_dialog(pNationDlg->pBeginWidgetList,
3418                                 pNationDlg->pEndWidgetList);
3419 
3420     cancel_help_dlg_callback(NULL);
3421 
3422     FC_FREE(pLeaderName);
3423 
3424     FC_FREE(pNationDlg->pScroll);
3425     FC_FREE(pNationDlg);
3426   }
3427 }
3428 
3429 /**************************************************************************
3430   The server has changed the set of selectable nations.
3431 **************************************************************************/
races_update_pickable(bool nationset_change)3432 void races_update_pickable(bool nationset_change)
3433 {
3434   /* If this is because of nationset change, update will take
3435    * place later when the new option value is received */
3436   if (pNationDlg != NULL && !nationset_change) {
3437     popdown_races_dialog();
3438     popup_races_dialog(client.conn.playing);
3439   }
3440 }
3441 
3442 /**************************************************************************
3443   Nationset selection update
3444 **************************************************************************/
nationset_changed(void)3445 void nationset_changed(void)
3446 {
3447   if (pNationDlg != NULL) {
3448     popdown_races_dialog();
3449     popup_races_dialog(client.conn.playing);
3450   }
3451 }
3452 
3453 /**************************************************************************
3454   In the nation selection dialog, make already-taken nations unavailable.
3455   This information is contained in the packet_nations_used packet.
3456 **************************************************************************/
races_toggles_set_sensitive(void)3457 void races_toggles_set_sensitive(void)
3458 {
3459   struct NAT *pSetup;
3460   bool change = FALSE;
3461   struct widget *pNat;
3462 
3463   if (!pNationDlg) {
3464     return;
3465   }
3466 
3467   pSetup = (struct NAT *)(pNationDlg->pEndWidgetList->data.ptr);
3468 
3469   nations_iterate(nation) {
3470     if (!is_nation_pickable(nation) || nation->player) {
3471       log_debug("  [%d]: %d = %s", nation_index(nation),
3472                 (!is_nation_pickable(nation) || nation->player),
3473                 nation_rule_name(nation));
3474 
3475       pNat = get_widget_pointer_from_main_list(MAX_ID - nation_index(nation));
3476       set_wstate(pNat, FC_WS_DISABLED);
3477 
3478       if (nation_index(nation) == pSetup->nation) {
3479         change = TRUE;
3480       }
3481     }
3482   } nations_iterate_end;
3483 
3484   if (change) {
3485     do {
3486       pSetup->nation = fc_rand(get_playable_nation_count());
3487       pNat = get_widget_pointer_from_main_list(MAX_ID - pSetup->nation);
3488     } while (get_wstate(pNat) == FC_WS_DISABLED);
3489 
3490     if (get_wstate(pSetup->pName_Edit) == FC_WS_PRESSED) {
3491       force_exit_from_event_loop();
3492       set_wstate(pSetup->pName_Edit, FC_WS_NORMAL);
3493     }
3494     change_nation_label();
3495     enable(MAX_ID - 1000 - pSetup->nation_style);
3496     pSetup->nation_style = style_number(style_of_nation(nation_by_number(pSetup->nation)));
3497     disable(MAX_ID - 1000 - pSetup->nation_style);
3498     select_random_leader(pSetup->nation);
3499   }
3500   redraw_group(pNationDlg->pBeginWidgetList, pNationDlg->pEndWidgetList, 0);
3501   widget_flush(pNationDlg->pEndWidgetList);
3502 }
3503 
3504 /**************************************************************************
3505   Ruleset (modpack) has suggested loading certain tileset. Confirm from
3506   user and load.
3507 **************************************************************************/
popup_tileset_suggestion_dialog(void)3508 void popup_tileset_suggestion_dialog(void)
3509 {
3510 }
3511 
3512 /****************************************************************
3513   Ruleset (modpack) has suggested loading certain soundset. Confirm from
3514   user and load.
3515 *****************************************************************/
popup_soundset_suggestion_dialog(void)3516 void popup_soundset_suggestion_dialog(void)
3517 {
3518 }
3519 
3520 /****************************************************************
3521   Ruleset (modpack) has suggested loading certain musicset. Confirm from
3522   user and load.
3523 *****************************************************************/
popup_musicset_suggestion_dialog(void)3524 void popup_musicset_suggestion_dialog(void)
3525 {
3526 }
3527 
3528 /**************************************************************************
3529   Tileset (modpack) has suggested loading certain theme. Confirm from
3530   user and load.
3531 **************************************************************************/
popup_theme_suggestion_dialog(const char * theme_name)3532 bool popup_theme_suggestion_dialog(const char *theme_name)
3533 {
3534   /* Don't load */
3535   return FALSE;
3536 }
3537 
3538 /****************************************************************
3539   Player has gained a new tech.
3540 *****************************************************************/
show_tech_gained_dialog(Tech_type_id tech)3541 void show_tech_gained_dialog(Tech_type_id tech)
3542 {
3543   /* PORTME */
3544 }
3545 
3546 /****************************************************************
3547   Show tileset error dialog.
3548 *****************************************************************/
show_tileset_error(const char * msg)3549 void show_tileset_error(const char *msg)
3550 {
3551   /* PORTME */
3552 }
3553 
3554 /****************************************************************
3555   Give a warning when user is about to edit scenario with manually
3556   set properties.
3557 *****************************************************************/
handmade_scenario_warning(void)3558 bool handmade_scenario_warning(void)
3559 {
3560   /* Just tell the client common code to handle this. */
3561   return FALSE;
3562 }
3563 
3564 /****************************************************************
3565   Update multipliers (policies) dialog.
3566 *****************************************************************/
real_multipliers_dialog_update(void * unused)3567 void real_multipliers_dialog_update(void *unused)
3568 {
3569   /* PORTME */
3570 }
3571 
3572 /****************************************************************
3573   Unit wants to get into some transport on given tile.
3574 *****************************************************************/
request_transport(struct unit * pcargo,struct tile * ptile)3575 bool request_transport(struct unit *pcargo, struct tile *ptile)
3576 {
3577   return FALSE; /* Unit was not handled here. */
3578 }
3579 
3580 /***************************************************************************
3581   Popup detailed information about battle or save information for
3582   some kind of statistics
3583 ***************************************************************************/
popup_combat_info(int attacker_unit_id,int defender_unit_id,int attacker_hp,int defender_hp,bool make_winner_veteran)3584 void popup_combat_info(int attacker_unit_id, int defender_unit_id,
3585                        int attacker_hp, int defender_hp,
3586                        bool make_winner_veteran)
3587 {
3588 }
3589