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