1 /***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12 ***********************************************************************/
13
14 /***********************************************************************
15 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 ***********************************************************************/
21
22 #ifdef HAVE_CONFIG_H
23 #include <fc_config.h>
24 #endif
25
26 /* SDL */
27 #include <SDL/SDL.h>
28
29 /* utility */
30 #include "bitvector.h"
31 #include "fcintl.h"
32 #include "log.h"
33
34 /* common */
35 #include "game.h"
36 #include "movement.h"
37 #include "specialist.h"
38 #include "unitlist.h"
39
40 /* client */
41 #include "client_main.h"
42 #include "climisc.h"
43 #include "control.h"
44 #include "text.h"
45
46 /* gui-sdl */
47 #include "cityrep.h"
48 #include "cma_fe.h"
49 #include "colors.h"
50 #include "dialogs.h"
51 #include "graphics.h"
52 #include "gui_iconv.h"
53 #include "gui_id.h"
54 #include "gui_main.h"
55 #include "gui_tilespec.h"
56 #include "mapview.h"
57 #include "menu.h"
58 #include "sprite.h"
59 #include "themespec.h"
60 #include "widget.h"
61 #include "wldlg.h"
62
63 #include "citydlg.h"
64
65 /* ============================================================= */
66
67 static struct city_dialog {
68 struct city *pCity;
69
70 enum {
71 INFO_PAGE = 0,
72 HAPPINESS_PAGE = 1,
73 ARMY_PAGE,
74 SUPPORTED_UNITS_PAGE,
75 MISC_PAGE
76 } page;
77
78 /* main window group list */
79 struct widget *pBeginCityWidgetList;
80 struct widget *pEndCityWidgetList;
81
82 /* Imprvm. vscrollbar */
83 struct ADVANCED_DLG *pImprv;
84
85 /* Penel group list */
86 struct ADVANCED_DLG *pPanel;
87
88 /* Menu imprv. dlg. */
89 struct widget *pBeginCityMenuWidgetList;
90 struct widget *pEndCityMenuWidgetList;
91
92 /* shortcuts */
93 struct widget *pAdd_Point;
94 struct widget *pBuy_Button;
95 struct widget *pResource_Map;
96 struct widget *pCity_Name_Edit;
97
98 int citizen_step;
99
100 SDL_Rect spec_area;
101
102 bool lock;
103 } *pCityDlg = NULL;
104
105 enum specialist_type {
106 SP_ELVIS, SP_SCIENTIST, SP_TAXMAN, SP_LAST
107 };
108
109 static float city_map_zoom = 1;
110
111 static struct SMALL_DLG *pHurry_Prod_Dlg = NULL;
112
113 static void popdown_hurry_production_dialog(void);
114 static void disable_city_dlg_widgets(void);
115 static void redraw_city_dialog(struct city *pCity);
116 static void rebuild_imprm_list(struct city *pCity);
117 static void rebuild_citydlg_title_str(struct widget *pWindow, struct city *pCity);
118
119 /* ======================================================================= */
120
121 /**************************************************************************
122 Return first building that has given effect.
123
124 FIXME: Some callers would work better if they got building actually
125 provides the effect at the moment, and not just first potential
126 one.
127 **************************************************************************/
get_building_for_effect(enum effect_type effect_type)128 struct impr_type *get_building_for_effect(enum effect_type effect_type)
129 {
130 improvement_iterate(pImprove) {
131 if (building_has_effect(pImprove, effect_type))
132 return pImprove;
133 } improvement_iterate_end;
134
135 return NULL;
136 }
137
138 /**************************************************************************
139 Destroy City Menu Dlg but not undraw.
140 **************************************************************************/
popdown_city_menu_dlg(bool enable_city_dialog_widgets)141 static void popdown_city_menu_dlg(bool enable_city_dialog_widgets)
142 {
143 if (pCityDlg->pEndCityMenuWidgetList) {
144 popdown_window_group_dialog(pCityDlg->pBeginCityMenuWidgetList,
145 pCityDlg->pEndCityMenuWidgetList);
146 pCityDlg->pEndCityMenuWidgetList = NULL;
147 }
148 if (enable_city_dialog_widgets) {
149 /* enable city dlg */
150 enable_city_dlg_widgets();
151 }
152 }
153
154 /**************************************************************************
155 Destroy City Dlg
156 **************************************************************************/
del_city_dialog(void)157 static void del_city_dialog(void)
158 {
159 if (pCityDlg) {
160
161 if (pCityDlg->pImprv->pEndWidgetList) {
162 del_group_of_widgets_from_gui_list(pCityDlg->pImprv->pBeginWidgetList,
163 pCityDlg->pImprv->pEndWidgetList);
164 }
165 FC_FREE(pCityDlg->pImprv->pScroll);
166 FC_FREE(pCityDlg->pImprv);
167
168 if (pCityDlg->pPanel) {
169 del_group_of_widgets_from_gui_list(pCityDlg->pPanel->pBeginWidgetList,
170 pCityDlg->pPanel->pEndWidgetList);
171 FC_FREE(pCityDlg->pPanel->pScroll);
172 FC_FREE(pCityDlg->pPanel);
173 }
174
175 if (pHurry_Prod_Dlg)
176 {
177 del_group_of_widgets_from_gui_list(pHurry_Prod_Dlg->pBeginWidgetList,
178 pHurry_Prod_Dlg->pEndWidgetList);
179
180 FC_FREE(pHurry_Prod_Dlg);
181 }
182
183 free_city_units_lists();
184 popdown_city_menu_dlg(FALSE);
185
186 popdown_window_group_dialog(pCityDlg->pBeginCityWidgetList,
187 pCityDlg->pEndCityWidgetList);
188 FC_FREE(pCityDlg);
189 }
190 }
191
192 /**************************************************************************
193 Main City Dlg. window callback.
194 This implements specialist change ( Elvis, Taxman, Scientist )
195 **************************************************************************/
city_dlg_callback(struct widget * pWindow)196 static int city_dlg_callback(struct widget *pWindow)
197 {
198 if (Main.event.button.button == SDL_BUTTON_LEFT) {
199 if (!cma_is_city_under_agent(pCityDlg->pCity, NULL)
200 && city_owner(pCityDlg->pCity) == client.conn.playing) {
201
202 if (is_in_rect_area(Main.event.motion.x, Main.event.motion.y,
203 pCityDlg->spec_area)) {
204 city_rotate_specialist(pCityDlg->pCity,
205 (Main.event.motion.x - pCityDlg->spec_area.x)
206 / pCityDlg->citizen_step);
207
208 return -1;
209 }
210 }
211
212 if (!pCityDlg->lock) {
213 if (pCityDlg->pPanel) {
214 sellect_window_group_dialog(pCityDlg->pBeginCityWidgetList, pWindow);
215 sellect_window_group_dialog(pCityDlg->pPanel->pBeginWidgetList,
216 pCityDlg->pPanel->pEndWidgetList);
217 widget_flush(pWindow);
218 } else {
219 if (sellect_window_group_dialog(pCityDlg->pBeginCityWidgetList, pWindow)) {
220 widget_flush(pWindow);
221 }
222 }
223 }
224 }
225 return -1;
226 }
227
228 /* ===================================================================== */
229 /* ========================== Units Orders Menu ======================== */
230 /* ===================================================================== */
231
232 /**************************************************************************
233 Popdown unit city orders menu.
234 **************************************************************************/
cancel_units_orders_city_dlg_callback(struct widget * pButton)235 static int cancel_units_orders_city_dlg_callback(struct widget *pButton)
236 {
237 if (Main.event.button.button == SDL_BUTTON_LEFT) {
238 popdown_window_group_dialog(pCityDlg->pBeginCityMenuWidgetList,
239 pCityDlg->pEndCityMenuWidgetList);
240 pCityDlg->pEndCityMenuWidgetList = NULL;
241
242 /* enable city dlg */
243 enable_city_dlg_widgets();
244 flush_dirty();
245 }
246 return -1;
247 }
248
249 /**************************************************************************
250 activate unit and del unit order dlg. widget group.
251 **************************************************************************/
activate_units_orders_city_dlg_callback(struct widget * pButton)252 static int activate_units_orders_city_dlg_callback(struct widget *pButton)
253 {
254 if (Main.event.button.button == SDL_BUTTON_LEFT) {
255 struct unit *pUnit = pButton->data.unit;
256
257 popdown_city_menu_dlg(TRUE);
258 if(pUnit) {
259 unit_focus_set(pUnit);
260 }
261 }
262 return -1;
263 }
264
265 /**************************************************************************
266 activate unit and popdow city dlg. + center on unit.
267 **************************************************************************/
activate_and_exit_units_orders_city_dlg_callback(struct widget * pButton)268 static int activate_and_exit_units_orders_city_dlg_callback(struct widget *pButton)
269 {
270 if (Main.event.button.button == SDL_BUTTON_LEFT) {
271 struct unit *pUnit = pButton->data.unit;
272
273 if(pUnit) {
274
275 popdown_window_group_dialog(pCityDlg->pBeginCityMenuWidgetList,
276 pCityDlg->pEndCityMenuWidgetList);
277 pCityDlg->pEndCityMenuWidgetList = NULL;
278
279 popdown_city_dialog(pCityDlg->pCity);
280
281 center_tile_mapcanvas(unit_tile(pUnit));
282 unit_focus_set(pUnit);
283 }
284 }
285 return -1;
286 }
287
288 /**************************************************************************
289 sentry unit and del unit order dlg. widget group.
290 **************************************************************************/
sentry_units_orders_city_dlg_callback(struct widget * pButton)291 static int sentry_units_orders_city_dlg_callback(struct widget *pButton)
292 {
293 if (Main.event.button.button == SDL_BUTTON_LEFT) {
294 struct unit *pUnit = pButton->data.unit;
295
296 popdown_city_menu_dlg(TRUE);
297 if(pUnit) {
298 request_unit_sentry(pUnit);
299 }
300 }
301 return -1;
302 }
303
304 /**************************************************************************
305 fortify unit and del unit order dlg. widget group.
306 **************************************************************************/
fortify_units_orders_city_dlg_callback(struct widget * pButton)307 static int fortify_units_orders_city_dlg_callback(struct widget *pButton)
308 {
309 if (Main.event.button.button == SDL_BUTTON_LEFT) {
310 struct unit *pUnit = pButton->data.unit;
311
312 popdown_city_menu_dlg(TRUE);
313 if(pUnit) {
314 request_unit_fortify(pUnit);
315 }
316 }
317 return -1;
318 }
319
320 /**************************************************************************
321 disband unit and del unit order dlg. widget group.
322 **************************************************************************/
disband_units_orders_city_dlg_callback(struct widget * pButton)323 static int disband_units_orders_city_dlg_callback(struct widget *pButton)
324 {
325 if (Main.event.button.button == SDL_BUTTON_LEFT) {
326 struct unit *pUnit = pButton->data.unit;
327
328 popdown_city_menu_dlg(TRUE);
329 popup_unit_disband_dlg(pUnit, TRUE);
330 }
331 return -1;
332 }
333
334 /**************************************************************************
335 homecity unit and del unit order dlg. widget group.
336 **************************************************************************/
homecity_units_orders_city_dlg_callback(struct widget * pButton)337 static int homecity_units_orders_city_dlg_callback(struct widget *pButton)
338 {
339 if (Main.event.button.button == SDL_BUTTON_LEFT) {
340 struct unit *pUnit = pButton->data.unit;
341
342 popdown_city_menu_dlg(TRUE);
343 if(pUnit) {
344 request_unit_change_homecity(pUnit);
345 }
346 }
347 return -1;
348 }
349
350 /**************************************************************************
351 upgrade unit and del unit order dlg. widget group.
352 **************************************************************************/
upgrade_units_orders_city_dlg_callback(struct widget * pButton)353 static int upgrade_units_orders_city_dlg_callback(struct widget *pButton)
354 {
355 if (Main.event.button.button == SDL_BUTTON_LEFT) {
356 struct unit *pUnit = pButton->data.unit;
357
358 popdown_city_menu_dlg(TRUE);
359 popup_unit_upgrade_dlg(pUnit, TRUE);
360 }
361 return -1;
362 }
363
364 /**************************************************************************
365 Main unit order dlg. callback.
366 **************************************************************************/
units_orders_dlg_callback(struct widget * pButton)367 static int units_orders_dlg_callback(struct widget *pButton)
368 {
369 return -1;
370 }
371
372 /**************************************************************************
373 popup units orders menu.
374 **************************************************************************/
units_orders_city_dlg_callback(struct widget * pButton)375 static int units_orders_city_dlg_callback(struct widget *pButton)
376 {
377 if (Main.event.button.button == SDL_BUTTON_LEFT) {
378 SDL_String16 *pStr;
379 char cBuf[80];
380 struct widget *pBuf, *pWindow = pCityDlg->pEndCityWidgetList;
381 struct unit *pUnit;
382 struct unit_type *pUType;
383 Uint16 i = 0, hh = 0;
384 SDL_Rect area;
385
386 pUnit = player_unit_by_number(client_player(), MAX_ID - pButton->ID);
387
388 if(!pUnit || !can_client_issue_orders()) {
389 return -1;
390 }
391
392 if(Main.event.button.button == SDL_BUTTON_RIGHT) {
393 popdown_city_dialog(pCityDlg->pCity);
394 center_tile_mapcanvas(unit_tile(pUnit));
395 unit_focus_set(pUnit);
396 return -1;
397 }
398
399 /* Disable city dlg */
400 unsellect_widget_action();
401 disable_city_dlg_widgets();
402
403 pUType = unit_type_get(pUnit);
404
405 /* window */
406 fc_snprintf(cBuf, sizeof(cBuf), "%s:", _("Unit commands"));
407 pStr = create_str16_from_char(cBuf, adj_font(12));
408 pStr->style |= TTF_STYLE_BOLD;
409 pWindow = create_window_skeleton(NULL, pStr, 0);
410
411 pWindow->action = units_orders_dlg_callback;
412 set_wstate(pWindow, FC_WS_NORMAL);
413 add_to_gui_list(ID_REVOLUTION_DLG_WINDOW, pWindow);
414 pCityDlg->pEndCityMenuWidgetList = pWindow;
415
416 area = pWindow->area;
417
418 /* unit description */
419 fc_snprintf(cBuf, sizeof(cBuf), "%s", unit_description(pUnit));
420 pStr = create_str16_from_char(cBuf, adj_font(12));
421 pStr->style |= (TTF_STYLE_BOLD|SF_CENTER);
422 pBuf = create_iconlabel(adj_surf(get_unittype_surface(pUType, pUnit->facing)),
423 pWindow->dst, pStr, WF_FREE_THEME);
424 area.w = MAX(area.w, pBuf->size.w);
425 add_to_gui_list(ID_LABEL, pBuf);
426
427 /* Activate unit */
428 pBuf =
429 create_icon_button_from_chars(NULL, pWindow->dst,
430 _("Activate unit"), adj_font(12), 0);
431 i++;
432 area.w = MAX(area.w, pBuf->size.w);
433 hh = MAX(hh, pBuf->size.h);
434 pBuf->action = activate_units_orders_city_dlg_callback;
435 pBuf->data = pButton->data;
436 set_wstate(pBuf, FC_WS_NORMAL);
437 add_to_gui_list(pButton->ID, pBuf);
438
439 /* Activate unit, close dlg. */
440 pBuf = create_icon_button_from_chars(NULL, pWindow->dst,
441 _("Activate unit, close dialog"), adj_font(12), 0);
442 i++;
443 area.w = MAX(area.w, pBuf->size.w);
444 hh = MAX(hh, pBuf->size.h);
445 pBuf->action = activate_and_exit_units_orders_city_dlg_callback;
446 pBuf->data = pButton->data;
447 set_wstate(pBuf, FC_WS_NORMAL);
448 add_to_gui_list(pButton->ID, pBuf);
449 /* ----- */
450
451 if (pCityDlg->page == ARMY_PAGE) {
452 /* Sentry unit */
453 pBuf = create_icon_button_from_chars(NULL, pWindow->dst,
454 _("Sentry unit"), adj_font(12), 0);
455 i++;
456 area.w = MAX(area.w, pBuf->size.w);
457 hh = MAX(hh, pBuf->size.h);
458 pBuf->data = pButton->data;
459 pBuf->action = sentry_units_orders_city_dlg_callback;
460 if (pUnit->activity != ACTIVITY_SENTRY
461 && can_unit_do_activity(pUnit, ACTIVITY_SENTRY)) {
462 set_wstate(pBuf, FC_WS_NORMAL);
463 }
464 add_to_gui_list(pButton->ID, pBuf);
465 /* ----- */
466
467 /* Fortify unit */
468 pBuf = create_icon_button_from_chars(NULL, pWindow->dst,
469 _("Fortify unit"), adj_font(12), 0);
470 i++;
471 area.w = MAX(area.w, pBuf->size.w);
472 hh = MAX(hh, pBuf->size.h);
473 pBuf->data = pButton->data;
474 pBuf->action = fortify_units_orders_city_dlg_callback;
475 if (pUnit->activity != ACTIVITY_FORTIFYING
476 && can_unit_do_activity(pUnit, ACTIVITY_FORTIFYING)) {
477 set_wstate(pBuf, FC_WS_NORMAL);
478 }
479 add_to_gui_list(pButton->ID, pBuf);
480 }
481 /* ----- */
482
483 /* Disband unit */
484 pBuf = create_icon_button_from_chars(NULL, pWindow->dst,
485 _("Disband unit"), adj_font(12), 0);
486 i++;
487 area.w = MAX(area.w, pBuf->size.w);
488 hh = MAX(hh, pBuf->size.h);
489 pBuf->data = pButton->data;
490 pBuf->action = disband_units_orders_city_dlg_callback;
491 set_wstate(pBuf, FC_WS_NORMAL);
492 add_to_gui_list(pButton->ID, pBuf);
493 /* ----- */
494
495 if (pCityDlg->page == ARMY_PAGE) {
496 if (pUnit->homecity != pCityDlg->pCity->id) {
497 /* Make new Homecity */
498 pBuf = create_icon_button_from_chars(NULL, pWindow->dst,
499 _("Set Home City"), adj_font(12), 0);
500 i++;
501 area.w = MAX(area.w, pBuf->size.w);
502 hh = MAX(hh, pBuf->size.h);
503 pBuf->data = pButton->data;
504 pBuf->action = homecity_units_orders_city_dlg_callback;
505 set_wstate(pBuf, FC_WS_NORMAL);
506 add_to_gui_list(pButton->ID, pBuf);
507 }
508 /* ----- */
509
510 if (can_upgrade_unittype(client.conn.playing, pUType)) {
511 /* Upgrade unit */
512 pBuf = create_icon_button_from_chars(NULL, pWindow->dst,
513 _("Upgrade unit"), adj_font(12), 0);
514 i++;
515 area.w = MAX(area.w, pBuf->size.w);
516 hh = MAX(hh, pBuf->size.h);
517 pBuf->data = pButton->data;
518 pBuf->action = upgrade_units_orders_city_dlg_callback;
519 set_wstate(pBuf, FC_WS_NORMAL);
520 add_to_gui_list(pButton->ID, pBuf);
521 }
522 }
523
524 /* ----- */
525 /* Cancel */
526 pBuf = create_icon_button_from_chars(NULL, pWindow->dst,
527 _("Cancel"), adj_font(12), 0);
528 i++;
529 area.w = MAX(area.w, pBuf->size.w);
530 hh = MAX(hh, pBuf->size.h);
531 pBuf->key = SDLK_ESCAPE;
532 pBuf->action = cancel_units_orders_city_dlg_callback;
533 set_wstate(pBuf, FC_WS_NORMAL);
534 add_to_gui_list(pButton->ID, pBuf);
535 pCityDlg->pBeginCityMenuWidgetList = pBuf;
536
537 /* ================================================== */
538 unsellect_widget_action();
539 /* ================================================== */
540
541 area.w += adj_size(10);
542 hh += adj_size(4);
543
544 /* create window background */
545 resize_window(pWindow, NULL, get_theme_color(COLOR_THEME_BACKGROUND),
546 (pWindow->size.w - pWindow->area.w) + area.w,
547 (pWindow->size.h - pWindow->area.h) + pWindow->prev->size.h +
548 (i * hh) + adj_size(5));
549
550 area = pWindow->area;
551
552 widget_set_position(pWindow,
553 pButton->size.x + adj_size(2),
554 pWindow->area.y + pButton->size.y + 1);
555
556 /* label */
557 pBuf = pWindow->prev;
558 pBuf->size.w = area.w;
559 pBuf->size.x = area.x;
560 pBuf->size.y = area.y + 1;
561 pBuf = pBuf->prev;
562
563 /* first button */
564 pBuf->size.w = area.w;
565 pBuf->size.h = hh;
566 pBuf->size.x = area.x;
567 pBuf->size.y = pBuf->next->size.y + pBuf->next->size.h + adj_size(5);
568 pBuf = pBuf->prev;
569
570 while (pBuf) {
571 pBuf->size.w = area.w;
572 pBuf->size.h = hh;
573 pBuf->size.x = pBuf->next->size.x;
574 pBuf->size.y = pBuf->next->size.y + pBuf->next->size.h;
575 if (pBuf == pCityDlg->pBeginCityMenuWidgetList) {
576 break;
577 }
578 pBuf = pBuf->prev;
579 }
580
581 /* ================================================== */
582 /* redraw */
583 redraw_group(pCityDlg->pBeginCityMenuWidgetList, pWindow, 0);
584 widget_flush(pWindow);
585 }
586 return -1;
587 }
588
589 /* ======================================================================= */
590 /* ======================= City Dlg. Panels ============================== */
591 /* ======================================================================= */
592
593 /**************************************************************************
594 create unit icon with support icons.
595 **************************************************************************/
create_unit_surface(struct unit * punit,bool support,int w,int h)596 static SDL_Surface *create_unit_surface(struct unit *punit, bool support,
597 int w, int h)
598 {
599 int i, step;
600 SDL_Rect src_rect, dest;
601 SDL_Surface *psurf;
602 struct canvas *destcanvas;
603
604 destcanvas = canvas_create_with_alpha(tileset_full_tile_width(tileset),
605 tileset_unit_with_small_upkeep_height(tileset));
606
607 put_unit(punit, destcanvas, 1.0, 0, 0);
608 /* Get unit sprite width, but do not limit height by it */
609 src_rect = get_smaller_surface_rect(destcanvas->surf);
610 src_rect.y = 0;
611 src_rect.h = destcanvas->surf->h;
612
613 if (support) {
614 int free_unhappy;
615 int happy_cost;
616
617 free_unhappy = get_city_bonus(pCityDlg->pCity, EFT_MAKE_CONTENT_MIL);
618 happy_cost = city_unit_unhappiness(punit, &free_unhappy);
619
620 i = punit->upkeep[O_SHIELD] + punit->upkeep[O_FOOD] +
621 punit->upkeep[O_GOLD] + happy_cost;
622
623 if (i * pIcons->pFood->w > src_rect.w / 2) {
624 step = (src_rect.w / 2 - pIcons->pFood->w) / (i - 1);
625 } else {
626 step = pIcons->pFood->w;
627 }
628
629 dest.y = tileset_unit_layout_small_offset_y(tileset);
630 dest.x = src_rect.x + src_rect.w / 8;
631
632 for (i = 0; i < punit->upkeep[O_SHIELD]; i++) {
633 alphablit(pIcons->pShield, NULL, destcanvas->surf, &dest);
634 dest.x += step;
635 }
636
637 for (i = 0; i < punit->upkeep[O_FOOD]; i++) {
638 alphablit(pIcons->pFood, NULL, destcanvas->surf, &dest);
639 dest.x += step;
640 }
641
642 for (i = 0; i < punit->upkeep[O_GOLD]; i++) {
643 alphablit(pIcons->pCoin, NULL, destcanvas->surf, &dest);
644 dest.x += step;
645 }
646
647 for (i = 0; i < happy_cost; i++) {
648 alphablit(pIcons->pFace, NULL, destcanvas->surf, &dest);
649 dest.x += step;
650 }
651 }
652
653 psurf = create_surf_alpha(src_rect.w, src_rect.h, SDL_SWSURFACE);
654 alphablit(destcanvas->surf, &src_rect, psurf, NULL);
655
656 canvas_free(destcanvas);
657
658 if (w != src_rect.w || h != src_rect.h) {
659 SDL_Surface *pzoomed;
660
661 pzoomed = ResizeSurfaceBox(psurf, w, h, 1, TRUE, TRUE);
662 FREESURFACE(psurf);
663 psurf = pzoomed;
664 }
665
666 return psurf;
667 }
668
669 /**************************************************************************
670 create present/supported units widget list
671 207 pixels is panel width in city dlg.
672 220 - max y position pixel position belong to panel area.
673 **************************************************************************/
create_present_supported_units_widget_list(struct unit_list * pList)674 static void create_present_supported_units_widget_list(struct unit_list *pList)
675 {
676 int i;
677 struct widget *pBuf = NULL;
678 struct widget *pEnd = NULL;
679 struct widget *pWindow = pCityDlg->pEndCityWidgetList;
680 struct city *pHome_City;
681 struct unit_type *pUType;
682 SDL_Surface *pSurf;
683 SDL_String16 *pStr;
684 char cBuf[256];
685 int num_x, num_y, w, h;
686
687 i = 0;
688
689 num_x = (adj_size(160) / (tileset_full_tile_width(tileset) + adj_size(4)));
690 if (num_x < 4) {
691 num_x = 4;
692 w = adj_size(160 - 4*4) / 4;
693 } else {
694 w = tileset_full_tile_width(tileset) + (adj_size(160) % (tileset_full_tile_width(tileset)+4)) / num_x;
695 }
696
697 num_y = (adj_size(151) / (tileset_full_tile_height(tileset)+4));
698 if (num_y < 4) {
699 num_y = 4;
700 h = adj_size(151 - 4*4) / 4;
701 } else {
702 h = tileset_full_tile_height(tileset) + (adj_size(151) % (tileset_full_tile_height(tileset)+4)) / num_y;
703 }
704
705 unit_list_iterate(pList, pUnit) {
706 const char *vetname;
707
708 pUType = unit_type_get(pUnit);
709 vetname = utype_veteran_name_translation(pUType, pUnit->veteran);
710 pHome_City = game_city_by_number(pUnit->homecity);
711 fc_snprintf(cBuf, sizeof(cBuf), "%s (%d,%d,%s)%s%s\n%s\n(%d/%d)\n%s",
712 utype_name_translation(pUType),
713 pUType->attack_strength,
714 pUType->defense_strength,
715 move_points_text(pUType->move_rate, FALSE),
716 (vetname != NULL ? "\n" : ""),
717 (vetname != NULL ? vetname : ""),
718 unit_activity_text(pUnit),
719 pUnit->hp, pUType->hp,
720 pHome_City ? pHome_City->name : Q_("?homecity:None"));
721
722 if (pCityDlg->page == SUPPORTED_UNITS_PAGE) {
723 int pCity_near_dist;
724 struct city *pNear_City = get_nearest_city(pUnit, &pCity_near_dist);
725
726 sz_strlcat(cBuf, "\n");
727 sz_strlcat(cBuf, get_nearest_city_text(pNear_City, pCity_near_dist));
728 pSurf = adj_surf(create_unit_surface(pUnit, TRUE, w, h));
729 } else {
730 pSurf = adj_surf(create_unit_surface(pUnit, FALSE, w, h));
731 }
732
733 pStr = create_str16_from_char(cBuf, adj_font(10));
734 pStr->style |= SF_CENTER;
735
736 pBuf = create_icon2(pSurf, pWindow->dst, WF_FREE_THEME
737 | WF_RESTORE_BACKGROUND | WF_WIDGET_HAS_INFO_LABEL);
738 pBuf->info_label = pStr;
739 pBuf->data.unit = pUnit;
740 add_to_gui_list(MAX_ID - pUnit->id, pBuf);
741
742 if (!pEnd) {
743 pEnd = pBuf;
744 }
745
746 if (++i > num_x * num_y) {
747 set_wflag(pBuf, WF_HIDDEN);
748 }
749
750 if (city_owner(pCityDlg->pCity) == client.conn.playing) {
751 set_wstate(pBuf, FC_WS_NORMAL);
752 }
753
754 pBuf->action = units_orders_city_dlg_callback;
755
756 } unit_list_iterate_end;
757
758 pCityDlg->pPanel = fc_calloc(1, sizeof(struct ADVANCED_DLG));
759 pCityDlg->pPanel->pEndWidgetList = pEnd;
760 pCityDlg->pPanel->pBeginWidgetList = pBuf;
761 pCityDlg->pPanel->pEndActiveWidgetList = pCityDlg->pPanel->pEndWidgetList;
762 pCityDlg->pPanel->pBeginActiveWidgetList = pCityDlg->pPanel->pBeginWidgetList;
763 pCityDlg->pPanel->pActiveWidgetList = pCityDlg->pPanel->pEndActiveWidgetList;
764
765 setup_vertical_widgets_position(num_x,
766 pWindow->area.x + adj_size(5),
767 pWindow->area.y + adj_size(44),
768 0, 0, pCityDlg->pPanel->pBeginActiveWidgetList,
769 pCityDlg->pPanel->pEndActiveWidgetList);
770
771 if (i > num_x * num_y) {
772
773 create_vertical_scrollbar(pCityDlg->pPanel,
774 num_x, num_y, TRUE, TRUE);
775
776 setup_vertical_scrollbar_area(pCityDlg->pPanel->pScroll,
777 pWindow->area.x + adj_size(185),
778 pWindow->area.y + adj_size(45),
779 adj_size(150), TRUE);
780 }
781
782 }
783
784 /**************************************************************************
785 free city present/supported units panel list.
786 **************************************************************************/
free_city_units_lists(void)787 void free_city_units_lists(void)
788 {
789 if (pCityDlg && pCityDlg->pPanel) {
790 del_group_of_widgets_from_gui_list(pCityDlg->pPanel->pBeginWidgetList,
791 pCityDlg->pPanel->pEndWidgetList);
792 FC_FREE(pCityDlg->pPanel->pScroll);
793 FC_FREE(pCityDlg->pPanel);
794 }
795 }
796
797 /**************************************************************************
798 change to present units panel.
799 **************************************************************************/
army_city_dlg_callback(struct widget * pButton)800 static int army_city_dlg_callback(struct widget *pButton)
801 {
802 if (Main.event.button.button == SDL_BUTTON_LEFT) {
803 if (pCityDlg->page != ARMY_PAGE) {
804 free_city_units_lists();
805 pCityDlg->page = ARMY_PAGE;
806 redraw_city_dialog(pCityDlg->pCity);
807 flush_dirty();
808 } else {
809 widget_redraw(pButton);
810 widget_flush(pButton);
811 }
812 }
813 return -1;
814 }
815
816 /**************************************************************************
817 change to supported units panel.
818 **************************************************************************/
supported_unit_city_dlg_callback(struct widget * pButton)819 static int supported_unit_city_dlg_callback(struct widget *pButton)
820 {
821 if (Main.event.button.button == SDL_BUTTON_LEFT) {
822 if (pCityDlg->page != SUPPORTED_UNITS_PAGE) {
823 free_city_units_lists();
824 pCityDlg->page = SUPPORTED_UNITS_PAGE;
825 redraw_city_dialog(pCityDlg->pCity);
826 flush_dirty();
827 } else {
828 widget_redraw(pButton);
829 widget_flush(pButton);
830 }
831 }
832 return -1;
833 }
834
835 /* ---------------------- */
836
837 /**************************************************************************
838 change to info panel.
839 **************************************************************************/
info_city_dlg_callback(struct widget * pButton)840 static int info_city_dlg_callback(struct widget *pButton)
841 {
842 if (Main.event.button.button == SDL_BUTTON_LEFT) {
843 if (pCityDlg->page != INFO_PAGE) {
844 free_city_units_lists();
845 pCityDlg->page = INFO_PAGE;
846 redraw_city_dialog(pCityDlg->pCity);
847 flush_dirty();
848 } else {
849 widget_redraw(pButton);
850 widget_flush(pButton);
851 }
852 }
853 return -1;
854 }
855
856 /* ---------------------- */
857 /**************************************************************************
858 change to happines panel.
859 **************************************************************************/
happy_city_dlg_callback(struct widget * pButton)860 static int happy_city_dlg_callback(struct widget *pButton)
861 {
862 if (Main.event.button.button == SDL_BUTTON_LEFT) {
863 if (pCityDlg->page != HAPPINESS_PAGE) {
864 free_city_units_lists();
865 pCityDlg->page = HAPPINESS_PAGE;
866 redraw_city_dialog(pCityDlg->pCity);
867 flush_dirty();
868 } else {
869 widget_redraw(pButton);
870 widget_flush(pButton);
871 }
872 }
873 return -1;
874 }
875
876 /**************************************************************************
877 city option callback
878 **************************************************************************/
misc_panel_city_dlg_callback(struct widget * pWidget)879 static int misc_panel_city_dlg_callback(struct widget *pWidget)
880 {
881 if (Main.event.button.button == SDL_BUTTON_LEFT) {
882 /* int new = pCityDlg->pCity->city_options & 0xff; */
883 bv_city_options new_options = pCityDlg->pCity->city_options;
884
885 switch (MAX_ID - pWidget->ID) {
886 case 0x10:
887 if (BV_ISSET(new_options, CITYO_DISBAND))
888 BV_CLR(new_options, CITYO_DISBAND);
889 else
890 BV_SET(new_options, CITYO_DISBAND);
891 break;
892 case 0x20:
893 if (BV_ISSET(new_options, CITYO_NEW_EINSTEIN))
894 BV_CLR(new_options, CITYO_NEW_EINSTEIN);
895 else
896 BV_SET(new_options, CITYO_NEW_EINSTEIN);
897
898 if (BV_ISSET(new_options, CITYO_NEW_TAXMAN))
899 BV_CLR(new_options, CITYO_NEW_TAXMAN);
900 else
901 BV_SET(new_options, CITYO_NEW_TAXMAN);
902
903 pWidget->theme2 = get_tax_surface(O_GOLD);
904 pWidget->ID = MAX_ID - 0x40;
905 widget_redraw(pWidget);
906 widget_flush(pWidget);
907 break;
908 case 0x40:
909 BV_CLR(new_options, CITYO_NEW_EINSTEIN);
910 BV_CLR(new_options, CITYO_NEW_TAXMAN);
911 pWidget->theme2 = get_tax_surface(O_LUXURY);
912 pWidget->ID = MAX_ID - 0x60;
913 widget_redraw(pWidget);
914 widget_flush(pWidget);
915 break;
916 case 0x60:
917 if (BV_ISSET(new_options, CITYO_NEW_EINSTEIN))
918 BV_CLR(new_options, CITYO_NEW_EINSTEIN);
919 else
920 BV_SET(new_options, CITYO_NEW_EINSTEIN);
921 pWidget->theme2 = get_tax_surface(O_SCIENCE);
922 pWidget->ID = MAX_ID - 0x20;
923 widget_redraw(pWidget);
924 widget_flush(pWidget);
925 break;
926 }
927
928 dsend_packet_city_options_req(&client.conn, pCityDlg->pCity->id, new_options);
929 }
930 return -1;
931 }
932
933 /**************************************************************************
934 Create city options widgets.
935 **************************************************************************/
create_city_options_widget_list(struct city * pCity)936 static void create_city_options_widget_list(struct city *pCity)
937 {
938 struct widget *pBuf, *pWindow = pCityDlg->pEndCityWidgetList;
939 SDL_Surface *pSurf;
940 SDL_String16 *pStr;
941 char cBuf[80];
942
943 fc_snprintf(cBuf, sizeof(cBuf),
944 _("Allow unit production\nto disband city"));
945 pStr = create_str16_from_char(cBuf, adj_font(10));
946 pStr->style |= TTF_STYLE_BOLD;
947 pStr->fgcol = *get_theme_color(COLOR_THEME_CHECKBOX_LABEL_TEXT);
948
949 pBuf =
950 create_textcheckbox(pWindow->dst, BV_ISSET(pCity->city_options, CITYO_DISBAND), pStr,
951 WF_RESTORE_BACKGROUND);
952 set_wstate(pBuf, FC_WS_NORMAL);
953 pBuf->action = misc_panel_city_dlg_callback;
954 add_to_gui_list(MAX_ID - 0x10, pBuf);
955 pBuf->size.x = pWindow->area.x + adj_size(7);
956 pBuf->size.y = pWindow->area.y + adj_size(45);
957
958 /* ----- */
959
960 pCityDlg->pPanel = fc_calloc(1, sizeof(struct ADVANCED_DLG));
961 pCityDlg->pPanel->pEndWidgetList = pBuf;
962
963 /* ----- */
964
965 fc_snprintf(cBuf, sizeof(cBuf), "%s:", _("New citizens are"));
966 pStr = create_str16_from_char(cBuf, adj_font(11));
967 pStr->style |= SF_CENTER;
968
969 if (BV_ISSET(pCity->city_options, CITYO_NEW_EINSTEIN)) {
970 pSurf = get_tax_surface(O_SCIENCE);
971 pBuf = create_icon_button(pSurf, pWindow->dst, pStr, WF_ICON_CENTER_RIGHT | WF_FREE_THEME2);
972 add_to_gui_list(MAX_ID - 0x20, pBuf);
973 } else {
974 if (BV_ISSET(pCity->city_options, CITYO_NEW_TAXMAN)) {
975 pSurf = get_tax_surface(O_GOLD);
976 pBuf = create_icon_button(pSurf, pWindow->dst,
977 pStr, WF_ICON_CENTER_RIGHT | WF_FREE_THEME2);
978 add_to_gui_list(MAX_ID - 0x40, pBuf);
979 } else {
980 pSurf = get_tax_surface(O_LUXURY);
981 pBuf = create_icon_button(pSurf, pWindow->dst,
982 pStr, WF_ICON_CENTER_RIGHT | WF_FREE_THEME2);
983 add_to_gui_list(MAX_ID - 0x60, pBuf);
984 }
985 }
986
987 pBuf->size.w = adj_size(177);
988 pBuf->action = misc_panel_city_dlg_callback;
989 set_wstate(pBuf, FC_WS_NORMAL);
990
991 pBuf->size.x = pBuf->next->size.x;
992 pBuf->size.y = pBuf->next->size.y + pBuf->next->size.h + adj_size(5);
993 pCityDlg->pPanel->pBeginWidgetList = pBuf;
994 }
995
996 /**************************************************************************
997 change to city options panel.
998 **************************************************************************/
options_city_dlg_callback(struct widget * pButton)999 static int options_city_dlg_callback(struct widget *pButton)
1000 {
1001 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1002 if (pCityDlg->page != MISC_PAGE) {
1003 free_city_units_lists();
1004 pCityDlg->page = MISC_PAGE;
1005 redraw_city_dialog(pCityDlg->pCity);
1006 flush_dirty();
1007 } else {
1008 widget_redraw(pButton);
1009 widget_flush(pButton);
1010 }
1011 }
1012 return -1;
1013 }
1014
1015 /* ======================================================================= */
1016
1017 /**************************************************************************
1018 User interacted with Citizen Governor button.
1019 **************************************************************************/
cma_city_dlg_callback(struct widget * pButton)1020 static int cma_city_dlg_callback(struct widget *pButton)
1021 {
1022 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1023 disable_city_dlg_widgets();
1024 popup_city_cma_dialog(pCityDlg->pCity);
1025 }
1026 return -1;
1027 }
1028
1029 /**************************************************************************
1030 Exit city dialog.
1031 **************************************************************************/
exit_city_dlg_callback(struct widget * pButton)1032 static int exit_city_dlg_callback(struct widget *pButton)
1033 {
1034 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1035 popdown_city_dialog(pCityDlg->pCity);
1036 }
1037 return -1;
1038 }
1039
1040 /* ======================================================================= */
1041 /* ======================== Buy Production Dlg. ========================== */
1042 /* ======================================================================= */
1043
1044 /**************************************************************************
1045 popdown buy productions dlg.
1046 **************************************************************************/
cancel_buy_prod_city_dlg_callback(struct widget * pButton)1047 static int cancel_buy_prod_city_dlg_callback(struct widget *pButton)
1048 {
1049 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1050 popdown_hurry_production_dialog();
1051
1052 if (pCityDlg)
1053 {
1054 /* enable city dlg */
1055 enable_city_dlg_widgets();
1056 }
1057 }
1058 return -1;
1059 }
1060
1061 /**************************************************************************
1062 buy productions.
1063 **************************************************************************/
ok_buy_prod_city_dlg_callback(struct widget * pButton)1064 static int ok_buy_prod_city_dlg_callback(struct widget *pButton)
1065 {
1066 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1067 struct city *pCity = pButton->data.city; /* Save it. */
1068
1069 popdown_hurry_production_dialog();
1070 city_buy_production(pCity);
1071
1072 if (pCityDlg) {
1073 /* enable city dlg */
1074 enable_city_dlg_widgets();
1075
1076 /* disable buy button */
1077 set_wstate(pCityDlg->pBuy_Button, FC_WS_DISABLED);
1078 widget_redraw(pCityDlg->pBuy_Button);
1079 widget_mark_dirty(pCityDlg->pBuy_Button);
1080 flush_dirty();
1081 }
1082
1083 }
1084 return -1;
1085 }
1086
1087 /**************************************************************************
1088 popup buy productions dlg.
1089 **************************************************************************/
buy_prod_city_dlg_callback(struct widget * pButton)1090 static int buy_prod_city_dlg_callback(struct widget *pButton)
1091 {
1092 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1093 widget_redraw(pButton);
1094 widget_flush(pButton);
1095 disable_city_dlg_widgets();
1096 popup_hurry_production_dialog(pCityDlg->pCity, pButton->dst->surface);
1097 }
1098 return -1;
1099 }
1100
1101 /**************************************************************************
1102 popup buy productions dlg.
1103 **************************************************************************/
popdown_hurry_production_dialog(void)1104 static void popdown_hurry_production_dialog(void)
1105 {
1106 if (pHurry_Prod_Dlg) {
1107 popdown_window_group_dialog(pHurry_Prod_Dlg->pBeginWidgetList,
1108 pHurry_Prod_Dlg->pEndWidgetList);
1109 FC_FREE(pHurry_Prod_Dlg);
1110 flush_dirty();
1111 }
1112 }
1113
1114 /**************************************************************************
1115 main hurry productions dlg. callback
1116 **************************************************************************/
hurry_production_window_callback(struct widget * pWindow)1117 static int hurry_production_window_callback(struct widget *pWindow)
1118 {
1119 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1120 move_window_group(pHurry_Prod_Dlg->pBeginWidgetList, pWindow);
1121 }
1122 return -1;
1123 }
1124
1125 /**************************************************************************
1126 popup buy productions dlg.
1127 **************************************************************************/
popup_hurry_production_dialog(struct city * pCity,SDL_Surface * pDest)1128 void popup_hurry_production_dialog(struct city *pCity, SDL_Surface *pDest)
1129 {
1130
1131 char tBuf[512], cBuf[512];
1132 struct widget *pBuf = NULL, *pWindow;
1133 SDL_String16 *pStr;
1134 SDL_Surface *pText;
1135 SDL_Rect dst;
1136 int window_x = 0, window_y = 0;
1137 SDL_Rect area;
1138 const char *name = city_production_name_translation(pCity);
1139 int value = city_production_buy_gold_cost(pCity);
1140
1141 if (pHurry_Prod_Dlg) {
1142 return;
1143 }
1144
1145 fc_snprintf(tBuf, ARRAY_SIZE(tBuf), PL_("Treasury contains %d gold.",
1146 "Treasury contains %d gold.",
1147 client_player()->economic.gold),
1148 client_player()->economic.gold);
1149
1150 pHurry_Prod_Dlg = fc_calloc(1, sizeof(struct SMALL_DLG));
1151
1152 if (city_can_buy(pCity)) {
1153 if (value <= client_player()->economic.gold) {
1154 fc_snprintf(cBuf, sizeof(cBuf),
1155 /* TRANS: Last %s is pre-pluralised "Treasury contains %d gold." */
1156 PL_("Buy %s for %d gold?\n%s",
1157 "Buy %s for %d gold?\n%s", value),
1158 name, value, tBuf);
1159 } else {
1160 fc_snprintf(cBuf, sizeof(cBuf),
1161 /* TRANS: Last %s is pre-pluralised "Treasury contains %d gold." */
1162 PL_("%s costs %d gold.\n%s",
1163 "%s costs %d gold.\n%s", value),
1164 name, value, tBuf);
1165 }
1166 } else {
1167 if (pCity->did_buy) {
1168 fc_snprintf(cBuf, sizeof(cBuf),
1169 _("Sorry, you have already bought here in this turn."));
1170 } else {
1171 fc_snprintf(cBuf, sizeof(cBuf),
1172 _("Sorry, you can't buy here in this turn."));
1173 }
1174 }
1175
1176 pStr = create_str16_from_char(_("Buy it?"), adj_font(12));
1177 pStr->style |= TTF_STYLE_BOLD;
1178 pWindow = create_window_skeleton(NULL, pStr, 0);
1179 pWindow->action = hurry_production_window_callback;
1180 set_wstate(pWindow, FC_WS_NORMAL);
1181 add_to_gui_list(ID_WINDOW, pWindow);
1182
1183 pHurry_Prod_Dlg->pEndWidgetList = pWindow;
1184
1185 area = pWindow->area;
1186
1187 area.h += 1;
1188
1189 /* ============================================================= */
1190
1191 /* label */
1192 pStr = create_str16_from_char(cBuf, adj_font(10));
1193 pStr->style |= (TTF_STYLE_BOLD|SF_CENTER);
1194 pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_BUY);
1195
1196 pText = create_text_surf_from_str16(pStr);
1197 FREESTRING16(pStr);
1198 area.w = MAX(area.w , pText->w);
1199 area.h += pText->h + adj_size(5);
1200
1201 pBuf = create_themeicon_button_from_chars(current_theme->CANCEL_Icon,
1202 pWindow->dst, _("No"), adj_font(12), 0);
1203
1204 pBuf->action = cancel_buy_prod_city_dlg_callback;
1205 set_wstate(pBuf, FC_WS_NORMAL);
1206 pBuf->key = SDLK_ESCAPE;
1207 area.h += pBuf->size.h;
1208
1209 add_to_gui_list(ID_BUTTON, pBuf);
1210
1211 if (city_can_buy(pCity) && (value <= client.conn.playing->economic.gold)) {
1212 pBuf = create_themeicon_button_from_chars(current_theme->OK_Icon, pWindow->dst,
1213 _("Yes"), adj_font(12), 0);
1214
1215 pBuf->action = ok_buy_prod_city_dlg_callback;
1216 set_wstate(pBuf, FC_WS_NORMAL);
1217 pBuf->data.city = pCity;
1218 pBuf->key = SDLK_RETURN;
1219 add_to_gui_list(ID_BUTTON, pBuf);
1220 pBuf->size.w = MAX(pBuf->next->size.w, pBuf->size.w);
1221 pBuf->next->size.w = pBuf->size.w;
1222 area.w = MAX(area.w , 2 * pBuf->size.w + adj_size(20));
1223 }
1224
1225 pHurry_Prod_Dlg->pBeginWidgetList = pBuf;
1226
1227 /* setup window size and start position */
1228 area.w += adj_size(10);
1229 area.h += adj_size(5);
1230
1231 resize_window(pWindow, NULL, get_theme_color(COLOR_THEME_BACKGROUND),
1232 (pWindow->size.w - pWindow->area.w) + area.w,
1233 (pWindow->size.h - pWindow->area.h) + area.h);
1234
1235 area = pWindow->area;
1236
1237 pBuf = pWindow->prev;
1238
1239 if (city_dialog_is_open(pCity))
1240 {
1241 window_x = pCityDlg->pBuy_Button->size.x;
1242 window_y = pCityDlg->pBuy_Button->size.y - pWindow->size.h;
1243 } else {
1244 if(is_city_report_open()) {
1245 fc_assert(pSellected_Widget != NULL);
1246 if (pSellected_Widget->size.x + tileset_tile_width(tileset) + pWindow->size.w > Main.screen->w)
1247 {
1248 window_x = pSellected_Widget->size.x - pWindow->size.w;
1249 } else {
1250 window_x = pSellected_Widget->size.x + tileset_tile_width(tileset);
1251 }
1252
1253 window_y = pSellected_Widget->size.y + (pSellected_Widget->size.h - pWindow->size.h) / 2;
1254 if (window_y + pWindow->size.h > Main.screen->h)
1255 {
1256 window_y = Main.screen->h - pWindow->size.h - 1;
1257 } else {
1258 if (window_y < 0) {
1259 window_y = 0;
1260 }
1261 }
1262 } else {
1263 put_window_near_map_tile(pWindow, pWindow->size.w, pWindow->size.h, pCity->tile);
1264 }
1265
1266 }
1267
1268 widget_set_position(pWindow, window_x, window_y);
1269
1270 /* setup rest of widgets */
1271 /* label */
1272 dst.x = area.x + (area.w - pText->w) / 2;
1273 dst.y = area.y + 1;
1274 alphablit(pText, NULL, pWindow->theme, &dst);
1275 dst.y += pText->h + adj_size(5);
1276 FREESURFACE(pText);
1277
1278 /* no */
1279 pBuf = pWindow->prev;
1280 pBuf->size.y = dst.y;
1281
1282 if (city_can_buy(pCity) && value <= client.conn.playing->economic.gold) {
1283 /* yes */
1284 pBuf = pBuf->prev;
1285 pBuf->size.x = area.x + (area.w - (2 * pBuf->size.w + adj_size(20))) / 2;
1286 pBuf->size.y = dst.y;
1287
1288 /* no */
1289 pBuf->next->size.x = pBuf->size.x + pBuf->size.w + adj_size(20);
1290 } else {
1291 /* no */
1292 pBuf->size.x = area.x + area.w - pBuf->size.w - adj_size(10);
1293 }
1294 /* ================================================== */
1295 /* redraw */
1296 redraw_group(pHurry_Prod_Dlg->pBeginWidgetList, pWindow, 0);
1297 widget_mark_dirty(pWindow);
1298 flush_dirty();
1299 }
1300
1301 /* =======================================================================*/
1302 /* ========================== CHANGE PRODUCTION ==========================*/
1303 /* =======================================================================*/
1304
1305 /**************************************************************************
1306 Popup the change production dialog.
1307 **************************************************************************/
change_prod_dlg_callback(struct widget * pButton)1308 static int change_prod_dlg_callback(struct widget *pButton)
1309 {
1310 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1311 widget_redraw(pButton);
1312 widget_flush(pButton);
1313
1314 disable_city_dlg_widgets();
1315 popup_worklist_editor(pCityDlg->pCity, NULL);
1316 }
1317 return -1;
1318 }
1319
1320 /* =======================================================================*/
1321 /* =========================== SELL IMPROVMENTS ==========================*/
1322 /* =======================================================================*/
1323
1324 /**************************************************************************
1325 Popdown Sell Imprv. Dlg. and exit without sell.
1326 **************************************************************************/
sell_imprvm_dlg_cancel_callback(struct widget * pCancel_Button)1327 static int sell_imprvm_dlg_cancel_callback(struct widget *pCancel_Button)
1328 {
1329 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1330 popdown_window_group_dialog(pCityDlg->pBeginCityMenuWidgetList,
1331 pCityDlg->pEndCityMenuWidgetList);
1332 pCityDlg->pEndCityMenuWidgetList = NULL;
1333 enable_city_dlg_widgets();
1334 redraw_city_dialog(pCityDlg->pCity);
1335 flush_dirty();
1336 }
1337 return -1;
1338 }
1339
1340 /**************************************************************************
1341 Popdown Sell Imprv. Dlg. and exit with sell.
1342 **************************************************************************/
sell_imprvm_dlg_ok_callback(struct widget * pOK_Button)1343 static int sell_imprvm_dlg_ok_callback(struct widget *pOK_Button)
1344 {
1345 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1346 struct widget *pTmp = (struct widget *)pOK_Button->data.ptr;
1347
1348 city_sell_improvement(pCityDlg->pCity, MAX_ID - 3000 - pTmp->ID);
1349
1350 /* popdown, we don't redraw and flush because this is made by redraw city dlg.
1351 when response from server comes */
1352 popdown_window_group_dialog(pCityDlg->pBeginCityMenuWidgetList,
1353 pCityDlg->pEndCityMenuWidgetList);
1354
1355 pCityDlg->pEndCityMenuWidgetList = NULL;
1356
1357 /* del imprv from widget list */
1358 del_widget_from_vertical_scroll_widget_list(pCityDlg->pImprv, pTmp);
1359
1360 enable_city_dlg_widgets();
1361
1362 if (pCityDlg->pImprv->pEndWidgetList) {
1363 set_group_state(pCityDlg->pImprv->pBeginActiveWidgetList,
1364 pCityDlg->pImprv->pEndActiveWidgetList, FC_WS_DISABLED);
1365 }
1366
1367 redraw_city_dialog(pCityDlg->pCity);
1368 flush_dirty();
1369 }
1370 return -1;
1371 }
1372
1373 /**************************************************************************
1374 Popup Sell Imprvm. Dlg.
1375 **************************************************************************/
sell_imprvm_dlg_callback(struct widget * pImpr)1376 static int sell_imprvm_dlg_callback(struct widget *pImpr)
1377 {
1378 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1379 struct SDL_String16 *pStr = NULL;
1380 struct widget *pLabel = NULL;
1381 struct widget *pWindow = NULL;
1382 struct widget *pCancel_Button = NULL;
1383 struct widget *pOK_Button = NULL;
1384 char cBuf[80];
1385 int id;
1386 SDL_Rect area;
1387 int price;
1388
1389 unsellect_widget_action();
1390 disable_city_dlg_widgets();
1391
1392 pStr = create_str16_from_char(_("Sell it?"), adj_font(12));
1393 pStr->style |= TTF_STYLE_BOLD;
1394 pWindow = create_window_skeleton(NULL, pStr, 0);
1395 /*pWindow->action = move_sell_imprvm_dlg_callback; */
1396 /*set_wstate( pWindow, FC_WS_NORMAL ); */
1397 add_to_gui_list(ID_WINDOW, pWindow);
1398 pCityDlg->pEndCityMenuWidgetList = pWindow;
1399
1400 area = pWindow->area;
1401
1402 /* create text label */
1403 id = MAX_ID - 3000 - pImpr->ID;
1404
1405 price = impr_sell_gold(improvement_by_number(id));
1406 fc_snprintf(cBuf, sizeof(cBuf), PL_("Sell %s for %d gold?",
1407 "Sell %s for %d gold?", price),
1408 city_improvement_name_translation(pCityDlg->pCity, improvement_by_number(id)),
1409 price);
1410 pStr = create_str16_from_char(cBuf, adj_font(10));
1411 pStr->style |= (TTF_STYLE_BOLD|SF_CENTER);
1412 pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_SELL);
1413 pLabel = create_iconlabel(NULL, pWindow->dst, pStr, 0);
1414 add_to_gui_list(ID_LABEL, pLabel);
1415
1416 /* create cancel button */
1417 pCancel_Button =
1418 create_themeicon_button_from_chars(current_theme->Small_CANCEL_Icon,
1419 pWindow->dst, _("Cancel"), adj_font(10), 0);
1420 pCancel_Button->action = sell_imprvm_dlg_cancel_callback;
1421 pCancel_Button->key = SDLK_ESCAPE;
1422 set_wstate(pCancel_Button, FC_WS_NORMAL);
1423 add_to_gui_list(ID_BUTTON, pCancel_Button);
1424
1425 /* create ok button */
1426 pOK_Button = create_themeicon_button_from_chars(current_theme->Small_OK_Icon,
1427 pWindow->dst, _("Sell"),
1428 adj_font(10), 0);
1429 pOK_Button->data.ptr = (void *)pImpr;
1430 pOK_Button->size.w = pCancel_Button->size.w;
1431 pOK_Button->action = sell_imprvm_dlg_ok_callback;
1432 pOK_Button->key = SDLK_RETURN;
1433 set_wstate(pOK_Button, FC_WS_NORMAL);
1434 add_to_gui_list(ID_BUTTON, pOK_Button);
1435
1436 pCityDlg->pBeginCityMenuWidgetList = pOK_Button;
1437
1438 /* correct sizes */
1439 if ((pOK_Button->size.w + pCancel_Button->size.w + adj_size(30)) >
1440 pLabel->size.w + adj_size(20)) {
1441 area.w = MAX(area.w, pOK_Button->size.w + pCancel_Button->size.w + adj_size(30));
1442 } else {
1443 area.w = MAX(area.w, pLabel->size.w + adj_size(20));
1444 }
1445
1446 area.h = MAX(area.h, pOK_Button->size.h + pLabel->size.h + adj_size(25));
1447
1448 /* create window background */
1449 resize_window(pWindow, NULL, get_theme_color(COLOR_THEME_BACKGROUND),
1450 (pWindow->size.w - pWindow->area.w) + area.w,
1451 (pWindow->size.h - pWindow->area.h) + area.h);
1452
1453 area = pWindow->area;
1454
1455 /* set start positions */
1456 widget_set_position(pWindow,
1457 (Main.screen->w - pWindow->size.w) / 2,
1458 (Main.screen->h - pWindow->size.h) / 2 + adj_size(10));
1459
1460 pOK_Button->size.x = area.x + adj_size(10);
1461 pOK_Button->size.y = area.y + area.h - pOK_Button->size.h - adj_size(10);
1462
1463 pCancel_Button->size.y = pOK_Button->size.y;
1464 pCancel_Button->size.x = area.x + area.w - pCancel_Button->size.w - adj_size(10);
1465
1466 pLabel->size.x = area.x;
1467 pLabel->size.y = area.y + adj_size(4);
1468 pLabel->size.w = area.w;
1469
1470 /* redraw */
1471 redraw_group(pCityDlg->pBeginCityMenuWidgetList,
1472 pCityDlg->pEndCityMenuWidgetList, 0);
1473
1474 widget_mark_dirty(pWindow);
1475 flush_dirty();
1476 }
1477 return -1;
1478 }
1479 /* ====================================================================== */
1480
1481 /**************************************************************************
1482 Enable city dialog widgets that can be enabled.
1483 **************************************************************************/
enable_city_dlg_widgets(void)1484 void enable_city_dlg_widgets(void)
1485 {
1486 if (pCityDlg) {
1487 set_group_state(pCityDlg->pBeginCityWidgetList,
1488 pCityDlg->pEndCityWidgetList->prev, FC_WS_NORMAL);
1489
1490 if (pCityDlg->pImprv->pEndActiveWidgetList) {
1491
1492 if (pCityDlg->pImprv->pScroll) {
1493 set_wstate(pCityDlg->pImprv->pScroll->pScrollBar, FC_WS_NORMAL); /* vscroll */
1494 set_wstate(pCityDlg->pImprv->pScroll->pUp_Left_Button, FC_WS_NORMAL); /* up */
1495 set_wstate(pCityDlg->pImprv->pScroll->pDown_Right_Button, FC_WS_NORMAL); /* down */
1496 }
1497
1498 /* There is common function test_player_sell_building_now(),
1499 * but we are not using it here, since we want to use set_group_state()
1500 * when possible */
1501 if (pCityDlg->pCity->did_sell
1502 || pCityDlg->pCity->owner != client.conn.playing) {
1503 set_group_state(pCityDlg->pImprv->pBeginActiveWidgetList,
1504 pCityDlg->pImprv->pEndActiveWidgetList, FC_WS_DISABLED);
1505 } else {
1506 struct widget *pTmpWidget = pCityDlg->pImprv->pEndActiveWidgetList;
1507
1508 while (TRUE) {
1509 struct impr_type *pimpr = improvement_by_number(MAX_ID - 3000 -
1510 pTmpWidget->ID);
1511
1512 if (!can_city_sell_building(pCityDlg->pCity, pimpr)) {
1513 set_wstate(pTmpWidget, FC_WS_DISABLED);
1514 } else {
1515 set_wstate(pTmpWidget, FC_WS_NORMAL);
1516 }
1517
1518 if (pTmpWidget == pCityDlg->pImprv->pBeginActiveWidgetList) {
1519 break;
1520 }
1521
1522 pTmpWidget = pTmpWidget->prev;
1523
1524 } /* while */
1525 }
1526 }
1527
1528 if (!city_can_buy(pCityDlg->pCity) && pCityDlg->pBuy_Button) {
1529 set_wstate(pCityDlg->pBuy_Button, FC_WS_DISABLED);
1530 }
1531
1532 if (pCityDlg->pPanel) {
1533 set_group_state(pCityDlg->pPanel->pBeginWidgetList,
1534 pCityDlg->pPanel->pEndWidgetList, FC_WS_NORMAL);
1535 }
1536
1537 if (cma_is_city_under_agent(pCityDlg->pCity, NULL)) {
1538 set_wstate(pCityDlg->pResource_Map, FC_WS_DISABLED);
1539 }
1540
1541 pCityDlg->lock = FALSE;
1542 }
1543 }
1544
1545 /**************************************************************************
1546 Disable all city dialog widgets
1547 **************************************************************************/
disable_city_dlg_widgets(void)1548 static void disable_city_dlg_widgets(void)
1549 {
1550 if (pCityDlg->pPanel) {
1551 set_group_state(pCityDlg->pPanel->pBeginWidgetList,
1552 pCityDlg->pPanel->pEndWidgetList, FC_WS_DISABLED);
1553 }
1554
1555
1556 if (pCityDlg->pImprv->pEndWidgetList) {
1557 set_group_state(pCityDlg->pImprv->pBeginWidgetList,
1558 pCityDlg->pImprv->pEndWidgetList, FC_WS_DISABLED);
1559 }
1560
1561 set_group_state(pCityDlg->pBeginCityWidgetList,
1562 pCityDlg->pEndCityWidgetList->prev, FC_WS_DISABLED);
1563 pCityDlg->lock = TRUE;
1564 }
1565 /* ======================================================================== */
1566
1567 /**************************************************************************
1568 Return scaled city map.
1569 **************************************************************************/
get_scaled_city_map(struct city * pCity)1570 SDL_Surface *get_scaled_city_map(struct city *pCity)
1571 {
1572 SDL_Surface *pBuf = create_city_map(pCity);
1573
1574 city_map_zoom = ((pBuf->w * 159 > pBuf->h * 249) ?
1575 (float)adj_size(249) / pBuf->w
1576 : (float)adj_size(159) / pBuf->h);
1577
1578 return zoomSurface(pBuf, city_map_zoom, city_map_zoom, 1);
1579 }
1580
1581 /**************************************************************************
1582 city resource map: event callback
1583 **************************************************************************/
resource_map_city_dlg_callback(struct widget * pMap)1584 static int resource_map_city_dlg_callback(struct widget *pMap)
1585 {
1586 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1587 int col, row;
1588
1589 if (canvas_to_city_pos(&col, &row,
1590 city_map_radius_sq_get(pCityDlg->pCity),
1591 1/city_map_zoom * (Main.event.motion.x - pMap->dst->dest_rect.x
1592 - pMap->size.x),
1593 1/city_map_zoom * (Main.event.motion.y - pMap->dst->dest_rect.y
1594 - pMap->size.y))) {
1595
1596 city_toggle_worker(pCityDlg->pCity, col, row);
1597 }
1598 }
1599 return -1;
1600 }
1601
1602 /* ====================================================================== */
1603
1604 /************************************************************************
1605 Helper for switch_city_callback.
1606 *************************************************************************/
city_comp_by_turn_founded(const void * a,const void * b)1607 static int city_comp_by_turn_founded(const void *a, const void *b)
1608 {
1609 struct city *pCity1 = *((struct city **) a);
1610 struct city *pCity2 = *((struct city **) b);
1611
1612 return pCity1->turn_founded - pCity2->turn_founded;
1613 }
1614
1615 /**************************************************************************
1616 Callback for next/prev city button
1617 **************************************************************************/
next_prev_city_dlg_callback(struct widget * pButton)1618 static int next_prev_city_dlg_callback(struct widget *pButton)
1619 {
1620 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1621 struct city **array;
1622 int i, dir, non_open_size;
1623 int size = city_list_size(client.conn.playing->cities);
1624
1625 fc_assert_ret_val(size >= 1, -1);
1626 fc_assert_ret_val(city_owner(pCityDlg->pCity)
1627 == client.conn.playing, -1);
1628
1629 if (size == 1) {
1630 return -1;
1631 }
1632
1633 /* dir = 1 will advance to the city, dir = -1 will get previous */
1634 if (pButton->ID == ID_CITY_DLG_NEXT_BUTTON) {
1635 dir = 1;
1636 } else {
1637 if (pButton->ID == ID_CITY_DLG_PREV_BUTTON) {
1638 dir = -1;
1639 } else {
1640 /* Always fails. */
1641 fc_assert_ret_val(pButton->ID == ID_CITY_DLG_NEXT_BUTTON
1642 || pButton->ID != ID_CITY_DLG_PREV_BUTTON, -1);
1643 dir = 1;
1644 }
1645 }
1646
1647 array = fc_calloc(1, size * sizeof(struct city *));
1648
1649 non_open_size = 0;
1650 for (i = 0; i < size; i++) {
1651 array[non_open_size++] = city_list_get(client.conn.playing->cities, i);
1652 }
1653
1654 fc_assert_ret_val(non_open_size > 0, -1);
1655
1656 if (non_open_size == 1) {
1657 FC_FREE(array);
1658 return -1;
1659 }
1660
1661 qsort(array, non_open_size, sizeof(struct city *),
1662 city_comp_by_turn_founded);
1663
1664 for (i = 0; i < non_open_size; i++) {
1665 if (pCityDlg->pCity == array[i]) {
1666 break;
1667 }
1668 }
1669
1670 fc_assert_ret_val(i < non_open_size, -1);
1671 pCityDlg->pCity = array[(i + dir + non_open_size) % non_open_size];
1672 FC_FREE(array);
1673
1674 /* free panel widgets */
1675 free_city_units_lists();
1676 /* refresh resource map */
1677 FREESURFACE(pCityDlg->pResource_Map->theme);
1678 pCityDlg->pResource_Map->theme = get_scaled_city_map(pCityDlg->pCity);
1679 rebuild_imprm_list(pCityDlg->pCity);
1680
1681 /* redraw */
1682 redraw_city_dialog(pCityDlg->pCity);
1683 flush_dirty();
1684 }
1685 return -1;
1686 }
1687
1688 /**************************************************************************
1689 Rename city name:
1690 **************************************************************************/
new_name_city_dlg_callback(struct widget * pEdit)1691 static int new_name_city_dlg_callback(struct widget *pEdit)
1692 {
1693 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1694 char *tmp = convert_to_chars(pEdit->string16->text);
1695
1696 if (tmp) {
1697 if (strcmp(tmp, city_name_get(pCityDlg->pCity))) {
1698 SDL_Client_Flags |= CF_CHANGED_CITY_NAME;
1699 city_rename(pCityDlg->pCity, tmp);
1700 }
1701
1702 FC_FREE(tmp);
1703 } else {
1704 /* empty input -> restore previous content */
1705 copy_chars_to_string16(pEdit->string16, city_name_get(pCityDlg->pCity));
1706 widget_redraw(pEdit);
1707 widget_mark_dirty(pEdit);
1708 flush_dirty();
1709 }
1710 }
1711
1712 return -1;
1713 }
1714
1715 /* ======================================================================= */
1716 /* ======================== Redrawing City Dlg. ========================== */
1717 /* ======================================================================= */
1718
1719 /**************************************************************************
1720 Refresh (update) the city names for the dialog
1721 **************************************************************************/
refresh_city_names(struct city * pcity)1722 static void refresh_city_names(struct city *pcity)
1723 {
1724 if (pCityDlg->pCity_Name_Edit) {
1725 char name[MAX_LEN_NAME];
1726
1727 convertcopy_to_chars(name, MAX_LEN_NAME,
1728 pCityDlg->pCity_Name_Edit->string16->text);
1729 if ((strcmp(city_name_get(pcity), name) != 0)
1730 || (SDL_Client_Flags & CF_CHANGED_CITY_NAME)) {
1731 copy_chars_to_string16(pCityDlg->pCity_Name_Edit->string16, city_name_get(pcity));
1732 rebuild_citydlg_title_str(pCityDlg->pEndCityWidgetList, pcity);
1733 SDL_Client_Flags &= ~CF_CHANGED_CITY_NAME;
1734 }
1735 }
1736 }
1737
1738 /**************************************************************************
1739 Redraw city option panel
1740 207 = max panel width
1741 **************************************************************************/
redraw_misc_city_dialog(struct widget * pCityWindow,struct city * pCity)1742 static void redraw_misc_city_dialog(struct widget *pCityWindow,
1743 struct city *pCity)
1744 {
1745 char cBuf[60];
1746 SDL_String16 *pStr;
1747 SDL_Surface *pSurf;
1748 SDL_Rect dest;
1749
1750 fc_snprintf(cBuf, sizeof(cBuf), _("City options"));
1751
1752 pStr = create_str16_from_char(cBuf, adj_font(10));
1753 pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_PANEL);
1754 pStr->style |= TTF_STYLE_BOLD;
1755
1756 pSurf = create_text_surf_from_str16(pStr);
1757
1758 dest.x = pCityWindow->area.x + adj_size(2) + (adj_size(192) - pSurf->w) / 2;
1759 dest.y = pCityWindow->area.y + adj_size(4) + current_theme->INFO_Icon->h;
1760
1761 alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest);
1762
1763 FREESURFACE(pSurf);
1764 FREESTRING16(pStr);
1765
1766 if (!pCityDlg->pPanel) {
1767 create_city_options_widget_list(pCity);
1768 }
1769 redraw_group(pCityDlg->pPanel->pBeginWidgetList,
1770 pCityDlg->pPanel->pEndWidgetList, 0);
1771 }
1772
1773 /**************************************************************************
1774 Redraw supported unit panel
1775 207 = max panel width
1776 **************************************************************************/
redraw_supported_units_city_dialog(struct widget * pCityWindow,struct city * pCity)1777 static void redraw_supported_units_city_dialog(struct widget *pCityWindow,
1778 struct city *pCity)
1779 {
1780 char cBuf[60];
1781 SDL_String16 *pStr;
1782 SDL_Surface *pSurf;
1783 SDL_Rect dest;
1784 struct unit_list *pList;
1785 int size;
1786
1787 if (city_owner(pCityDlg->pCity) != client.conn.playing) {
1788 pList = (pCityDlg->pCity->client.info_units_supported);
1789 } else {
1790 pList = (pCityDlg->pCity->units_supported);
1791 }
1792
1793 size = unit_list_size(pList);
1794
1795 fc_snprintf(cBuf, sizeof(cBuf), _("Supported units: %d"), size);
1796
1797 pStr = create_str16_from_char(cBuf, adj_font(10));
1798 pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_PANEL);
1799 pStr->style |= TTF_STYLE_BOLD;
1800
1801 pSurf = create_text_surf_from_str16(pStr);
1802
1803 dest.x = pCityWindow->area.x + adj_size(2) + (adj_size(192) - pSurf->w) / 2;
1804 dest.y = pCityWindow->area.y + + adj_size(4) + current_theme->INFO_Icon->h;
1805
1806 alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest);
1807
1808 FREESURFACE(pSurf);
1809 FREESTRING16(pStr);
1810
1811 if (pCityDlg->pPanel) {
1812 if (size) {
1813 redraw_group(pCityDlg->pPanel->pBeginWidgetList,
1814 pCityDlg->pPanel->pEndWidgetList, 0);
1815 } else {
1816 del_group_of_widgets_from_gui_list(pCityDlg->pPanel->pBeginWidgetList,
1817 pCityDlg->pPanel->pEndWidgetList);
1818 FC_FREE(pCityDlg->pPanel->pScroll);
1819 FC_FREE(pCityDlg->pPanel);
1820 }
1821 } else {
1822 if (size) {
1823 create_present_supported_units_widget_list(pList);
1824 redraw_group(pCityDlg->pPanel->pBeginWidgetList,
1825 pCityDlg->pPanel->pEndWidgetList, 0);
1826 }
1827 }
1828 }
1829
1830 /**************************************************************************
1831 Redraw garrison panel
1832 207 = max panel width
1833 **************************************************************************/
redraw_army_city_dialog(struct widget * pCityWindow,struct city * pCity)1834 static void redraw_army_city_dialog(struct widget *pCityWindow,
1835 struct city *pCity)
1836 {
1837 char cBuf[60];
1838 SDL_String16 *pStr;
1839 SDL_Surface *pSurf;
1840 SDL_Rect dest;
1841 struct unit_list *pList;
1842
1843 int size;
1844
1845 if (city_owner(pCityDlg->pCity) != client.conn.playing) {
1846 pList = pCityDlg->pCity->client.info_units_present;
1847 } else {
1848 pList = pCityDlg->pCity->tile->units;
1849 }
1850
1851 size = unit_list_size(pList);
1852
1853 fc_snprintf(cBuf, sizeof(cBuf), _("Present units: %d"), size);
1854
1855 pStr = create_str16_from_char(cBuf, adj_font(10));
1856 pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_PANEL);
1857 pStr->style |= TTF_STYLE_BOLD;
1858
1859 pSurf = create_text_surf_from_str16(pStr);
1860
1861 dest.x = pCityWindow->area.x + adj_size(2) + (adj_size(192) - pSurf->w) / 2;
1862 dest.y = pCityWindow->area.y + adj_size(4) + current_theme->INFO_Icon->h;
1863
1864 alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest);
1865
1866 FREESURFACE(pSurf);
1867 FREESTRING16(pStr);
1868
1869 if (pCityDlg->pPanel) {
1870 if (size) {
1871 redraw_group(pCityDlg->pPanel->pBeginWidgetList,
1872 pCityDlg->pPanel->pEndWidgetList, 0);
1873 } else {
1874 del_group_of_widgets_from_gui_list(pCityDlg->pPanel->pBeginWidgetList,
1875 pCityDlg->pPanel->pEndWidgetList);
1876 FC_FREE(pCityDlg->pPanel->pScroll);
1877 FC_FREE(pCityDlg->pPanel);
1878 }
1879 } else {
1880 if (size) {
1881 create_present_supported_units_widget_list(pList);
1882 redraw_group(pCityDlg->pPanel->pBeginWidgetList,
1883 pCityDlg->pPanel->pEndWidgetList, 0);
1884 }
1885 }
1886 }
1887
1888 /**************************************************************************
1889 Redraw Info panel
1890 207 = max panel width
1891 **************************************************************************/
redraw_info_city_dialog(struct widget * pCityWindow,struct city * pCity)1892 static void redraw_info_city_dialog(struct widget *pCityWindow,
1893 struct city *pCity)
1894 {
1895 char cBuf[30];
1896 struct city *pTradeCity = NULL;
1897 int step, i, xx;
1898 SDL_String16 *pStr = NULL;
1899 SDL_Surface *pSurf = NULL;
1900 SDL_Rect dest;
1901
1902 fc_snprintf(cBuf, sizeof(cBuf), _("City info"));
1903 pStr = create_str16_from_char(cBuf, adj_font(10));
1904 pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_PANEL);
1905 pStr->style |= TTF_STYLE_BOLD;
1906
1907 pSurf = create_text_surf_from_str16(pStr);
1908
1909 dest.x = pCityWindow->area.x + adj_size(2) + (adj_size(192) - pSurf->w) / 2;
1910 dest.y = pCityWindow->area.y + adj_size(4) + current_theme->INFO_Icon->h;
1911
1912 alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest);
1913
1914 dest.x = pCityWindow->size.x + adj_size(10);
1915 dest.y += pSurf->h + 1;
1916
1917 FREESURFACE(pSurf);
1918
1919 change_ptsize16(pStr, adj_font(11));
1920 pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_INFOPANEL);
1921
1922 if (pCity->pollution) {
1923 fc_snprintf(cBuf, sizeof(cBuf), _("Pollution: %d"),
1924 pCity->pollution);
1925
1926 copy_chars_to_string16(pStr, cBuf);
1927
1928 pSurf = create_text_surf_from_str16(pStr);
1929
1930 alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest);
1931
1932 dest.y += pSurf->h + adj_size(3);
1933
1934 FREESURFACE(pSurf);
1935
1936 if (((pIcons->pPollution->w + 1) * pCity->pollution) > adj_size(187)) {
1937 step = (adj_size(187) - pIcons->pPollution->w) / (pCity->pollution - 1);
1938 } else {
1939 step = pIcons->pPollution->w + 1;
1940 }
1941
1942 for (i = 0; i < pCity->pollution; i++) {
1943 alphablit(pIcons->pPollution, NULL, pCityWindow->dst->surface, &dest);
1944 dest.x += step;
1945 }
1946
1947 dest.x = pCityWindow->size.x + adj_size(10);
1948 dest.y += pIcons->pPollution->h + adj_size(3);
1949
1950 } else {
1951 fc_snprintf(cBuf, sizeof(cBuf), _("Pollution: none"));
1952
1953 copy_chars_to_string16(pStr, cBuf);
1954
1955 pSurf = create_text_surf_from_str16(pStr);
1956
1957 alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest);
1958
1959 dest.y += pSurf->h + adj_size(3);
1960
1961 FREESURFACE(pSurf);
1962 }
1963
1964 if (game.info.illness_on) {
1965 int risk_pml = city_illness_calc(pCity, NULL, NULL, NULL, NULL);
1966
1967 fc_snprintf(cBuf, sizeof(cBuf), _("Plague risk: %.1f%%"),
1968 (double)risk_pml / 10.0);
1969 } else {
1970 fc_snprintf(cBuf, sizeof(cBuf), _("Plague risk: none"));
1971 }
1972
1973 copy_chars_to_string16(pStr, cBuf);
1974 pSurf = create_text_surf_from_str16(pStr);
1975 alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest);
1976 dest.y += pSurf->h + adj_size(3);
1977 FREESURFACE(pSurf);
1978
1979 fc_snprintf(cBuf, sizeof(cBuf), _("Trade routes: "));
1980
1981 copy_chars_to_string16(pStr, cBuf);
1982
1983 pSurf = create_text_surf_from_str16(pStr);
1984
1985 alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest);
1986
1987 xx = dest.x + pSurf->w;
1988 dest.y += pSurf->h + adj_size(3);
1989
1990 FREESURFACE(pSurf);
1991
1992 step = 0;
1993 dest.x = pCityWindow->size.x + adj_size(10);
1994
1995 for (i = 0; i < MAX_TRADE_ROUTES; i++) {
1996 if (pCity->trade[i]) {
1997 step += pCity->trade_value[i];
1998
1999 if ((pTradeCity = game_city_by_number(pCity->trade[i]))) {
2000 fc_snprintf(cBuf, sizeof(cBuf), "%s: +%d", city_name_get(pTradeCity),
2001 pCity->trade_value[i]);
2002 } else {
2003 fc_snprintf(cBuf, sizeof(cBuf), "%s: +%d", _("Unknown"),
2004 pCity->trade_value[i]);
2005 }
2006
2007 copy_chars_to_string16(pStr, cBuf);
2008
2009 pSurf = create_text_surf_from_str16(pStr);
2010
2011 alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest);
2012
2013 /* blit trade icon */
2014 dest.x += pSurf->w + adj_size(3);
2015 dest.y += adj_size(4);
2016 alphablit(pIcons->pTrade, NULL, pCityWindow->dst->surface, &dest);
2017 dest.x = pCityWindow->size.x + adj_size(10);
2018 dest.y -= adj_size(4);
2019
2020 dest.y += pSurf->h;
2021
2022 FREESURFACE(pSurf);
2023 }
2024 }
2025
2026 if (step) {
2027 fc_snprintf(cBuf, sizeof(cBuf), _("Trade: +%d"), step);
2028
2029 copy_chars_to_string16(pStr, cBuf);
2030 pSurf = create_text_surf_from_str16(pStr);
2031 alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest);
2032
2033 dest.x += pSurf->w + adj_size(3);
2034 dest.y += adj_size(4);
2035 alphablit(pIcons->pTrade, NULL, pCityWindow->dst->surface, &dest);
2036
2037 FREESURFACE(pSurf);
2038 } else {
2039 fc_snprintf(cBuf, sizeof(cBuf), _("none"));
2040
2041 copy_chars_to_string16(pStr, cBuf);
2042
2043 pSurf = create_text_surf_from_str16(pStr);
2044
2045 dest.x = xx;
2046 dest.y -= pSurf->h + adj_size(3);
2047 alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest);
2048
2049 FREESURFACE(pSurf);
2050 }
2051
2052
2053 FREESTRING16(pStr);
2054 }
2055
2056 /**************************************************************************
2057 Redraw (refresh/update) the happiness info for the dialog
2058 207 - max panel width
2059 180 - max citizens icons area width
2060 **************************************************************************/
redraw_happyness_city_dialog(const struct widget * pCityWindow,struct city * pCity)2061 static void redraw_happyness_city_dialog(const struct widget *pCityWindow,
2062 struct city *pCity)
2063 {
2064 char cBuf[30];
2065 int step, i, j, count;
2066 SDL_Surface *pTmp;
2067 SDL_String16 *pStr = NULL;
2068 SDL_Surface *pSurf = NULL;
2069 SDL_Rect dest = {0, 0, 0, 0};
2070 struct effect_list *sources = effect_list_new();
2071
2072 fc_snprintf(cBuf, sizeof(cBuf), _("Happiness"));
2073
2074 pStr = create_str16_from_char(cBuf, adj_font(10));
2075 pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_PANEL);
2076 pStr->style |= TTF_STYLE_BOLD;
2077
2078 pSurf = create_text_surf_from_str16(pStr);
2079
2080 dest.x = pCityWindow->area.x + adj_size(2) + (adj_size(192) - pSurf->w) / 2;
2081 dest.y = pCityWindow->area.y + adj_size(4) + current_theme->INFO_Icon->h;
2082 alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest);
2083
2084 dest.x = pCityWindow->size.x + adj_size(10);
2085 dest.y += pSurf->h + 1;
2086
2087 FREESURFACE(pSurf);
2088 FREESTRING16(pStr);
2089
2090 count = (pCity->feel[CITIZEN_HAPPY][FEELING_FINAL] + pCity->feel[CITIZEN_CONTENT][FEELING_FINAL]
2091 + pCity->feel[CITIZEN_UNHAPPY][FEELING_FINAL] + pCity->feel[CITIZEN_ANGRY][FEELING_FINAL]
2092 + city_specialists(pCity));
2093
2094 if (count * pIcons->pMale_Happy->w > adj_size(166)) {
2095 step = (adj_size(166) - pIcons->pMale_Happy->w) / (count - 1);
2096 } else {
2097 step = pIcons->pMale_Happy->w;
2098 }
2099
2100 for (j = 0; j < FEELING_LAST; j++) {
2101 if (j == 0 || pCity->feel[CITIZEN_HAPPY][j - 1] != pCity->feel[CITIZEN_HAPPY][j]
2102 || pCity->feel[CITIZEN_CONTENT][j - 1] != pCity->feel[CITIZEN_CONTENT][j]
2103 || pCity->feel[CITIZEN_UNHAPPY][j - 1] != pCity->feel[CITIZEN_UNHAPPY][j]
2104 || pCity->feel[CITIZEN_ANGRY][j - 1] != pCity->feel[CITIZEN_ANGRY][j]) {
2105 int spe, spe_max;
2106
2107 if (j != 0) {
2108 putline(pCityWindow->dst->surface,
2109 dest.x, dest.y, dest.x + adj_size(176), dest.y,
2110 get_theme_color(COLOR_THEME_CITYDLG_FRAME));
2111 dest.y += adj_size(5);
2112 }
2113
2114 if (pCity->feel[CITIZEN_HAPPY][j]) {
2115 pSurf = pIcons->pMale_Happy;
2116 for (i = 0; i < pCity->feel[CITIZEN_HAPPY][j]; i++) {
2117 alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest);
2118 dest.x += step;
2119 if (pSurf == pIcons->pMale_Happy) {
2120 pSurf = pIcons->pFemale_Happy;
2121 } else {
2122 pSurf = pIcons->pMale_Happy;
2123 }
2124 }
2125 }
2126
2127 if (pCity->feel[CITIZEN_CONTENT][j]) {
2128 pSurf = pIcons->pMale_Content;
2129 for (i = 0; i < pCity->feel[CITIZEN_CONTENT][j]; i++) {
2130 alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest);
2131 dest.x += step;
2132 if (pSurf == pIcons->pMale_Content) {
2133 pSurf = pIcons->pFemale_Content;
2134 } else {
2135 pSurf = pIcons->pMale_Content;
2136 }
2137 }
2138 }
2139
2140 if (pCity->feel[CITIZEN_UNHAPPY][j]) {
2141 pSurf = pIcons->pMale_Unhappy;
2142 for (i = 0; i < pCity->feel[CITIZEN_UNHAPPY][j]; i++) {
2143 alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest);
2144 dest.x += step;
2145 if (pSurf == pIcons->pMale_Unhappy) {
2146 pSurf = pIcons->pFemale_Unhappy;
2147 } else {
2148 pSurf = pIcons->pMale_Unhappy;
2149 }
2150 }
2151 }
2152
2153 if (pCity->feel[CITIZEN_ANGRY][j]) {
2154 pSurf = pIcons->pMale_Angry;
2155 for (i = 0; i < pCity->feel[CITIZEN_ANGRY][j]; i++) {
2156 alphablit(pSurf, NULL, pCityWindow->dst->surface, &dest);
2157 dest.x += step;
2158 if (pSurf == pIcons->pMale_Angry) {
2159 pSurf = pIcons->pFemale_Angry;
2160 } else {
2161 pSurf = pIcons->pMale_Angry;
2162 }
2163 }
2164 }
2165
2166 spe_max = specialist_count();
2167 for (spe = 0 ; spe < spe_max; spe++) {
2168 if (pCity->specialists[spe]) {
2169 for (i = 0; i < pCity->specialists[spe]; i++) {
2170 alphablit(pIcons->specialists[spe], NULL, pCityWindow->dst->surface, &dest);
2171 dest.x += step;
2172 }
2173 }
2174 }
2175
2176 if (j == 1) { /* luxury effect */
2177 dest.x =
2178 pCityWindow->size.x + adj_size(212) - pIcons->pBIG_Luxury->w - adj_size(2);
2179 count = dest.y;
2180 dest.y += (pIcons->pMale_Happy->h -
2181 pIcons->pBIG_Luxury->h) / 2;
2182 alphablit(pIcons->pBIG_Luxury, NULL, pCityWindow->dst->surface, &dest);
2183 dest.y = count;
2184 }
2185
2186 if (j == 2) { /* improvements effects */
2187 pSurf = NULL;
2188 count = 0;
2189
2190 get_city_bonus_effects(sources, pCity, NULL, EFT_MAKE_CONTENT);
2191
2192 effect_list_iterate(sources, psource) {
2193
2194 pTmp = get_building_surface(get_building_for_effect(psource->type));
2195 pTmp = zoomSurface(pTmp, DEFAULT_ZOOM * ((float)18 / pTmp->w), DEFAULT_ZOOM * ((float)18 / pTmp->w), 1);
2196
2197 count += (pTmp->h + 1);
2198
2199 if (!pSurf) {
2200 pSurf = pTmp;
2201 } else {
2202 FREESURFACE(pTmp);
2203 }
2204
2205 } effect_list_iterate_end;
2206
2207 dest.x = pCityWindow->size.x + adj_size(187) - pSurf->w - adj_size(2);
2208 i = dest.y;
2209 dest.y += (pIcons->pMale_Happy->h - count) / 2;
2210
2211 FREESURFACE(pSurf);
2212
2213 effect_list_iterate(sources, psource) {
2214
2215 pTmp = get_building_surface(get_building_for_effect(psource->type));
2216 pTmp = zoomSurface(pTmp, DEFAULT_ZOOM * ((float)18 / pTmp->w), DEFAULT_ZOOM * ((float)18 / pTmp->w), 1);
2217
2218 alphablit(pTmp, NULL, pCityWindow->dst->surface, &dest);
2219 dest.y += (pTmp->h + 1);
2220
2221 FREESURFACE(pTmp);
2222 } effect_list_iterate_end;
2223
2224 effect_list_clear(sources);
2225
2226 dest.y = i;
2227
2228 /* TODO: check if code replacement above is correct */
2229 #if 0
2230 if (city_has_building(pCity, improvement_by_number(B_TEMPLE))) {
2231 pTmp1 =
2232 zoomSurface(GET_SURF(improvement_by_number(B_TEMPLE)->sprite),
2233 0.5, 0.5, 1);
2234 count += (pTmp1->h + 1);
2235 pSurf = pTmp1;
2236 } else {
2237 pTmp1 = NULL;
2238 }
2239
2240 if (city_has_building(pCity, improvement_by_number(B_COLOSSEUM))) {
2241 pTmp2 =
2242 zoomSurface(GET_SURF(improvement_by_number(B_COLOSSEUM)->sprite),
2243 0.5, 0.5, 1);
2244 count += (pTmp2->h + 1);
2245 if (!pSurf) {
2246 pSurf = pTmp2;
2247 }
2248 } else {
2249 pTmp2 = NULL;
2250 }
2251
2252 if (city_has_building(pCity, improvement_by_number(B_CATHEDRAL)) ||
2253 city_affected_by_wonder(pCity, B_MICHELANGELO)) {
2254 pTmp3 =
2255 zoomSurface(GET_SURF(improvement_by_number(B_CATHEDRAL)->sprite),
2256 0.5, 0.5, 1);
2257 count += (pTmp3->h + 1);
2258 if (!pSurf) {
2259 pSurf = pTmp3;
2260 }
2261 } else {
2262 pTmp3 = NULL;
2263 }
2264
2265
2266 dest.x = pCityWindow->size.x + adj_size(212) - pSurf->w - adj_size(2);
2267 i = dest.y;
2268 dest.y += (pIcons->pMale_Happy->h - count) / 2;
2269
2270
2271 if (pTmp1) { /* Temple */
2272 alphablit(pTmp1, NULL, pCityWindow->dst->surface, &dest);
2273 dest.y += (pTmp1->h + 1);
2274 }
2275
2276 if (pTmp2) { /* Colosseum */
2277 alphablit(pTmp2, NULL, pCityWindow->dst->surface, &dest);
2278 dest.y += (pTmp2->h + 1);
2279 }
2280
2281 if (pTmp3) { /* Cathedral */
2282 alphablit(pTmp3, NULL, pCityWindow->dst->surface, &dest);
2283 /*dest.y += (pTmp3->h + 1); */
2284 }
2285
2286
2287 FREESURFACE(pTmp1);
2288 FREESURFACE(pTmp2);
2289 FREESURFACE(pTmp3);
2290 dest.y = i;
2291 #endif
2292 }
2293
2294 if (j == 3) { /* police effect */
2295 dest.x = pCityWindow->size.x + adj_size(187) - pIcons->pPolice->w - adj_size(5);
2296 i = dest.y;
2297 dest.y +=
2298 (pIcons->pMale_Happy->h - pIcons->pPolice->h) / 2;
2299 alphablit(pIcons->pPolice, NULL, pCityWindow->dst->surface, &dest);
2300 dest.y = i;
2301 }
2302
2303 if (j == 4) { /* wonders effect */
2304 count = 0;
2305
2306 get_city_bonus_effects(sources, pCity, NULL, EFT_MAKE_HAPPY);
2307 effect_list_iterate(sources, psource) {
2308
2309 pTmp = get_building_surface(get_building_for_effect( psource->type));
2310 pTmp = zoomSurface(pTmp, DEFAULT_ZOOM * ((float)18 / pTmp->w), DEFAULT_ZOOM * ((float)18 / pTmp->w), 1);
2311
2312 count += (pTmp->h + 1);
2313
2314 if (!pSurf) {
2315 pSurf = pTmp;
2316 } else {
2317 FREESURFACE(pTmp);
2318 }
2319
2320 } effect_list_iterate_end;
2321
2322 effect_list_clear(sources);
2323
2324 get_city_bonus_effects(sources, pCity, NULL, EFT_FORCE_CONTENT);
2325
2326 effect_list_iterate(sources, psource) {
2327
2328 pTmp = get_building_surface(get_building_for_effect(psource->type));
2329 pTmp = zoomSurface(pTmp, DEFAULT_ZOOM * ((float)18 / pTmp->w), DEFAULT_ZOOM * ((float)18 / pTmp->w), 1);
2330 count += (pTmp->h + 1);
2331
2332 if (!pSurf) {
2333 pSurf = pTmp;
2334 } else {
2335 FREESURFACE(pTmp);
2336 }
2337
2338 } effect_list_iterate_end;
2339
2340 effect_list_clear(sources);
2341
2342 get_city_bonus_effects(sources, pCity, NULL, EFT_NO_UNHAPPY);
2343
2344 effect_list_iterate(sources, psource) {
2345
2346 pTmp = get_building_surface(get_building_for_effect(psource->type));
2347 pTmp = zoomSurface(pTmp, DEFAULT_ZOOM * ((float)18 / pTmp->w), DEFAULT_ZOOM * ((float)18 / pTmp->w), 1);
2348
2349 count += (pTmp->h + 1);
2350
2351 FREESURFACE(pTmp);
2352
2353 } effect_list_iterate_end;
2354
2355 effect_list_clear(sources);
2356
2357
2358 dest.x = pCityWindow->size.x + adj_size(187) - pSurf->w - adj_size(2);
2359 i = dest.y;
2360 dest.y += (pIcons->pMale_Happy->h - count) / 2;
2361
2362 FREESURFACE(pSurf);
2363
2364 get_city_bonus_effects(sources, pCity, NULL, EFT_MAKE_HAPPY);
2365
2366 effect_list_iterate(sources, psource) {
2367
2368 pTmp = get_building_surface(get_building_for_effect(psource->type));
2369 pTmp = zoomSurface(pTmp, DEFAULT_ZOOM * ((float)18 / pTmp->w), DEFAULT_ZOOM * ((float)18 / pTmp->w), 1);
2370
2371 alphablit(pTmp, NULL, pCityWindow->dst->surface, &dest);
2372 dest.y += (pTmp->h + 1);
2373
2374 FREESURFACE(pTmp);
2375
2376 } effect_list_iterate_end;
2377 effect_list_clear(sources);
2378
2379 get_city_bonus_effects(sources, pCity, NULL, EFT_FORCE_CONTENT);
2380
2381 effect_list_iterate(sources, psource) {
2382
2383 pTmp = get_building_surface(get_building_for_effect(psource->type));
2384 pTmp = zoomSurface(pTmp, DEFAULT_ZOOM * ((float)18 / pTmp->w), DEFAULT_ZOOM * ((float)18 / pTmp->w), 1);
2385
2386 alphablit(pTmp, NULL, pCityWindow->dst->surface, &dest);
2387 dest.y += (pTmp->h + 1);
2388
2389 FREESURFACE(pTmp);
2390
2391 } effect_list_iterate_end;
2392 effect_list_clear(sources);
2393
2394 get_city_bonus_effects(sources, pCity, NULL, EFT_NO_UNHAPPY);
2395
2396 effect_list_iterate(sources, psource) {
2397
2398 pTmp = get_building_surface(get_building_for_effect(psource->type));
2399 pTmp = zoomSurface(pTmp, DEFAULT_ZOOM * ((float)18 / pTmp->w), DEFAULT_ZOOM * ((float)18 / pTmp->w), 1);
2400
2401 alphablit(pTmp, NULL, pCityWindow->dst->surface, &dest);
2402 dest.y += (pTmp->h + 1);
2403
2404 FREESURFACE(pTmp);
2405
2406 } effect_list_iterate_end;
2407 effect_list_clear(sources);
2408
2409 dest.y = i;
2410
2411 /* TODO: check if code replacement above is correct */
2412 #if 0
2413 if (city_affected_by_wonder(pCity, B_CURE)) {
2414 pTmp1 =
2415 zoomSurface(GET_SURF(improvement_by_number(B_CURE)->sprite),
2416 0.5, 0.5, 1);
2417 count += (pTmp1->h + 1);
2418 pSurf = pTmp1;
2419 } else {
2420 pTmp1 = NULL;
2421 }
2422
2423 if (city_affected_by_wonder(pCity, B_SHAKESPEARE)) {
2424 pTmp2 = zoomSurface(
2425 GET_SURF(improvement_by_number(B_SHAKESPEARE)->sprite),
2426 0.5, 0.5, 1);
2427 count += (pTmp2->h + 1);
2428 if (!pSurf) {
2429 pSurf = pTmp2;
2430 }
2431 } else {
2432 pTmp2 = NULL;
2433 }
2434
2435 if (city_affected_by_wonder(pCity, B_BACH)) {
2436 pTmp3 =
2437 zoomSurface(GET_SURF(improvement_by_number(B_BACH)->sprite),
2438 0.5, 0.5, 1);
2439 count += (pTmp3->h + 1);
2440 if (!pSurf) {
2441 pSurf = pTmp3;
2442 }
2443 } else {
2444 pTmp3 = NULL;
2445 }
2446
2447 if (city_affected_by_wonder(pCity, B_HANGING)) {
2448 pTmp4 =
2449 zoomSurface(GET_SURF(improvement_by_number(B_HANGING)->sprite),
2450 0.5, 0.5, 1);
2451 count += (pTmp4->h + 1);
2452 if (!pSurf) {
2453 pSurf = pTmp4;
2454 }
2455 } else {
2456 pTmp4 = NULL;
2457 }
2458
2459 dest.x = pCityWindow->size.x + adj_size(187) - pSurf->w - adj_size(2);
2460 i = dest.y;
2461 dest.y += (pIcons->pMale_Happy->h - count) / 2;
2462
2463
2464 if (pTmp1) { /* Cure of Cancer */
2465 alphablit(pTmp1, NULL, pCityWindow->dst->surface, &dest);
2466 dest.y += (pTmp1->h + 1);
2467 }
2468
2469 if (pTmp2) { /* Shakespeare Theater */
2470 alphablit(pTmp2, NULL, pCityWindow->dst->surface, &dest);
2471 dest.y += (pTmp2->h + 1);
2472 }
2473
2474 if (pTmp3) { /* J. S. Bach ... */
2475 alphablit(pTmp3, NULL, pCityWindow->dst->surface, &dest);
2476 dest.y += (pTmp3->h + 1);
2477 }
2478
2479 if (pTmp4) { /* Hanging Gardens */
2480 alphablit(pTmp4, NULL, pCityWindow->dst->surface, &dest);
2481 /*dest.y += (pTmp4->h + 1); */
2482 }
2483
2484 FREESURFACE(pTmp1);
2485 FREESURFACE(pTmp2);
2486 FREESURFACE(pTmp3);
2487 FREESURFACE(pTmp4);
2488 dest.y = i;
2489 #endif /* 0 */
2490 }
2491
2492 dest.x = pCityWindow->size.x + adj_size(10);
2493 dest.y += pIcons->pMale_Happy->h + adj_size(5);
2494
2495 }
2496 }
2497
2498 effect_list_destroy(sources);
2499 }
2500
2501 /**************************************************************************
2502 Redraw the dialog.
2503 **************************************************************************/
redraw_city_dialog(struct city * pCity)2504 static void redraw_city_dialog(struct city *pCity)
2505 {
2506 char cBuf[40];
2507 int i, step, count, limit;
2508 int cost = 0;
2509 SDL_Rect dest;
2510 struct widget *pWindow = pCityDlg->pEndCityWidgetList;
2511 SDL_Surface *pBuf = NULL, *pBuf2 = NULL;
2512 SDL_String16 *pStr = NULL;
2513 int spe, spe_max;
2514
2515 refresh_city_names(pCity);
2516
2517 if ((city_unhappy(pCity) || city_celebrating(pCity) || city_happy(pCity) ||
2518 cma_is_city_under_agent(pCity, NULL))
2519 ^ ((SDL_Client_Flags & CF_CITY_STATUS_SPECIAL) == CF_CITY_STATUS_SPECIAL)) {
2520 /* city status was changed : NORMAL <-> DISORDER, HAPPY, CELEBR. */
2521
2522 SDL_Client_Flags ^= CF_CITY_STATUS_SPECIAL;
2523
2524 #if 0
2525 /* upd. resource map */
2526 FREESURFACE(pCityDlg->pResource_Map->theme);
2527 pCityDlg->pResource_Map->theme = get_scaled_city_map(pCity);
2528 #endif
2529
2530 /* upd. window title */
2531 rebuild_citydlg_title_str(pCityDlg->pEndCityWidgetList, pCity);
2532 }
2533
2534 /* update resource map */
2535 FREESURFACE(pCityDlg->pResource_Map->theme);
2536 pCityDlg->pResource_Map->theme = get_scaled_city_map(pCity);
2537
2538 /* redraw city dlg */
2539 redraw_group(pCityDlg->pBeginCityWidgetList,
2540 pCityDlg->pEndCityWidgetList, 0);
2541
2542 /* ================================================================= */
2543 fc_snprintf(cBuf, sizeof(cBuf), _("City map"));
2544
2545 pStr = create_str16_from_char(cBuf, adj_font(10));
2546 pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_GOLD);
2547 pStr->style |= TTF_STYLE_BOLD;
2548
2549 pBuf = create_text_surf_from_str16(pStr);
2550
2551 dest.x = pWindow->size.x + adj_size(196) + (adj_size(132) - pBuf->w) / 2;
2552 dest.y = pWindow->size.y + adj_size(49) + (adj_size(13) - pBuf->h) / 2;
2553
2554 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
2555
2556 FREESURFACE(pBuf);
2557
2558 fc_snprintf(cBuf, sizeof(cBuf), _("Citizens"));
2559
2560 copy_chars_to_string16(pStr, cBuf);
2561 pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_LUX);
2562
2563 pBuf = create_text_surf_from_str16(pStr);
2564
2565 dest.x = pWindow->size.x + adj_size(344) + (adj_size(146) - pBuf->w) / 2;
2566 dest.y = pWindow->size.y + adj_size(47) + (adj_size(13) - pBuf->h) / 2;
2567
2568 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
2569
2570 FREESURFACE(pBuf);
2571
2572 fc_snprintf(cBuf, sizeof(cBuf), _("City improvements"));
2573
2574 copy_chars_to_string16(pStr, cBuf);
2575 pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_GOLD);
2576
2577 pBuf = create_text_surf_from_str16(pStr);
2578
2579 dest.x = pWindow->size.x + adj_size(504) + (adj_size(132) - pBuf->w) / 2;
2580 dest.y = pWindow->size.y + adj_size(49) + (adj_size(13) - pBuf->h) / 2;
2581
2582 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
2583
2584 FREESURFACE(pBuf);
2585 /* ================================================================= */
2586 /* food label */
2587 fc_snprintf(cBuf, sizeof(cBuf), _("Food: %d per turn"),
2588 pCity->prod[O_FOOD]);
2589
2590 copy_chars_to_string16(pStr, cBuf);
2591
2592 pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_FOODPERTURN);
2593
2594 pBuf = create_text_surf_from_str16(pStr);
2595
2596 dest.x = pWindow->size.x + adj_size(200);
2597 dest.y = pWindow->size.y + adj_size(228) + (adj_size(16) - pBuf->h) / 2;
2598
2599 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
2600
2601 FREESURFACE(pBuf);
2602
2603 /* draw food income */
2604 dest.y = pWindow->size.y + adj_size(246) + (adj_size(16) - pIcons->pBIG_Food->h) / 2;
2605 dest.x = pWindow->size.x + adj_size(203);
2606
2607 if (pCity->surplus[O_FOOD] >= 0) {
2608 count = pCity->prod[O_FOOD] - pCity->surplus[O_FOOD];
2609 } else {
2610 count = pCity->prod[O_FOOD];
2611 }
2612
2613 if (((pIcons->pBIG_Food->w + 1) * count) > adj_size(200)) {
2614 step = (adj_size(200) - pIcons->pBIG_Food->w) / (count - 1);
2615 } else {
2616 step = pIcons->pBIG_Food->w + 1;
2617 }
2618
2619 for (i = 0; i < count; i++) {
2620 alphablit(pIcons->pBIG_Food, NULL, pWindow->dst->surface, &dest);
2621 dest.x += step;
2622 }
2623
2624 fc_snprintf(cBuf, sizeof(cBuf), Q_("?food:Surplus: %d"),
2625 pCity->surplus[O_FOOD]);
2626
2627 copy_chars_to_string16(pStr, cBuf);
2628 pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_FOOD_SURPLUS);
2629
2630 pBuf = create_text_surf_from_str16(pStr);
2631
2632 dest.x = pWindow->size.x + adj_size(440) - pBuf->w;
2633 dest.y = pWindow->size.y + adj_size(228) + (adj_size(16) - pBuf->h) / 2;
2634
2635 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
2636
2637 FREESURFACE(pBuf);
2638
2639 /* draw surplus of food */
2640 if (pCity->surplus[O_FOOD]) {
2641
2642 if (pCity->surplus[O_FOOD] > 0) {
2643 count = pCity->surplus[O_FOOD];
2644 pBuf = pIcons->pBIG_Food;
2645 } else {
2646 count = -1 * pCity->surplus[O_FOOD];
2647 pBuf = pIcons->pBIG_Food_Corr;
2648 }
2649
2650 dest.x = pWindow->size.x + adj_size(423);
2651 dest.y = pWindow->size.y + adj_size(246) + (adj_size(16) - pBuf->h) / 2;
2652
2653 /*if ( ((pBuf->w + 1) * count ) > 30 ) */
2654 if (count > 2) {
2655 if (count < 18) {
2656 step = (adj_size(30) - pBuf->w) / (count - 1);
2657 } else {
2658 step = 1;
2659 count = 17;
2660 }
2661 } else {
2662 step = pBuf->w + 1;
2663 }
2664
2665 for (i = 0; i < count; i++) {
2666 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
2667 dest.x -= step;
2668 }
2669 }
2670 /* ================================================================= */
2671 /* productions label */
2672 fc_snprintf(cBuf, sizeof(cBuf), _("Production: %d (%d) per turn"),
2673 pCity->surplus[O_SHIELD] ,
2674 pCity->prod[O_SHIELD] + pCity->waste[O_SHIELD]);
2675
2676 copy_chars_to_string16(pStr, cBuf);
2677 pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_PROD);
2678
2679 pBuf = create_text_surf_from_str16(pStr);
2680
2681 dest.x = pWindow->size.x + adj_size(200);
2682 dest.y = pWindow->size.y + adj_size(263) + (adj_size(15) - pBuf->h) / 2;
2683
2684 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
2685
2686 FREESURFACE(pBuf);
2687
2688 /* draw productions schields */
2689 if (pCity->surplus[O_SHIELD]) {
2690
2691 if (pCity->surplus[O_SHIELD] > 0) {
2692 count = pCity->surplus[O_SHIELD] + pCity->waste[O_SHIELD];
2693 pBuf = pIcons->pBIG_Shield;
2694 } else {
2695 count = -1 * pCity->surplus[O_SHIELD];
2696 pBuf = pIcons->pBIG_Shield_Corr;
2697 }
2698
2699 dest.y = pWindow->size.y + adj_size(281) + (adj_size(16) - pBuf->h) / 2;
2700 dest.x = pWindow->size.x + adj_size(203);
2701
2702 if ((pBuf->w * count) > adj_size(200)) {
2703 step = (adj_size(200) - pBuf->w) / (count - 1);
2704 } else {
2705 step = pBuf->w;
2706 }
2707
2708 for (i = 0; i < count; i++) {
2709 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
2710 dest.x += step;
2711 if(i > pCity->surplus[O_SHIELD]) {
2712 pBuf = pIcons->pBIG_Shield_Corr;
2713 }
2714 }
2715 }
2716
2717 /* support shields label */
2718 fc_snprintf(cBuf, sizeof(cBuf), Q_("?production:Support: %d"),
2719 pCity->prod[O_SHIELD] + pCity->waste[O_SHIELD] - pCity->surplus[O_SHIELD]);
2720
2721 copy_chars_to_string16(pStr, cBuf);
2722 pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_SUPPORT);
2723
2724 pBuf = create_text_surf_from_str16(pStr);
2725
2726 dest.x = pWindow->size.x + adj_size(440) - pBuf->w;
2727 dest.y = pWindow->size.y + adj_size(263) + (adj_size(15) - pBuf->h) / 2;
2728
2729 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
2730
2731 FREESURFACE(pBuf);
2732
2733 /* draw support shields */
2734 if (pCity->prod[O_SHIELD] - pCity->surplus[O_SHIELD]) {
2735 dest.x = pWindow->size.x + adj_size(423);
2736 dest.y =
2737 pWindow->size.y + adj_size(281) + (adj_size(16) - pIcons->pBIG_Shield->h) / 2;
2738
2739 if ((pIcons->pBIG_Shield->w + 1) * (pCity->prod[O_SHIELD] -
2740 pCity->surplus[O_SHIELD]) > adj_size(30)) {
2741 step =
2742 (adj_size(30) - pIcons->pBIG_Food->w) / (pCity->prod[O_SHIELD] -
2743 pCity->surplus[O_SHIELD] - 1);
2744 } else {
2745 step = pIcons->pBIG_Shield->w + 1;
2746 }
2747
2748 for (i = 0; i < (pCity->prod[O_SHIELD] - pCity->surplus[O_SHIELD]); i++) {
2749 alphablit(pIcons->pBIG_Shield, NULL, pWindow->dst->surface, &dest);
2750 dest.x -= step;
2751 }
2752 }
2753 /* ================================================================= */
2754
2755 /* trade label */
2756 fc_snprintf(cBuf, sizeof(cBuf), _("Trade: %d per turn"),
2757 pCity->surplus[O_TRADE]);
2758
2759 copy_chars_to_string16(pStr, cBuf);
2760 pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_TRADE);
2761
2762 pBuf = create_text_surf_from_str16(pStr);
2763
2764 dest.x = pWindow->size.x + adj_size(200);
2765 dest.y = pWindow->size.y + adj_size(298) + (adj_size(15) - pBuf->h) / 2;
2766
2767 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
2768
2769 FREESURFACE(pBuf);
2770
2771 /* draw total (trade - corruption) */
2772 if (pCity->surplus[O_TRADE]) {
2773 dest.y =
2774 pWindow->size.y + adj_size(316) + (adj_size(16) - pIcons->pBIG_Trade->h) / 2;
2775 dest.x = pWindow->size.x + adj_size(203);
2776
2777 if (((pIcons->pBIG_Trade->w + 1) * pCity->surplus[O_TRADE]) > adj_size(200)) {
2778 step = (adj_size(200) - pIcons->pBIG_Trade->w) / (pCity->surplus[O_TRADE] - 1);
2779 } else {
2780 step = pIcons->pBIG_Trade->w + 1;
2781 }
2782
2783 for (i = 0; i < pCity->surplus[O_TRADE]; i++) {
2784 alphablit(pIcons->pBIG_Trade, NULL, pWindow->dst->surface, &dest);
2785 dest.x += step;
2786 }
2787 }
2788
2789 /* corruption label */
2790 fc_snprintf(cBuf, sizeof(cBuf), _("Corruption: %d"),
2791 pCity->waste[O_TRADE]);
2792
2793 copy_chars_to_string16(pStr, cBuf);
2794 pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_CORRUPTION);
2795
2796 pBuf = create_text_surf_from_str16(pStr);
2797
2798 dest.x = pWindow->size.x + adj_size(440) - pBuf->w;
2799 dest.y = pWindow->size.y + adj_size(298) + (adj_size(15) - pBuf->h) / 2;
2800
2801 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
2802
2803 FREESURFACE(pBuf);
2804
2805 /* draw corruption */
2806 if (pCity->waste[O_TRADE] > 0) {
2807 dest.x = pWindow->size.x + adj_size(423);
2808 dest.y =
2809 pWindow->size.y + adj_size(316) + (adj_size(16) - pIcons->pBIG_Trade->h) / 2;
2810
2811 if (((pIcons->pBIG_Trade_Corr->w + 1) * pCity->waste[O_TRADE]) > adj_size(30)) {
2812 step =
2813 (adj_size(30) - pIcons->pBIG_Trade_Corr->w) / (pCity->waste[O_TRADE] - 1);
2814 } else {
2815 step = pIcons->pBIG_Trade_Corr->w + 1;
2816 }
2817
2818 for (i = 0; i < pCity->waste[O_TRADE]; i++) {
2819 alphablit(pIcons->pBIG_Trade_Corr, NULL, pWindow->dst->surface,
2820 &dest);
2821 dest.x -= step;
2822 }
2823
2824 }
2825 /* ================================================================= */
2826 /* gold label */
2827 fc_snprintf(cBuf, sizeof(cBuf), _("Gold: %d (%d) per turn"),
2828 pCity->surplus[O_GOLD], pCity->prod[O_GOLD]);
2829
2830 copy_chars_to_string16(pStr, cBuf);
2831 pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_GOLD);
2832
2833 pBuf = create_text_surf_from_str16(pStr);
2834
2835 dest.x = pWindow->size.x + adj_size(200);
2836 dest.y = pWindow->size.y + adj_size(342) + (adj_size(15) - pBuf->h) / 2;
2837
2838 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
2839
2840 FREESURFACE(pBuf);
2841
2842 /* draw coins */
2843 count = pCity->surplus[O_GOLD];
2844 if (count) {
2845
2846 if (count > 0) {
2847 pBuf = pIcons->pBIG_Coin;
2848 } else {
2849 count *= -1;
2850 pBuf = pIcons->pBIG_Coin_Corr;
2851 }
2852
2853 dest.y = pWindow->size.y + adj_size(359) + (adj_size(16) - pBuf->h) / 2;
2854 dest.x = pWindow->size.x + adj_size(203);
2855
2856 if ((pBuf->w * count) > adj_size(110)) {
2857 step = (adj_size(110) - pBuf->w) / (count - 1);
2858 if (!step) {
2859 step = 1;
2860 count = 97;
2861 }
2862 } else {
2863 step = pBuf->w;
2864 }
2865
2866 for (i = 0; i < count; i++) {
2867 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
2868 dest.x += step;
2869 }
2870
2871 }
2872
2873 /* upkeep label */
2874 fc_snprintf(cBuf, sizeof(cBuf), _("Upkeep: %d"),
2875 pCity->prod[O_GOLD] - pCity->surplus[O_GOLD]);
2876
2877 copy_chars_to_string16(pStr, cBuf);
2878 pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_UPKEEP);
2879
2880 pBuf = create_text_surf_from_str16(pStr);
2881
2882 dest.x = pWindow->size.x + adj_size(440) - pBuf->w;
2883 dest.y = pWindow->size.y + adj_size(342) + (adj_size(15) - pBuf->h) / 2;
2884
2885 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
2886
2887 FREESURFACE(pBuf);
2888
2889 /* draw upkeep */
2890 count = pCity->surplus[O_GOLD];
2891 if (pCity->prod[O_GOLD] - count) {
2892
2893 dest.x = pWindow->size.x + adj_size(423);
2894 dest.y = pWindow->size.y + adj_size(359)
2895 + (adj_size(16) - pIcons->pBIG_Coin_UpKeep->h) / 2;
2896
2897 if (((pIcons->pBIG_Coin_UpKeep->w + 1) *
2898 (pCity->prod[O_GOLD] - count)) > adj_size(110)) {
2899 step = (adj_size(110) - pIcons->pBIG_Coin_UpKeep->w) /
2900 (pCity->prod[O_GOLD] - count - 1);
2901 } else {
2902 step = pIcons->pBIG_Coin_UpKeep->w + 1;
2903 }
2904
2905 for (i = 0; i < (pCity->prod[O_GOLD] - count); i++) {
2906 alphablit(pIcons->pBIG_Coin_UpKeep, NULL, pWindow->dst->surface,
2907 &dest);
2908 dest.x -= step;
2909 }
2910 }
2911 /* ================================================================= */
2912 /* science label */
2913 fc_snprintf(cBuf, sizeof(cBuf), _("Science: %d per turn"),
2914 pCity->prod[O_SCIENCE]);
2915
2916 copy_chars_to_string16(pStr, cBuf);
2917 pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_SCIENCE);
2918
2919 pBuf = create_text_surf_from_str16(pStr);
2920
2921 dest.x = pWindow->size.x + adj_size(200);
2922 dest.y = pWindow->size.y + adj_size(376) + (adj_size(15) - pBuf->h) / 2;
2923
2924 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
2925
2926 FREESURFACE(pBuf);
2927
2928 /* draw colb */
2929 count = pCity->prod[O_SCIENCE];
2930 if (count) {
2931
2932 dest.y =
2933 pWindow->size.y + adj_size(394) + (adj_size(16) - pIcons->pBIG_Colb->h) / 2;
2934 dest.x = pWindow->size.x + adj_size(203);
2935
2936 if ((pIcons->pBIG_Colb->w * count) > adj_size(235)) {
2937 step = (adj_size(235) - pIcons->pBIG_Colb->w) / (count - 1);
2938 if (!step) {
2939 step = 1;
2940 count = 222;
2941 }
2942 } else {
2943 step = pIcons->pBIG_Colb->w;
2944 }
2945
2946 for (i = 0; i < count; i++) {
2947 alphablit(pIcons->pBIG_Colb, NULL, pWindow->dst->surface, &dest);
2948 dest.x += step;
2949 }
2950 }
2951 /* ================================================================= */
2952 /* luxury label */
2953 fc_snprintf(cBuf, sizeof(cBuf), _("Luxury: %d per turn"),
2954 pCity->prod[O_LUXURY]);
2955
2956 copy_chars_to_string16(pStr, cBuf);
2957 pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_LUX);
2958
2959 pBuf = create_text_surf_from_str16(pStr);
2960
2961 dest.x = pWindow->size.x + adj_size(200);
2962 dest.y = pWindow->size.y + adj_size(412) + (adj_size(15) - pBuf->h) / 2;
2963
2964 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
2965
2966 FREESURFACE(pBuf);
2967
2968 /* draw luxury */
2969 if (pCity->prod[O_LUXURY]) {
2970
2971 dest.y =
2972 pWindow->size.y + adj_size(429) + (adj_size(16) - pIcons->pBIG_Luxury->h) / 2;
2973 dest.x = pWindow->size.x + adj_size(203);
2974
2975 if ((pIcons->pBIG_Luxury->w * pCity->prod[O_LUXURY]) > adj_size(235)) {
2976 step =
2977 (adj_size(235) - pIcons->pBIG_Luxury->w) / (pCity->prod[O_LUXURY] - 1);
2978 } else {
2979 step = pIcons->pBIG_Luxury->w;
2980 }
2981
2982 for (i = 0; i < pCity->prod[O_LUXURY]; i++) {
2983 alphablit(pIcons->pBIG_Luxury, NULL, pWindow->dst->surface, &dest);
2984 dest.x += step;
2985 }
2986 }
2987 /* ================================================================= */
2988 /* turns to grow label */
2989 count = city_turns_to_grow(pCity);
2990 if (count == 0) {
2991 fc_snprintf(cBuf, sizeof(cBuf), _("City growth: blocked"));
2992 } else if (count == FC_INFINITY) {
2993 fc_snprintf(cBuf, sizeof(cBuf), _("City growth: never"));
2994 } else if (count < 0) {
2995 /* turns until famine */
2996 fc_snprintf(cBuf, sizeof(cBuf),
2997 _("City shrinks: %d %s"), abs(count),
2998 PL_("turn", "turns", abs(count)));
2999 } else {
3000 fc_snprintf(cBuf, sizeof(cBuf),
3001 _("City growth: %d %s"), count,
3002 PL_("turn", "turns", count));
3003 }
3004
3005 copy_chars_to_string16(pStr, cBuf);
3006
3007 pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_GROWTH);
3008
3009 pBuf = create_text_surf_from_str16(pStr);
3010
3011 dest.x = pWindow->size.x + adj_size(445) + (adj_size(192) - pBuf->w) / 2;
3012 dest.y = pWindow->size.y + adj_size(227);
3013
3014 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
3015
3016 FREESURFACE(pBuf);
3017
3018
3019 count = (city_granary_size(city_size_get(pCity))) / 10;
3020
3021 if (count > 12) {
3022 step = (adj_size(168) - pIcons->pBIG_Food->h) / adj_size((11 + count - 12));
3023 i = (count - 1) * step + 14;
3024 count = 12;
3025 } else {
3026 step = pIcons->pBIG_Food->h;
3027 i = count * step;
3028 }
3029
3030 /* food stock */
3031
3032 /* FIXME: check if this code replacement is correct */
3033 /* if (city_has_building(pCity, improvement_by_number(B_GRANARY)) */
3034 /* || city_affected_by_wonder(pCity, B_PYRAMIDS)) { */
3035
3036 if (get_city_bonus(pCity, EFT_GROWTH_FOOD) > 0) {
3037
3038 /* with granary */
3039 /* stocks label */
3040 copy_chars_to_string16(pStr, _("Stock"));
3041 pBuf = create_text_surf_from_str16(pStr);
3042
3043 dest.x = pWindow->size.x + adj_size(461) + (adj_size(76) - pBuf->w) / 2;
3044 dest.y = pWindow->size.y + adj_size(258) - pBuf->h - 1;
3045
3046 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
3047
3048 FREESURFACE(pBuf);
3049
3050 /* granary label */
3051 copy_chars_to_string16(pStr, _("Granary"));
3052 pBuf = create_text_surf_from_str16(pStr);
3053
3054 dest.x = pWindow->size.x + adj_size(549) + (adj_size(76) - pBuf->w) / 2;
3055 dest.y = pWindow->size.y + adj_size(258) - pBuf->h - 1;
3056
3057 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
3058
3059 FREESURFACE(pBuf);
3060
3061 /* draw bcgd granary */
3062 dest.x = pWindow->size.x + adj_size(462);
3063 dest.y = pWindow->size.y + adj_size(260);
3064 dest.w = 70 + 4;
3065 dest.h = i + 4;
3066
3067 SDL_FillRectAlpha(pWindow->dst->surface, &dest, get_theme_color(COLOR_THEME_CITYDLG_GRANARY));
3068
3069 putframe(pWindow->dst->surface,
3070 dest.x - 1, dest.y - 1, dest.x + dest.w, dest.y + dest.h,
3071 get_theme_color(COLOR_THEME_CITYDLG_FRAME));
3072
3073 /* draw bcgd stocks*/
3074 dest.x = pWindow->size.x + adj_size(550);
3075 dest.y = pWindow->size.y + adj_size(260);
3076
3077 SDL_FillRectAlpha(pWindow->dst->surface, &dest, get_theme_color(COLOR_THEME_CITYDLG_STOCKS));
3078
3079 putframe(pWindow->dst->surface,
3080 dest.x - 1, dest.y - 1, dest.x + dest.w, dest.y + dest.h,
3081 get_theme_color(COLOR_THEME_CITYDLG_FRAME));
3082
3083 /* draw stocks icons */
3084 cost = city_granary_size(city_size_get(pCity));
3085 if (pCity->food_stock + pCity->surplus[O_FOOD] > cost) {
3086 count = cost;
3087 } else {
3088 if(pCity->surplus[O_FOOD] < 0) {
3089 count = pCity->food_stock;
3090 } else {
3091 count = pCity->food_stock + pCity->surplus[O_FOOD];
3092 }
3093 }
3094 cost /= 2;
3095
3096 if(pCity->surplus[O_FOOD] < 0) {
3097 limit = pCity->food_stock + pCity->surplus[O_FOOD];
3098 if(limit < 0) {
3099 limit = 0;
3100 }
3101 } else {
3102 limit = 0xffff;
3103 }
3104
3105 dest.x += 2;
3106 dest.y += 2;
3107 i = 0;
3108 pBuf = pIcons->pBIG_Food;
3109 while (count && cost) {
3110 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
3111 dest.x += pBuf->w;
3112 count--;
3113 cost--;
3114 i++;
3115 if (dest.x > pWindow->size.x + adj_size(620)) {
3116 dest.x = pWindow->size.x + adj_size(552);
3117 dest.y += step;
3118 }
3119 if(i > limit - 1) {
3120 pBuf = pIcons->pBIG_Food_Corr;
3121 } else {
3122 if(i > pCity->food_stock - 1)
3123 {
3124 pBuf = pIcons->pBIG_Food_Surplus;
3125 }
3126 }
3127 }
3128 /* draw granary icons */
3129 dest.x = pWindow->size.x + adj_size(462) + adj_size(2);
3130 dest.y = pWindow->size.y + adj_size(260) + adj_size(2);
3131
3132 while (count) {
3133 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
3134 dest.x += pBuf->w;
3135 count--;
3136 i++;
3137 if (dest.x > pWindow->size.x + adj_size(532)) {
3138 dest.x = pWindow->size.x + adj_size(464);
3139 dest.y += step;
3140 }
3141 if(i > limit - 1) {
3142 pBuf = pIcons->pBIG_Food_Corr;
3143 } else {
3144 if(i > pCity->food_stock - 1)
3145 {
3146 pBuf = pIcons->pBIG_Food_Surplus;
3147 }
3148 }
3149 }
3150
3151 } else {
3152 /* without granary */
3153 /* stocks label */
3154 copy_chars_to_string16(pStr, _("Stock"));
3155 pBuf = create_text_surf_from_str16(pStr);
3156
3157 dest.x = pWindow->size.x + adj_size(461) + (adj_size(144) - pBuf->w) / 2;
3158 dest.y = pWindow->size.y + adj_size(258) - pBuf->h - 1;
3159
3160 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
3161 FREESURFACE(pBuf);
3162
3163 /* food stock */
3164
3165 /* draw bcgd */
3166 dest.x = pWindow->size.x + adj_size(462);
3167 dest.y = pWindow->size.y + adj_size(260);
3168 dest.w = adj_size(144);
3169 dest.h = i + adj_size(4);
3170
3171 SDL_FillRectAlpha(pWindow->dst->surface, &dest, get_theme_color(COLOR_THEME_CITYDLG_FOODSTOCK));
3172
3173 putframe(pWindow->dst->surface,
3174 dest.x - 1, dest.y - 1, dest.x + dest.w, dest.y + dest.h,
3175 get_theme_color(COLOR_THEME_CITYDLG_FRAME));
3176
3177 /* draw icons */
3178 cost = city_granary_size(city_size_get(pCity));
3179 if (pCity->food_stock + pCity->surplus[O_FOOD] > cost) {
3180 count = cost;
3181 } else {
3182 if(pCity->surplus[O_FOOD] < 0) {
3183 count = pCity->food_stock;
3184 } else {
3185 count = pCity->food_stock + pCity->surplus[O_FOOD];
3186 }
3187 }
3188
3189 if(pCity->surplus[O_FOOD] < 0) {
3190 limit = pCity->food_stock + pCity->surplus[O_FOOD];
3191 if(limit < 0) {
3192 limit = 0;
3193 }
3194 } else {
3195 limit = 0xffff;
3196 }
3197
3198 dest.x += adj_size(2);
3199 dest.y += adj_size(2);
3200 i = 0;
3201 pBuf = pIcons->pBIG_Food;
3202 while (count) {
3203 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
3204 dest.x += pBuf->w;
3205 count--;
3206 i++;
3207 if (dest.x > pWindow->size.x + adj_size(602)) {
3208 dest.x = pWindow->size.x + adj_size(464);
3209 dest.y += step;
3210 }
3211 if(i > limit - 1) {
3212 pBuf = pIcons->pBIG_Food_Corr;
3213 } else {
3214 if(i > pCity->food_stock - 1)
3215 {
3216 pBuf = pIcons->pBIG_Food_Surplus;
3217 }
3218 }
3219 }
3220 }
3221 /* ================================================================= */
3222
3223 /* draw productions shields progress */
3224 if (VUT_UTYPE == pCity->production.kind) {
3225 struct unit_type *pUnitType = pCity->production.value.utype;
3226 cost = utype_build_shield_cost(pUnitType);
3227 count = cost / 10;
3228
3229 copy_chars_to_string16(pStr, utype_name_translation(pUnitType));
3230 pBuf = create_text_surf_from_str16(pStr);
3231
3232 pBuf2 = get_unittype_surface(pUnitType, direction8_invalid());
3233 pBuf2 = zoomSurface(pBuf2, DEFAULT_ZOOM * ((float)32 / pBuf2->h), DEFAULT_ZOOM * ((float)32 / pBuf2->h), 1);
3234
3235 /* blit unit icon */
3236 dest.x = pWindow->size.x + adj_size(6) + (adj_size(185) - (pBuf->w + pBuf2->w + adj_size(5))) / 2;
3237 dest.y = pWindow->size.y + adj_size(233);
3238
3239 alphablit(pBuf2, NULL, pWindow->dst->surface, &dest);
3240
3241 dest.y += (pBuf2->h - pBuf->h) / 2;
3242 dest.x += pBuf2->w + adj_size(5);
3243
3244 } else {
3245 struct impr_type *pImprove = pCity->production.value.building;
3246
3247 if (improvement_has_flag(pImprove, IF_GOLD)) {
3248
3249 if (pCityDlg->pBuy_Button
3250 && get_wstate(pCityDlg->pBuy_Button) != FC_WS_DISABLED) {
3251 set_wstate(pCityDlg->pBuy_Button, FC_WS_DISABLED);
3252 widget_redraw(pCityDlg->pBuy_Button);
3253 }
3254
3255 /* You can't see capitalization progres */
3256 count = 0;
3257
3258 } else {
3259
3260 if (city_can_buy(pCity) && pCityDlg->pBuy_Button
3261 && (get_wstate(pCityDlg->pBuy_Button) == FC_WS_DISABLED)) {
3262 set_wstate(pCityDlg->pBuy_Button, FC_WS_NORMAL);
3263 widget_redraw(pCityDlg->pBuy_Button);
3264 }
3265
3266 cost = impr_build_shield_cost(pImprove);
3267 count = cost / 10;
3268
3269 }
3270
3271 copy_chars_to_string16(pStr, improvement_name_translation(pImprove));
3272 pBuf = create_text_surf_from_str16(pStr);
3273
3274 pBuf2 = get_building_surface(pCity->production.value.building);
3275 pBuf2 = zoomSurface(pBuf2, DEFAULT_ZOOM * ((float)32 / pBuf2->h), DEFAULT_ZOOM * ((float)32 / pBuf2->h), 1);
3276
3277 /* blit impr icon */
3278 dest.x = pWindow->size.x + adj_size(6) + (adj_size(185) - (pBuf->w + pBuf2->w + adj_size(5))) / 2;
3279 dest.y = pWindow->size.y + adj_size(233);
3280
3281 alphablit(pBuf2, NULL, pWindow->dst->surface, &dest);
3282
3283 dest.y += (pBuf2->h - pBuf->h) / 2;
3284 dest.x += pBuf2->w + adj_size(5);
3285 }
3286
3287 /* blit unit/impr name */
3288 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
3289
3290 FREESURFACE(pBuf);
3291 FREESURFACE(pBuf2);
3292
3293 if (count) {
3294 if (count > 11) {
3295 step = (adj_size(154) - pIcons->pBIG_Shield->h) / adj_size((10 + count - 11));
3296
3297 if(!step) step = 1;
3298
3299 i = (step * (count - 1)) + pIcons->pBIG_Shield->h;
3300 } else {
3301 step = pIcons->pBIG_Shield->h;
3302 i = count * step;
3303 }
3304
3305 /* draw sheild stock background */
3306 dest.x = pWindow->size.x + adj_size(28);
3307 dest.y = pWindow->size.y + adj_size(270);
3308 dest.w = adj_size(144);
3309 dest.h = i + adj_size(4);
3310
3311 SDL_FillRectAlpha(pWindow->dst->surface, &dest, get_theme_color(COLOR_THEME_CITYDLG_SHIELDSTOCK));
3312 putframe(pWindow->dst->surface,
3313 dest.x - 1, dest.y - 1, dest.x + dest.w, dest.y + dest.h,
3314 get_theme_color(COLOR_THEME_CITYDLG_FRAME));
3315
3316 /* draw production progres text */
3317 dest.y = pWindow->size.y + adj_size(270) + dest.h + 1;
3318
3319 if (pCity->shield_stock < cost) {
3320 count = city_production_turns_to_build(pCity, TRUE);
3321 if (count == 999) {
3322 fc_snprintf(cBuf, sizeof(cBuf), "(%d/%d) %s!",
3323 pCity->shield_stock, cost, _("blocked"));
3324 } else {
3325 fc_snprintf(cBuf, sizeof(cBuf), "(%d/%d) %d %s",
3326 pCity->shield_stock, cost, count, PL_("turn", "turns", count));
3327 }
3328 } else {
3329 fc_snprintf(cBuf, sizeof(cBuf), "(%d/%d) %s!",
3330 pCity->shield_stock, cost, _("finished"));
3331 }
3332
3333 copy_chars_to_string16(pStr, cBuf);
3334 pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_LUX);
3335
3336 pBuf = create_text_surf_from_str16(pStr);
3337
3338 dest.x = pWindow->size.x + adj_size(6) + (adj_size(185) - pBuf->w) / 2;
3339
3340 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
3341
3342 FREESTRING16(pStr);
3343 FREESURFACE(pBuf);
3344
3345 /* draw sheild stock */
3346 if (pCity->shield_stock + pCity->surplus[O_SHIELD] <= cost) {
3347 count = pCity->shield_stock + pCity->surplus[O_SHIELD];
3348 } else {
3349 count = cost;
3350 }
3351 dest.x = pWindow->size.x + adj_size(29) + adj_size(2);
3352 dest.y = pWindow->size.y + adj_size(270) + adj_size(2);
3353 i = 0;
3354
3355 pBuf = pIcons->pBIG_Shield;
3356 while (count > 0) {
3357 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
3358 dest.x += pBuf->w;
3359 count--;
3360 if (dest.x > pWindow->size.x + adj_size(170)) {
3361 dest.x = pWindow->size.x + adj_size(31);
3362 dest.y += step;
3363 }
3364 i++;
3365 if(i > pCity->shield_stock - 1) {
3366 pBuf = pIcons->pBIG_Shield_Surplus;
3367 }
3368 }
3369 }
3370
3371 /* count != 0 */
3372 /* ==================================================== */
3373 /* Draw Citizens */
3374 count = (pCity->feel[CITIZEN_HAPPY][FEELING_FINAL] + pCity->feel[CITIZEN_CONTENT][FEELING_FINAL]
3375 + pCity->feel[CITIZEN_UNHAPPY][FEELING_FINAL] + pCity->feel[CITIZEN_ANGRY][FEELING_FINAL]
3376 + city_specialists(pCity));
3377
3378 pBuf = get_citizen_surface(CITIZEN_HAPPY, 0);
3379
3380 if (count > 13) {
3381 step = (adj_size(440) - pBuf->w) / (adj_size(12 + count - 13));
3382 } else {
3383 step = pBuf->w;
3384 }
3385
3386 pCityDlg->citizen_step = step;
3387
3388 dest.x = pWindow->size.x + adj_size(198);
3389 dest.y = pWindow->size.y + pWindow->area.y + adj_size(1) + (adj_size(22) - pBuf->h) / 2;
3390
3391 pCityDlg->spec_area.x = pWindow->dst->dest_rect.x + dest.x;
3392 pCityDlg->spec_area.y = pWindow->dst->dest_rect.y + dest.y;
3393 pCityDlg->spec_area.w = count * step;
3394 pCityDlg->spec_area.h = pBuf->h;
3395
3396 if (pCity->feel[CITIZEN_HAPPY][FEELING_FINAL]) {
3397 for (i = 0; i < pCity->feel[CITIZEN_HAPPY][FEELING_FINAL]; i++) {
3398 pBuf = adj_surf(get_citizen_surface(CITIZEN_HAPPY, i));
3399
3400 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
3401 dest.x += step;
3402 FREESURFACE(pBuf);
3403 }
3404 }
3405
3406 if (pCity->feel[CITIZEN_CONTENT][FEELING_FINAL]) {
3407 for (i = 0; i < pCity->feel[CITIZEN_CONTENT][FEELING_FINAL]; i++) {
3408 pBuf = adj_surf(get_citizen_surface(CITIZEN_CONTENT, i));
3409
3410 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
3411 dest.x += step;
3412 FREESURFACE(pBuf);
3413 }
3414 }
3415
3416 if (pCity->feel[CITIZEN_UNHAPPY][FEELING_FINAL]) {
3417 for (i = 0; i < pCity->feel[CITIZEN_UNHAPPY][FEELING_FINAL]; i++) {
3418 pBuf = adj_surf(get_citizen_surface(CITIZEN_UNHAPPY, i));
3419
3420 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
3421 dest.x += step;
3422 FREESURFACE(pBuf);
3423 }
3424 }
3425
3426 if (pCity->feel[CITIZEN_ANGRY][FEELING_FINAL]) {
3427 for (i = 0; i < pCity->feel[CITIZEN_ANGRY][FEELING_FINAL]; i++) {
3428 pBuf = adj_surf(get_citizen_surface(CITIZEN_ANGRY, i));
3429 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
3430 dest.x += step;
3431 FREESURFACE(pBuf);
3432 }
3433 }
3434
3435 spe_max = specialist_count();
3436 for (spe = 0; spe < spe_max; spe++) {
3437 if (pCity->specialists[spe] > 0) {
3438 pBuf = adj_surf(get_citizen_surface(CITIZEN_SPECIALIST + spe, i));
3439
3440 for (i = 0; i < pCity->specialists[spe]; i++) {
3441 alphablit(pBuf, NULL, pWindow->dst->surface, &dest);
3442 dest.x += step;
3443 }
3444 FREESURFACE(pBuf);
3445 }
3446 }
3447
3448 /* ==================================================== */
3449
3450
3451 switch (pCityDlg->page) {
3452 case INFO_PAGE:
3453 redraw_info_city_dialog(pWindow, pCity);
3454 break;
3455
3456 case HAPPINESS_PAGE:
3457 redraw_happyness_city_dialog(pWindow, pCity);
3458 break;
3459
3460 case ARMY_PAGE:
3461 redraw_army_city_dialog(pWindow, pCity);
3462 break;
3463
3464 case SUPPORTED_UNITS_PAGE:
3465 redraw_supported_units_city_dialog(pWindow, pCity);
3466 break;
3467
3468 case MISC_PAGE:
3469 redraw_misc_city_dialog(pWindow, pCity);
3470 break;
3471
3472 default:
3473 break;
3474
3475 }
3476
3477 /* redraw "sell improvement" dialog */
3478 redraw_group(pCityDlg->pBeginCityMenuWidgetList,
3479 pCityDlg->pEndCityMenuWidgetList, 0);
3480
3481 widget_mark_dirty(pWindow);
3482 }
3483
3484 /* ============================================================== */
3485
3486 /**************************************************************************
3487 Recreate improvement list for city dialog.
3488 **************************************************************************/
rebuild_imprm_list(struct city * pCity)3489 static void rebuild_imprm_list(struct city *pCity)
3490 {
3491 int count = 0;
3492 struct widget *pWindow = pCityDlg->pEndCityWidgetList;
3493 struct widget *pAdd_Dock, *pBuf, *pLast;
3494 SDL_Surface *pLogo = NULL;
3495 SDL_String16 *pStr = NULL;
3496 struct player *pOwner = city_owner(pCity);
3497 int prev_y = 0;
3498
3499 if(!pCityDlg->pImprv) {
3500 pCityDlg->pImprv = fc_calloc(1, sizeof(struct ADVANCED_DLG));
3501 }
3502
3503 /* free old list */
3504 if (pCityDlg->pImprv->pEndWidgetList) {
3505 del_group_of_widgets_from_gui_list(pCityDlg->pImprv->pBeginWidgetList,
3506 pCityDlg->pImprv->pEndWidgetList);
3507 pCityDlg->pImprv->pEndWidgetList = NULL;
3508 pCityDlg->pImprv->pBeginWidgetList = NULL;
3509 pCityDlg->pImprv->pEndActiveWidgetList = NULL;
3510 pCityDlg->pImprv->pBeginActiveWidgetList = NULL;
3511 pCityDlg->pImprv->pActiveWidgetList = NULL;
3512 FC_FREE(pCityDlg->pImprv->pScroll);
3513 }
3514
3515 pAdd_Dock = pCityDlg->pAdd_Point;
3516 pBuf = pLast = pAdd_Dock;
3517
3518 /* allock new */
3519 city_built_iterate(pCity, pImprove) {
3520
3521 pStr = create_str16_from_char(city_improvement_name_translation(pCity, pImprove), adj_font(10));
3522 pStr->fgcol = *get_theme_color(COLOR_THEME_CITYDLG_IMPR);
3523
3524 pStr->style |= TTF_STYLE_BOLD;
3525
3526 pLogo = get_building_surface(pImprove);
3527 pLogo = ResizeSurfaceBox(pLogo, adj_size(22), adj_size(22), 1, TRUE, TRUE);
3528
3529 pBuf = create_iconlabel(pLogo, pWindow->dst, pStr,
3530 (WF_FREE_THEME | WF_RESTORE_BACKGROUND));
3531
3532 pBuf->size.x = pWindow->size.x + adj_size(450);
3533 pBuf->size.y = pWindow->size.y + adj_size(66) + prev_y;
3534
3535 prev_y += pBuf->size.h;
3536
3537 pBuf->size.w = adj_size(165);
3538 pBuf->action = sell_imprvm_dlg_callback;
3539
3540 if (!pCityDlg->pCity->did_sell
3541 && !is_wonder(pImprove) && (pOwner == client.conn.playing)) {
3542 set_wstate(pBuf, FC_WS_NORMAL);
3543 }
3544
3545 pBuf->ID = MAX_ID - improvement_number(pImprove) - 3000;
3546 DownAdd(pBuf, pAdd_Dock);
3547 pAdd_Dock = pBuf;
3548
3549 count++;
3550
3551 if (count > 7) {
3552 set_wflag(pBuf, WF_HIDDEN);
3553 }
3554
3555 } city_built_iterate_end;
3556
3557 if (count) {
3558 pCityDlg->pImprv->pEndWidgetList = pLast->prev;
3559 pCityDlg->pImprv->pEndActiveWidgetList = pCityDlg->pImprv->pEndWidgetList;
3560 pCityDlg->pImprv->pBeginWidgetList = pBuf;
3561 pCityDlg->pImprv->pBeginActiveWidgetList = pCityDlg->pImprv->pBeginWidgetList;
3562
3563 if (count > 7) {
3564 pCityDlg->pImprv->pActiveWidgetList = pCityDlg->pImprv->pEndActiveWidgetList;
3565
3566 create_vertical_scrollbar(pCityDlg->pImprv, 1, 7, TRUE, TRUE);
3567
3568 setup_vertical_scrollbar_area(pCityDlg->pImprv->pScroll,
3569 pWindow->size.x + adj_size(635),
3570 pWindow->size.y + adj_size(66),
3571 adj_size(155), TRUE);
3572 }
3573 }
3574 }
3575
3576 /**************************************************************************
3577 Recreate citydialog title.
3578 **************************************************************************/
rebuild_citydlg_title_str(struct widget * pWindow,struct city * pCity)3579 static void rebuild_citydlg_title_str(struct widget *pWindow,
3580 struct city *pCity)
3581 {
3582 char cBuf[512];
3583
3584 fc_snprintf(cBuf, sizeof(cBuf),
3585 _("City of %s (Population %s citizens)"),
3586 city_name_get(pCity),
3587 population_to_text(city_population(pCity)));
3588
3589 if (city_unhappy(pCity)) {
3590 /* TRANS: preserve leading space */
3591 fc_strlcat(cBuf, _(" - DISORDER"), sizeof(cBuf));
3592 } else {
3593 if (city_celebrating(pCity)) {
3594 /* TRANS: preserve leading space */
3595 fc_strlcat(cBuf, _(" - celebrating"), sizeof(cBuf));
3596 } else {
3597 if (city_happy(pCity)) {
3598 /* TRANS: preserve leading space */
3599 fc_strlcat(cBuf, _(" - happy"), sizeof(cBuf));
3600 }
3601 }
3602 }
3603
3604 if (cma_is_city_under_agent(pCity, NULL)) {
3605 /* TRANS: preserve leading space */
3606 fc_strlcat(cBuf, _(" - under Citizen Governor control."), sizeof(cBuf));
3607 }
3608
3609 copy_chars_to_string16(pWindow->string16, cBuf);
3610 }
3611
3612
3613 /* ========================= Public ================================== */
3614
3615 /**************************************************************************
3616 Pop up (or bring to the front) a dialog for the given city. It may or
3617 may not be modal.
3618 **************************************************************************/
real_city_dialog_popup(struct city * pCity)3619 void real_city_dialog_popup(struct city *pCity)
3620 {
3621 struct widget *pWindow = NULL, *pBuf = NULL;
3622 SDL_Surface *pLogo = NULL;
3623 SDL_String16 *pStr = NULL;
3624 int cs;
3625 struct player *pOwner = city_owner(pCity);
3626 SDL_Rect area;
3627
3628 if (pCityDlg) {
3629 return;
3630 }
3631
3632 menus_update();
3633
3634 pCityDlg = fc_calloc(1, sizeof(struct city_dialog));
3635 pCityDlg->pCity = pCity;
3636 pCityDlg->page = ARMY_PAGE;
3637
3638 pStr = create_string16(NULL, 0, adj_font(12));
3639 pStr->style |= TTF_STYLE_BOLD;
3640 pWindow = create_window(NULL, pStr, adj_size(640), adj_size(480), 0);
3641
3642 rebuild_citydlg_title_str(pWindow, pCity);
3643
3644 pWindow->action = city_dlg_callback;
3645 set_wstate(pWindow, FC_WS_NORMAL);
3646
3647 add_to_gui_list(ID_CITY_DLG_WINDOW, pWindow);
3648
3649 pCityDlg->pEndCityWidgetList = pWindow;
3650
3651 /* create window background */
3652 pLogo = theme_get_background(theme, BACKGROUND_CITYDLG);
3653 if (resize_window(pWindow, pLogo, NULL, adj_size(640), adj_size(480))) {
3654 FREESURFACE(pLogo);
3655 }
3656
3657 pLogo = get_city_gfx();
3658 alphablit(pLogo, NULL, pWindow->theme, NULL);
3659
3660 area = pWindow->area;
3661
3662 widget_set_position(pWindow,
3663 (Main.screen->w - pWindow->size.w) / 2,
3664 (Main.screen->h - pWindow->size.h) / 2);
3665
3666 /* ============================================================= */
3667
3668 /* close dialog button */
3669 pBuf = create_themeicon(current_theme->Small_CANCEL_Icon, pWindow->dst,
3670 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
3671 pBuf->info_label = create_str16_from_char(_("Close Dialog (Esc)"),
3672 adj_font(12));
3673 pBuf->action = exit_city_dlg_callback;
3674 pBuf->size.x = area.x + area.w - pBuf->size.w;
3675 pBuf->size.y = pWindow->size.y + adj_size(2);
3676 pBuf->key = SDLK_ESCAPE;
3677 set_wstate(pBuf, FC_WS_NORMAL);
3678 add_to_gui_list(ID_CITY_DLG_EXIT_BUTTON, pBuf);
3679
3680 /* -------- */
3681
3682 pBuf = create_themeicon(current_theme->Army_Icon, pWindow->dst,
3683 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
3684 pBuf->info_label = create_str16_from_char(_("Present units"),
3685 adj_font(12));
3686 pBuf->action = army_city_dlg_callback;
3687 pBuf->size.x = area.x + adj_size(2) + ((adj_size(183) - 5 * pBuf->size.w) / 6);
3688 pBuf->size.y = area.y + adj_size(2);
3689 set_wstate(pBuf, FC_WS_NORMAL);
3690 add_to_gui_list(ID_CITY_DLG_ARMY_BUTTON, pBuf);
3691 /* -------- */
3692
3693 pBuf = create_themeicon(current_theme->Support_Icon, pWindow->dst,
3694 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
3695 pBuf->info_label = create_str16_from_char(_("Supported units"),
3696 adj_font(12));
3697 pBuf->action = supported_unit_city_dlg_callback;
3698 pBuf->size.x =
3699 area.x + adj_size(2) + 2 * ((adj_size(183) - 5 * pBuf->size.w) / 6) + pBuf->size.w;
3700 pBuf->size.y = area.y + adj_size(2);
3701
3702 set_wstate(pBuf, FC_WS_NORMAL);
3703 add_to_gui_list(ID_CITY_DLG_SUPPORT_BUTTON, pBuf);
3704 /* -------- */
3705
3706 pBuf = create_themeicon(current_theme->Happy_Icon, pWindow->dst,
3707 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
3708 pBuf->info_label = create_str16_from_char(_("Happiness"), adj_font(12));
3709 pBuf->action = happy_city_dlg_callback;
3710 pBuf->size.x =
3711 area.x + adj_size(2) + 3 * ((adj_size(183) - 5 * pBuf->size.w) / 6) + 2 * pBuf->size.w;
3712 pBuf->size.y = area.y + adj_size(2);
3713 set_wstate(pBuf, FC_WS_NORMAL);
3714 add_to_gui_list(ID_CITY_DLG_HAPPY_BUTTON, pBuf);
3715 /* -------- */
3716
3717 pBuf = create_themeicon(current_theme->INFO_Icon, pWindow->dst,
3718 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
3719 pBuf->info_label = create_str16_from_char(_("City info"), adj_font(12));
3720 pBuf->action = info_city_dlg_callback;
3721 pBuf->size.x =
3722 area.x + adj_size(4) + 4 * ((adj_size(183) - 5 * pBuf->size.w) / 6) + 3 * pBuf->size.w;
3723 pBuf->size.y = area.y + adj_size(2);
3724 set_wstate(pBuf, FC_WS_NORMAL);
3725 add_to_gui_list(ID_CITY_DLG_INFO_BUTTON, pBuf);
3726
3727 pCityDlg->pAdd_Point = pBuf;
3728 pCityDlg->pBeginCityWidgetList = pBuf;
3729 /* ===================================================== */
3730 rebuild_imprm_list(pCity);
3731 /* ===================================================== */
3732
3733 pLogo = get_scaled_city_map(pCity);
3734
3735 pBuf = create_themelabel(pLogo, pWindow->dst, NULL,
3736 pLogo->w, pLogo->h, WF_SELLECT_WITHOUT_BAR);
3737
3738 pCityDlg->pResource_Map = pBuf;
3739
3740 pBuf->action = resource_map_city_dlg_callback;
3741 if (!cma_is_city_under_agent(pCity, NULL) && (pOwner == client.conn.playing)) {
3742 set_wstate(pBuf, FC_WS_NORMAL);
3743 }
3744 pBuf->size.x = area.x + adj_size(193) + (adj_size(249) - pBuf->size.w) / 2;
3745 pBuf->size.y = area.y + adj_size(41) + (adj_size(158) - pBuf->size.h) / 2;
3746 add_to_gui_list(ID_CITY_DLG_RESOURCE_MAP, pBuf);
3747 /* -------- */
3748
3749 pBuf = create_themeicon(current_theme->Options_Icon, pWindow->dst,
3750 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
3751 pBuf->info_label = create_str16_from_char(_("City options"), adj_font(12));
3752 pBuf->action = options_city_dlg_callback;
3753 pBuf->size.x =
3754 area.x + adj_size(4) + 5 * ((adj_size(183) - 5 * pBuf->size.w) / 6) + 4 * pBuf->size.w;
3755 pBuf->size.y = area.y + adj_size(2);
3756 if (pOwner == client.conn.playing) {
3757 set_wstate(pBuf, FC_WS_NORMAL);
3758 }
3759 add_to_gui_list(ID_CITY_DLG_OPTIONS_BUTTON, pBuf);
3760 /* -------- */
3761
3762 pBuf = create_themeicon(current_theme->PROD_Icon, pWindow->dst,
3763 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
3764 pBuf->info_label = create_str16_from_char(_("Change production"),
3765 adj_font(12));
3766 pBuf->action = change_prod_dlg_callback;
3767 pBuf->size.x = area.x + adj_size(7);
3768 pBuf->size.y = area.y + area.h - pBuf->size.h - adj_size(5);
3769 if (pOwner == client.conn.playing) {
3770 set_wstate(pBuf, FC_WS_NORMAL);
3771 }
3772 pBuf->key = SDLK_c;
3773 add_to_gui_list(ID_CITY_DLG_CHANGE_PROD_BUTTON, pBuf);
3774 /* -------- */
3775
3776 pBuf = create_themeicon(current_theme->Buy_PROD_Icon, pWindow->dst,
3777 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
3778 pBuf->info_label = create_str16_from_char(_("Hurry production"),
3779 adj_font(12));
3780 pBuf->action = buy_prod_city_dlg_callback;
3781 pBuf->size.x = area.x + adj_size(7) + (pBuf->size.w + adj_size(2));
3782 pBuf->size.y = area.y + area.h - pBuf->size.h - adj_size(5);
3783 pCityDlg->pBuy_Button = pBuf;
3784 pBuf->key = SDLK_h;
3785 if (city_can_buy(pCity)) {
3786 set_wstate(pBuf, FC_WS_NORMAL);
3787 }
3788 add_to_gui_list(ID_CITY_DLG_PROD_BUY_BUTTON, pBuf);
3789 /* -------- */
3790
3791 pBuf = create_themeicon(current_theme->CMA_Icon, pWindow->dst,
3792 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
3793 pBuf->info_label = create_str16_from_char(_("Citizen Governor"),
3794 adj_font(12));
3795 pBuf->action = cma_city_dlg_callback;
3796 pBuf->key = SDLK_a;
3797 pBuf->size.x = area.x + adj_size(7) + (pBuf->size.w + adj_size(2)) * 2;
3798 pBuf->size.y = area.y + area.h - pBuf->size.h - adj_size(5);
3799 if (pOwner == client.conn.playing) {
3800 set_wstate(pBuf, FC_WS_NORMAL);
3801 }
3802 add_to_gui_list(ID_CITY_DLG_CMA_BUTTON, pBuf);
3803
3804 /* -------- */
3805
3806 pBuf = create_themeicon(current_theme->L_ARROW_Icon, pWindow->dst,
3807 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
3808 pBuf->info_label = create_str16_from_char(_("Previous city"),
3809 adj_font(12));
3810 pBuf->action = next_prev_city_dlg_callback;
3811 pBuf->size.x = area.x + adj_size(220) - pBuf->size.w - adj_size(8);
3812 pBuf->size.y = area.y + area.h - pBuf->size.h;
3813 if (pOwner == client.conn.playing) {
3814 set_wstate(pBuf, FC_WS_NORMAL);
3815 }
3816 pBuf->key = SDLK_LEFT;
3817 pBuf->mod = KMOD_LSHIFT;
3818 add_to_gui_list(ID_CITY_DLG_PREV_BUTTON, pBuf);
3819 /* -------- */
3820
3821 pBuf = create_themeicon(current_theme->R_ARROW_Icon, pWindow->dst,
3822 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
3823 pBuf->info_label = create_str16_from_char(_("Next city"), adj_font(12));
3824 pBuf->action = next_prev_city_dlg_callback;
3825 pBuf->size.x = area.x + adj_size(420) + adj_size(2);
3826 pBuf->size.y = area.y + area.h - pBuf->size.h;
3827 if (pOwner == client.conn.playing) {
3828 set_wstate(pBuf, FC_WS_NORMAL);
3829 }
3830 pBuf->key = SDLK_RIGHT;
3831 pBuf->mod = KMOD_LSHIFT;
3832 add_to_gui_list(ID_CITY_DLG_NEXT_BUTTON, pBuf);
3833 /* -------- */
3834
3835 pBuf = create_edit_from_chars(NULL, pWindow->dst, city_name_get(pCity),
3836 adj_font(10), adj_size(200), WF_RESTORE_BACKGROUND);
3837 pBuf->action = new_name_city_dlg_callback;
3838 pBuf->size.x = area.x + (area.w - pBuf->size.w) / 2;
3839 pBuf->size.y = area.y + area.h - pBuf->size.h - adj_size(2);
3840 if (pOwner == client.conn.playing) {
3841 set_wstate(pBuf, FC_WS_NORMAL);
3842 }
3843
3844 pCityDlg->pCity_Name_Edit = pBuf;
3845 add_to_gui_list(ID_CITY_DLG_NAME_EDIT, pBuf);
3846
3847 pCityDlg->pBeginCityWidgetList = pBuf;
3848
3849 /* check if Citizen Icons style was loaded */
3850 cs = style_of_city(pCity);
3851
3852 if (cs != pIcons->style) {
3853 reload_citizens_icons(cs);
3854 }
3855
3856 /* ===================================================== */
3857 if ((city_unhappy(pCity) || city_celebrating(pCity)
3858 || city_happy(pCity))) {
3859 SDL_Client_Flags |= CF_CITY_STATUS_SPECIAL;
3860 }
3861 /* ===================================================== */
3862
3863 redraw_city_dialog(pCity);
3864 flush_dirty();
3865 }
3866
3867 /**************************************************************************
3868 Close the dialog for the given city.
3869 **************************************************************************/
popdown_city_dialog(struct city * pCity)3870 void popdown_city_dialog(struct city *pCity)
3871 {
3872 if (city_dialog_is_open(pCity)) {
3873 del_city_dialog();
3874
3875 flush_dirty();
3876
3877 SDL_Client_Flags &= ~CF_CITY_STATUS_SPECIAL;
3878 menus_update();
3879 }
3880 }
3881
3882 /**************************************************************************
3883 Close all cities dialogs.
3884 **************************************************************************/
popdown_all_city_dialogs(void)3885 void popdown_all_city_dialogs(void)
3886 {
3887 if (pCityDlg) {
3888 popdown_city_dialog(pCityDlg->pCity);
3889 }
3890 }
3891
3892 /**************************************************************************
3893 Refresh (update) all data for the given city's dialog.
3894 **************************************************************************/
real_city_dialog_refresh(struct city * pCity)3895 void real_city_dialog_refresh(struct city *pCity)
3896 {
3897 if (city_dialog_is_open(pCity)) {
3898 redraw_city_dialog(pCityDlg->pCity);
3899 flush_dirty();
3900 }
3901 }
3902
3903 /**************************************************************************
3904 Update city dialogs when the given unit's status changes. This
3905 typically means updating both the unit's home city (if any) and the
3906 city in which it is present (if any).
3907 **************************************************************************/
refresh_unit_city_dialogs(struct unit * pUnit)3908 void refresh_unit_city_dialogs(struct unit *pUnit)
3909 {
3910
3911 struct city *pCity_sup = game_city_by_number(pUnit->homecity);
3912 struct city *pCity_pre = tile_city(unit_tile(pUnit));
3913
3914 if (pCityDlg && ((pCityDlg->pCity == pCity_sup)
3915 || (pCityDlg->pCity == pCity_pre))) {
3916 free_city_units_lists();
3917 redraw_city_dialog(pCityDlg->pCity);
3918 flush_dirty();
3919 }
3920
3921 }
3922
3923 /**************************************************************************
3924 Return whether the dialog for the given city is open.
3925 **************************************************************************/
city_dialog_is_open(struct city * pCity)3926 bool city_dialog_is_open(struct city *pCity)
3927 {
3928 return (pCityDlg && (pCityDlg->pCity == pCity));
3929 }
3930
3931 /**************************************************************************
3932 City is about to disappear from client
3933 **************************************************************************/
city_to_disappear(struct city * pcity)3934 void city_to_disappear(struct city *pcity)
3935 {
3936 }
3937