Use correct factor in all situations when scaling down sdl-client citymap.
[freeciv.git] / client / gui-sdl2 / citydlg.c
blob20ba3b921846fcea8621145aec963377e5cde3f8
1 /***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12 ***********************************************************************/
14 /***********************************************************************
15 citydlg.c - description
16 -------------------
17 begin : Wed Sep 04 2002
18 copyright : (C) 2002 by Rafał Bursig
19 email : Rafał Bursig <bursig@poczta.fm>
20 ***********************************************************************/
22 #ifdef HAVE_CONFIG_H
23 #include <fc_config.h>
24 #endif
26 /* SDL2 */
27 #ifdef SDL2_PLAIN_INCLUDE
28 #include <SDL.h>
29 #else /* SDL2_PLAIN_INCLUDE */
30 #include <SDL2/SDL.h>
31 #endif /* SDL2_PLAIN_INCLUDE */
33 /* utility */
34 #include "bitvector.h"
35 #include "fcintl.h"
36 #include "log.h"
38 /* common */
39 #include "game.h"
40 #include "movement.h"
41 #include "specialist.h"
42 #include "unitlist.h"
44 /* client */
45 #include "client_main.h"
46 #include "climisc.h"
47 #include "control.h"
48 #include "text.h"
50 /* gui-sdl2 */
51 #include "cityrep.h"
52 #include "cma_fe.h"
53 #include "colors.h"
54 #include "dialogs.h"
55 #include "graphics.h"
56 #include "gui_iconv.h"
57 #include "gui_id.h"
58 #include "gui_main.h"
59 #include "gui_tilespec.h"
60 #include "mapview.h"
61 #include "menu.h"
62 #include "sprite.h"
63 #include "themespec.h"
64 #include "widget.h"
65 #include "wldlg.h"
67 #include "citydlg.h"
69 /* ============================================================= */
71 static struct city_dialog {
72 struct city *pCity;
74 enum {
75 INFO_PAGE = 0,
76 HAPPINESS_PAGE = 1,
77 ARMY_PAGE,
78 SUPPORTED_UNITS_PAGE,
79 MISC_PAGE
80 } page;
82 /* main window group list */
83 struct widget *pBeginCityWidgetList;
84 struct widget *pEndCityWidgetList;
86 /* Imprvm. vscrollbar */
87 struct ADVANCED_DLG *pImprv;
89 /* Penel group list */
90 struct ADVANCED_DLG *pPanel;
92 /* Menu imprv. dlg. */
93 struct widget *pBeginCityMenuWidgetList;
94 struct widget *pEndCityMenuWidgetList;
96 /* shortcuts */
97 struct widget *pAdd_Point;
98 struct widget *pBuy_Button;
99 struct widget *pResource_Map;
100 struct widget *pCity_Name_Edit;
102 int citizen_step;
104 SDL_Rect spec_area;
106 bool lock;
107 } *pCityDlg = NULL;
109 enum specialist_type {
110 SP_ELVIS, SP_SCIENTIST, SP_TAXMAN, SP_LAST
113 static float city_map_zoom = 1;
115 static struct SMALL_DLG *pHurry_Prod_Dlg = NULL;
117 static void popdown_hurry_production_dialog(void);
118 static void disable_city_dlg_widgets(void);
119 static void redraw_city_dialog(struct city *pCity);
120 static void rebuild_imprm_list(struct city *pCity);
121 static void rebuild_citydlg_title_str(struct widget *pWindow, struct city *pCity);
123 /* ======================================================================= */
125 /**************************************************************************
126 Return first building that has given effect.
128 FIXME: Some callers would work better if they got building actually
129 provides the effect at the moment, and not just first potential
130 one.
131 **************************************************************************/
132 struct impr_type *get_building_for_effect(enum effect_type effect_type)
134 improvement_iterate(pImprove) {
135 if (building_has_effect(pImprove, effect_type)) {
136 return pImprove;
138 } improvement_iterate_end;
140 return NULL;
143 /**************************************************************************
144 Destroy City Menu Dlg but not undraw.
145 **************************************************************************/
146 static void popdown_city_menu_dlg(bool enable_city_dialog_widgets)
148 if (pCityDlg->pEndCityMenuWidgetList) {
149 popdown_window_group_dialog(pCityDlg->pBeginCityMenuWidgetList,
150 pCityDlg->pEndCityMenuWidgetList);
151 pCityDlg->pEndCityMenuWidgetList = NULL;
153 if (enable_city_dialog_widgets) {
154 /* enable city dlg */
155 enable_city_dlg_widgets();
159 /**************************************************************************
160 Destroy City Dlg
161 **************************************************************************/
162 static void del_city_dialog(void)
164 if (pCityDlg) {
165 if (pCityDlg->pImprv->pEndWidgetList) {
166 del_group_of_widgets_from_gui_list(pCityDlg->pImprv->pBeginWidgetList,
167 pCityDlg->pImprv->pEndWidgetList);
169 FC_FREE(pCityDlg->pImprv->pScroll);
170 FC_FREE(pCityDlg->pImprv);
172 if (pCityDlg->pPanel) {
173 del_group_of_widgets_from_gui_list(pCityDlg->pPanel->pBeginWidgetList,
174 pCityDlg->pPanel->pEndWidgetList);
175 FC_FREE(pCityDlg->pPanel->pScroll);
176 FC_FREE(pCityDlg->pPanel);
179 if (pHurry_Prod_Dlg) {
180 del_group_of_widgets_from_gui_list(pHurry_Prod_Dlg->pBeginWidgetList,
181 pHurry_Prod_Dlg->pEndWidgetList);
183 FC_FREE(pHurry_Prod_Dlg);
186 free_city_units_lists();
187 popdown_city_menu_dlg(FALSE);
189 popdown_window_group_dialog(pCityDlg->pBeginCityWidgetList,
190 pCityDlg->pEndCityWidgetList);
191 FC_FREE(pCityDlg);
195 /**************************************************************************
196 Main City Dlg. window callback.
197 This implements specialist change ( Elvis, Taxman, Scientist )
198 **************************************************************************/
199 static int city_dlg_callback(struct widget *pWindow)
201 if (Main.event.button.button == SDL_BUTTON_LEFT) {
202 if (!cma_is_city_under_agent(pCityDlg->pCity, NULL)
203 && city_owner(pCityDlg->pCity) == client.conn.playing) {
205 if (is_in_rect_area(Main.event.motion.x, Main.event.motion.y,
206 pCityDlg->spec_area)) {
207 city_rotate_specialist(pCityDlg->pCity,
208 (Main.event.motion.x - pCityDlg->spec_area.x)
209 / pCityDlg->citizen_step);
211 return -1;
215 if (!pCityDlg->lock) {
216 if (pCityDlg->pPanel) {
217 select_window_group_dialog(pCityDlg->pBeginCityWidgetList, pWindow);
218 select_window_group_dialog(pCityDlg->pPanel->pBeginWidgetList,
219 pCityDlg->pPanel->pEndWidgetList);
220 widget_flush(pWindow);
221 } else {
222 if (select_window_group_dialog(pCityDlg->pBeginCityWidgetList, pWindow)) {
223 widget_flush(pWindow);
228 return -1;
231 /* ===================================================================== */
232 /* ========================== Units Orders Menu ======================== */
233 /* ===================================================================== */
235 /**************************************************************************
236 Popdown unit city orders menu.
237 **************************************************************************/
238 static int cancel_units_orders_city_dlg_callback(struct widget *pButton)
240 if (Main.event.button.button == SDL_BUTTON_LEFT) {
241 popdown_window_group_dialog(pCityDlg->pBeginCityMenuWidgetList,
242 pCityDlg->pEndCityMenuWidgetList);
243 pCityDlg->pEndCityMenuWidgetList = NULL;
245 /* enable city dlg */
246 enable_city_dlg_widgets();
247 flush_dirty();
249 return -1;
252 /**************************************************************************
253 activate unit and del unit order dlg. widget group.
254 **************************************************************************/
255 static int activate_units_orders_city_dlg_callback(struct widget *pButton)
257 if (Main.event.button.button == SDL_BUTTON_LEFT) {
258 struct unit *pUnit = pButton->data.unit;
260 popdown_city_menu_dlg(TRUE);
261 if (pUnit) {
262 unit_focus_set(pUnit);
265 return -1;
268 /**************************************************************************
269 activate unit and popdow city dlg. + center on unit.
270 **************************************************************************/
271 static int activate_and_exit_units_orders_city_dlg_callback(struct widget *pButton)
273 if (Main.event.button.button == SDL_BUTTON_LEFT) {
274 struct unit *pUnit = pButton->data.unit;
276 if (pUnit) {
277 popdown_window_group_dialog(pCityDlg->pBeginCityMenuWidgetList,
278 pCityDlg->pEndCityMenuWidgetList);
279 pCityDlg->pEndCityMenuWidgetList = NULL;
281 popdown_city_dialog(pCityDlg->pCity);
283 center_tile_mapcanvas(unit_tile(pUnit));
284 unit_focus_set(pUnit);
287 return -1;
290 /**************************************************************************
291 sentry unit and del unit order dlg. widget group.
292 **************************************************************************/
293 static int sentry_units_orders_city_dlg_callback(struct widget *pButton)
295 if (Main.event.button.button == SDL_BUTTON_LEFT) {
296 struct unit *pUnit = pButton->data.unit;
298 popdown_city_menu_dlg(TRUE);
299 if (pUnit) {
300 request_unit_sentry(pUnit);
303 return -1;
306 /**************************************************************************
307 fortify unit and del unit order dlg. widget group.
308 **************************************************************************/
309 static int fortify_units_orders_city_dlg_callback(struct widget *pButton)
311 if (Main.event.button.button == SDL_BUTTON_LEFT) {
312 struct unit *pUnit = pButton->data.unit;
314 popdown_city_menu_dlg(TRUE);
315 if (pUnit) {
316 request_unit_fortify(pUnit);
319 return -1;
322 /**************************************************************************
323 disband unit and del unit order dlg. widget group.
324 **************************************************************************/
325 static int disband_units_orders_city_dlg_callback(struct widget *pButton)
327 if (Main.event.button.button == SDL_BUTTON_LEFT) {
328 struct unit *pUnit = pButton->data.unit;
330 popdown_city_menu_dlg(TRUE);
331 popup_unit_disband_dlg(pUnit, TRUE);
333 return -1;
336 /**************************************************************************
337 homecity unit and del unit order dlg. widget group.
338 **************************************************************************/
339 static int homecity_units_orders_city_dlg_callback(struct widget *pButton)
341 if (Main.event.button.button == SDL_BUTTON_LEFT) {
342 struct unit *pUnit = pButton->data.unit;
344 popdown_city_menu_dlg(TRUE);
345 if (pUnit) {
346 request_unit_change_homecity(pUnit);
349 return -1;
352 /**************************************************************************
353 upgrade unit and del unit order dlg. widget group.
354 **************************************************************************/
355 static int upgrade_units_orders_city_dlg_callback(struct widget *pButton)
357 if (Main.event.button.button == SDL_BUTTON_LEFT) {
358 struct unit *pUnit = pButton->data.unit;
360 popdown_city_menu_dlg(TRUE);
361 popup_unit_upgrade_dlg(pUnit, TRUE);
363 return -1;
366 /**************************************************************************
367 Main unit order dlg. callback.
368 **************************************************************************/
369 static int units_orders_dlg_callback(struct widget *pButton)
371 return -1;
374 /**************************************************************************
375 popup units orders menu.
376 **************************************************************************/
377 static int units_orders_city_dlg_callback(struct widget *pButton)
379 if (Main.event.button.button == SDL_BUTTON_LEFT) {
380 utf8_str *pstr;
381 char cBuf[80];
382 struct widget *pBuf, *pWindow = pCityDlg->pEndCityWidgetList;
383 struct unit *punit;
384 struct unit_type *pUType;
385 Uint16 i = 0, hh = 0;
386 SDL_Rect area;
388 punit = player_unit_by_number(client_player(), MAX_ID - pButton->ID);
390 if (!punit || !can_client_issue_orders()) {
391 return -1;
394 if (Main.event.button.button == SDL_BUTTON_RIGHT) {
395 popdown_city_dialog(pCityDlg->pCity);
396 center_tile_mapcanvas(unit_tile(punit));
397 unit_focus_set(punit);
398 return -1;
401 /* Disable city dlg */
402 unselect_widget_action();
403 disable_city_dlg_widgets();
405 pUType = unit_type_get(punit);
407 /* window */
408 fc_snprintf(cBuf, sizeof(cBuf), "%s:", _("Unit commands"));
409 pstr = create_utf8_from_char(cBuf, adj_font(12));
410 pstr->style |= TTF_STYLE_BOLD;
411 pWindow = create_window_skeleton(NULL, pstr, 0);
413 pWindow->action = units_orders_dlg_callback;
414 set_wstate(pWindow, FC_WS_NORMAL);
415 add_to_gui_list(ID_REVOLUTION_DLG_WINDOW, pWindow);
416 pCityDlg->pEndCityMenuWidgetList = pWindow;
418 area = pWindow->area;
420 /* unit description */
421 fc_snprintf(cBuf, sizeof(cBuf), "%s", unit_description(punit));
422 pstr = create_utf8_from_char(cBuf, adj_font(12));
423 pstr->style |= (TTF_STYLE_BOLD|SF_CENTER);
424 pBuf = create_iconlabel(adj_surf(get_unittype_surface(pUType, punit->facing)),
425 pWindow->dst, pstr, WF_FREE_THEME);
426 area.w = MAX(area.w, pBuf->size.w);
427 add_to_gui_list(ID_LABEL, pBuf);
429 /* Activate unit */
430 pBuf = create_icon_button_from_chars(NULL, pWindow->dst,
431 _("Activate unit"), adj_font(12), 0);
432 i++;
433 area.w = MAX(area.w, pBuf->size.w);
434 hh = MAX(hh, pBuf->size.h);
435 pBuf->action = activate_units_orders_city_dlg_callback;
436 pBuf->data = pButton->data;
437 set_wstate(pBuf, FC_WS_NORMAL);
438 add_to_gui_list(pButton->ID, pBuf);
440 /* Activate unit, close dlg. */
441 pBuf = create_icon_button_from_chars(NULL, pWindow->dst,
442 _("Activate unit, close dialog"), adj_font(12), 0);
443 i++;
444 area.w = MAX(area.w, pBuf->size.w);
445 hh = MAX(hh, pBuf->size.h);
446 pBuf->action = activate_and_exit_units_orders_city_dlg_callback;
447 pBuf->data = pButton->data;
448 set_wstate(pBuf, FC_WS_NORMAL);
449 add_to_gui_list(pButton->ID, pBuf);
450 /* ----- */
452 if (pCityDlg->page == ARMY_PAGE) {
453 /* Sentry unit */
454 pBuf = create_icon_button_from_chars(NULL, pWindow->dst,
455 _("Sentry unit"), adj_font(12), 0);
456 i++;
457 area.w = MAX(area.w, pBuf->size.w);
458 hh = MAX(hh, pBuf->size.h);
459 pBuf->data = pButton->data;
460 pBuf->action = sentry_units_orders_city_dlg_callback;
461 if (punit->activity != ACTIVITY_SENTRY
462 && can_unit_do_activity(punit, ACTIVITY_SENTRY)) {
463 set_wstate(pBuf, FC_WS_NORMAL);
465 add_to_gui_list(pButton->ID, pBuf);
466 /* ----- */
468 /* Fortify unit */
469 pBuf = create_icon_button_from_chars(NULL, pWindow->dst,
470 _("Fortify unit"), adj_font(12), 0);
471 i++;
472 area.w = MAX(area.w, pBuf->size.w);
473 hh = MAX(hh, pBuf->size.h);
474 pBuf->data = pButton->data;
475 pBuf->action = fortify_units_orders_city_dlg_callback;
476 if (punit->activity != ACTIVITY_FORTIFYING
477 && can_unit_do_activity(punit, ACTIVITY_FORTIFYING)) {
478 set_wstate(pBuf, FC_WS_NORMAL);
480 add_to_gui_list(pButton->ID, pBuf);
482 /* ----- */
484 /* Disband unit */
485 pBuf = create_icon_button_from_chars(NULL, pWindow->dst,
486 _("Disband unit"), adj_font(12), 0);
487 i++;
488 area.w = MAX(area.w, pBuf->size.w);
489 hh = MAX(hh, pBuf->size.h);
490 pBuf->data = pButton->data;
491 pBuf->action = disband_units_orders_city_dlg_callback;
492 set_wstate(pBuf, FC_WS_NORMAL);
493 add_to_gui_list(pButton->ID, pBuf);
494 /* ----- */
496 if (pCityDlg->page == ARMY_PAGE) {
497 if (punit->homecity != pCityDlg->pCity->id) {
498 /* Make new Homecity */
499 pBuf = create_icon_button_from_chars(NULL, pWindow->dst,
500 _("Set Home City"), adj_font(12), 0);
501 i++;
502 area.w = MAX(area.w, pBuf->size.w);
503 hh = MAX(hh, pBuf->size.h);
504 pBuf->data = pButton->data;
505 pBuf->action = homecity_units_orders_city_dlg_callback;
506 set_wstate(pBuf, FC_WS_NORMAL);
507 add_to_gui_list(pButton->ID, pBuf);
509 /* ----- */
511 if (can_upgrade_unittype(client.conn.playing, pUType)) {
512 /* Upgrade unit */
513 pBuf = create_icon_button_from_chars(NULL, pWindow->dst,
514 _("Upgrade unit"), adj_font(12), 0);
515 i++;
516 area.w = MAX(area.w, pBuf->size.w);
517 hh = MAX(hh, pBuf->size.h);
518 pBuf->data = pButton->data;
519 pBuf->action = upgrade_units_orders_city_dlg_callback;
520 set_wstate(pBuf, FC_WS_NORMAL);
521 add_to_gui_list(pButton->ID, pBuf);
525 /* ----- */
526 /* Cancel */
527 pBuf = create_icon_button_from_chars(NULL, pWindow->dst,
528 _("Cancel"), adj_font(12), 0);
529 i++;
530 area.w = MAX(area.w, pBuf->size.w);
531 hh = MAX(hh, pBuf->size.h);
532 pBuf->key = SDLK_ESCAPE;
533 pBuf->action = cancel_units_orders_city_dlg_callback;
534 set_wstate(pBuf, FC_WS_NORMAL);
535 add_to_gui_list(pButton->ID, pBuf);
536 pCityDlg->pBeginCityMenuWidgetList = pBuf;
538 /* ================================================== */
539 unselect_widget_action();
540 /* ================================================== */
542 area.w += adj_size(10);
543 hh += adj_size(4);
545 /* create window background */
546 resize_window(pWindow, NULL, get_theme_color(COLOR_THEME_BACKGROUND),
547 (pWindow->size.w - pWindow->area.w) + area.w,
548 (pWindow->size.h - pWindow->area.h) + pWindow->prev->size.h +
549 (i * hh) + adj_size(5));
551 area = pWindow->area;
553 widget_set_position(pWindow,
554 pButton->size.x + adj_size(2),
555 pWindow->area.y + pButton->size.y + 1);
557 /* label */
558 pBuf = pWindow->prev;
559 pBuf->size.w = area.w;
560 pBuf->size.x = area.x;
561 pBuf->size.y = area.y + 1;
562 pBuf = pBuf->prev;
564 /* first button */
565 pBuf->size.w = area.w;
566 pBuf->size.h = hh;
567 pBuf->size.x = area.x;
568 pBuf->size.y = pBuf->next->size.y + pBuf->next->size.h + adj_size(5);
569 pBuf = pBuf->prev;
571 while (pBuf) {
572 pBuf->size.w = area.w;
573 pBuf->size.h = hh;
574 pBuf->size.x = pBuf->next->size.x;
575 pBuf->size.y = pBuf->next->size.y + pBuf->next->size.h;
576 if (pBuf == pCityDlg->pBeginCityMenuWidgetList) {
577 break;
579 pBuf = pBuf->prev;
582 /* ================================================== */
583 /* redraw */
584 redraw_group(pCityDlg->pBeginCityMenuWidgetList, pWindow, 0);
585 widget_flush(pWindow);
587 return -1;
590 /* ======================================================================= */
591 /* ======================= City Dlg. Panels ============================== */
592 /* ======================================================================= */
594 /**************************************************************************
595 create unit icon with support icons.
596 **************************************************************************/
597 static SDL_Surface *create_unit_surface(struct unit *punit, bool support,
598 int w, int h)
600 SDL_Rect src_rect;
601 SDL_Surface *psurf;
602 struct canvas *destcanvas;
604 destcanvas = canvas_create(tileset_full_tile_width(tileset),
605 tileset_unit_with_small_upkeep_height(tileset));
607 put_unit(punit, destcanvas, 1.0, 0, 0);
609 /* Get unit sprite width, but do not limit height by it */
610 src_rect = get_smaller_surface_rect(destcanvas->surf);
611 src_rect.y = 0;
612 src_rect.h = destcanvas->surf->h;
614 if (support) {
615 int i, step;
616 int free_unhappy;
617 int happy_cost;
618 SDL_Rect dest;
620 free_unhappy = get_city_bonus(pCityDlg->pCity, EFT_MAKE_CONTENT_MIL);
621 happy_cost = city_unit_unhappiness(punit, &free_unhappy);
623 i = punit->upkeep[O_SHIELD] + punit->upkeep[O_FOOD] +
624 punit->upkeep[O_GOLD] + happy_cost;
626 if (i * pIcons->pFood->w > src_rect.w / 2) {
627 step = (src_rect.w / 2 - pIcons->pFood->w) / (i - 1);
628 } else {
629 step = pIcons->pFood->w;
632 dest.y = tileset_unit_layout_small_offset_y(tileset);
633 dest.x = src_rect.x + src_rect.w / 8;
635 for (i = 0; i < punit->upkeep[O_SHIELD]; i++) {
636 alphablit(pIcons->pShield, NULL, destcanvas->surf, &dest, 255);
637 dest.x += step;
640 for (i = 0; i < punit->upkeep[O_FOOD]; i++) {
641 alphablit(pIcons->pFood, NULL, destcanvas->surf, &dest, 255);
642 dest.x += step;
645 for (i = 0; i < punit->upkeep[O_GOLD]; i++) {
646 alphablit(pIcons->pCoin, NULL, destcanvas->surf, &dest, 255);
647 dest.x += step;
650 for (i = 0; i < happy_cost; i++) {
651 alphablit(pIcons->pFace, NULL, destcanvas->surf, &dest, 255);
652 dest.x += step;
657 psurf = create_surf(src_rect.w, src_rect.h, SDL_SWSURFACE);
658 alphablit(destcanvas->surf, &src_rect, psurf, NULL, 255);
660 canvas_free(destcanvas);
662 if (w != src_rect.w || h != src_rect.h) {
663 SDL_Surface *pzoomed;
665 pzoomed = ResizeSurfaceBox(psurf, w, h, 1, TRUE, TRUE);
666 FREESURFACE(psurf);
667 psurf = pzoomed;
670 return psurf;
673 /**************************************************************************
674 create present/supported units widget list
675 207 pixels is panel width in city dlg.
676 220 - max y position pixel position belong to panel area.
677 **************************************************************************/
678 static void create_present_supported_units_widget_list(struct unit_list *pList)
680 int i;
681 struct widget *pBuf = NULL;
682 struct widget *pEnd = NULL;
683 struct widget *pWindow = pCityDlg->pEndCityWidgetList;
684 struct city *pHome_City;
685 struct unit_type *pUType;
686 SDL_Surface *pSurf;
687 utf8_str *pstr;
688 char cBuf[256];
689 int num_x, num_y, w, h;
691 i = 0;
693 num_x = (adj_size(160) / (tileset_full_tile_width(tileset) + adj_size(4)));
694 if (num_x < 4) {
695 num_x = 4;
696 w = adj_size(160 - 4*4) / 4;
697 } else {
698 w = tileset_full_tile_width(tileset) + (adj_size(160) % (tileset_full_tile_width(tileset)+4)) / num_x;
701 num_y = (adj_size(151) / (tileset_full_tile_height(tileset)+4));
702 if (num_y < 4) {
703 num_y = 4;
704 h = adj_size(151 - 4*4) / 4;
705 } else {
706 h = tileset_full_tile_height(tileset) + (adj_size(151) % (tileset_full_tile_height(tileset)+4)) / num_y;
709 unit_list_iterate(pList, pUnit) {
710 const char *vetname;
712 pUType = unit_type_get(pUnit);
713 vetname = utype_veteran_name_translation(pUType, pUnit->veteran);
714 pHome_City = game_city_by_number(pUnit->homecity);
715 fc_snprintf(cBuf, sizeof(cBuf), "%s (%d,%d,%s)%s%s\n%s\n(%d/%d)\n%s",
716 utype_name_translation(pUType),
717 pUType->attack_strength,
718 pUType->defense_strength,
719 move_points_text(pUType->move_rate, FALSE),
720 (vetname != NULL ? "\n" : ""),
721 (vetname != NULL ? vetname : ""),
722 unit_activity_text(pUnit),
723 pUnit->hp, pUType->hp,
724 pHome_City ? pHome_City->name : Q_("?homecity:None"));
726 if (pCityDlg->page == SUPPORTED_UNITS_PAGE) {
727 int pCity_near_dist;
728 struct city *pNear_City = get_nearest_city(pUnit, &pCity_near_dist);
730 sz_strlcat(cBuf, "\n");
731 sz_strlcat(cBuf, get_nearest_city_text(pNear_City, pCity_near_dist));
732 pSurf = adj_surf(create_unit_surface(pUnit, TRUE, w, h));
733 } else {
734 pSurf = adj_surf(create_unit_surface(pUnit, FALSE, w, h));
737 pstr = create_utf8_from_char(cBuf, adj_font(10));
738 pstr->style |= SF_CENTER;
740 pBuf = create_icon2(pSurf, pWindow->dst, WF_FREE_THEME
741 | WF_RESTORE_BACKGROUND | WF_WIDGET_HAS_INFO_LABEL);
742 pBuf->info_label = pstr;
743 pBuf->data.unit = pUnit;
744 add_to_gui_list(MAX_ID - pUnit->id, pBuf);
746 if (!pEnd) {
747 pEnd = pBuf;
750 if (++i > num_x * num_y) {
751 set_wflag(pBuf, WF_HIDDEN);
754 if (city_owner(pCityDlg->pCity) == client.conn.playing) {
755 set_wstate(pBuf, FC_WS_NORMAL);
758 pBuf->action = units_orders_city_dlg_callback;
759 } unit_list_iterate_end;
761 pCityDlg->pPanel = fc_calloc(1, sizeof(struct ADVANCED_DLG));
762 pCityDlg->pPanel->pEndWidgetList = pEnd;
763 pCityDlg->pPanel->pBeginWidgetList = pBuf;
764 pCityDlg->pPanel->pEndActiveWidgetList = pCityDlg->pPanel->pEndWidgetList;
765 pCityDlg->pPanel->pBeginActiveWidgetList = pCityDlg->pPanel->pBeginWidgetList;
766 pCityDlg->pPanel->pActiveWidgetList = pCityDlg->pPanel->pEndActiveWidgetList;
768 setup_vertical_widgets_position(num_x,
769 pWindow->area.x + adj_size(5),
770 pWindow->area.y + adj_size(44),
771 0, 0, pCityDlg->pPanel->pBeginActiveWidgetList,
772 pCityDlg->pPanel->pEndActiveWidgetList);
774 if (i > num_x * num_y) {
775 create_vertical_scrollbar(pCityDlg->pPanel,
776 num_x, num_y, TRUE, TRUE);
778 setup_vertical_scrollbar_area(pCityDlg->pPanel->pScroll,
779 pWindow->area.x + adj_size(185),
780 pWindow->area.y + adj_size(45),
781 adj_size(150), TRUE);
785 /**************************************************************************
786 free city present/supported units panel list.
787 **************************************************************************/
788 void free_city_units_lists(void)
790 if (pCityDlg && pCityDlg->pPanel) {
791 del_group_of_widgets_from_gui_list(pCityDlg->pPanel->pBeginWidgetList,
792 pCityDlg->pPanel->pEndWidgetList);
793 FC_FREE(pCityDlg->pPanel->pScroll);
794 FC_FREE(pCityDlg->pPanel);
798 /**************************************************************************
799 change to present units panel.
800 **************************************************************************/
801 static int army_city_dlg_callback(struct widget *pButton)
803 if (Main.event.button.button == SDL_BUTTON_LEFT) {
804 if (pCityDlg->page != ARMY_PAGE) {
805 free_city_units_lists();
806 pCityDlg->page = ARMY_PAGE;
807 redraw_city_dialog(pCityDlg->pCity);
808 flush_dirty();
809 } else {
810 widget_redraw(pButton);
811 widget_flush(pButton);
814 return -1;
817 /**************************************************************************
818 change to supported units panel.
819 **************************************************************************/
820 static int supported_unit_city_dlg_callback(struct widget *pButton)
822 if (Main.event.button.button == SDL_BUTTON_LEFT) {
823 if (pCityDlg->page != SUPPORTED_UNITS_PAGE) {
824 free_city_units_lists();
825 pCityDlg->page = SUPPORTED_UNITS_PAGE;
826 redraw_city_dialog(pCityDlg->pCity);
827 flush_dirty();
828 } else {
829 widget_redraw(pButton);
830 widget_flush(pButton);
833 return -1;
836 /* ---------------------- */
838 /**************************************************************************
839 change to info panel.
840 **************************************************************************/
841 static int info_city_dlg_callback(struct widget *pButton)
843 if (Main.event.button.button == SDL_BUTTON_LEFT) {
844 if (pCityDlg->page != INFO_PAGE) {
845 free_city_units_lists();
846 pCityDlg->page = INFO_PAGE;
847 redraw_city_dialog(pCityDlg->pCity);
848 flush_dirty();
849 } else {
850 widget_redraw(pButton);
851 widget_flush(pButton);
854 return -1;
857 /* ---------------------- */
858 /**************************************************************************
859 change to happines panel.
860 **************************************************************************/
861 static int happy_city_dlg_callback(struct widget *pButton)
863 if (Main.event.button.button == SDL_BUTTON_LEFT) {
864 if (pCityDlg->page != HAPPINESS_PAGE) {
865 free_city_units_lists();
866 pCityDlg->page = HAPPINESS_PAGE;
867 redraw_city_dialog(pCityDlg->pCity);
868 flush_dirty();
869 } else {
870 widget_redraw(pButton);
871 widget_flush(pButton);
874 return -1;
877 /**************************************************************************
878 city option callback
879 **************************************************************************/
880 static int misc_panel_city_dlg_callback(struct widget *pWidget)
882 if (Main.event.button.button == SDL_BUTTON_LEFT) {
883 /* int new = pCityDlg->pCity->city_options & 0xff; */
884 bv_city_options new_options = pCityDlg->pCity->city_options;
886 switch (MAX_ID - pWidget->ID) {
887 case 0x10:
888 if (BV_ISSET(new_options, CITYO_DISBAND)) {
889 BV_CLR(new_options, CITYO_DISBAND);
890 } else {
891 BV_SET(new_options, CITYO_DISBAND);
893 break;
894 case 0x20:
895 if (BV_ISSET(new_options, CITYO_NEW_EINSTEIN)) {
896 BV_CLR(new_options, CITYO_NEW_EINSTEIN);
897 } else {
898 BV_SET(new_options, CITYO_NEW_EINSTEIN);
900 if (BV_ISSET(new_options, CITYO_NEW_TAXMAN)) {
901 BV_CLR(new_options, CITYO_NEW_TAXMAN);
902 } else {
903 BV_SET(new_options, CITYO_NEW_TAXMAN);
906 pWidget->theme2 = get_tax_surface(O_GOLD);
907 pWidget->ID = MAX_ID - 0x40;
908 widget_redraw(pWidget);
909 widget_flush(pWidget);
910 break;
911 case 0x40:
912 BV_CLR(new_options, CITYO_NEW_EINSTEIN);
913 BV_CLR(new_options, CITYO_NEW_TAXMAN);
914 pWidget->theme2 = get_tax_surface(O_LUXURY);
915 pWidget->ID = MAX_ID - 0x60;
916 widget_redraw(pWidget);
917 widget_flush(pWidget);
918 break;
919 case 0x60:
920 if (BV_ISSET(new_options, CITYO_NEW_EINSTEIN)) {
921 BV_CLR(new_options, CITYO_NEW_EINSTEIN);
922 } else {
923 BV_SET(new_options, CITYO_NEW_EINSTEIN);
926 pWidget->theme2 = get_tax_surface(O_SCIENCE);
927 pWidget->ID = MAX_ID - 0x20;
928 widget_redraw(pWidget);
929 widget_flush(pWidget);
930 break;
933 dsend_packet_city_options_req(&client.conn, pCityDlg->pCity->id, new_options);
935 return -1;
938 /**************************************************************************
939 Create city options widgets.
940 **************************************************************************/
941 static void create_city_options_widget_list(struct city *pCity)
943 struct widget *pBuf, *pWindow = pCityDlg->pEndCityWidgetList;
944 SDL_Surface *pSurf;
945 utf8_str *pstr;
946 char cBuf[80];
948 fc_snprintf(cBuf, sizeof(cBuf),
949 _("Disband if build\nsettler at size 1"));
950 pstr = create_utf8_from_char(cBuf, adj_font(10));
951 pstr->style |= TTF_STYLE_BOLD;
952 pstr->fgcol = *get_theme_color(COLOR_THEME_CHECKBOX_LABEL_TEXT);
954 pBuf =
955 create_textcheckbox(pWindow->dst, BV_ISSET(pCity->city_options, CITYO_DISBAND), pstr,
956 WF_RESTORE_BACKGROUND);
957 set_wstate(pBuf, FC_WS_NORMAL);
958 pBuf->action = misc_panel_city_dlg_callback;
959 add_to_gui_list(MAX_ID - 0x10, pBuf);
960 pBuf->size.x = pWindow->area.x + adj_size(7);
961 pBuf->size.y = pWindow->area.y + adj_size(45);
963 /* ----- */
965 pCityDlg->pPanel = fc_calloc(1, sizeof(struct ADVANCED_DLG));
966 pCityDlg->pPanel->pEndWidgetList = pBuf;
968 /* ----- */
970 fc_snprintf(cBuf, sizeof(cBuf), "%s:", _("New citizens are"));
971 pstr = create_utf8_from_char(cBuf, adj_font(11));
972 pstr->style |= SF_CENTER;
974 if (BV_ISSET(pCity->city_options, CITYO_NEW_EINSTEIN)) {
975 pSurf = get_tax_surface(O_SCIENCE);
976 pBuf = create_icon_button(pSurf, pWindow->dst, pstr, WF_ICON_CENTER_RIGHT | WF_FREE_THEME2);
977 add_to_gui_list(MAX_ID - 0x20, pBuf);
978 } else {
979 if (BV_ISSET(pCity->city_options, CITYO_NEW_TAXMAN)) {
980 pSurf = get_tax_surface(O_GOLD);
981 pBuf = create_icon_button(pSurf, pWindow->dst,
982 pstr, WF_ICON_CENTER_RIGHT | WF_FREE_THEME2);
983 add_to_gui_list(MAX_ID - 0x40, pBuf);
984 } else {
985 pSurf = get_tax_surface(O_LUXURY);
986 pBuf = create_icon_button(pSurf, pWindow->dst,
987 pstr, WF_ICON_CENTER_RIGHT | WF_FREE_THEME2);
988 add_to_gui_list(MAX_ID - 0x60, pBuf);
992 pBuf->size.w = adj_size(177);
993 pBuf->action = misc_panel_city_dlg_callback;
994 set_wstate(pBuf, FC_WS_NORMAL);
996 pBuf->size.x = pBuf->next->size.x;
997 pBuf->size.y = pBuf->next->size.y + pBuf->next->size.h + adj_size(5);
998 pCityDlg->pPanel->pBeginWidgetList = pBuf;
1001 /**************************************************************************
1002 change to city options panel.
1003 **************************************************************************/
1004 static int options_city_dlg_callback(struct widget *pButton)
1006 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1007 if (pCityDlg->page != MISC_PAGE) {
1008 free_city_units_lists();
1009 pCityDlg->page = MISC_PAGE;
1010 redraw_city_dialog(pCityDlg->pCity);
1011 flush_dirty();
1012 } else {
1013 widget_redraw(pButton);
1014 widget_flush(pButton);
1017 return -1;
1020 /* ======================================================================= */
1022 /**************************************************************************
1023 User interacted with Citizen Governor button.
1024 **************************************************************************/
1025 static int cma_city_dlg_callback(struct widget *pButton)
1027 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1028 disable_city_dlg_widgets();
1029 popup_city_cma_dialog(pCityDlg->pCity);
1031 return -1;
1034 /**************************************************************************
1035 Exit city dialog.
1036 **************************************************************************/
1037 static int exit_city_dlg_callback(struct widget *pButton)
1039 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1040 popdown_city_dialog(pCityDlg->pCity);
1042 return -1;
1045 /* ======================================================================= */
1046 /* ======================== Buy Production Dlg. ========================== */
1047 /* ======================================================================= */
1049 /**************************************************************************
1050 popdown buy productions dlg.
1051 **************************************************************************/
1052 static int cancel_buy_prod_city_dlg_callback(struct widget *pButton)
1054 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1055 popdown_hurry_production_dialog();
1057 if (pCityDlg) {
1058 /* enable city dlg */
1059 enable_city_dlg_widgets();
1062 return -1;
1065 /**************************************************************************
1066 buy productions.
1067 **************************************************************************/
1068 static int ok_buy_prod_city_dlg_callback(struct widget *pButton)
1070 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1071 struct city *pCity = pButton->data.city; /* Save it. */
1073 popdown_hurry_production_dialog();
1074 city_buy_production(pCity);
1076 if (pCityDlg) {
1077 /* enable city dlg */
1078 enable_city_dlg_widgets();
1080 /* disable buy button */
1081 set_wstate(pCityDlg->pBuy_Button, FC_WS_DISABLED);
1082 widget_redraw(pCityDlg->pBuy_Button);
1083 widget_mark_dirty(pCityDlg->pBuy_Button);
1084 flush_dirty();
1087 return -1;
1090 /**************************************************************************
1091 popup buy productions dlg.
1092 **************************************************************************/
1093 static int buy_prod_city_dlg_callback(struct widget *pButton)
1095 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1096 widget_redraw(pButton);
1097 widget_flush(pButton);
1098 disable_city_dlg_widgets();
1099 popup_hurry_production_dialog(pCityDlg->pCity, pButton->dst->surface);
1101 return -1;
1104 /**************************************************************************
1105 popup buy productions dlg.
1106 **************************************************************************/
1107 static void popdown_hurry_production_dialog(void)
1109 if (pHurry_Prod_Dlg) {
1110 popdown_window_group_dialog(pHurry_Prod_Dlg->pBeginWidgetList,
1111 pHurry_Prod_Dlg->pEndWidgetList);
1112 FC_FREE(pHurry_Prod_Dlg);
1113 flush_dirty();
1117 /**************************************************************************
1118 main hurry productions dlg. callback
1119 **************************************************************************/
1120 static int hurry_production_window_callback(struct widget *pWindow)
1122 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1123 move_window_group(pHurry_Prod_Dlg->pBeginWidgetList, pWindow);
1125 return -1;
1128 /**************************************************************************
1129 popup buy productions dlg.
1130 **************************************************************************/
1131 void popup_hurry_production_dialog(struct city *pCity, SDL_Surface *pDest)
1133 char tBuf[512], cBuf[512];
1134 struct widget *pBuf = NULL, *pWindow;
1135 utf8_str *pstr;
1136 SDL_Surface *pText;
1137 SDL_Rect dst;
1138 int window_x = 0, window_y = 0;
1139 SDL_Rect area;
1140 const char *name = city_production_name_translation(pCity);
1141 int value = city_production_buy_gold_cost(pCity);
1143 if (pHurry_Prod_Dlg) {
1144 return;
1147 fc_snprintf(tBuf, ARRAY_SIZE(tBuf), PL_("Treasury contains %d gold.",
1148 "Treasury contains %d gold.",
1149 client_player()->economic.gold),
1150 client_player()->economic.gold);
1152 pHurry_Prod_Dlg = fc_calloc(1, sizeof(struct SMALL_DLG));
1154 if (city_can_buy(pCity)) {
1155 if (value <= client_player()->economic.gold) {
1156 fc_snprintf(cBuf, sizeof(cBuf),
1157 /* TRANS: Last %s is pre-pluralised "Treasury contains %d gold." */
1158 PL_("Buy %s for %d gold?\n%s",
1159 "Buy %s for %d gold?\n%s", value),
1160 name, value, tBuf);
1161 } else {
1162 fc_snprintf(cBuf, sizeof(cBuf),
1163 /* TRANS: Last %s is pre-pluralised "Treasury contains %d gold." */
1164 PL_("%s costs %d gold.\n%s",
1165 "%s costs %d gold.\n%s", value),
1166 name, value, tBuf);
1168 } else {
1169 if (pCity->did_buy) {
1170 fc_snprintf(cBuf, sizeof(cBuf),
1171 _("Sorry, you have already bought here in this turn."));
1172 } else {
1173 fc_snprintf(cBuf, sizeof(cBuf),
1174 _("Sorry, you can't buy here in this turn."));
1178 pstr = create_utf8_from_char(_("Buy it?"), adj_font(12));
1179 pstr->style |= TTF_STYLE_BOLD;
1180 pWindow = create_window_skeleton(NULL, pstr, 0);
1181 pWindow->action = hurry_production_window_callback;
1182 set_wstate(pWindow, FC_WS_NORMAL);
1183 add_to_gui_list(ID_WINDOW, pWindow);
1185 pHurry_Prod_Dlg->pEndWidgetList = pWindow;
1187 area = pWindow->area;
1189 area.h += 1;
1191 /* ============================================================= */
1193 /* label */
1194 pstr = create_utf8_from_char(cBuf, adj_font(10));
1195 pstr->style |= (TTF_STYLE_BOLD|SF_CENTER);
1196 pstr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_BUY);
1198 pText = create_text_surf_from_utf8(pstr);
1199 FREEUTF8STR(pstr);
1200 area.w = MAX(area.w , pText->w);
1201 area.h += pText->h + adj_size(5);
1203 pBuf = create_themeicon_button_from_chars(current_theme->CANCEL_Icon,
1204 pWindow->dst, _("No"), adj_font(12), 0);
1206 pBuf->action = cancel_buy_prod_city_dlg_callback;
1207 set_wstate(pBuf, FC_WS_NORMAL);
1208 pBuf->key = SDLK_ESCAPE;
1209 area.h += pBuf->size.h;
1211 add_to_gui_list(ID_BUTTON, pBuf);
1213 if (city_can_buy(pCity) && (value <= client.conn.playing->economic.gold)) {
1214 pBuf = create_themeicon_button_from_chars(current_theme->OK_Icon, pWindow->dst,
1215 _("Yes"), adj_font(12), 0);
1217 pBuf->action = ok_buy_prod_city_dlg_callback;
1218 set_wstate(pBuf, FC_WS_NORMAL);
1219 pBuf->data.city = pCity;
1220 pBuf->key = SDLK_RETURN;
1221 add_to_gui_list(ID_BUTTON, pBuf);
1222 pBuf->size.w = MAX(pBuf->next->size.w, pBuf->size.w);
1223 pBuf->next->size.w = pBuf->size.w;
1224 area.w = MAX(area.w , 2 * pBuf->size.w + adj_size(20));
1227 pHurry_Prod_Dlg->pBeginWidgetList = pBuf;
1229 /* setup window size and start position */
1230 area.w += adj_size(10);
1231 area.h += adj_size(5);
1233 resize_window(pWindow, NULL, get_theme_color(COLOR_THEME_BACKGROUND),
1234 (pWindow->size.w - pWindow->area.w) + area.w,
1235 (pWindow->size.h - pWindow->area.h) + area.h);
1237 area = pWindow->area;
1239 pBuf = pWindow->prev;
1241 if (city_dialog_is_open(pCity)) {
1242 window_x = pCityDlg->pBuy_Button->size.x;
1243 window_y = pCityDlg->pBuy_Button->size.y - pWindow->size.h;
1244 } else {
1245 if (is_city_report_open()) {
1246 fc_assert(selected_widget != NULL);
1247 if (selected_widget->size.x + tileset_tile_width(tileset) + pWindow->size.w > main_window_width()) {
1248 window_x = selected_widget->size.x - pWindow->size.w;
1249 } else {
1250 window_x = selected_widget->size.x + tileset_tile_width(tileset);
1253 window_y = selected_widget->size.y + (selected_widget->size.h - pWindow->size.h) / 2;
1254 if (window_y + pWindow->size.h > main_window_height()) {
1255 window_y = main_window_height() - pWindow->size.h - 1;
1256 } else {
1257 if (window_y < 0) {
1258 window_y = 0;
1261 } else {
1262 put_window_near_map_tile(pWindow, pWindow->size.w, pWindow->size.h, pCity->tile);
1266 widget_set_position(pWindow, window_x, window_y);
1268 /* setup rest of widgets */
1269 /* label */
1270 dst.x = area.x + (area.w - pText->w) / 2;
1271 dst.y = area.y + 1;
1272 alphablit(pText, NULL, pWindow->theme, &dst, 255);
1273 dst.y += pText->h + adj_size(5);
1274 FREESURFACE(pText);
1276 /* no */
1277 pBuf = pWindow->prev;
1278 pBuf->size.y = dst.y;
1280 if (city_can_buy(pCity) && value <= client.conn.playing->economic.gold) {
1281 /* yes */
1282 pBuf = pBuf->prev;
1283 pBuf->size.x = area.x + (area.w - (2 * pBuf->size.w + adj_size(20))) / 2;
1284 pBuf->size.y = dst.y;
1286 /* no */
1287 pBuf->next->size.x = pBuf->size.x + pBuf->size.w + adj_size(20);
1288 } else {
1289 /* no */
1290 pBuf->size.x = area.x + area.w - pBuf->size.w - adj_size(10);
1292 /* ================================================== */
1293 /* redraw */
1294 redraw_group(pHurry_Prod_Dlg->pBeginWidgetList, pWindow, 0);
1295 widget_mark_dirty(pWindow);
1296 flush_dirty();
1299 /* =======================================================================*/
1300 /* ========================== CHANGE PRODUCTION ==========================*/
1301 /* =======================================================================*/
1303 /**************************************************************************
1304 Popup the change production dialog.
1305 **************************************************************************/
1306 static int change_prod_dlg_callback(struct widget *pButton)
1308 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1309 widget_redraw(pButton);
1310 widget_flush(pButton);
1312 disable_city_dlg_widgets();
1313 popup_worklist_editor(pCityDlg->pCity, NULL);
1315 return -1;
1318 /* =======================================================================*/
1319 /* =========================== SELL IMPROVMENTS ==========================*/
1320 /* =======================================================================*/
1322 /**************************************************************************
1323 Popdown Sell Imprv. Dlg. and exit without sell.
1324 **************************************************************************/
1325 static int sell_imprvm_dlg_cancel_callback(struct widget *pCancel_Button)
1327 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1328 popdown_window_group_dialog(pCityDlg->pBeginCityMenuWidgetList,
1329 pCityDlg->pEndCityMenuWidgetList);
1330 pCityDlg->pEndCityMenuWidgetList = NULL;
1331 enable_city_dlg_widgets();
1332 redraw_city_dialog(pCityDlg->pCity);
1333 flush_dirty();
1335 return -1;
1338 /**************************************************************************
1339 Popdown Sell Imprv. Dlg. and exit with sell.
1340 **************************************************************************/
1341 static int sell_imprvm_dlg_ok_callback(struct widget *pOK_Button)
1343 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1344 struct widget *pTmp = (struct widget *)pOK_Button->data.ptr;
1346 city_sell_improvement(pCityDlg->pCity, MAX_ID - 3000 - pTmp->ID);
1348 /* popdown, we don't redraw and flush becouse this is make by redraw city dlg.
1349 when response from server come */
1350 popdown_window_group_dialog(pCityDlg->pBeginCityMenuWidgetList,
1351 pCityDlg->pEndCityMenuWidgetList);
1353 pCityDlg->pEndCityMenuWidgetList = NULL;
1355 /* del imprv from widget list */
1356 del_widget_from_vertical_scroll_widget_list(pCityDlg->pImprv, pTmp);
1358 enable_city_dlg_widgets();
1360 if (pCityDlg->pImprv->pEndWidgetList) {
1361 set_group_state(pCityDlg->pImprv->pBeginActiveWidgetList,
1362 pCityDlg->pImprv->pEndActiveWidgetList, FC_WS_DISABLED);
1365 redraw_city_dialog(pCityDlg->pCity);
1366 flush_dirty();
1368 return -1;
1371 /**************************************************************************
1372 Popup Sell Imprvm. Dlg.
1373 **************************************************************************/
1374 static int sell_imprvm_dlg_callback(struct widget *pImpr)
1376 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1377 utf8_str *pstr = NULL;
1378 struct widget *pLabel = NULL;
1379 struct widget *pWindow = NULL;
1380 struct widget *pCancel_Button = NULL;
1381 struct widget *pOK_Button = NULL;
1382 char cBuf[80];
1383 int id;
1384 SDL_Rect area;
1385 int price;
1387 unselect_widget_action();
1388 disable_city_dlg_widgets();
1390 pstr = create_utf8_from_char(_("Sell it?"), adj_font(12));
1391 pstr->style |= TTF_STYLE_BOLD;
1392 pWindow = create_window_skeleton(NULL, pstr, 0);
1393 /*pWindow->action = move_sell_imprvm_dlg_callback; */
1394 /*set_wstate( pWindow, FC_WS_NORMAL ); */
1395 add_to_gui_list(ID_WINDOW, pWindow);
1396 pCityDlg->pEndCityMenuWidgetList = pWindow;
1398 area = pWindow->area;
1400 /* create text label */
1401 id = MAX_ID - 3000 - pImpr->ID;
1403 price = impr_sell_gold(improvement_by_number(id));
1404 fc_snprintf(cBuf, sizeof(cBuf), PL_("Sell %s for %d gold?",
1405 "Sell %s for %d gold?", price),
1406 city_improvement_name_translation(pCityDlg->pCity, improvement_by_number(id)),
1407 price);
1408 pstr = create_utf8_from_char(cBuf, adj_font(10));
1409 pstr->style |= (TTF_STYLE_BOLD|SF_CENTER);
1410 pstr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_SELL);
1411 pLabel = create_iconlabel(NULL, pWindow->dst, pstr, 0);
1412 add_to_gui_list(ID_LABEL, pLabel);
1414 /* create cancel button */
1415 pCancel_Button =
1416 create_themeicon_button_from_chars(current_theme->Small_CANCEL_Icon,
1417 pWindow->dst, _("Cancel"), adj_font(10), 0);
1418 pCancel_Button->action = sell_imprvm_dlg_cancel_callback;
1419 pCancel_Button->key = SDLK_ESCAPE;
1420 set_wstate(pCancel_Button, FC_WS_NORMAL);
1421 add_to_gui_list(ID_BUTTON, pCancel_Button);
1423 /* create ok button */
1424 pOK_Button = create_themeicon_button_from_chars(current_theme->Small_OK_Icon,
1425 pWindow->dst, _("Sell"),
1426 adj_font(10), 0);
1427 pOK_Button->data.ptr = (void *)pImpr;
1428 pOK_Button->size.w = pCancel_Button->size.w;
1429 pOK_Button->action = sell_imprvm_dlg_ok_callback;
1430 pOK_Button->key = SDLK_RETURN;
1431 set_wstate(pOK_Button, FC_WS_NORMAL);
1432 add_to_gui_list(ID_BUTTON, pOK_Button);
1434 pCityDlg->pBeginCityMenuWidgetList = pOK_Button;
1436 /* correct sizes */
1437 if ((pOK_Button->size.w + pCancel_Button->size.w + adj_size(30)) >
1438 pLabel->size.w + adj_size(20)) {
1439 area.w = MAX(area.w, pOK_Button->size.w + pCancel_Button->size.w + adj_size(30));
1440 } else {
1441 area.w = MAX(area.w, pLabel->size.w + adj_size(20));
1444 area.h = MAX(area.h, pOK_Button->size.h + pLabel->size.h + adj_size(25));
1446 /* create window background */
1447 resize_window(pWindow, NULL, get_theme_color(COLOR_THEME_BACKGROUND),
1448 (pWindow->size.w - pWindow->area.w) + area.w,
1449 (pWindow->size.h - pWindow->area.h) + area.h);
1451 area = pWindow->area;
1453 /* set start positions */
1454 widget_set_position(pWindow,
1455 (main_window_width() - pWindow->size.w) / 2,
1456 (main_window_height() - pWindow->size.h) / 2 + adj_size(10));
1458 pOK_Button->size.x = area.x + adj_size(10);
1459 pOK_Button->size.y = area.y + area.h - pOK_Button->size.h - adj_size(10);
1461 pCancel_Button->size.y = pOK_Button->size.y;
1462 pCancel_Button->size.x = area.x + area.w - pCancel_Button->size.w - adj_size(10);
1464 pLabel->size.x = area.x;
1465 pLabel->size.y = area.y + adj_size(4);
1466 pLabel->size.w = area.w;
1468 /* redraw */
1469 redraw_group(pCityDlg->pBeginCityMenuWidgetList,
1470 pCityDlg->pEndCityMenuWidgetList, 0);
1472 widget_mark_dirty(pWindow);
1473 flush_dirty();
1475 return -1;
1477 /* ====================================================================== */
1479 /**************************************************************************
1480 Enable city dialog widgets that can be enabled.
1481 **************************************************************************/
1482 void enable_city_dlg_widgets(void)
1484 if (pCityDlg) {
1485 set_group_state(pCityDlg->pBeginCityWidgetList,
1486 pCityDlg->pEndCityWidgetList->prev, FC_WS_NORMAL);
1488 if (pCityDlg->pImprv->pEndActiveWidgetList) {
1489 if (pCityDlg->pImprv->pScroll) {
1490 set_wstate(pCityDlg->pImprv->pScroll->pScrollBar, FC_WS_NORMAL); /* vscroll */
1491 set_wstate(pCityDlg->pImprv->pScroll->pUp_Left_Button, FC_WS_NORMAL); /* up */
1492 set_wstate(pCityDlg->pImprv->pScroll->pDown_Right_Button, FC_WS_NORMAL); /* down */
1495 /* There is common function test_player_sell_building_now(),
1496 * but we are not using it here, since we want to use set_group_state()
1497 * when possible */
1498 if (pCityDlg->pCity->did_sell
1499 || pCityDlg->pCity->owner != client.conn.playing) {
1500 set_group_state(pCityDlg->pImprv->pBeginActiveWidgetList,
1501 pCityDlg->pImprv->pEndActiveWidgetList, FC_WS_DISABLED);
1502 } else {
1503 struct widget *pTmpWidget = pCityDlg->pImprv->pEndActiveWidgetList;
1505 while (TRUE) {
1506 struct impr_type *pimpr = improvement_by_number(MAX_ID - 3000 -
1507 pTmpWidget->ID);
1509 if (!can_city_sell_building(pCityDlg->pCity, pimpr)) {
1510 set_wstate(pTmpWidget, FC_WS_DISABLED);
1511 } else {
1512 set_wstate(pTmpWidget, FC_WS_NORMAL);
1515 if (pTmpWidget == pCityDlg->pImprv->pBeginActiveWidgetList) {
1516 break;
1519 pTmpWidget = pTmpWidget->prev;
1521 } /* while */
1525 if (!city_can_buy(pCityDlg->pCity) && pCityDlg->pBuy_Button) {
1526 set_wstate(pCityDlg->pBuy_Button, FC_WS_DISABLED);
1529 if (pCityDlg->pPanel) {
1530 set_group_state(pCityDlg->pPanel->pBeginWidgetList,
1531 pCityDlg->pPanel->pEndWidgetList, FC_WS_NORMAL);
1534 if (cma_is_city_under_agent(pCityDlg->pCity, NULL)) {
1535 set_wstate(pCityDlg->pResource_Map, FC_WS_DISABLED);
1538 pCityDlg->lock = FALSE;
1542 /**************************************************************************
1543 Disable all city dialog widgets
1544 **************************************************************************/
1545 static void disable_city_dlg_widgets(void)
1547 if (pCityDlg->pPanel) {
1548 set_group_state(pCityDlg->pPanel->pBeginWidgetList,
1549 pCityDlg->pPanel->pEndWidgetList, FC_WS_DISABLED);
1553 if (pCityDlg->pImprv->pEndWidgetList) {
1554 set_group_state(pCityDlg->pImprv->pBeginWidgetList,
1555 pCityDlg->pImprv->pEndWidgetList, FC_WS_DISABLED);
1558 set_group_state(pCityDlg->pBeginCityWidgetList,
1559 pCityDlg->pEndCityWidgetList->prev, FC_WS_DISABLED);
1560 pCityDlg->lock = TRUE;
1563 /* ======================================================================== */
1565 /**************************************************************************
1566 Return scaled city map.
1567 **************************************************************************/
1568 SDL_Surface *get_scaled_city_map(struct city *pCity)
1570 SDL_Surface *pBuf = create_city_map(pCity);
1572 city_map_zoom = ((pBuf->w * 159 > pBuf->h * 249) ?
1573 (float)adj_size(249) / pBuf->w
1574 : (float)adj_size(159) / pBuf->h);
1576 return zoomSurface(pBuf, city_map_zoom, city_map_zoom, 1);
1579 /**************************************************************************
1580 city resource map: event callback
1581 **************************************************************************/
1582 static int resource_map_city_dlg_callback(struct widget *pMap)
1584 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1585 int col, row;
1587 if (canvas_to_city_pos(&col, &row,
1588 city_map_radius_sq_get(pCityDlg->pCity),
1589 1/city_map_zoom * (Main.event.motion.x - pMap->dst->dest_rect.x
1590 - pMap->size.x),
1591 1/city_map_zoom * (Main.event.motion.y - pMap->dst->dest_rect.y
1592 - pMap->size.y))) {
1594 city_toggle_worker(pCityDlg->pCity, col, row);
1597 return -1;
1600 /* ====================================================================== */
1602 /************************************************************************
1603 Helper for switch_city_callback.
1604 *************************************************************************/
1605 static int city_comp_by_turn_founded(const void *a, const void *b)
1607 struct city *pCity1 = *((struct city **) a);
1608 struct city *pCity2 = *((struct city **) b);
1610 return pCity1->turn_founded - pCity2->turn_founded;
1613 /**************************************************************************
1614 Callback for next/prev city button
1615 **************************************************************************/
1616 static int next_prev_city_dlg_callback(struct widget *pButton)
1618 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1619 struct city **array;
1620 int i, dir, non_open_size;
1621 int size = city_list_size(client.conn.playing->cities);
1623 fc_assert_ret_val(size >= 1, -1);
1624 fc_assert_ret_val(city_owner(pCityDlg->pCity)
1625 == client.conn.playing, -1);
1627 if (size == 1) {
1628 return -1;
1631 /* dir = 1 will advance to the city, dir = -1 will get previous */
1632 if (pButton->ID == ID_CITY_DLG_NEXT_BUTTON) {
1633 dir = 1;
1634 } else {
1635 if (pButton->ID == ID_CITY_DLG_PREV_BUTTON) {
1636 dir = -1;
1637 } else {
1638 /* Always fails. */
1639 fc_assert_ret_val(pButton->ID == ID_CITY_DLG_NEXT_BUTTON
1640 || pButton->ID != ID_CITY_DLG_PREV_BUTTON, -1);
1641 dir = 1;
1645 array = fc_calloc(1, size * sizeof(struct city *));
1647 non_open_size = 0;
1648 for (i = 0; i < size; i++) {
1649 array[non_open_size++] = city_list_get(client.conn.playing->cities, i);
1652 fc_assert_ret_val(non_open_size > 0, -1);
1654 if (non_open_size == 1) {
1655 FC_FREE(array);
1656 return -1;
1659 qsort(array, non_open_size, sizeof(struct city *),
1660 city_comp_by_turn_founded);
1662 for (i = 0; i < non_open_size; i++) {
1663 if (pCityDlg->pCity == array[i]) {
1664 break;
1668 fc_assert_ret_val(i < non_open_size, -1);
1669 pCityDlg->pCity = array[(i + dir + non_open_size) % non_open_size];
1670 FC_FREE(array);
1672 /* free panel widgets */
1673 free_city_units_lists();
1674 /* refresh resource map */
1675 FREESURFACE(pCityDlg->pResource_Map->theme);
1676 pCityDlg->pResource_Map->theme = get_scaled_city_map(pCityDlg->pCity);
1677 rebuild_imprm_list(pCityDlg->pCity);
1679 /* redraw */
1680 redraw_city_dialog(pCityDlg->pCity);
1681 flush_dirty();
1683 return -1;
1686 /**************************************************************************
1687 Rename city name:
1688 **************************************************************************/
1689 static int new_name_city_dlg_callback(struct widget *pEdit)
1691 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1692 if (pEdit->string_utf8->text != NULL) {
1693 if (strcmp(pEdit->string_utf8->text, city_name_get(pCityDlg->pCity))) {
1694 SDL_Client_Flags |= CF_CHANGED_CITY_NAME;
1695 city_rename(pCityDlg->pCity, pEdit->string_utf8->text);
1697 } else {
1698 /* empty input -> restore previous content */
1699 copy_chars_to_utf8_str(pEdit->string_utf8, city_name_get(pCityDlg->pCity));
1700 widget_redraw(pEdit);
1701 widget_mark_dirty(pEdit);
1702 flush_dirty();
1706 return -1;
1709 /* ======================================================================= */
1710 /* ======================== Redrawing City Dlg. ========================== */
1711 /* ======================================================================= */
1713 /**************************************************************************
1714 Refresh (update) the city names for the dialog
1715 **************************************************************************/
1716 static void refresh_city_names(struct city *pcity)
1718 if (pCityDlg->pCity_Name_Edit) {
1719 char name[MAX_LEN_NAME];
1721 fc_snprintf(name, MAX_LEN_NAME, "%s", pCityDlg->pCity_Name_Edit->string_utf8->text);
1722 if ((strcmp(city_name_get(pcity), name) != 0)
1723 || (SDL_Client_Flags & CF_CHANGED_CITY_NAME)) {
1724 copy_chars_to_utf8_str(pCityDlg->pCity_Name_Edit->string_utf8, city_name_get(pcity));
1725 rebuild_citydlg_title_str(pCityDlg->pEndCityWidgetList, pcity);
1726 SDL_Client_Flags &= ~CF_CHANGED_CITY_NAME;
1731 /**************************************************************************
1732 Redraw city option panel
1733 207 = max panel width
1734 **************************************************************************/
1735 static void redraw_misc_city_dialog(struct widget *pCityWindow,
1736 struct city *pCity)
1738 char cBuf[60];
1739 utf8_str *pstr;
1740 SDL_Surface *pSurf;
1741 SDL_Rect dest;
1743 fc_snprintf(cBuf, sizeof(cBuf), _("City options"));
1745 pstr = create_utf8_from_char(cBuf, adj_font(10));
1746 pstr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_PANEL);
1747 pstr->style |= TTF_STYLE_BOLD;
1749 pSurf = create_text_surf_from_utf8(pstr);
1751 dest.x = pCityWindow->area.x + adj_size(2) + (adj_size(192) - pSurf->w) / 2;
1752 dest.y = pCityWindow->area.y + adj_size(4) + current_theme->INFO_Icon->h;
1754 alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest, 255);
1756 FREESURFACE(pSurf);
1757 FREEUTF8STR(pstr);
1759 if (!pCityDlg->pPanel) {
1760 create_city_options_widget_list(pCity);
1762 redraw_group(pCityDlg->pPanel->pBeginWidgetList,
1763 pCityDlg->pPanel->pEndWidgetList, 0);
1766 /**************************************************************************
1767 Redraw supported unit panel
1768 207 = max panel width
1769 **************************************************************************/
1770 static void redraw_supported_units_city_dialog(struct widget *pCityWindow,
1771 struct city *pCity)
1773 char cBuf[60];
1774 utf8_str *pstr;
1775 SDL_Surface *pSurf;
1776 SDL_Rect dest;
1777 struct unit_list *pList;
1778 int size;
1780 if (city_owner(pCityDlg->pCity) != client.conn.playing) {
1781 pList = (pCityDlg->pCity->client.info_units_supported);
1782 } else {
1783 pList = (pCityDlg->pCity->units_supported);
1786 size = unit_list_size(pList);
1788 fc_snprintf(cBuf, sizeof(cBuf), _("Supported units: %d"), size);
1790 pstr = create_utf8_from_char(cBuf, adj_font(10));
1791 pstr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_PANEL);
1792 pstr->style |= TTF_STYLE_BOLD;
1794 pSurf = create_text_surf_from_utf8(pstr);
1796 dest.x = pCityWindow->area.x + adj_size(2) + (adj_size(192) - pSurf->w) / 2;
1797 dest.y = pCityWindow->area.y + + adj_size(4) + current_theme->INFO_Icon->h;
1799 alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest, 255);
1801 FREESURFACE(pSurf);
1802 FREEUTF8STR(pstr);
1804 if (pCityDlg->pPanel) {
1805 if (size > 0) {
1806 redraw_group(pCityDlg->pPanel->pBeginWidgetList,
1807 pCityDlg->pPanel->pEndWidgetList, 0);
1808 } else {
1809 del_group_of_widgets_from_gui_list(pCityDlg->pPanel->pBeginWidgetList,
1810 pCityDlg->pPanel->pEndWidgetList);
1811 FC_FREE(pCityDlg->pPanel->pScroll);
1812 FC_FREE(pCityDlg->pPanel);
1814 } else {
1815 if (size > 0) {
1816 create_present_supported_units_widget_list(pList);
1817 redraw_group(pCityDlg->pPanel->pBeginWidgetList,
1818 pCityDlg->pPanel->pEndWidgetList, 0);
1823 /**************************************************************************
1824 Redraw garrison panel
1825 207 = max panel width
1826 **************************************************************************/
1827 static void redraw_army_city_dialog(struct widget *pCityWindow,
1828 struct city *pCity)
1830 char cBuf[60];
1831 utf8_str *pstr;
1832 SDL_Surface *pSurf;
1833 SDL_Rect dest;
1834 struct unit_list *pList;
1835 int size;
1837 if (city_owner(pCityDlg->pCity) != client.conn.playing) {
1838 pList = pCityDlg->pCity->client.info_units_present;
1839 } else {
1840 pList = pCityDlg->pCity->tile->units;
1843 size = unit_list_size(pList);
1845 fc_snprintf(cBuf, sizeof(cBuf), _("Present units: %d"), size);
1847 pstr = create_utf8_from_char(cBuf, adj_font(10));
1848 pstr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_PANEL);
1849 pstr->style |= TTF_STYLE_BOLD;
1851 pSurf = create_text_surf_from_utf8(pstr);
1853 dest.x = pCityWindow->area.x + adj_size(2) + (adj_size(192) - pSurf->w) / 2;
1854 dest.y = pCityWindow->area.y + adj_size(4) + current_theme->INFO_Icon->h;
1856 alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest, 255);
1858 FREESURFACE(pSurf);
1859 FREEUTF8STR(pstr);
1861 if (pCityDlg->pPanel) {
1862 if (size) {
1863 redraw_group(pCityDlg->pPanel->pBeginWidgetList,
1864 pCityDlg->pPanel->pEndWidgetList, 0);
1865 } else {
1866 del_group_of_widgets_from_gui_list(pCityDlg->pPanel->pBeginWidgetList,
1867 pCityDlg->pPanel->pEndWidgetList);
1868 FC_FREE(pCityDlg->pPanel->pScroll);
1869 FC_FREE(pCityDlg->pPanel);
1871 } else {
1872 if (size) {
1873 create_present_supported_units_widget_list(pList);
1874 redraw_group(pCityDlg->pPanel->pBeginWidgetList,
1875 pCityDlg->pPanel->pEndWidgetList, 0);
1880 /**************************************************************************
1881 Redraw Info panel
1882 207 = max panel width
1883 **************************************************************************/
1884 static void redraw_info_city_dialog(struct widget *pCityWindow,
1885 struct city *pCity)
1887 char cBuf[30];
1888 struct city *pTradeCity = NULL;
1889 int step, i, xx;
1890 utf8_str *pstr = NULL;
1891 SDL_Surface *pSurf = NULL;
1892 SDL_Rect dest;
1894 fc_snprintf(cBuf, sizeof(cBuf), _("City info"));
1895 pstr = create_utf8_from_char(cBuf, adj_font(10));
1896 pstr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_PANEL);
1897 pstr->style |= TTF_STYLE_BOLD;
1899 pSurf = create_text_surf_from_utf8(pstr);
1901 dest.x = pCityWindow->area.x + adj_size(2) + (adj_size(192) - pSurf->w) / 2;
1902 dest.y = pCityWindow->area.y + adj_size(4) + current_theme->INFO_Icon->h;
1904 alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest, 255);
1906 dest.x = pCityWindow->size.x + adj_size(10);
1907 dest.y += pSurf->h + 1;
1909 FREESURFACE(pSurf);
1911 change_ptsize_utf8(pstr, adj_font(11));
1912 pstr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_INFOPANEL);
1914 if (pCity->pollution) {
1915 fc_snprintf(cBuf, sizeof(cBuf), _("Pollution: %d"),
1916 pCity->pollution);
1918 copy_chars_to_utf8_str(pstr, cBuf);
1920 pSurf = create_text_surf_from_utf8(pstr);
1922 alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest, 255);
1924 dest.y += pSurf->h + adj_size(3);
1926 FREESURFACE(pSurf);
1928 if (((pIcons->pPollution->w + 1) * pCity->pollution) > adj_size(187)) {
1929 step = (adj_size(187) - pIcons->pPollution->w) / (pCity->pollution - 1);
1930 } else {
1931 step = pIcons->pPollution->w + 1;
1934 for (i = 0; i < pCity->pollution; i++) {
1935 alphablit(pIcons->pPollution, NULL, pCityWindow->dst->surface, &dest, 255);
1936 dest.x += step;
1939 dest.x = pCityWindow->size.x + adj_size(10);
1940 dest.y += pIcons->pPollution->h + adj_size(30);
1942 } else {
1943 fc_snprintf(cBuf, sizeof(cBuf), _("Pollution: none"));
1945 copy_chars_to_utf8_str(pstr, cBuf);
1947 pSurf = create_text_surf_from_utf8(pstr);
1949 alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest, 255);
1951 dest.y += pSurf->h + adj_size(3);
1953 FREESURFACE(pSurf);
1956 fc_snprintf(cBuf, sizeof(cBuf), _("Trade routes: "));
1958 copy_chars_to_utf8_str(pstr, cBuf);
1960 pSurf = create_text_surf_from_utf8(pstr);
1962 alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest, 255);
1964 xx = dest.x + pSurf->w;
1965 dest.y += pSurf->h + adj_size(3);
1967 FREESURFACE(pSurf);
1969 step = 0;
1970 dest.x = pCityWindow->size.x + adj_size(10);
1972 for (i = 0; i < MAX_TRADE_ROUTES; i++) {
1973 if (pCity->trade[i]) {
1974 step += pCity->trade_value[i];
1976 if ((pTradeCity = game_city_by_number(pCity->trade[i]))) {
1977 fc_snprintf(cBuf, sizeof(cBuf), "%s: +%d", city_name_get(pTradeCity),
1978 pCity->trade_value[i]);
1979 } else {
1980 fc_snprintf(cBuf, sizeof(cBuf), "%s: +%d", _("Unknown"),
1981 pCity->trade_value[i]);
1984 copy_chars_to_utf8_str(pstr, cBuf);
1986 pSurf = create_text_surf_from_utf8(pstr);
1988 alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest, 255);
1990 /* blit trade icon */
1991 dest.x += pSurf->w + adj_size(3);
1992 dest.y += adj_size(4);
1993 alphablit(pIcons->pTrade, NULL, pCityWindow->dst->surface, &dest, 255);
1994 dest.x = pCityWindow->size.x + adj_size(10);
1995 dest.y -= adj_size(4);
1997 dest.y += pSurf->h;
1999 FREESURFACE(pSurf);
2003 if (step) {
2004 fc_snprintf(cBuf, sizeof(cBuf), _("Trade: +%d"), step);
2006 copy_chars_to_utf8_str(pstr, cBuf);
2007 pSurf = create_text_surf_from_utf8(pstr);
2008 alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest, 255);
2010 dest.x += pSurf->w + adj_size(3);
2011 dest.y += adj_size(4);
2012 alphablit(pIcons->pTrade, NULL, pCityWindow->dst->surface, &dest, 255);
2014 FREESURFACE(pSurf);
2015 } else {
2016 fc_snprintf(cBuf, sizeof(cBuf), _("none"));
2018 copy_chars_to_utf8_str(pstr, cBuf);
2020 pSurf = create_text_surf_from_utf8(pstr);
2022 dest.x = xx;
2023 dest.y -= pSurf->h + adj_size(3);
2024 alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest, 255);
2026 FREESURFACE(pSurf);
2029 FREEUTF8STR(pstr);
2032 /**************************************************************************
2033 Redraw (refresh/update) the happiness info for the dialog
2034 207 - max panel width
2035 180 - max citizens icons area width
2036 **************************************************************************/
2037 static void redraw_happiness_city_dialog(const struct widget *pCityWindow,
2038 struct city *pCity)
2040 char cBuf[30];
2041 int step, i, j, count;
2042 SDL_Surface *pTmp;
2043 utf8_str *pstr = NULL;
2044 SDL_Surface *pSurf = NULL;
2045 SDL_Rect dest = {0, 0, 0, 0};
2046 struct effect_list *sources = effect_list_new();
2048 fc_snprintf(cBuf, sizeof(cBuf), _("Happiness"));
2050 pstr = create_utf8_from_char(cBuf, adj_font(10));
2051 pstr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_PANEL);
2052 pstr->style |= TTF_STYLE_BOLD;
2054 pSurf = create_text_surf_from_utf8(pstr);
2056 dest.x = pCityWindow->area.x + adj_size(2) + (adj_size(192) - pSurf->w) / 2;
2057 dest.y = pCityWindow->area.y + adj_size(4) + current_theme->INFO_Icon->h;
2058 alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest, 255);
2060 dest.x = pCityWindow->size.x + adj_size(10);
2061 dest.y += pSurf->h + 1;
2063 FREESURFACE(pSurf);
2064 FREEUTF8STR(pstr);
2066 count = (pCity->feel[CITIZEN_HAPPY][FEELING_FINAL] + pCity->feel[CITIZEN_CONTENT][FEELING_FINAL]
2067 + pCity->feel[CITIZEN_UNHAPPY][FEELING_FINAL] + pCity->feel[CITIZEN_ANGRY][FEELING_FINAL]
2068 + city_specialists(pCity));
2070 if (count * pIcons->pMale_Happy->w > adj_size(166)) {
2071 step = (adj_size(166) - pIcons->pMale_Happy->w) / (count - 1);
2072 } else {
2073 step = pIcons->pMale_Happy->w;
2076 for (j = 0; j < FEELING_LAST; j++) {
2077 if (j == 0 || pCity->feel[CITIZEN_HAPPY][j - 1] != pCity->feel[CITIZEN_HAPPY][j]
2078 || pCity->feel[CITIZEN_CONTENT][j - 1] != pCity->feel[CITIZEN_CONTENT][j]
2079 || pCity->feel[CITIZEN_UNHAPPY][j - 1] != pCity->feel[CITIZEN_UNHAPPY][j]
2080 || pCity->feel[CITIZEN_ANGRY][j - 1] != pCity->feel[CITIZEN_ANGRY][j]) {
2081 int spe, spe_max;
2083 if (j != 0) {
2084 create_line(pCityWindow->dst->surface,
2085 dest.x, dest.y, dest.x + adj_size(176), dest.y,
2086 get_theme_color(COLOR_THEME_CITYDLG_FRAME));
2087 dest.y += adj_size(5);
2090 if (pCity->feel[CITIZEN_HAPPY][j]) {
2091 pSurf = pIcons->pMale_Happy;
2092 for (i = 0; i < pCity->feel[CITIZEN_HAPPY][j]; i++) {
2093 alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest, 255);
2094 dest.x += step;
2095 if (pSurf == pIcons->pMale_Happy) {
2096 pSurf = pIcons->pFemale_Happy;
2097 } else {
2098 pSurf = pIcons->pMale_Happy;
2103 if (pCity->feel[CITIZEN_CONTENT][j]) {
2104 pSurf = pIcons->pMale_Content;
2105 for (i = 0; i < pCity->feel[CITIZEN_CONTENT][j]; i++) {
2106 alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest, 255);
2107 dest.x += step;
2108 if (pSurf == pIcons->pMale_Content) {
2109 pSurf = pIcons->pFemale_Content;
2110 } else {
2111 pSurf = pIcons->pMale_Content;
2116 if (pCity->feel[CITIZEN_UNHAPPY][j]) {
2117 pSurf = pIcons->pMale_Unhappy;
2118 for (i = 0; i < pCity->feel[CITIZEN_UNHAPPY][j]; i++) {
2119 alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest, 255);
2120 dest.x += step;
2121 if (pSurf == pIcons->pMale_Unhappy) {
2122 pSurf = pIcons->pFemale_Unhappy;
2123 } else {
2124 pSurf = pIcons->pMale_Unhappy;
2129 if (pCity->feel[CITIZEN_ANGRY][j]) {
2130 pSurf = pIcons->pMale_Angry;
2131 for (i = 0; i < pCity->feel[CITIZEN_ANGRY][j]; i++) {
2132 alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest, 255);
2133 dest.x += step;
2134 if (pSurf == pIcons->pMale_Angry) {
2135 pSurf = pIcons->pFemale_Angry;
2136 } else {
2137 pSurf = pIcons->pMale_Angry;
2142 spe_max = specialist_count();
2143 for (spe = 0 ; spe < spe_max; spe++) {
2144 if (pCity->specialists[spe]) {
2145 for (i = 0; i < pCity->specialists[spe]; i++) {
2146 alphablit(pIcons->specialists[spe], NULL, pCityWindow->dst->surface, &dest, 255);
2147 dest.x += step;
2152 if (j == 1) { /* luxury effect */
2153 dest.x =
2154 pCityWindow->size.x + adj_size(212) - pIcons->pBIG_Luxury->w - adj_size(2);
2155 count = dest.y;
2156 dest.y += (pIcons->pMale_Happy->h -
2157 pIcons->pBIG_Luxury->h) / 2;
2158 alphablit(pIcons->pBIG_Luxury, NULL, pCityWindow->dst->surface, &dest, 255);
2159 dest.y = count;
2162 if (j == 2) { /* improvements effects */
2163 pSurf = NULL;
2164 count = 0;
2166 get_city_bonus_effects(sources, pCity, NULL, EFT_MAKE_CONTENT);
2168 effect_list_iterate(sources, psource) {
2170 pTmp = get_building_surface(get_building_for_effect(psource->type));
2171 pTmp = zoomSurface(pTmp, DEFAULT_ZOOM * ((float)18 / pTmp->w), DEFAULT_ZOOM * ((float)18 / pTmp->w), 1);
2173 count += (pTmp->h + 1);
2175 if (!pSurf) {
2176 pSurf = pTmp;
2177 } else {
2178 FREESURFACE(pTmp);
2181 } effect_list_iterate_end;
2183 dest.x = pCityWindow->size.x + adj_size(187) - pSurf->w - adj_size(2);
2184 i = dest.y;
2185 dest.y += (pIcons->pMale_Happy->h - count) / 2;
2187 FREESURFACE(pSurf);
2189 effect_list_iterate(sources, psource) {
2190 pTmp = get_building_surface(get_building_for_effect(psource->type));
2191 pTmp = zoomSurface(pTmp, DEFAULT_ZOOM * ((float)18 / pTmp->w), DEFAULT_ZOOM * ((float)18 / pTmp->w), 1);
2193 alphablit(pTmp, NULL, pCityWindow->dst->surface, &dest, 255);
2194 dest.y += (pTmp->h + 1);
2196 FREESURFACE(pTmp);
2197 } effect_list_iterate_end;
2199 effect_list_clear(sources);
2201 dest.y = i;
2203 /* TODO: check if code replacement above is correct */
2204 #if 0
2205 if (city_has_building(pCity, improvement_by_number(B_TEMPLE))) {
2206 pTmp1 =
2207 zoomSurface(GET_SURF(improvement_by_number(B_TEMPLE)->sprite),
2208 0.5, 0.5, 1);
2209 count += (pTmp1->h + 1);
2210 pSurf = pTmp1;
2211 } else {
2212 pTmp1 = NULL;
2215 if (city_has_building(pCity, improvement_by_number(B_COLOSSEUM))) {
2216 pTmp2 =
2217 zoomSurface(GET_SURF(improvement_by_number(B_COLOSSEUM)->sprite),
2218 0.5, 0.5, 1);
2219 count += (pTmp2->h + 1);
2220 if (!pSurf) {
2221 pSurf = pTmp2;
2223 } else {
2224 pTmp2 = NULL;
2227 if (city_has_building(pCity, improvement_by_number(B_CATHEDRAL))
2228 || city_affected_by_wonder(pCity, B_MICHELANGELO)) {
2229 pTmp3 =
2230 zoomSurface(GET_SURF(improvement_by_number(B_CATHEDRAL)->sprite),
2231 0.5, 0.5, 1);
2232 count += (pTmp3->h + 1);
2233 if (!pSurf) {
2234 pSurf = pTmp3;
2236 } else {
2237 pTmp3 = NULL;
2241 dest.x = pCityWindow->size.x + adj_size(212) - pSurf->w - adj_size(2);
2242 i = dest.y;
2243 dest.y += (pIcons->pMale_Happy->h - count) / 2;
2246 if (pTmp1) { /* Temple */
2247 alphablit(pTmp1, NULL, pCityWindow->dst->surface, &dest, 255);
2248 dest.y += (pTmp1->h + 1);
2251 if (pTmp2) { /* Colosseum */
2252 alphablit(pTmp2, NULL, pCityWindow->dst->surface, &dest, 255);
2253 dest.y += (pTmp2->h + 1);
2256 if (pTmp3) { /* Cathedral */
2257 alphablit(pTmp3, NULL, pCityWindow->dst->surface, &dest, 255);
2258 /*dest.y += (pTmp3->h + 1); */
2262 FREESURFACE(pTmp1);
2263 FREESURFACE(pTmp2);
2264 FREESURFACE(pTmp3);
2265 dest.y = i;
2266 #endif /* 0 */
2269 if (j == 3) { /* police effect */
2270 dest.x = pCityWindow->size.x + adj_size(187) - pIcons->pPolice->w - adj_size(5);
2271 i = dest.y;
2272 dest.y +=
2273 (pIcons->pMale_Happy->h - pIcons->pPolice->h) / 2;
2274 alphablit(pIcons->pPolice, NULL, pCityWindow->dst->surface, &dest, 255);
2275 dest.y = i;
2278 if (j == 4) { /* wonders effect */
2279 count = 0;
2281 get_city_bonus_effects(sources, pCity, NULL, EFT_MAKE_HAPPY);
2282 effect_list_iterate(sources, psource) {
2284 pTmp = get_building_surface(get_building_for_effect(psource->type));
2285 pTmp = zoomSurface(pTmp, DEFAULT_ZOOM * ((float)18 / pTmp->w), DEFAULT_ZOOM * ((float)18 / pTmp->w), 1);
2287 count += (pTmp->h + 1);
2289 if (!pSurf) {
2290 pSurf = pTmp;
2291 } else {
2292 FREESURFACE(pTmp);
2295 } effect_list_iterate_end;
2297 effect_list_clear(sources);
2299 get_city_bonus_effects(sources, pCity, NULL, EFT_FORCE_CONTENT);
2301 effect_list_iterate(sources, psource) {
2303 pTmp = get_building_surface(get_building_for_effect(psource->type));
2304 pTmp = zoomSurface(pTmp, DEFAULT_ZOOM * ((float)18 / pTmp->w), DEFAULT_ZOOM * ((float)18 / pTmp->w), 1);
2305 count += (pTmp->h + 1);
2307 if (!pSurf) {
2308 pSurf = pTmp;
2309 } else {
2310 FREESURFACE(pTmp);
2313 } effect_list_iterate_end;
2315 effect_list_clear(sources);
2317 get_city_bonus_effects(sources, pCity, NULL, EFT_NO_UNHAPPY);
2319 effect_list_iterate(sources, psource) {
2320 pTmp = get_building_surface(get_building_for_effect(psource->type));
2321 pTmp = zoomSurface(pTmp, DEFAULT_ZOOM * ((float)18 / pTmp->w), DEFAULT_ZOOM * ((float)18 / pTmp->w), 1);
2323 count += (pTmp->h + 1);
2325 FREESURFACE(pTmp);
2326 } effect_list_iterate_end;
2328 effect_list_clear(sources);
2330 dest.x = pCityWindow->size.x + adj_size(187) - pSurf->w - adj_size(2);
2331 i = dest.y;
2332 dest.y += (pIcons->pMale_Happy->h - count) / 2;
2334 FREESURFACE(pSurf);
2336 get_city_bonus_effects(sources, pCity, NULL, EFT_MAKE_HAPPY);
2338 effect_list_iterate(sources, psource) {
2339 pTmp = get_building_surface(get_building_for_effect(psource->type));
2340 pTmp = zoomSurface(pTmp, DEFAULT_ZOOM * ((float)18 / pTmp->w), DEFAULT_ZOOM * ((float)18 / pTmp->w), 1);
2342 alphablit(pTmp, NULL, pCityWindow->dst->surface, &dest, 255);
2343 dest.y += (pTmp->h + 1);
2345 FREESURFACE(pTmp);
2346 } effect_list_iterate_end;
2347 effect_list_clear(sources);
2349 get_city_bonus_effects(sources, pCity, NULL, EFT_FORCE_CONTENT);
2351 effect_list_iterate(sources, psource) {
2352 pTmp = get_building_surface(get_building_for_effect(psource->type));
2353 pTmp = zoomSurface(pTmp, DEFAULT_ZOOM * ((float)18 / pTmp->w), DEFAULT_ZOOM * ((float)18 / pTmp->w), 1);
2355 alphablit(pTmp, NULL, pCityWindow->dst->surface, &dest, 255);
2356 dest.y += (pTmp->h + 1);
2358 FREESURFACE(pTmp);
2359 } effect_list_iterate_end;
2360 effect_list_clear(sources);
2362 get_city_bonus_effects(sources, pCity, NULL, EFT_NO_UNHAPPY);
2364 effect_list_iterate(sources, psource) {
2365 pTmp = get_building_surface(get_building_for_effect(psource->type));
2366 pTmp = zoomSurface(pTmp, DEFAULT_ZOOM * ((float)18 / pTmp->w), DEFAULT_ZOOM * ((float)18 / pTmp->w), 1);
2368 alphablit(pTmp, NULL, pCityWindow->dst->surface, &dest, 255);
2369 dest.y += (pTmp->h + 1);
2371 FREESURFACE(pTmp);
2372 } effect_list_iterate_end;
2373 effect_list_clear(sources);
2375 dest.y = i;
2377 /* TODO: check if code replacement above is correct */
2378 #if 0
2379 if (city_affected_by_wonder(pCity, B_CURE)) {
2380 pTmp1 =
2381 zoomSurface(GET_SURF(improvement_by_number(B_CURE)->sprite),
2382 0.5, 0.5, 1);
2383 count += (pTmp1->h + 1);
2384 pSurf = pTmp1;
2385 } else {
2386 pTmp1 = NULL;
2389 if (city_affected_by_wonder(pCity, B_SHAKESPEARE)) {
2390 pTmp2 = zoomSurface(
2391 GET_SURF(improvement_by_number(B_SHAKESPEARE)->sprite),
2392 0.5, 0.5, 1);
2393 count += (pTmp2->h + 1);
2394 if (!pSurf) {
2395 pSurf = pTmp2;
2397 } else {
2398 pTmp2 = NULL;
2401 if (city_affected_by_wonder(pCity, B_BACH)) {
2402 pTmp3 =
2403 zoomSurface(GET_SURF(improvement_by_number(B_BACH)->sprite),
2404 0.5, 0.5, 1);
2405 count += (pTmp3->h + 1);
2406 if (!pSurf) {
2407 pSurf = pTmp3;
2409 } else {
2410 pTmp3 = NULL;
2413 if (city_affected_by_wonder(pCity, B_HANGING)) {
2414 pTmp4 =
2415 zoomSurface(GET_SURF(improvement_by_number(B_HANGING)->sprite),
2416 0.5, 0.5, 1);
2417 count += (pTmp4->h + 1);
2418 if (!pSurf) {
2419 pSurf = pTmp4;
2421 } else {
2422 pTmp4 = NULL;
2425 dest.x = pCityWindow->size.x + adj_size(187) - pSurf->w - adj_size(2);
2426 i = dest.y;
2427 dest.y += (pIcons->pMale_Happy->h - count) / 2;
2429 if (pTmp1) { /* Cure of Cancer */
2430 alphablit(pTmp1, NULL, pCityWindow->dst->surface, &dest, 255);
2431 dest.y += (pTmp1->h + 1);
2434 if (pTmp2) { /* Shakespeare Theater */
2435 alphablit(pTmp2, NULL, pCityWindow->dst->surface, &dest, 255);
2436 dest.y += (pTmp2->h + 1);
2439 if (pTmp3) { /* J. S. Bach ... */
2440 alphablit(pTmp3, NULL, pCityWindow->dst->surface, &dest, 255);
2441 dest.y += (pTmp3->h + 1);
2444 if (pTmp4) { /* Hanging Gardens */
2445 alphablit(pTmp4, NULL, pCityWindow->dst->surface, &dest, 255);
2446 /*dest.y += (pTmp4->h + 1); */
2449 FREESURFACE(pTmp1);
2450 FREESURFACE(pTmp2);
2451 FREESURFACE(pTmp3);
2452 FREESURFACE(pTmp4);
2453 dest.y = i;
2454 #endif /* 0 */
2457 dest.x = pCityWindow->size.x + adj_size(10);
2458 dest.y += pIcons->pMale_Happy->h + adj_size(5);
2463 effect_list_destroy(sources);
2466 /**************************************************************************
2467 Redraw the dialog.
2468 **************************************************************************/
2469 static void redraw_city_dialog(struct city *pCity)
2471 char cBuf[40];
2472 int i, step, count, limit;
2473 int cost = 0;
2474 SDL_Rect dest;
2475 struct widget *pWindow = pCityDlg->pEndCityWidgetList;
2476 SDL_Surface *pBuf = NULL, *pBuf2 = NULL;
2477 utf8_str *pstr = NULL;
2478 int spe, spe_max;
2480 refresh_city_names(pCity);
2482 if ((city_unhappy(pCity) || city_celebrating(pCity) || city_happy(pCity)
2483 || cma_is_city_under_agent(pCity, NULL))
2484 ^ ((SDL_Client_Flags & CF_CITY_STATUS_SPECIAL) == CF_CITY_STATUS_SPECIAL)) {
2485 /* city status was changed : NORMAL <-> DISORDER, HAPPY, CELEBR. */
2487 SDL_Client_Flags ^= CF_CITY_STATUS_SPECIAL;
2489 #if 0
2490 /* upd. resource map */
2491 FREESURFACE(pCityDlg->pResource_Map->theme);
2492 pCityDlg->pResource_Map->theme = get_scaled_city_map(pCity);
2493 #endif
2495 /* upd. window title */
2496 rebuild_citydlg_title_str(pCityDlg->pEndCityWidgetList, pCity);
2499 /* update resource map */
2500 FREESURFACE(pCityDlg->pResource_Map->theme);
2501 pCityDlg->pResource_Map->theme = get_scaled_city_map(pCity);
2503 /* redraw city dlg */
2504 redraw_group(pCityDlg->pBeginCityWidgetList,
2505 pCityDlg->pEndCityWidgetList, 0);
2507 /* ================================================================= */
2508 fc_snprintf(cBuf, sizeof(cBuf), _("City map"));
2510 pstr = create_utf8_from_char(cBuf, adj_font(10));
2511 pstr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_GOLD);
2512 pstr->style |= TTF_STYLE_BOLD;
2514 pBuf = create_text_surf_from_utf8(pstr);
2516 dest.x = pWindow->size.x + adj_size(196) + (adj_size(132) - pBuf->w) / 2;
2517 dest.y = pWindow->size.y + adj_size(49) + (adj_size(13) - pBuf->h) / 2;
2519 alphablit(pBuf, NULL, pWindow->dst->surface, &dest, 255);
2521 FREESURFACE(pBuf);
2523 fc_snprintf(cBuf, sizeof(cBuf), _("Citizens"));
2525 copy_chars_to_utf8_str(pstr, cBuf);
2526 pstr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_LUX);
2528 pBuf = create_text_surf_from_utf8(pstr);
2530 dest.x = pWindow->size.x + adj_size(344) + (adj_size(146) - pBuf->w) / 2;
2531 dest.y = pWindow->size.y + adj_size(47) + (adj_size(13) - pBuf->h) / 2;
2533 alphablit(pBuf, NULL, pWindow->dst->surface, &dest, 255);
2535 FREESURFACE(pBuf);
2537 fc_snprintf(cBuf, sizeof(cBuf), _("City improvements"));
2539 copy_chars_to_utf8_str(pstr, cBuf);
2540 pstr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_GOLD);
2542 pBuf = create_text_surf_from_utf8(pstr);
2544 dest.x = pWindow->size.x + adj_size(504) + (adj_size(132) - pBuf->w) / 2;
2545 dest.y = pWindow->size.y + adj_size(49) + (adj_size(13) - pBuf->h) / 2;
2547 alphablit(pBuf, NULL, pWindow->dst->surface, &dest, 255);
2549 FREESURFACE(pBuf);
2550 /* ================================================================= */
2551 /* food label */
2552 fc_snprintf(cBuf, sizeof(cBuf), _("Food: %d per turn"),
2553 pCity->prod[O_FOOD]);
2555 copy_chars_to_utf8_str(pstr, cBuf);
2557 pstr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_FOODPERTURN);
2559 pBuf = create_text_surf_from_utf8(pstr);
2561 dest.x = pWindow->size.x + adj_size(200);
2562 dest.y = pWindow->size.y + adj_size(228) + (adj_size(16) - pBuf->h) / 2;
2564 alphablit(pBuf, NULL, pWindow->dst->surface, &dest, 255);
2566 FREESURFACE(pBuf);
2568 /* draw food income */
2569 dest.y = pWindow->size.y + adj_size(246) + (adj_size(16) - pIcons->pBIG_Food->h) / 2;
2570 dest.x = pWindow->size.x + adj_size(203);
2572 if (pCity->surplus[O_FOOD] >= 0) {
2573 count = pCity->prod[O_FOOD] - pCity->surplus[O_FOOD];
2574 } else {
2575 count = pCity->prod[O_FOOD];
2578 if (((pIcons->pBIG_Food->w + 1) * count) > adj_size(200)) {
2579 step = (adj_size(200) - pIcons->pBIG_Food->w) / (count - 1);
2580 } else {
2581 step = pIcons->pBIG_Food->w + 1;
2584 for (i = 0; i < count; i++) {
2585 alphablit(pIcons->pBIG_Food, NULL, pWindow->dst->surface, &dest, 255);
2586 dest.x += step;
2589 fc_snprintf(cBuf, sizeof(cBuf), Q_("?food:Surplus: %d"),
2590 pCity->surplus[O_FOOD]);
2592 copy_chars_to_utf8_str(pstr, cBuf);
2593 pstr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_FOOD_SURPLUS);
2595 pBuf = create_text_surf_from_utf8(pstr);
2597 dest.x = pWindow->size.x + adj_size(440) - pBuf->w;
2598 dest.y = pWindow->size.y + adj_size(228) + (adj_size(16) - pBuf->h) / 2;
2600 alphablit(pBuf, NULL, pWindow->dst->surface, &dest, 255);
2602 FREESURFACE(pBuf);
2604 /* draw surplus of food */
2605 if (pCity->surplus[O_FOOD]) {
2606 if (pCity->surplus[O_FOOD] > 0) {
2607 count = pCity->surplus[O_FOOD];
2608 pBuf = pIcons->pBIG_Food;
2609 } else {
2610 count = -1 * pCity->surplus[O_FOOD];
2611 pBuf = pIcons->pBIG_Food_Corr;
2614 dest.x = pWindow->size.x + adj_size(423);
2615 dest.y = pWindow->size.y + adj_size(246) + (adj_size(16) - pBuf->h) / 2;
2617 if (count > 2) {
2618 if (count < 18) {
2619 step = (adj_size(30) - pBuf->w) / (count - 1);
2620 } else {
2621 step = 1;
2622 count = 17;
2624 } else {
2625 step = pBuf->w + 1;
2628 for (i = 0; i < count; i++) {
2629 alphablit(pBuf, NULL, pWindow->dst->surface, &dest, 255);
2630 dest.x -= step;
2633 /* ================================================================= */
2634 /* productions label */
2635 fc_snprintf(cBuf, sizeof(cBuf), _("Production: %d (%d) per turn"),
2636 pCity->surplus[O_SHIELD],
2637 pCity->prod[O_SHIELD] + pCity->waste[O_SHIELD]);
2639 copy_chars_to_utf8_str(pstr, cBuf);
2640 pstr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_PROD);
2642 pBuf = create_text_surf_from_utf8(pstr);
2644 dest.x = pWindow->size.x + adj_size(200);
2645 dest.y = pWindow->size.y + adj_size(263) + (adj_size(15) - pBuf->h) / 2;
2647 alphablit(pBuf, NULL, pWindow->dst->surface, &dest, 255);
2649 FREESURFACE(pBuf);
2651 /* draw productions schields */
2652 if (pCity->surplus[O_SHIELD]) {
2654 if (pCity->surplus[O_SHIELD] > 0) {
2655 count = pCity->surplus[O_SHIELD] + pCity->waste[O_SHIELD];
2656 pBuf = pIcons->pBIG_Shield;
2657 } else {
2658 count = -1 * pCity->surplus[O_SHIELD];
2659 pBuf = pIcons->pBIG_Shield_Corr;
2662 dest.y = pWindow->size.y + adj_size(281) + (adj_size(16) - pBuf->h) / 2;
2663 dest.x = pWindow->size.x + adj_size(203);
2665 if ((pBuf->w * count) > adj_size(200)) {
2666 step = (adj_size(200) - pBuf->w) / (count - 1);
2667 } else {
2668 step = pBuf->w;
2671 for (i = 0; i < count; i++) {
2672 alphablit(pBuf, NULL, pWindow->dst->surface, &dest, 255);
2673 dest.x += step;
2674 if (i > pCity->surplus[O_SHIELD]) {
2675 pBuf = pIcons->pBIG_Shield_Corr;
2680 /* support shields label */
2681 fc_snprintf(cBuf, sizeof(cBuf), Q_("?production:Support: %d"),
2682 pCity->prod[O_SHIELD] + pCity->waste[O_SHIELD] -
2683 pCity->surplus[O_SHIELD]);
2685 copy_chars_to_utf8_str(pstr, cBuf);
2686 pstr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_SUPPORT);
2688 pBuf = create_text_surf_from_utf8(pstr);
2690 dest.x = pWindow->size.x + adj_size(440) - pBuf->w;
2691 dest.y = pWindow->size.y + adj_size(263) + (adj_size(15) - pBuf->h) / 2;
2693 alphablit(pBuf, NULL, pWindow->dst->surface, &dest, 255);
2695 FREESURFACE(pBuf);
2697 /* draw support shields */
2698 if (pCity->prod[O_SHIELD] - pCity->surplus[O_SHIELD]) {
2699 dest.x = pWindow->size.x + adj_size(423);
2700 dest.y =
2701 pWindow->size.y + adj_size(281) + (adj_size(16) - pIcons->pBIG_Shield->h) / 2;
2703 if ((pIcons->pBIG_Shield->w + 1) * (pCity->prod[O_SHIELD] -
2704 pCity->surplus[O_SHIELD]) > adj_size(30)) {
2705 step =
2706 (adj_size(30) - pIcons->pBIG_Food->w) / (pCity->prod[O_SHIELD] -
2707 pCity->surplus[O_SHIELD] - 1);
2708 } else {
2709 step = pIcons->pBIG_Shield->w + 1;
2712 for (i = 0; i < (pCity->prod[O_SHIELD] - pCity->surplus[O_SHIELD]); i++) {
2713 alphablit(pIcons->pBIG_Shield, NULL, pWindow->dst->surface, &dest, 255);
2714 dest.x -= step;
2717 /* ================================================================= */
2719 /* trade label */
2720 fc_snprintf(cBuf, sizeof(cBuf), _("Trade: %d per turn"),
2721 pCity->surplus[O_TRADE]);
2723 copy_chars_to_utf8_str(pstr, cBuf);
2724 pstr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_TRADE);
2726 pBuf = create_text_surf_from_utf8(pstr);
2728 dest.x = pWindow->size.x + adj_size(200);
2729 dest.y = pWindow->size.y + adj_size(298) + (adj_size(15) - pBuf->h) / 2;
2731 alphablit(pBuf, NULL, pWindow->dst->surface, &dest, 255);
2733 FREESURFACE(pBuf);
2735 /* draw total (trade - corruption) */
2736 if (pCity->surplus[O_TRADE]) {
2737 dest.y =
2738 pWindow->size.y + adj_size(316) + (adj_size(16) - pIcons->pBIG_Trade->h) / 2;
2739 dest.x = pWindow->size.x + adj_size(203);
2741 if (((pIcons->pBIG_Trade->w + 1) * pCity->surplus[O_TRADE]) > adj_size(200)) {
2742 step = (adj_size(200) - pIcons->pBIG_Trade->w) / (pCity->surplus[O_TRADE] - 1);
2743 } else {
2744 step = pIcons->pBIG_Trade->w + 1;
2747 for (i = 0; i < pCity->surplus[O_TRADE]; i++) {
2748 alphablit(pIcons->pBIG_Trade, NULL, pWindow->dst->surface, &dest, 255);
2749 dest.x += step;
2753 /* corruption label */
2754 fc_snprintf(cBuf, sizeof(cBuf), _("Corruption: %d"),
2755 pCity->waste[O_TRADE]);
2757 copy_chars_to_utf8_str(pstr, cBuf);
2758 pstr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_CORRUPTION);
2760 pBuf = create_text_surf_from_utf8(pstr);
2762 dest.x = pWindow->size.x + adj_size(440) - pBuf->w;
2763 dest.y = pWindow->size.y + adj_size(298) + (adj_size(15) - pBuf->h) / 2;
2765 alphablit(pBuf, NULL, pWindow->dst->surface, &dest, 255);
2767 FREESURFACE(pBuf);
2769 /* draw corruption */
2770 if (pCity->waste[O_TRADE] > 0) {
2771 dest.x = pWindow->size.x + adj_size(423);
2772 dest.y =
2773 pWindow->size.y + adj_size(316) + (adj_size(16) - pIcons->pBIG_Trade->h) / 2;
2775 if (((pIcons->pBIG_Trade_Corr->w + 1) * pCity->waste[O_TRADE]) > adj_size(30)) {
2776 step =
2777 (adj_size(30) - pIcons->pBIG_Trade_Corr->w) / (pCity->waste[O_TRADE] - 1);
2778 } else {
2779 step = pIcons->pBIG_Trade_Corr->w + 1;
2782 for (i = 0; i < pCity->waste[O_TRADE]; i++) {
2783 alphablit(pIcons->pBIG_Trade_Corr, NULL, pWindow->dst->surface,
2784 &dest, 255);
2785 dest.x -= step;
2788 /* ================================================================= */
2789 /* gold label */
2790 fc_snprintf(cBuf, sizeof(cBuf), _("Gold: %d (%d) per turn"),
2791 pCity->surplus[O_GOLD], pCity->prod[O_GOLD]);
2793 copy_chars_to_utf8_str(pstr, cBuf);
2794 pstr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_GOLD);
2796 pBuf = create_text_surf_from_utf8(pstr);
2798 dest.x = pWindow->size.x + adj_size(200);
2799 dest.y = pWindow->size.y + adj_size(342) + (adj_size(15) - pBuf->h) / 2;
2801 alphablit(pBuf, NULL, pWindow->dst->surface, &dest, 255);
2803 FREESURFACE(pBuf);
2805 /* draw coins */
2806 count = pCity->surplus[O_GOLD];
2807 if (count) {
2809 if (count > 0) {
2810 pBuf = pIcons->pBIG_Coin;
2811 } else {
2812 count *= -1;
2813 pBuf = pIcons->pBIG_Coin_Corr;
2816 dest.y = pWindow->size.y + adj_size(359) + (adj_size(16) - pBuf->h) / 2;
2817 dest.x = pWindow->size.x + adj_size(203);
2819 if ((pBuf->w * count) > adj_size(110)) {
2820 step = (adj_size(110) - pBuf->w) / (count - 1);
2821 if (!step) {
2822 step = 1;
2823 count = 97;
2825 } else {
2826 step = pBuf->w;
2829 for (i = 0; i < count; i++) {
2830 alphablit(pBuf, NULL, pWindow->dst->surface, &dest, 255);
2831 dest.x += step;
2836 /* upkeep label */
2837 fc_snprintf(cBuf, sizeof(cBuf), _("Upkeep: %d"),
2838 pCity->prod[O_GOLD] - pCity->surplus[O_GOLD]);
2840 copy_chars_to_utf8_str(pstr, cBuf);
2841 pstr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_UPKEEP);
2843 pBuf = create_text_surf_from_utf8(pstr);
2845 dest.x = pWindow->size.x + adj_size(440) - pBuf->w;
2846 dest.y = pWindow->size.y + adj_size(342) + (adj_size(15) - pBuf->h) / 2;
2848 alphablit(pBuf, NULL, pWindow->dst->surface, &dest, 255);
2850 FREESURFACE(pBuf);
2852 /* draw upkeep */
2853 count = pCity->surplus[O_GOLD];
2854 if (pCity->prod[O_GOLD] - count) {
2856 dest.x = pWindow->size.x + adj_size(423);
2857 dest.y = pWindow->size.y + adj_size(359)
2858 + (adj_size(16) - pIcons->pBIG_Coin_UpKeep->h) / 2;
2860 if (((pIcons->pBIG_Coin_UpKeep->w + 1) *
2861 (pCity->prod[O_GOLD] - count)) > adj_size(110)) {
2862 step = (adj_size(110) - pIcons->pBIG_Coin_UpKeep->w) /
2863 (pCity->prod[O_GOLD] - count - 1);
2864 } else {
2865 step = pIcons->pBIG_Coin_UpKeep->w + 1;
2868 for (i = 0; i < (pCity->prod[O_GOLD] - count); i++) {
2869 alphablit(pIcons->pBIG_Coin_UpKeep, NULL, pWindow->dst->surface,
2870 &dest, 255);
2871 dest.x -= step;
2874 /* ================================================================= */
2875 /* science label */
2876 fc_snprintf(cBuf, sizeof(cBuf), _("Science: %d per turn"),
2877 pCity->prod[O_SCIENCE]);
2879 copy_chars_to_utf8_str(pstr, cBuf);
2880 pstr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_SCIENCE);
2882 pBuf = create_text_surf_from_utf8(pstr);
2884 dest.x = pWindow->size.x + adj_size(200);
2885 dest.y = pWindow->size.y + adj_size(376) + (adj_size(15) - pBuf->h) / 2;
2887 alphablit(pBuf, NULL, pWindow->dst->surface, &dest, 255);
2889 FREESURFACE(pBuf);
2891 /* draw colb */
2892 count = pCity->prod[O_SCIENCE];
2893 if (count) {
2895 dest.y =
2896 pWindow->size.y + adj_size(394) + (adj_size(16) - pIcons->pBIG_Colb->h) / 2;
2897 dest.x = pWindow->size.x + adj_size(203);
2899 if ((pIcons->pBIG_Colb->w * count) > adj_size(235)) {
2900 step = (adj_size(235) - pIcons->pBIG_Colb->w) / (count - 1);
2901 if (!step) {
2902 step = 1;
2903 count = 222;
2905 } else {
2906 step = pIcons->pBIG_Colb->w;
2909 for (i = 0; i < count; i++) {
2910 alphablit(pIcons->pBIG_Colb, NULL, pWindow->dst->surface, &dest, 255);
2911 dest.x += step;
2914 /* ================================================================= */
2915 /* luxury label */
2916 fc_snprintf(cBuf, sizeof(cBuf), _("Luxury: %d per turn"),
2917 pCity->prod[O_LUXURY]);
2919 copy_chars_to_utf8_str(pstr, cBuf);
2920 pstr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_LUX);
2922 pBuf = create_text_surf_from_utf8(pstr);
2924 dest.x = pWindow->size.x + adj_size(200);
2925 dest.y = pWindow->size.y + adj_size(412) + (adj_size(15) - pBuf->h) / 2;
2927 alphablit(pBuf, NULL, pWindow->dst->surface, &dest, 255);
2929 FREESURFACE(pBuf);
2931 /* draw luxury */
2932 if (pCity->prod[O_LUXURY]) {
2934 dest.y =
2935 pWindow->size.y + adj_size(429) + (adj_size(16) - pIcons->pBIG_Luxury->h) / 2;
2936 dest.x = pWindow->size.x + adj_size(203);
2938 if ((pIcons->pBIG_Luxury->w * pCity->prod[O_LUXURY]) > adj_size(235)) {
2939 step =
2940 (adj_size(235) - pIcons->pBIG_Luxury->w) / (pCity->prod[O_LUXURY] - 1);
2941 } else {
2942 step = pIcons->pBIG_Luxury->w;
2945 for (i = 0; i < pCity->prod[O_LUXURY]; i++) {
2946 alphablit(pIcons->pBIG_Luxury, NULL, pWindow->dst->surface, &dest, 255);
2947 dest.x += step;
2950 /* ================================================================= */
2951 /* turns to grow label */
2952 count = city_turns_to_grow(pCity);
2953 if (count == 0) {
2954 fc_snprintf(cBuf, sizeof(cBuf), _("City growth: blocked"));
2955 } else if (count == FC_INFINITY) {
2956 fc_snprintf(cBuf, sizeof(cBuf), _("City growth: never"));
2957 } else if (count < 0) {
2958 /* turns until famine */
2959 fc_snprintf(cBuf, sizeof(cBuf),
2960 _("City shrinks: %d %s"), abs(count),
2961 PL_("turn", "turns", abs(count)));
2962 } else {
2963 fc_snprintf(cBuf, sizeof(cBuf),
2964 _("City growth: %d %s"), count,
2965 PL_("turn", "turns", count));
2968 copy_chars_to_utf8_str(pstr, cBuf);
2970 pstr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_GROWTH);
2972 pBuf = create_text_surf_from_utf8(pstr);
2974 dest.x = pWindow->size.x + adj_size(445) + (adj_size(192) - pBuf->w) / 2;
2975 dest.y = pWindow->size.y + adj_size(227);
2977 alphablit(pBuf, NULL, pWindow->dst->surface, &dest, 255);
2979 FREESURFACE(pBuf);
2982 count = (city_granary_size(city_size_get(pCity))) / 10;
2984 if (count > 12) {
2985 step = (adj_size(168) - pIcons->pBIG_Food->h) / adj_size((11 + count - 12));
2986 i = (count - 1) * step + 14;
2987 count = 12;
2988 } else {
2989 step = pIcons->pBIG_Food->h;
2990 i = count * step;
2993 /* food stock */
2995 if (get_city_bonus(pCity, EFT_GROWTH_FOOD) > 0) {
2996 /* with granary */
2997 /* stocks label */
2998 copy_chars_to_utf8_str(pstr, _("Stock"));
2999 pBuf = create_text_surf_from_utf8(pstr);
3001 dest.x = pWindow->size.x + adj_size(461) + (adj_size(76) - pBuf->w) / 2;
3002 dest.y = pWindow->size.y + adj_size(258) - pBuf->h - 1;
3004 alphablit(pBuf, NULL, pWindow->dst->surface, &dest, 255);
3006 FREESURFACE(pBuf);
3008 /* granary label */
3009 copy_chars_to_utf8_str(pstr, _("Granary"));
3010 pBuf = create_text_surf_from_utf8(pstr);
3012 dest.x = pWindow->size.x + adj_size(549) + (adj_size(76) - pBuf->w) / 2;
3013 dest.y = pWindow->size.y + adj_size(258) - pBuf->h - 1;
3015 alphablit(pBuf, NULL, pWindow->dst->surface, &dest, 255);
3017 FREESURFACE(pBuf);
3019 /* draw bcgd granary */
3020 dest.x = pWindow->size.x + adj_size(462);
3021 dest.y = pWindow->size.y + adj_size(260);
3022 dest.w = 70 + 4;
3023 dest.h = i + 4;
3025 fill_rect_alpha(pWindow->dst->surface, &dest, get_theme_color(COLOR_THEME_CITYDLG_GRANARY));
3027 create_frame(pWindow->dst->surface,
3028 dest.x - 1, dest.y - 1, dest.w, dest.h,
3029 get_theme_color(COLOR_THEME_CITYDLG_FRAME));
3031 /* draw bcgd stocks*/
3032 dest.x = pWindow->size.x + adj_size(550);
3033 dest.y = pWindow->size.y + adj_size(260);
3035 fill_rect_alpha(pWindow->dst->surface, &dest, get_theme_color(COLOR_THEME_CITYDLG_STOCKS));
3037 create_frame(pWindow->dst->surface,
3038 dest.x - 1, dest.y - 1, dest.w, dest.h,
3039 get_theme_color(COLOR_THEME_CITYDLG_FRAME));
3041 /* draw stocks icons */
3042 cost = city_granary_size(city_size_get(pCity));
3043 if (pCity->food_stock + pCity->surplus[O_FOOD] > cost) {
3044 count = cost;
3045 } else {
3046 if(pCity->surplus[O_FOOD] < 0) {
3047 count = pCity->food_stock;
3048 } else {
3049 count = pCity->food_stock + pCity->surplus[O_FOOD];
3052 cost /= 2;
3054 if (pCity->surplus[O_FOOD] < 0) {
3055 limit = pCity->food_stock + pCity->surplus[O_FOOD];
3056 if (limit < 0) {
3057 limit = 0;
3059 } else {
3060 limit = 0xffff;
3063 dest.x += 2;
3064 dest.y += 2;
3065 i = 0;
3066 pBuf = pIcons->pBIG_Food;
3067 while (count && cost) {
3068 alphablit(pBuf, NULL, pWindow->dst->surface, &dest, 255);
3069 dest.x += pBuf->w;
3070 count--;
3071 cost--;
3072 i++;
3073 if (dest.x > pWindow->size.x + adj_size(620)) {
3074 dest.x = pWindow->size.x + adj_size(552);
3075 dest.y += step;
3077 if (i > limit - 1) {
3078 pBuf = pIcons->pBIG_Food_Corr;
3079 } else {
3080 if (i > pCity->food_stock - 1) {
3081 pBuf = pIcons->pBIG_Food_Surplus;
3085 /* draw granary icons */
3086 dest.x = pWindow->size.x + adj_size(462) + adj_size(2);
3087 dest.y = pWindow->size.y + adj_size(260) + adj_size(2);
3089 while (count) {
3090 alphablit(pBuf, NULL, pWindow->dst->surface, &dest, 255);
3091 dest.x += pBuf->w;
3092 count--;
3093 i++;
3094 if (dest.x > pWindow->size.x + adj_size(532)) {
3095 dest.x = pWindow->size.x + adj_size(464);
3096 dest.y += step;
3098 if (i > limit - 1) {
3099 pBuf = pIcons->pBIG_Food_Corr;
3100 } else {
3101 if (i > pCity->food_stock - 1) {
3102 pBuf = pIcons->pBIG_Food_Surplus;
3107 } else {
3108 /* without granary */
3109 /* stocks label */
3110 copy_chars_to_utf8_str(pstr, _("Stock"));
3111 pBuf = create_text_surf_from_utf8(pstr);
3113 dest.x = pWindow->size.x + adj_size(461) + (adj_size(144) - pBuf->w) / 2;
3114 dest.y = pWindow->size.y + adj_size(258) - pBuf->h - 1;
3116 alphablit(pBuf, NULL, pWindow->dst->surface, &dest, 255);
3117 FREESURFACE(pBuf);
3119 /* food stock */
3121 /* draw bcgd */
3122 dest.x = pWindow->size.x + adj_size(462);
3123 dest.y = pWindow->size.y + adj_size(260);
3124 dest.w = adj_size(144);
3125 dest.h = i + adj_size(4);
3127 fill_rect_alpha(pWindow->dst->surface, &dest,
3128 get_theme_color(COLOR_THEME_CITYDLG_FOODSTOCK));
3130 create_frame(pWindow->dst->surface,
3131 dest.x - 1, dest.y - 1, dest.w, dest.h,
3132 get_theme_color(COLOR_THEME_CITYDLG_FRAME));
3134 /* draw icons */
3135 cost = city_granary_size(city_size_get(pCity));
3136 if (pCity->food_stock + pCity->surplus[O_FOOD] > cost) {
3137 count = cost;
3138 } else {
3139 if (pCity->surplus[O_FOOD] < 0) {
3140 count = pCity->food_stock;
3141 } else {
3142 count = pCity->food_stock + pCity->surplus[O_FOOD];
3146 if (pCity->surplus[O_FOOD] < 0) {
3147 limit = pCity->food_stock + pCity->surplus[O_FOOD];
3148 if (limit < 0) {
3149 limit = 0;
3151 } else {
3152 limit = 0xffff;
3155 dest.x += adj_size(2);
3156 dest.y += adj_size(2);
3157 i = 0;
3158 pBuf = pIcons->pBIG_Food;
3159 while (count) {
3160 alphablit(pBuf, NULL, pWindow->dst->surface, &dest, 255);
3161 dest.x += pBuf->w;
3162 count--;
3163 i++;
3164 if (dest.x > pWindow->size.x + adj_size(602)) {
3165 dest.x = pWindow->size.x + adj_size(464);
3166 dest.y += step;
3168 if (i > limit - 1) {
3169 pBuf = pIcons->pBIG_Food_Corr;
3170 } else {
3171 if (i > pCity->food_stock - 1) {
3172 pBuf = pIcons->pBIG_Food_Surplus;
3177 /* ================================================================= */
3179 /* draw productions shields progress */
3180 if (VUT_UTYPE == pCity->production.kind) {
3181 struct unit_type *pUnitType = pCity->production.value.utype;
3182 cost = utype_build_shield_cost(pUnitType);
3183 count = cost / 10;
3185 copy_chars_to_utf8_str(pstr, utype_name_translation(pUnitType));
3186 pBuf = create_text_surf_from_utf8(pstr);
3188 pBuf2 = get_unittype_surface(pUnitType, direction8_invalid());
3189 pBuf2 = zoomSurface(pBuf2, DEFAULT_ZOOM * ((float)32 / pBuf2->h),
3190 DEFAULT_ZOOM * ((float)32 / pBuf2->h), 1);
3192 /* blit unit icon */
3193 dest.x = pWindow->size.x + adj_size(6) + (adj_size(185) - (pBuf->w + pBuf2->w + adj_size(5))) / 2;
3194 dest.y = pWindow->size.y + adj_size(233);
3196 alphablit(pBuf2, NULL, pWindow->dst->surface, &dest, 255);
3198 dest.y += (pBuf2->h - pBuf->h) / 2;
3199 dest.x += pBuf2->w + adj_size(5);
3201 } else {
3202 struct impr_type *pImprove = pCity->production.value.building;
3204 if (improvement_has_flag(pImprove, IF_GOLD)) {
3206 if (pCityDlg->pBuy_Button
3207 && get_wstate(pCityDlg->pBuy_Button) != FC_WS_DISABLED) {
3208 set_wstate(pCityDlg->pBuy_Button, FC_WS_DISABLED);
3209 widget_redraw(pCityDlg->pBuy_Button);
3212 /* You can't see capitalization progres */
3213 count = 0;
3215 } else {
3217 if (city_can_buy(pCity) && pCityDlg->pBuy_Button
3218 && (get_wstate(pCityDlg->pBuy_Button) == FC_WS_DISABLED)) {
3219 set_wstate(pCityDlg->pBuy_Button, FC_WS_NORMAL);
3220 widget_redraw(pCityDlg->pBuy_Button);
3223 cost = impr_build_shield_cost(pImprove);
3224 count = cost / 10;
3227 copy_chars_to_utf8_str(pstr, improvement_name_translation(pImprove));
3228 pBuf = create_text_surf_from_utf8(pstr);
3230 pBuf2 = get_building_surface(pCity->production.value.building);
3231 pBuf2 = zoomSurface(pBuf2, DEFAULT_ZOOM * ((float)32 / pBuf2->h), DEFAULT_ZOOM * ((float)32 / pBuf2->h), 1);
3233 /* blit impr icon */
3234 dest.x = pWindow->size.x + adj_size(6) + (adj_size(185) - (pBuf->w + pBuf2->w + adj_size(5))) / 2;
3235 dest.y = pWindow->size.y + adj_size(233);
3237 alphablit(pBuf2, NULL, pWindow->dst->surface, &dest, 255);
3239 dest.y += (pBuf2->h - pBuf->h) / 2;
3240 dest.x += pBuf2->w + adj_size(5);
3243 /* blit unit/impr name */
3244 alphablit(pBuf, NULL, pWindow->dst->surface, &dest, 255);
3246 FREESURFACE(pBuf);
3247 FREESURFACE(pBuf2);
3249 if (count) {
3250 if (count > 11) {
3251 step = (adj_size(154) - pIcons->pBIG_Shield->h) / adj_size((10 + count - 11));
3253 if (!step) {
3254 step = 1;
3257 i = (step * (count - 1)) + pIcons->pBIG_Shield->h;
3258 } else {
3259 step = pIcons->pBIG_Shield->h;
3260 i = count * step;
3263 /* draw shield stock background */
3264 dest.x = pWindow->size.x + adj_size(28);
3265 dest.y = pWindow->size.y + adj_size(270);
3266 dest.w = adj_size(144);
3267 dest.h = i + adj_size(4);
3269 fill_rect_alpha(pWindow->dst->surface, &dest,
3270 get_theme_color(COLOR_THEME_CITYDLG_SHIELDSTOCK));
3272 create_frame(pWindow->dst->surface,
3273 dest.x - 1, dest.y - 1, dest.w, dest.h,
3274 get_theme_color(COLOR_THEME_CITYDLG_FRAME));
3276 /* draw production progres text */
3277 dest.y = pWindow->size.y + adj_size(270) + dest.h + 1;
3279 if (pCity->shield_stock < cost) {
3280 count = city_production_turns_to_build(pCity, TRUE);
3281 if (count == 999) {
3282 fc_snprintf(cBuf, sizeof(cBuf), "(%d/%d) %s!",
3283 pCity->shield_stock, cost, _("blocked"));
3284 } else {
3285 fc_snprintf(cBuf, sizeof(cBuf), "(%d/%d) %d %s",
3286 pCity->shield_stock, cost, count, PL_("turn", "turns", count));
3288 } else {
3289 fc_snprintf(cBuf, sizeof(cBuf), "(%d/%d) %s!",
3290 pCity->shield_stock, cost, _("finished"));
3293 copy_chars_to_utf8_str(pstr, cBuf);
3294 pstr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_LUX);
3296 pBuf = create_text_surf_from_utf8(pstr);
3298 dest.x = pWindow->size.x + adj_size(6) + (adj_size(185) - pBuf->w) / 2;
3300 alphablit(pBuf, NULL, pWindow->dst->surface, &dest, 255);
3302 FREEUTF8STR(pstr);
3303 FREESURFACE(pBuf);
3305 /* draw shield stock */
3306 if (pCity->shield_stock + pCity->surplus[O_SHIELD] <= cost) {
3307 count = pCity->shield_stock + pCity->surplus[O_SHIELD];
3308 } else {
3309 count = cost;
3311 dest.x = pWindow->size.x + adj_size(29) + adj_size(2);
3312 dest.y = pWindow->size.y + adj_size(270) + adj_size(2);
3313 i = 0;
3315 pBuf = pIcons->pBIG_Shield;
3316 while (count > 0) {
3317 alphablit(pBuf, NULL, pWindow->dst->surface, &dest, 255);
3318 dest.x += pBuf->w;
3319 count--;
3320 if (dest.x > pWindow->size.x + adj_size(170)) {
3321 dest.x = pWindow->size.x + adj_size(31);
3322 dest.y += step;
3324 i++;
3325 if (i > pCity->shield_stock - 1) {
3326 pBuf = pIcons->pBIG_Shield_Surplus;
3331 /* count != 0 */
3332 /* ==================================================== */
3333 /* Draw Citizens */
3334 count = (pCity->feel[CITIZEN_HAPPY][FEELING_FINAL] + pCity->feel[CITIZEN_CONTENT][FEELING_FINAL]
3335 + pCity->feel[CITIZEN_UNHAPPY][FEELING_FINAL] + pCity->feel[CITIZEN_ANGRY][FEELING_FINAL]
3336 + city_specialists(pCity));
3338 pBuf = get_citizen_surface(CITIZEN_HAPPY, 0);
3340 if (count > 13) {
3341 step = (adj_size(440) - pBuf->w) / (adj_size(12 + count - 13));
3342 } else {
3343 step = pBuf->w;
3346 pCityDlg->citizen_step = step;
3348 dest.x = pWindow->size.x + adj_size(198);
3349 dest.y = pWindow->size.y + pWindow->area.y + adj_size(1) + (adj_size(22) - pBuf->h) / 2;
3350 pCityDlg->spec_area.x = pWindow->dst->dest_rect.x + dest.x;
3351 pCityDlg->spec_area.y = pWindow->dst->dest_rect.y + dest.y;
3352 pCityDlg->spec_area.w = count * step;
3353 pCityDlg->spec_area.h = pBuf->h;
3355 if (pCity->feel[CITIZEN_HAPPY][FEELING_FINAL]) {
3356 for (i = 0; i < pCity->feel[CITIZEN_HAPPY][FEELING_FINAL]; i++) {
3357 pBuf = adj_surf(get_citizen_surface(CITIZEN_HAPPY, i));
3359 alphablit(pBuf, NULL, pWindow->dst->surface, &dest, 255);
3360 dest.x += step;
3361 FREESURFACE(pBuf);
3365 if (pCity->feel[CITIZEN_CONTENT][FEELING_FINAL]) {
3366 for (i = 0; i < pCity->feel[CITIZEN_CONTENT][FEELING_FINAL]; i++) {
3367 pBuf = adj_surf(get_citizen_surface(CITIZEN_CONTENT, i));
3369 alphablit(pBuf, NULL, pWindow->dst->surface, &dest, 255);
3370 dest.x += step;
3371 FREESURFACE(pBuf);
3375 if (pCity->feel[CITIZEN_UNHAPPY][FEELING_FINAL]) {
3376 for (i = 0; i < pCity->feel[CITIZEN_UNHAPPY][FEELING_FINAL]; i++) {
3377 pBuf = adj_surf(get_citizen_surface(CITIZEN_UNHAPPY, i));
3379 alphablit(pBuf, NULL, pWindow->dst->surface, &dest, 255);
3380 dest.x += step;
3381 FREESURFACE(pBuf);
3385 if (pCity->feel[CITIZEN_ANGRY][FEELING_FINAL]) {
3386 for (i = 0; i < pCity->feel[CITIZEN_ANGRY][FEELING_FINAL]; i++) {
3387 pBuf = adj_surf(get_citizen_surface(CITIZEN_ANGRY, i));
3389 alphablit(pBuf, NULL, pWindow->dst->surface, &dest, 255);
3390 dest.x += step;
3391 FREESURFACE(pBuf);
3395 spe_max = specialist_count();
3396 for (spe = 0; spe < spe_max; spe++) {
3397 if (pCity->specialists[spe] > 0) {
3398 pBuf = adj_surf(get_citizen_surface(CITIZEN_SPECIALIST + spe, i));
3400 for (i = 0; i < pCity->specialists[spe]; i++) {
3401 alphablit(pBuf, NULL, pWindow->dst->surface, &dest, 255);
3402 dest.x += step;
3404 FREESURFACE(pBuf);
3408 /* ==================================================== */
3411 switch (pCityDlg->page) {
3412 case INFO_PAGE:
3413 redraw_info_city_dialog(pWindow, pCity);
3414 break;
3416 case HAPPINESS_PAGE:
3417 redraw_happiness_city_dialog(pWindow, pCity);
3418 break;
3420 case ARMY_PAGE:
3421 redraw_army_city_dialog(pWindow, pCity);
3422 break;
3424 case SUPPORTED_UNITS_PAGE:
3425 redraw_supported_units_city_dialog(pWindow, pCity);
3426 break;
3428 case MISC_PAGE:
3429 redraw_misc_city_dialog(pWindow, pCity);
3430 break;
3432 default:
3433 break;
3437 /* redraw "sell improvement" dialog */
3438 redraw_group(pCityDlg->pBeginCityMenuWidgetList,
3439 pCityDlg->pEndCityMenuWidgetList, 0);
3441 widget_mark_dirty(pWindow);
3444 /* ============================================================== */
3446 /**************************************************************************
3447 Recreate improvement list for city dialog.
3448 **************************************************************************/
3449 static void rebuild_imprm_list(struct city *pCity)
3451 int count = 0;
3452 struct widget *pWindow = pCityDlg->pEndCityWidgetList;
3453 struct widget *pAdd_Dock, *pBuf, *pLast;
3454 SDL_Surface *pLogo = NULL;
3455 utf8_str *pstr = NULL;
3456 struct player *pOwner = city_owner(pCity);
3457 int prev_y = 0;
3459 if (!pCityDlg->pImprv) {
3460 pCityDlg->pImprv = fc_calloc(1, sizeof(struct ADVANCED_DLG));
3463 /* free old list */
3464 if (pCityDlg->pImprv->pEndWidgetList) {
3465 del_group_of_widgets_from_gui_list(pCityDlg->pImprv->pBeginWidgetList,
3466 pCityDlg->pImprv->pEndWidgetList);
3467 pCityDlg->pImprv->pEndWidgetList = NULL;
3468 pCityDlg->pImprv->pBeginWidgetList = NULL;
3469 pCityDlg->pImprv->pEndActiveWidgetList = NULL;
3470 pCityDlg->pImprv->pBeginActiveWidgetList = NULL;
3471 pCityDlg->pImprv->pActiveWidgetList = NULL;
3472 FC_FREE(pCityDlg->pImprv->pScroll);
3475 pAdd_Dock = pCityDlg->pAdd_Point;
3476 pBuf = pLast = pAdd_Dock;
3478 /* allock new */
3479 city_built_iterate(pCity, pImprove) {
3480 pstr = create_utf8_from_char(city_improvement_name_translation(pCity, pImprove), adj_font(10));
3481 pstr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_IMPR);
3483 pstr->style |= TTF_STYLE_BOLD;
3485 pLogo = get_building_surface(pImprove);
3486 pLogo = ResizeSurfaceBox(pLogo, adj_size(22), adj_size(22), 1, TRUE, TRUE);
3488 pBuf = create_iconlabel(pLogo, pWindow->dst, pstr,
3489 (WF_FREE_THEME | WF_RESTORE_BACKGROUND));
3491 pBuf->size.x = pWindow->size.x + adj_size(450);
3492 pBuf->size.y = pWindow->size.y + adj_size(66) + prev_y;
3494 prev_y += pBuf->size.h;
3496 pBuf->size.w = adj_size(165);
3497 pBuf->action = sell_imprvm_dlg_callback;
3499 if (!pCityDlg->pCity->did_sell
3500 && !is_wonder(pImprove) && (pOwner == client.conn.playing)) {
3501 set_wstate(pBuf, FC_WS_NORMAL);
3504 pBuf->ID = MAX_ID - improvement_number(pImprove) - 3000;
3505 DownAdd(pBuf, pAdd_Dock);
3506 pAdd_Dock = pBuf;
3508 count++;
3510 if (count > 7) {
3511 set_wflag(pBuf, WF_HIDDEN);
3514 } city_built_iterate_end;
3516 if (count) {
3517 pCityDlg->pImprv->pEndWidgetList = pLast->prev;
3518 pCityDlg->pImprv->pEndActiveWidgetList = pCityDlg->pImprv->pEndWidgetList;
3519 pCityDlg->pImprv->pBeginWidgetList = pBuf;
3520 pCityDlg->pImprv->pBeginActiveWidgetList = pCityDlg->pImprv->pBeginWidgetList;
3522 if (count > 7) {
3523 pCityDlg->pImprv->pActiveWidgetList = pCityDlg->pImprv->pEndActiveWidgetList;
3525 create_vertical_scrollbar(pCityDlg->pImprv, 1, 7, TRUE, TRUE);
3527 setup_vertical_scrollbar_area(pCityDlg->pImprv->pScroll,
3528 pWindow->size.x + adj_size(635),
3529 pWindow->size.y + adj_size(66),
3530 adj_size(155), TRUE);
3535 /**************************************************************************
3536 Recreate citydialog title.
3537 **************************************************************************/
3538 static void rebuild_citydlg_title_str(struct widget *pWindow,
3539 struct city *pCity)
3541 char cbuf[512];
3543 fc_snprintf(cbuf, sizeof(cbuf),
3544 _("City of %s (Population %s citizens)"),
3545 city_name_get(pCity),
3546 population_to_text(city_population(pCity)));
3548 if (city_unhappy(pCity)) {
3549 fc_strlcat(cbuf, _(" - DISORDER"), sizeof(cbuf));
3550 } else {
3551 if (city_celebrating(pCity)) {
3552 fc_strlcat(cbuf, _(" - celebrating"), sizeof(cbuf));
3553 } else {
3554 if (city_happy(pCity)) {
3555 fc_strlcat(cbuf, _(" - happy"), sizeof(cbuf));
3560 if (cma_is_city_under_agent(pCity, NULL)) {
3561 fc_strlcat(cbuf, _(" - under Citizen Governor control."), sizeof(cbuf));
3564 copy_chars_to_utf8_str(pWindow->string_utf8, cbuf);
3568 /* ========================= Public ================================== */
3570 /**************************************************************************
3571 Pop up (or bring to the front) a dialog for the given city. It may or
3572 may not be modal.
3573 **************************************************************************/
3574 void real_city_dialog_popup(struct city *pCity)
3576 struct widget *pWindow = NULL, *pBuf = NULL;
3577 SDL_Surface *pLogo = NULL;
3578 utf8_str *pstr = NULL;
3579 int cs;
3580 struct player *pOwner = city_owner(pCity);
3581 SDL_Rect area;
3583 if (pCityDlg) {
3584 return;
3587 menus_update();
3589 pCityDlg = fc_calloc(1, sizeof(struct city_dialog));
3590 pCityDlg->pCity = pCity;
3591 pCityDlg->page = ARMY_PAGE;
3593 pstr = create_utf8_str(NULL, 0, adj_font(12));
3594 pstr->style |= TTF_STYLE_BOLD;
3595 pWindow = create_window(NULL, pstr, adj_size(640), adj_size(480), 0);
3597 rebuild_citydlg_title_str(pWindow, pCity);
3599 pWindow->action = city_dlg_callback;
3600 set_wstate(pWindow, FC_WS_NORMAL);
3602 add_to_gui_list(ID_CITY_DLG_WINDOW, pWindow);
3604 pCityDlg->pEndCityWidgetList = pWindow;
3606 /* create window background */
3607 pLogo = theme_get_background(theme, BACKGROUND_CITYDLG);
3608 if (resize_window(pWindow, pLogo, NULL, adj_size(640), adj_size(480))) {
3609 FREESURFACE(pLogo);
3612 pLogo = get_city_gfx();
3613 alphablit(pLogo, NULL, pWindow->theme, NULL, 255);
3615 area = pWindow->area;
3617 widget_set_position(pWindow,
3618 (main_window_width() - pWindow->size.w) / 2,
3619 (main_window_height() - pWindow->size.h) / 2);
3621 /* ============================================================= */
3623 /* close dialog button */
3624 pBuf = create_themeicon(current_theme->Small_CANCEL_Icon, pWindow->dst,
3625 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
3626 pBuf->info_label = create_utf8_from_char(_("Close Dialog (Esc)"),
3627 adj_font(12));
3628 pBuf->action = exit_city_dlg_callback;
3629 pBuf->size.x = area.x + area.w - pBuf->size.w;
3630 pBuf->size.y = pWindow->size.y + adj_size(2);
3631 pBuf->key = SDLK_ESCAPE;
3632 set_wstate(pBuf, FC_WS_NORMAL);
3633 add_to_gui_list(ID_CITY_DLG_EXIT_BUTTON, pBuf);
3635 /* -------- */
3637 pBuf = create_themeicon(current_theme->Army_Icon, pWindow->dst,
3638 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
3639 pBuf->info_label = create_utf8_from_char(_("Present units"),
3640 adj_font(12));
3641 pBuf->action = army_city_dlg_callback;
3642 pBuf->size.x = area.x + adj_size(2) + ((adj_size(183) - 5 * pBuf->size.w) / 6);
3643 pBuf->size.y = area.y + adj_size(2);
3644 set_wstate(pBuf, FC_WS_NORMAL);
3645 add_to_gui_list(ID_CITY_DLG_ARMY_BUTTON, pBuf);
3646 /* -------- */
3648 pBuf = create_themeicon(current_theme->Support_Icon, pWindow->dst,
3649 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
3650 pBuf->info_label = create_utf8_from_char(_("Supported units"),
3651 adj_font(12));
3652 pBuf->action = supported_unit_city_dlg_callback;
3653 pBuf->size.x =
3654 area.x + adj_size(2) + 2 * ((adj_size(183) - 5 * pBuf->size.w) / 6) + pBuf->size.w;
3655 pBuf->size.y = area.y + adj_size(2);
3657 set_wstate(pBuf, FC_WS_NORMAL);
3658 add_to_gui_list(ID_CITY_DLG_SUPPORT_BUTTON, pBuf);
3659 /* -------- */
3661 pBuf = create_themeicon(current_theme->Happy_Icon, pWindow->dst,
3662 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
3663 pBuf->info_label = create_utf8_from_char(_("Happiness"), adj_font(12));
3664 pBuf->action = happy_city_dlg_callback;
3665 pBuf->size.x =
3666 area.x + adj_size(2) + 3 * ((adj_size(183) - 5 * pBuf->size.w) / 6) + 2 * pBuf->size.w;
3667 pBuf->size.y = area.y + adj_size(2);
3668 set_wstate(pBuf, FC_WS_NORMAL);
3669 add_to_gui_list(ID_CITY_DLG_HAPPY_BUTTON, pBuf);
3670 /* -------- */
3672 pBuf = create_themeicon(current_theme->INFO_Icon, pWindow->dst,
3673 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
3674 pBuf->info_label = create_utf8_from_char(_("City info"), adj_font(12));
3675 pBuf->action = info_city_dlg_callback;
3676 pBuf->size.x =
3677 area.x + adj_size(4) + 4 * ((adj_size(183) - 5 * pBuf->size.w) / 6) + 3 * pBuf->size.w;
3678 pBuf->size.y = area.y + adj_size(2);
3679 set_wstate(pBuf, FC_WS_NORMAL);
3680 add_to_gui_list(ID_CITY_DLG_INFO_BUTTON, pBuf);
3682 pCityDlg->pAdd_Point = pBuf;
3683 pCityDlg->pBeginCityWidgetList = pBuf;
3684 /* ===================================================== */
3685 rebuild_imprm_list(pCity);
3686 /* ===================================================== */
3688 pLogo = get_scaled_city_map(pCity);
3690 pBuf = create_themelabel(pLogo, pWindow->dst, NULL,
3691 pLogo->w, pLogo->h, WF_SELECT_WITHOUT_BAR);
3693 pCityDlg->pResource_Map = pBuf;
3695 pBuf->action = resource_map_city_dlg_callback;
3696 if (!cma_is_city_under_agent(pCity, NULL) && (pOwner == client.conn.playing)) {
3697 set_wstate(pBuf, FC_WS_NORMAL);
3699 pBuf->size.x = area.x + adj_size(193) + (adj_size(249) - pBuf->size.w) / 2;
3700 pBuf->size.y = area.y + adj_size(41) + (adj_size(158) - pBuf->size.h) / 2;
3701 add_to_gui_list(ID_CITY_DLG_RESOURCE_MAP, pBuf);
3702 /* -------- */
3704 pBuf = create_themeicon(current_theme->Options_Icon, pWindow->dst,
3705 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
3706 pBuf->info_label = create_utf8_from_char(_("City options"), adj_font(12));
3707 pBuf->action = options_city_dlg_callback;
3708 pBuf->size.x =
3709 area.x + adj_size(4) + 5 * ((adj_size(183) - 5 * pBuf->size.w) / 6) + 4 * pBuf->size.w;
3710 pBuf->size.y = area.y + adj_size(2);
3711 if (pOwner == client.conn.playing) {
3712 set_wstate(pBuf, FC_WS_NORMAL);
3714 add_to_gui_list(ID_CITY_DLG_OPTIONS_BUTTON, pBuf);
3715 /* -------- */
3717 pBuf = create_themeicon(current_theme->PROD_Icon, pWindow->dst,
3718 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
3719 pBuf->info_label = create_utf8_from_char(_("Change production"),
3720 adj_font(12));
3721 pBuf->action = change_prod_dlg_callback;
3722 pBuf->size.x = area.x + adj_size(7);
3723 pBuf->size.y = area.y + area.h - pBuf->size.h - adj_size(5);
3724 if (pOwner == client.conn.playing) {
3725 set_wstate(pBuf, FC_WS_NORMAL);
3727 pBuf->key = SDLK_c;
3728 add_to_gui_list(ID_CITY_DLG_CHANGE_PROD_BUTTON, pBuf);
3729 /* -------- */
3731 pBuf = create_themeicon(current_theme->Buy_PROD_Icon, pWindow->dst,
3732 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
3733 pBuf->info_label = create_utf8_from_char(_("Hurry production"),
3734 adj_font(12));
3735 pBuf->action = buy_prod_city_dlg_callback;
3736 pBuf->size.x = area.x + adj_size(7) + (pBuf->size.w + adj_size(2));
3737 pBuf->size.y = area.y + area.h - pBuf->size.h - adj_size(5);
3738 pCityDlg->pBuy_Button = pBuf;
3739 pBuf->key = SDLK_h;
3740 if (city_can_buy(pCity)) {
3741 set_wstate(pBuf, FC_WS_NORMAL);
3743 add_to_gui_list(ID_CITY_DLG_PROD_BUY_BUTTON, pBuf);
3744 /* -------- */
3746 pBuf = create_themeicon(current_theme->CMA_Icon, pWindow->dst,
3747 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
3748 pBuf->info_label = create_utf8_from_char(_("Citizen Governor"),
3749 adj_font(12));
3750 pBuf->action = cma_city_dlg_callback;
3751 pBuf->key = SDLK_a;
3752 pBuf->size.x = area.x + adj_size(7) + (pBuf->size.w + adj_size(2)) * 2;
3753 pBuf->size.y = area.y + area.h - pBuf->size.h - adj_size(5);
3754 if (pOwner == client.conn.playing) {
3755 set_wstate(pBuf, FC_WS_NORMAL);
3757 add_to_gui_list(ID_CITY_DLG_CMA_BUTTON, pBuf);
3760 /* -------- */
3761 pBuf = create_themeicon(current_theme->L_ARROW_Icon, pWindow->dst,
3762 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
3763 pBuf->info_label = create_utf8_from_char(_("Previous city"),
3764 adj_font(12));
3765 pBuf->action = next_prev_city_dlg_callback;
3766 pBuf->size.x = area.x + adj_size(220) - pBuf->size.w - adj_size(8);
3767 pBuf->size.y = area.y + area.h - pBuf->size.h;
3768 if (pOwner == client.conn.playing) {
3769 set_wstate(pBuf, FC_WS_NORMAL);
3771 pBuf->key = SDLK_LEFT;
3772 pBuf->mod = KMOD_LSHIFT;
3773 add_to_gui_list(ID_CITY_DLG_PREV_BUTTON, pBuf);
3774 /* -------- */
3776 pBuf = create_themeicon(current_theme->R_ARROW_Icon, pWindow->dst,
3777 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
3778 pBuf->info_label = create_utf8_from_char(_("Next city"), adj_font(12));
3779 pBuf->action = next_prev_city_dlg_callback;
3780 pBuf->size.x = area.x + adj_size(420) + adj_size(2);
3781 pBuf->size.y = area.y + area.h - pBuf->size.h;
3782 if (pOwner == client.conn.playing) {
3783 set_wstate(pBuf, FC_WS_NORMAL);
3785 pBuf->key = SDLK_RIGHT;
3786 pBuf->mod = KMOD_LSHIFT;
3787 add_to_gui_list(ID_CITY_DLG_NEXT_BUTTON, pBuf);
3788 /* -------- */
3790 pBuf = create_edit_from_chars(NULL, pWindow->dst, city_name_get(pCity),
3791 adj_font(10), adj_size(200), WF_RESTORE_BACKGROUND);
3792 pBuf->action = new_name_city_dlg_callback;
3793 pBuf->size.x = area.x + (area.w - pBuf->size.w) / 2;
3794 pBuf->size.y = area.y + area.h - pBuf->size.h - adj_size(2);
3795 if (pOwner == client.conn.playing) {
3796 set_wstate(pBuf, FC_WS_NORMAL);
3799 pCityDlg->pCity_Name_Edit = pBuf;
3800 add_to_gui_list(ID_CITY_DLG_NAME_EDIT, pBuf);
3802 pCityDlg->pBeginCityWidgetList = pBuf;
3804 /* check if Citizen Icons style was loaded */
3805 cs = style_of_city(pCity);
3807 if (cs != pIcons->style) {
3808 reload_citizens_icons(cs);
3811 /* ===================================================== */
3812 if ((city_unhappy(pCity) || city_celebrating(pCity)
3813 || city_happy(pCity))) {
3814 SDL_Client_Flags |= CF_CITY_STATUS_SPECIAL;
3816 /* ===================================================== */
3818 redraw_city_dialog(pCity);
3819 flush_dirty();
3822 /**************************************************************************
3823 Close the dialog for the given city.
3824 **************************************************************************/
3825 void popdown_city_dialog(struct city *pCity)
3827 if (city_dialog_is_open(pCity)) {
3828 del_city_dialog();
3830 flush_dirty();
3832 SDL_Client_Flags &= ~CF_CITY_STATUS_SPECIAL;
3833 menus_update();
3837 /**************************************************************************
3838 Close all cities dialogs.
3839 **************************************************************************/
3840 void popdown_all_city_dialogs(void)
3842 if (pCityDlg) {
3843 popdown_city_dialog(pCityDlg->pCity);
3847 /**************************************************************************
3848 Refresh (update) all data for the given city's dialog.
3849 **************************************************************************/
3850 void real_city_dialog_refresh(struct city *pCity)
3852 if (city_dialog_is_open(pCity)) {
3853 redraw_city_dialog(pCityDlg->pCity);
3854 flush_dirty();
3858 /**************************************************************************
3859 Update city dialogs when the given unit's status changes. This
3860 typically means updating both the unit's home city (if any) and the
3861 city in which it is present (if any).
3862 **************************************************************************/
3863 void refresh_unit_city_dialogs(struct unit *pUnit)
3865 struct city *pCity_sup = game_city_by_number(pUnit->homecity);
3866 struct city *pCity_pre = tile_city(unit_tile(pUnit));
3868 if (pCityDlg && ((pCityDlg->pCity == pCity_sup)
3869 || (pCityDlg->pCity == pCity_pre))) {
3870 free_city_units_lists();
3871 redraw_city_dialog(pCityDlg->pCity);
3872 flush_dirty();
3876 /**************************************************************************
3877 Return whether the dialog for the given city is open.
3878 **************************************************************************/
3879 bool city_dialog_is_open(struct city *pCity)
3881 return (pCityDlg && (pCityDlg->pCity == pCity));