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 repodlgs.c - description
16 -------------------
17 begin : Nov 15 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 /* utility */
27 #include "fcintl.h"
28 #include "log.h"
29
30 /* common */
31 #include "game.h"
32 #include "government.h"
33 #include "research.h"
34 #include "unitlist.h"
35
36 /* client */
37 #include "client_main.h"
38 #include "text.h"
39
40 /* gui-sdl2 */
41 #include "cityrep.h"
42 #include "colors.h"
43 #include "dialogs.h"
44 #include "graphics.h"
45 #include "gui_id.h"
46 #include "gui_main.h"
47 #include "gui_tilespec.h"
48 #include "helpdlg.h"
49 #include "mapctrl.h"
50 #include "mapview.h"
51 #include "sprite.h"
52 #include "themespec.h"
53 #include "widget.h"
54
55 #include "repodlgs.h"
56
57
58 /* ===================================================================== */
59 /* ======================== Active Units Report ======================== */
60 /* ===================================================================== */
61 static struct ADVANCED_DLG *pUnitsDlg = NULL;
62 static struct SMALL_DLG *pUnits_Upg_Dlg = NULL;
63
64 struct units_entry {
65 int active_count;
66 int upkeep[O_LAST];
67 int building_count;
68 int soonest_completions;
69 };
70
71 /**************************************************************************
72 Fill unit types specific report data + totals.
73 **************************************************************************/
get_units_report_data(struct units_entry * entries,struct units_entry * total)74 static void get_units_report_data(struct units_entry *entries,
75 struct units_entry *total)
76 {
77 int time_to_build;
78
79 memset(entries, '\0', U_LAST * sizeof(struct units_entry));
80 memset(total, '\0', sizeof(struct units_entry));
81 for (time_to_build = 0; time_to_build < U_LAST; time_to_build++) {
82 entries[time_to_build].soonest_completions = FC_INFINITY;
83 }
84
85 unit_list_iterate(client.conn.playing->units, punit) {
86 Unit_type_id uti = utype_index(unit_type_get(punit));
87
88 (entries[uti].active_count)++;
89 (total->active_count)++;
90 if (punit->homecity) {
91 output_type_iterate(o) {
92 entries[uti].upkeep[o] += punit->upkeep[o];
93 total->upkeep[o] += punit->upkeep[o];
94 } output_type_iterate_end;
95 }
96 } unit_list_iterate_end;
97
98 city_list_iterate(client.conn.playing->cities, pCity) {
99 if (VUT_UTYPE == pCity->production.kind) {
100 struct unit_type *pUnitType = pCity->production.value.utype;
101 Unit_type_id uti = utype_index(pUnitType);
102 int num_units;
103
104 /* Account for build slots in city */
105 (void) city_production_build_units(pCity, TRUE, &num_units);
106 /* Unit is in progress even if it won't be done this turn */
107 num_units = MAX(num_units, 1);
108 (entries[uti].building_count) += num_units;
109 (total->building_count) += num_units;
110 entries[uti].soonest_completions =
111 MIN(entries[uti].soonest_completions,
112 city_production_turns_to_build(pCity, TRUE));
113 }
114 } city_list_iterate_end;
115 }
116
117 /**************************************************************************
118 User interacted with Units Report button.
119 **************************************************************************/
units_dialog_callback(struct widget * pWindow)120 static int units_dialog_callback(struct widget *pWindow)
121 {
122 if (PRESSED_EVENT(Main.event)) {
123 move_window_group(pUnitsDlg->pBeginWidgetList, pWindow);
124 }
125
126 return -1;
127 }
128
129 /* --------------------------------------------------------------- */
130
131 /**************************************************************************
132 User interacted with accept button of the unit upgrade dialog.
133 **************************************************************************/
ok_upgrade_unit_window_callback(struct widget * pWidget)134 static int ok_upgrade_unit_window_callback(struct widget *pWidget)
135 {
136 if (PRESSED_EVENT(Main.event)) {
137 int ut1 = MAX_ID - pWidget->ID;
138
139 /* popdown upgrade dlg */
140 popdown_window_group_dialog(pUnits_Upg_Dlg->pBeginWidgetList,
141 pUnits_Upg_Dlg->pEndWidgetList);
142 FC_FREE(pUnits_Upg_Dlg);
143
144 dsend_packet_unit_type_upgrade(&client.conn, ut1);
145 }
146
147 return -1;
148 }
149
150 /**************************************************************************
151 User interacted with Upgrade Obsolete button of the unit upgrade dialog.
152 **************************************************************************/
upgrade_unit_window_callback(struct widget * pWindow)153 static int upgrade_unit_window_callback(struct widget *pWindow)
154 {
155 if (PRESSED_EVENT(Main.event)) {
156 move_window_group(pUnits_Upg_Dlg->pBeginWidgetList, pWindow);
157 }
158
159 return -1;
160 }
161
162 /**************************************************************************
163 User interacted with Cancel button of the unit upgrade dialog.
164 **************************************************************************/
cancel_upgrade_unit_callback(struct widget * pWidget)165 static int cancel_upgrade_unit_callback(struct widget *pWidget)
166 {
167 if (PRESSED_EVENT(Main.event)) {
168 if (pUnits_Upg_Dlg) {
169 popdown_window_group_dialog(pUnits_Upg_Dlg->pBeginWidgetList,
170 pUnits_Upg_Dlg->pEndWidgetList);
171 FC_FREE(pUnits_Upg_Dlg);
172 flush_dirty();
173 }
174 }
175
176 return -1;
177 }
178
179 /**************************************************************************
180 Open dialog for upgrading units.
181 **************************************************************************/
popup_upgrade_unit_callback(struct widget * pWidget)182 static int popup_upgrade_unit_callback(struct widget *pWidget)
183 {
184 if (PRESSED_EVENT(Main.event)) {
185 struct unit_type *ut1;
186 struct unit_type *ut2;
187 int value;
188 char tBuf[128], cBuf[128];
189 struct widget *pBuf = NULL, *pWindow;
190 utf8_str *pstr;
191 SDL_Surface *pText;
192 SDL_Rect dst;
193 SDL_Rect area;
194
195 ut1 = utype_by_number(MAX_ID - pWidget->ID);
196
197 if (pUnits_Upg_Dlg) {
198 return 1;
199 }
200
201 set_wstate(pWidget, FC_WS_NORMAL);
202 selected_widget = NULL;
203 widget_redraw(pWidget);
204 widget_mark_dirty(pWidget);
205
206 pUnits_Upg_Dlg = fc_calloc(1, sizeof(struct SMALL_DLG));
207
208 ut2 = can_upgrade_unittype(client.conn.playing, ut1);
209 value = unit_upgrade_price(client.conn.playing, ut1, ut2);
210
211 fc_snprintf(tBuf, ARRAY_SIZE(tBuf), PL_("Treasury contains %d gold.",
212 "Treasury contains %d gold.",
213 client_player()->economic.gold),
214 client_player()->economic.gold);
215
216 fc_snprintf(cBuf, sizeof(cBuf),
217 /* TRANS: Last %s is pre-pluralised "Treasury contains %d gold." */
218 PL_("Upgrade as many %s to %s as possible for %d gold each?\n%s",
219 "Upgrade as many %s to %s as possible for %d gold each?\n%s",
220 value),
221 utype_name_translation(ut1),
222 utype_name_translation(ut2),
223 value, tBuf);
224
225 pstr = create_utf8_from_char(_("Upgrade Obsolete Units"), adj_font(12));
226 pstr->style |= TTF_STYLE_BOLD;
227
228 pWindow = create_window_skeleton(NULL, pstr, 0);
229
230 pWindow->action = upgrade_unit_window_callback;
231 set_wstate(pWindow, FC_WS_NORMAL);
232
233 add_to_gui_list(ID_WINDOW, pWindow);
234
235 pUnits_Upg_Dlg->pEndWidgetList = pWindow;
236
237 area = pWindow->area;
238
239 /* ============================================================= */
240
241 /* create text label */
242 pstr = create_utf8_from_char(cBuf, adj_font(10));
243 pstr->style |= (TTF_STYLE_BOLD|SF_CENTER);
244 pstr->fgcol = *get_theme_color(COLOR_THEME_UNITUPGRADE_TEXT);
245
246 pText = create_text_surf_from_utf8(pstr);
247 FREEUTF8STR(pstr);
248
249 area.h += (pText->h + adj_size(10));
250 area.w = MAX(area.w, pText->w + adj_size(20));
251
252 /* cancel button */
253 pBuf = create_themeicon_button_from_chars(current_theme->CANCEL_Icon,
254 pWindow->dst, _("No"),
255 adj_font(12), 0);
256
257 pBuf->action = cancel_upgrade_unit_callback;
258 set_wstate(pBuf, FC_WS_NORMAL);
259
260 area.h += (pBuf->size.h + adj_size(20));
261
262 add_to_gui_list(ID_BUTTON, pBuf);
263
264 if (value <= client.conn.playing->economic.gold) {
265 pBuf = create_themeicon_button_from_chars(current_theme->OK_Icon, pWindow->dst,
266 _("Yes"), adj_font(12), 0);
267
268 pBuf->action = ok_upgrade_unit_window_callback;
269 set_wstate(pBuf, FC_WS_NORMAL);
270
271 add_to_gui_list(pWidget->ID, pBuf);
272 pBuf->size.w = MAX(pBuf->size.w, pBuf->next->size.w);
273 pBuf->next->size.w = pBuf->size.w;
274 area.w = MAX(area.w, adj_size(30) + pBuf->size.w * 2);
275 } else {
276 area.w = MAX(area.w, pBuf->size.w + adj_size(20));
277 }
278 /* ============================================ */
279
280 pUnits_Upg_Dlg->pBeginWidgetList = pBuf;
281
282 resize_window(pWindow, NULL, get_theme_color(COLOR_THEME_BACKGROUND),
283 (pWindow->size.w - pWindow->area.w) + area.w,
284 (pWindow->size.h - pWindow->area.h) + area.h);
285
286 widget_set_position(pWindow,
287 pUnitsDlg->pEndWidgetList->size.x +
288 (pUnitsDlg->pEndWidgetList->size.w - pWindow->size.w) / 2,
289 pUnitsDlg->pEndWidgetList->size.y +
290 (pUnitsDlg->pEndWidgetList->size.h - pWindow->size.h) / 2);
291
292 /* setup rest of widgets */
293 /* label */
294 dst.x = area.x + (area.w - pText->w) / 2;
295 dst.y = area.y + adj_size(10);
296 alphablit(pText, NULL, pWindow->theme, &dst, 255);
297 FREESURFACE(pText);
298
299 /* cancel button */
300 pBuf = pWindow->prev;
301 pBuf->size.y = area.y + area.h - pBuf->size.h - adj_size(10);
302
303 if (value <= client.conn.playing->economic.gold) {
304 /* sell button */
305 pBuf = pBuf->prev;
306 pBuf->size.x = area.x + (area.w - (2 * pBuf->size.w + adj_size(10))) / 2;
307 pBuf->size.y = pBuf->next->size.y;
308
309 /* cancel button */
310 pBuf->next->size.x = pBuf->size.x + pBuf->size.w + adj_size(10);
311 } else {
312 /* x position of cancel button */
313 pBuf->size.x = area.x + area.w - pBuf->size.w - adj_size(10);
314 }
315
316 /* ================================================== */
317 /* redraw */
318 redraw_group(pUnits_Upg_Dlg->pBeginWidgetList, pWindow, 0);
319
320 widget_mark_dirty(pWindow);
321 flush_dirty();
322 }
323
324 return -1;
325 }
326
327 /**************************************************************************
328 User interacted with units dialog Close Dialog button.
329 **************************************************************************/
exit_units_dlg_callback(struct widget * pWidget)330 static int exit_units_dlg_callback(struct widget *pWidget)
331 {
332 if (PRESSED_EVENT(Main.event)) {
333 if (pUnitsDlg) {
334 if (pUnits_Upg_Dlg) {
335 del_group_of_widgets_from_gui_list(pUnits_Upg_Dlg->pBeginWidgetList,
336 pUnits_Upg_Dlg->pEndWidgetList);
337 FC_FREE(pUnits_Upg_Dlg);
338 }
339 popdown_window_group_dialog(pUnitsDlg->pBeginWidgetList,
340 pUnitsDlg->pEndWidgetList);
341 FC_FREE(pUnitsDlg->pScroll);
342 FC_FREE(pUnitsDlg);
343 flush_dirty();
344 }
345 }
346
347 return -1;
348 }
349
350 /**************************************************************************
351 Rebuild the units report.
352 **************************************************************************/
real_activeunits_report_dialog_update(struct units_entry * units,struct units_entry * total)353 static void real_activeunits_report_dialog_update(struct units_entry *units,
354 struct units_entry *total)
355 {
356 SDL_Color bg_color = {255, 255, 255, 136};
357 struct widget *pBuf = NULL;
358 struct widget *pWindow, *pLast;
359 utf8_str *pstr;
360 SDL_Surface *pText1, *pText2, *pText3 , *pText4, *pText5, *pLogo;
361 int w = 0 , count, ww, hh = 0, name_w = 0;
362 char cbuf[64];
363 SDL_Rect dst;
364 bool upgrade = FALSE;
365 SDL_Rect area;
366
367 if (pUnitsDlg) {
368 popdown_window_group_dialog(pUnitsDlg->pBeginWidgetList,
369 pUnitsDlg->pEndWidgetList);
370 } else {
371 pUnitsDlg = fc_calloc(1, sizeof(struct ADVANCED_DLG));
372 }
373
374 fc_snprintf(cbuf, sizeof(cbuf), _("active"));
375 pstr = create_utf8_from_char(cbuf, adj_font(10));
376 pstr->style |= SF_CENTER;
377 pText1 = create_text_surf_from_utf8(pstr);
378
379 fc_snprintf(cbuf, sizeof(cbuf), _("under\nconstruction"));
380 copy_chars_to_utf8_str(pstr, cbuf);
381 pText2 = create_text_surf_from_utf8(pstr);
382
383 fc_snprintf(cbuf, sizeof(cbuf), _("soonest\ncompletion"));
384 copy_chars_to_utf8_str(pstr, cbuf);
385 pText5 = create_text_surf_from_utf8(pstr);
386
387 fc_snprintf(cbuf, sizeof(cbuf), _("Total"));
388 copy_chars_to_utf8_str(pstr, cbuf);
389 pText3 = create_text_surf_from_utf8(pstr);
390
391 fc_snprintf(cbuf, sizeof(cbuf), _("Units"));
392 copy_chars_to_utf8_str(pstr, cbuf);
393 pText4 = create_text_surf_from_utf8(pstr);
394 name_w = pText4->w;
395 FREEUTF8STR(pstr);
396
397 /* --------------- */
398 pstr = create_utf8_from_char(_("Units Report"), adj_font(12));
399 pstr->style |= TTF_STYLE_BOLD;
400
401 pWindow = create_window_skeleton(NULL, pstr, 0);
402 set_wstate(pWindow, FC_WS_NORMAL);
403 pWindow->action = units_dialog_callback;
404
405 add_to_gui_list(ID_UNITS_DIALOG_WINDOW, pWindow);
406
407 pUnitsDlg->pEndWidgetList = pWindow;
408
409 area = pWindow->area;
410
411 /* ------------------------- */
412 /* exit button */
413 pBuf = create_themeicon(current_theme->Small_CANCEL_Icon, pWindow->dst,
414 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
415 pBuf->info_label = create_utf8_from_char(_("Close Dialog (Esc)"), adj_font(12));
416 pBuf->action = exit_units_dlg_callback;
417 set_wstate(pBuf, FC_WS_NORMAL);
418 pBuf->key = SDLK_ESCAPE;
419
420 add_to_gui_list(ID_BUTTON, pBuf);
421 /* ------------------------- */
422 /* totals */
423 fc_snprintf(cbuf, sizeof(cbuf), "%d", total->active_count);
424
425 pstr = create_utf8_from_char(cbuf, adj_font(10));
426 pstr->style |= (TTF_STYLE_BOLD|SF_CENTER);
427
428 pBuf = create_iconlabel(NULL, pWindow->dst, pstr,
429 WF_RESTORE_BACKGROUND);
430
431 area.h += pBuf->size.h;
432 pBuf->size.w = pText1->w + adj_size(6);
433 add_to_gui_list(ID_LABEL, pBuf);
434 /* ---------------------------------------------- */
435 fc_snprintf(cbuf, sizeof(cbuf), "%d", total->upkeep[O_SHIELD]);
436
437 pstr = create_utf8_from_char(cbuf, adj_font(10));
438 pstr->style |= (TTF_STYLE_BOLD|SF_CENTER);
439
440 pBuf = create_iconlabel(NULL, pWindow->dst, pstr, WF_RESTORE_BACKGROUND);
441
442 pBuf->size.w = pText1->w;
443 add_to_gui_list(ID_LABEL, pBuf);
444 /* ---------------------------------------------- */
445 fc_snprintf(cbuf, sizeof(cbuf), "%d", total->upkeep[O_FOOD]);
446
447 pstr = create_utf8_from_char(cbuf, adj_font(10));
448 pstr->style |= (TTF_STYLE_BOLD|SF_CENTER);
449
450 pBuf = create_iconlabel(NULL, pWindow->dst, pstr, WF_RESTORE_BACKGROUND);
451
452 pBuf->size.w = pText1->w;
453 add_to_gui_list(ID_LABEL, pBuf);
454 /* ---------------------------------------------- */
455 fc_snprintf(cbuf, sizeof(cbuf), "%d", total->upkeep[O_GOLD]);
456
457 pstr = create_utf8_from_char(cbuf, adj_font(10));
458 pstr->style |= (TTF_STYLE_BOLD|SF_CENTER);
459
460 pBuf = create_iconlabel(NULL, pWindow->dst, pstr, WF_RESTORE_BACKGROUND);
461
462 pBuf->size.w = pText1->w;
463 add_to_gui_list(ID_LABEL, pBuf);
464 /* ---------------------------------------------- */
465 fc_snprintf(cbuf, sizeof(cbuf), "%d", total->building_count);
466
467 pstr = create_utf8_from_char(cbuf, adj_font(10));
468 pstr->style |= (TTF_STYLE_BOLD|SF_CENTER);
469
470 pBuf = create_iconlabel(NULL, pWindow->dst, pstr,
471 WF_RESTORE_BACKGROUND);
472
473 pBuf->size.w = pText2->w + adj_size(6);
474 add_to_gui_list(ID_LABEL, pBuf);
475
476 /* ------------------------- */
477 pLast = pBuf;
478 count = 0;
479 unit_type_iterate(i) {
480 if ((units[utype_index(i)].active_count > 0)
481 || (units[utype_index(i)].building_count > 0)) {
482 upgrade = (can_upgrade_unittype(client.conn.playing, i) != NULL);
483
484 /* unit type icon */
485 pBuf = create_iconlabel(adj_surf(get_unittype_surface(i, direction8_invalid())), pWindow->dst, NULL,
486 WF_RESTORE_BACKGROUND | WF_FREE_THEME);
487 if (count > adj_size(72)) {
488 set_wflag(pBuf, WF_HIDDEN);
489 }
490 hh = pBuf->size.h;
491 add_to_gui_list(MAX_ID - utype_number(i), pBuf);
492
493 /* unit type name */
494 pstr = create_utf8_from_char(utype_name_translation(i), adj_font(12));
495 pstr->style |= (TTF_STYLE_BOLD|SF_CENTER);
496 pBuf = create_iconlabel(NULL, pWindow->dst, pstr,
497 (WF_RESTORE_BACKGROUND | WF_SELECT_WITHOUT_BAR));
498 if (upgrade) {
499 pBuf->string_utf8->fgcol = *get_theme_color(COLOR_THEME_UNITUPGRADE_TEXT);
500 pBuf->action = popup_upgrade_unit_callback;
501 set_wstate(pBuf, FC_WS_NORMAL);
502 } else {
503 pBuf->string_utf8->fgcol = *get_theme_color(COLOR_THEME_UNITSREP_TEXT);
504 }
505 pBuf->string_utf8->style &= ~SF_CENTER;
506 if (count > adj_size(72)) {
507 set_wflag(pBuf , WF_HIDDEN);
508 }
509 hh = MAX(hh, pBuf->size.h);
510 name_w = MAX(pBuf->size.w, name_w);
511 add_to_gui_list(MAX_ID - utype_number(i), pBuf);
512
513 /* active */
514 fc_snprintf(cbuf, sizeof(cbuf), "%d", units[utype_index(i)].active_count);
515 pstr = create_utf8_from_char(cbuf, adj_font(10));
516 pstr->style |= SF_CENTER;
517 pBuf = create_iconlabel(NULL, pWindow->dst, pstr,
518 WF_RESTORE_BACKGROUND);
519 if (count > adj_size(72)) {
520 set_wflag(pBuf, WF_HIDDEN);
521 }
522 hh = MAX(hh, pBuf->size.h);
523 pBuf->size.w = pText1->w + adj_size(6);
524 add_to_gui_list(MAX_ID - utype_number(i), pBuf);
525
526 /* shield upkeep */
527 fc_snprintf(cbuf, sizeof(cbuf), "%d", units[utype_index(i)].upkeep[O_SHIELD]);
528 pstr = create_utf8_from_char(cbuf, adj_font(10));
529 pstr->style |= SF_CENTER;
530 pBuf = create_iconlabel(NULL, pWindow->dst, pstr,
531 WF_RESTORE_BACKGROUND);
532 if (count > adj_size(72)) {
533 set_wflag(pBuf, WF_HIDDEN);
534 }
535 hh = MAX(hh, pBuf->size.h);
536 pBuf->size.w = pText1->w;
537 add_to_gui_list(MAX_ID - utype_number(i), pBuf);
538
539 /* food upkeep */
540 fc_snprintf(cbuf, sizeof(cbuf), "%d", units[utype_index(i)].upkeep[O_FOOD]);
541 pstr = create_utf8_from_char(cbuf, adj_font(10));
542 pstr->style |= SF_CENTER;
543 pBuf = create_iconlabel(NULL, pWindow->dst, pstr,
544 WF_RESTORE_BACKGROUND);
545 if (count > adj_size(72)) {
546 set_wflag(pBuf, WF_HIDDEN);
547 }
548
549 hh = MAX(hh, pBuf->size.h);
550 pBuf->size.w = pText1->w;
551 add_to_gui_list(MAX_ID - utype_number(i), pBuf);
552
553 /* gold upkeep */
554 fc_snprintf(cbuf, sizeof(cbuf), "%d", units[utype_index(i)].upkeep[O_GOLD]);
555 pstr = create_utf8_from_char(cbuf, adj_font(10));
556 pstr->style |= SF_CENTER;
557 pBuf = create_iconlabel(NULL, pWindow->dst, pstr,
558 WF_RESTORE_BACKGROUND);
559 if (count > adj_size(72)) {
560 set_wflag(pBuf, WF_HIDDEN);
561 }
562
563 hh = MAX(hh, pBuf->size.h);
564 pBuf->size.w = pText1->w;
565 add_to_gui_list(MAX_ID - utype_number(i), pBuf);
566
567 /* building */
568 if (units[utype_index(i)].building_count > 0) {
569 fc_snprintf(cbuf, sizeof(cbuf), "%d", units[utype_index(i)].building_count);
570 } else {
571 fc_snprintf(cbuf, sizeof(cbuf), "--");
572 }
573 pstr = create_utf8_from_char(cbuf, adj_font(10));
574 pstr->style |= SF_CENTER;
575 pBuf = create_iconlabel(NULL, pWindow->dst, pstr,
576 WF_RESTORE_BACKGROUND);
577 if (count > adj_size(72)) {
578 set_wflag(pBuf, WF_HIDDEN);
579 }
580 hh = MAX(hh, pBuf->size.h);
581 pBuf->size.w = pText2->w + adj_size(6);
582 add_to_gui_list(MAX_ID - utype_number(i), pBuf);
583
584 /* soonest completion */
585 if (units[utype_index(i)].building_count > 0) {
586 fc_snprintf(cbuf, sizeof(cbuf), "%d %s", units[utype_index(i)].soonest_completions,
587 PL_("turn", "turns", units[utype_index(i)].soonest_completions));
588 } else {
589 fc_snprintf(cbuf, sizeof(cbuf), "--");
590 }
591
592 pstr = create_utf8_from_char(cbuf, adj_font(10));
593 pstr->style |= SF_CENTER;
594 pBuf = create_iconlabel(NULL, pWindow->dst, pstr,
595 WF_RESTORE_BACKGROUND);
596
597 if (count > adj_size(72)) {
598 set_wflag(pBuf, WF_HIDDEN);
599 }
600 hh = MAX(hh, pBuf->size.h);
601 pBuf->size.w = pText5->w + adj_size(6);
602 add_to_gui_list(MAX_ID - utype_number(i), pBuf);
603
604 count += adj_size(8);
605 area.h += (hh/2);
606 }
607 } unit_type_iterate_end;
608
609 pUnitsDlg->pBeginWidgetList = pBuf;
610 area.w = MAX(area.w, (tileset_full_tile_width(tileset) * 2 + name_w + adj_size(15))
611 + (adj_size(4) * pText1->w + adj_size(46)) + (pText2->w + adj_size(16))
612 + (pText5->w + adj_size(6)) + adj_size(2));
613 if (count > 0) {
614 pUnitsDlg->pEndActiveWidgetList = pLast->prev;
615 pUnitsDlg->pBeginActiveWidgetList = pUnitsDlg->pBeginWidgetList;
616 if (count > adj_size(80)) {
617 pUnitsDlg->pActiveWidgetList = pUnitsDlg->pEndActiveWidgetList;
618 if (pUnitsDlg->pScroll) {
619 pUnitsDlg->pScroll->count = count;
620 }
621 ww = create_vertical_scrollbar(pUnitsDlg, 8, 10, TRUE, TRUE);
622 area.w += ww;
623 area.h = (hh + 9 * (hh/2) + adj_size(10));
624 } else {
625 area.h += hh/2;
626 }
627 } else {
628 area.h = adj_size(50);
629 }
630
631 area.h += pText1->h + adj_size(10);
632 area.w += adj_size(2);
633
634 pLogo = theme_get_background(theme, BACKGROUND_UNITSREP);
635 resize_window(pWindow, pLogo, NULL,
636 (pWindow->size.w - pWindow->area.w) + area.w,
637 (pWindow->size.h - pWindow->area.h) + area.h);
638 FREESURFACE(pLogo);
639
640 #if 0
641 pLogo = SDL_DisplayFormat(pWindow->theme);
642 FREESURFACE(pWindow->theme);
643 pWindow->theme = pLogo;
644 pLogo = NULL;
645 #endif /* 0 */
646
647 area = pWindow->area;
648
649 widget_set_position(pWindow,
650 (main_window_width() - pWindow->size.w) / 2,
651 (main_window_height() - pWindow->size.h) / 2);
652
653 /* exit button */
654 pBuf = pWindow->prev;
655 pBuf->size.x = area.x + area.w - pBuf->size.w - 1;
656 pBuf->size.y = pWindow->size.y + adj_size(2);
657
658 /* totals background and label */
659 dst.x = area.x + adj_size(2);
660 dst.y = area.y + area.h - (pText3->h + adj_size(2)) - adj_size(2);
661 dst.w = name_w + tileset_full_tile_width(tileset) * 2 + adj_size(5);
662 dst.h = pText3->h + adj_size(2);
663 fill_rect_alpha(pWindow->theme, &dst, &bg_color);
664
665 create_frame(pWindow->theme,
666 dst.x, dst.y, dst.w, dst.h - 1,
667 get_theme_color(COLOR_THEME_UNITSREP_FRAME));
668
669 dst.y += 1;
670 dst.x += ((name_w + tileset_full_tile_width(tileset) * 2 + adj_size(5)) - pText3->w) / 2;
671 alphablit(pText3, NULL, pWindow->theme, &dst, 255);
672 FREESURFACE(pText3);
673
674 /* total active widget */
675 pBuf = pBuf->prev;
676 pBuf->size.x = area.x + name_w
677 + tileset_full_tile_width(tileset) * 2 + adj_size(17);
678 pBuf->size.y = dst.y;
679
680 /* total shields cost widget */
681 pBuf = pBuf->prev;
682 pBuf->size.x = pBuf->next->size.x + pBuf->next->size.w + adj_size(10);
683 pBuf->size.y = dst.y;
684
685 /* total food cost widget */
686 pBuf = pBuf->prev;
687 pBuf->size.x = pBuf->next->size.x + pBuf->next->size.w + adj_size(10);
688 pBuf->size.y = dst.y;
689
690 /* total gold cost widget */
691 pBuf = pBuf->prev;
692 pBuf->size.x = pBuf->next->size.x + pBuf->next->size.w + adj_size(10);
693 pBuf->size.y = dst.y;
694
695 /* total building count widget */
696 pBuf = pBuf->prev;
697 pBuf->size.x = pBuf->next->size.x + pBuf->next->size.w + adj_size(10);
698 pBuf->size.y = dst.y;
699
700 /* units background and labels */
701 dst.x = area.x + adj_size(2);
702 dst.y = area.y + 1;
703 dst.w = name_w + tileset_full_tile_width(tileset) * 2 + adj_size(5);
704 dst.h = pText4->h + adj_size(2);
705 fill_rect_alpha(pWindow->theme, &dst, &bg_color);
706
707 create_frame(pWindow->theme,
708 dst.x, dst.y, dst.w, dst.h - 1,
709 get_theme_color(COLOR_THEME_UNITSREP_FRAME));
710
711 dst.y += 1;
712 dst.x += ((name_w + tileset_full_tile_width(tileset) * 2 + adj_size(5))- pText4->w) / 2;
713 alphablit(pText4, NULL, pWindow->theme, &dst, 255);
714 FREESURFACE(pText4);
715
716 /* active count background and label */
717 dst.x = area.x + adj_size(2) + name_w + tileset_full_tile_width(tileset) * 2 + adj_size(15);
718 dst.y = area.y + 1;
719 dst.w = pText1->w + adj_size(6);
720 dst.h = area.h - adj_size(3);
721 fill_rect_alpha(pWindow->theme, &dst, &bg_color);
722
723 create_frame(pWindow->theme,
724 dst.x, dst.y, dst.w, dst.h - 1,
725 get_theme_color(COLOR_THEME_UNITSREP_FRAME));
726
727 dst.x += adj_size(3);
728 alphablit(pText1, NULL, pWindow->theme, &dst, 255);
729 ww = pText1->w;
730 hh = pText1->h;
731 FREESURFACE(pText1);
732
733 /* shields cost background and label */
734 dst.x += (ww + adj_size(13));
735 w = dst.x;
736 dst.w = ww;
737 dst.h = area.h - adj_size(3);
738 fill_rect_alpha(pWindow->theme, &dst, &bg_color);
739
740 create_frame(pWindow->theme,
741 dst.x, dst.y, dst.w, dst.h - 1,
742 get_theme_color(COLOR_THEME_UNITSREP_FRAME));
743
744 dst.y = area.y + adj_size(3);
745 dst.x += ((ww - pIcons->pBIG_Shield->w) / 2);
746 alphablit(pIcons->pBIG_Shield, NULL, pWindow->theme, &dst, 255);
747
748 /* food cost background and label */
749 dst.x = w + ww + adj_size(10);
750 w = dst.x;
751 dst.y = area.y + 1;
752 dst.w = ww;
753 dst.h = area.h - adj_size(3);
754 fill_rect_alpha(pWindow->theme, &dst, &bg_color);
755
756 create_frame(pWindow->theme,
757 dst.x, dst.y, dst.w, dst.h - 1,
758 get_theme_color(COLOR_THEME_UNITSREP_FRAME));
759
760 dst.y = area.y + adj_size(3);
761 dst.x += ((ww - pIcons->pBIG_Food->w) / 2);
762 alphablit(pIcons->pBIG_Food, NULL, pWindow->theme, &dst, 255);
763
764 /* gold cost background and label */
765 dst.x = w + ww + adj_size(10);
766 w = dst.x;
767 dst.y = area.y + 1;
768 dst.w = ww;
769 dst.h = area.h - adj_size(3);
770 fill_rect_alpha(pWindow->theme, &dst, &bg_color);
771
772 create_frame(pWindow->theme,
773 dst.x, dst.y, dst.w, dst.h - 1,
774 get_theme_color(COLOR_THEME_UNITSREP_FRAME));
775
776 dst.y = area.y + adj_size(3);
777 dst.x += ((ww - pIcons->pBIG_Coin->w) / 2);
778 alphablit(pIcons->pBIG_Coin, NULL, pWindow->theme, &dst, 255);
779
780 /* building count background and label */
781 dst.x = w + ww + adj_size(10);
782 dst.y = area.y + 1;
783 dst.w = pText2->w + adj_size(6);
784 ww = pText2->w + adj_size(6);
785 w = dst.x;
786 dst.h = area.h - adj_size(3);
787 fill_rect_alpha(pWindow->theme, &dst, &bg_color);
788
789 create_frame(pWindow->theme,
790 dst.x, dst.y, dst.w, dst.h - 1,
791 get_theme_color(COLOR_THEME_UNITSREP_FRAME));
792
793 dst.x += adj_size(3);
794 alphablit(pText2, NULL, pWindow->theme, &dst, 255);
795 FREESURFACE(pText2);
796
797 /* building count background and label */
798 dst.x = w + ww + adj_size(10);
799 dst.y = area.y + 1;
800 dst.w = pText5->w + adj_size(6);
801 dst.h = area.h - adj_size(3);
802 fill_rect_alpha(pWindow->theme, &dst, &bg_color);
803
804 create_frame(pWindow->theme,
805 dst.x, dst.y, dst.w, dst.h - 1,
806 get_theme_color(COLOR_THEME_UNITSREP_FRAME));
807
808 dst.x += adj_size(3);
809 alphablit(pText5, NULL, pWindow->theme, &dst, 255);
810 FREESURFACE(pText5);
811
812 if (count) {
813 int start_x = area.x + adj_size(2);
814 int start_y = area.y + hh + adj_size(3);
815 int mod = 0;
816
817 pBuf = pBuf->prev;
818 while (TRUE) {
819 /* Unit type icon */
820 pBuf->size.x = start_x + (mod ? tileset_full_tile_width(tileset) : 0);
821 pBuf->size.y = start_y;
822 hh = pBuf->size.h;
823 mod ^= 1;
824
825 /* Unit type name */
826 pBuf = pBuf->prev;
827 pBuf->size.w = name_w;
828 pBuf->size.x = start_x + tileset_full_tile_width(tileset) * 2 + adj_size(5);
829 pBuf->size.y = start_y + (hh - pBuf->size.h) / 2;
830
831 /* Number active */
832 pBuf = pBuf->prev;
833 pBuf->size.x = pBuf->next->size.x + pBuf->next->size.w + adj_size(10);
834 pBuf->size.y = start_y + (hh - pBuf->size.h) / 2;
835
836 /* Shield upkeep */
837 pBuf = pBuf->prev;
838 pBuf->size.x = pBuf->next->size.x + pBuf->next->size.w + adj_size(10);
839 pBuf->size.y = start_y + (hh - pBuf->size.h) / 2;
840
841 /* Food upkeep */
842 pBuf = pBuf->prev;
843 pBuf->size.x = pBuf->next->size.x + pBuf->next->size.w + adj_size(10);
844 pBuf->size.y = start_y + (hh - pBuf->size.h) / 2;
845
846 /* Gold upkeep */
847 pBuf = pBuf->prev;
848 pBuf->size.x = pBuf->next->size.x + pBuf->next->size.w + adj_size(10);
849 pBuf->size.y = start_y + (hh - pBuf->size.h) / 2;
850
851 /* Number under construction */
852 pBuf = pBuf->prev;
853 pBuf->size.x = pBuf->next->size.x + pBuf->next->size.w + adj_size(10);
854 pBuf->size.y = start_y + (hh - pBuf->size.h) / 2;
855
856 /* Soonest completion */
857 pBuf = pBuf->prev;
858 pBuf->size.x = pBuf->next->size.x + pBuf->next->size.w + adj_size(10);
859 pBuf->size.y = start_y + (hh - pBuf->size.h) / 2;
860
861 start_y += (hh >> 1);
862 if (pBuf == pUnitsDlg->pBeginActiveWidgetList) {
863 break;
864 }
865 pBuf = pBuf->prev;
866 }
867
868 if (pUnitsDlg->pScroll) {
869 setup_vertical_scrollbar_area(pUnitsDlg->pScroll,
870 area.x + area.w, area.y,
871 area.h, TRUE);
872 }
873
874 }
875 /* ----------------------------------- */
876 redraw_group(pUnitsDlg->pBeginWidgetList, pWindow, 0);
877 widget_mark_dirty(pWindow);
878
879 flush_dirty();
880 }
881
882 /**************************************************************************
883 update the units report.
884 **************************************************************************/
real_units_report_dialog_update(void * unused)885 void real_units_report_dialog_update(void *unused)
886 {
887 if (pUnitsDlg) {
888 struct units_entry units[U_LAST];
889 struct units_entry units_total;
890 struct widget *pWidget, *pbuf;
891 bool is_in_list = FALSE;
892 char cbuf[32];
893 bool upgrade;
894 bool search_finished;
895
896 get_units_report_data(units, &units_total);
897
898 /* find if there are new units entry (if not then rebuild all) */
899 pWidget = pUnitsDlg->pEndActiveWidgetList; /* icon of first list entry */
900 unit_type_iterate(i) {
901 if ((units[utype_index(i)].active_count > 0)
902 || (units[utype_index(i)].building_count > 0)) {
903 is_in_list = FALSE;
904
905 pbuf = pWidget; /* unit type icon */
906 while (pbuf) {
907 if ((MAX_ID - pbuf->ID) == utype_number(i)) {
908 is_in_list = TRUE;
909 pWidget = pbuf;
910 break;
911 }
912 if (pbuf->prev->prev->prev->prev->prev->prev->prev ==
913 pUnitsDlg->pBeginActiveWidgetList) {
914 break;
915 }
916
917 /* first widget of next list entry */
918 pbuf = pbuf->prev->prev->prev->prev->prev->prev->prev->prev;
919 }
920
921 if (!is_in_list) {
922 real_activeunits_report_dialog_update(units, &units_total);
923 return;
924 }
925 }
926 } unit_type_iterate_end;
927
928 /* update list */
929 pWidget = pUnitsDlg->pEndActiveWidgetList;
930 unit_type_iterate(i) {
931 pbuf = pWidget; /* first widget (icon) of the first list entry */
932
933 if ((units[utype_index(i)].active_count > 0) || (units[utype_index(i)].building_count > 0)) {
934 /* the player has at least one unit of this type */
935
936 search_finished = FALSE;
937 while (!search_finished) {
938 if ((MAX_ID - pbuf->ID) == utype_number(i)) { /* list entry for this unit type found */
939
940 upgrade = (can_upgrade_unittype(client.conn.playing, i) != NULL);
941
942 pbuf = pbuf->prev; /* unit type name */
943 if (upgrade) {
944 pbuf->string_utf8->fgcol = *get_theme_color(COLOR_THEME_UNITUPGRADE_TEXT);
945 pbuf->action = popup_upgrade_unit_callback;
946 set_wstate(pbuf, FC_WS_NORMAL);
947 }
948
949 pbuf = pbuf->prev; /* active */
950 fc_snprintf(cbuf, sizeof(cbuf), "%d", units[utype_index(i)].active_count);
951 copy_chars_to_utf8_str(pbuf->string_utf8, cbuf);
952
953 pbuf = pbuf->prev; /* shield upkeep */
954 fc_snprintf(cbuf, sizeof(cbuf), "%d", units[utype_index(i)].upkeep[O_SHIELD]);
955 copy_chars_to_utf8_str(pbuf->string_utf8, cbuf);
956
957 pbuf = pbuf->prev; /* food upkeep */
958 fc_snprintf(cbuf, sizeof(cbuf), "%d", units[utype_index(i)].upkeep[O_FOOD]);
959 copy_chars_to_utf8_str(pbuf->string_utf8, cbuf);
960
961 pbuf = pbuf->prev; /* gold upkeep */
962 fc_snprintf(cbuf, sizeof(cbuf), "%d", units[utype_index(i)].upkeep[O_GOLD]);
963 copy_chars_to_utf8_str(pbuf->string_utf8, cbuf);
964
965 pbuf = pbuf->prev; /* building */
966 if (units[utype_index(i)].building_count > 0) {
967 fc_snprintf(cbuf, sizeof(cbuf), "%d", units[utype_index(i)].building_count);
968 } else {
969 fc_snprintf(cbuf, sizeof(cbuf), "--");
970 }
971 copy_chars_to_utf8_str(pbuf->string_utf8, cbuf);
972
973 pbuf = pbuf->prev; /* soonest completion */
974 if (units[utype_index(i)].building_count > 0) {
975 fc_snprintf(cbuf, sizeof(cbuf), "%d %s", units[utype_index(i)].soonest_completions,
976 PL_("turn", "turns", units[utype_index(i)].soonest_completions));
977 } else {
978 fc_snprintf(cbuf, sizeof(cbuf), "--");
979 }
980 copy_chars_to_utf8_str(pbuf->string_utf8, cbuf);
981
982 pWidget = pbuf->prev; /* icon of next unit type */
983
984 search_finished = TRUE;
985
986 } else { /* list entry for this unit type not found yet */
987
988 /* search it */
989 pbuf = pWidget->next;
990 do {
991 del_widget_from_vertical_scroll_widget_list(pUnitsDlg, pbuf->prev);
992 } while (((MAX_ID - pbuf->prev->ID) != utype_number(i))
993 && (pbuf->prev != pUnitsDlg->pBeginActiveWidgetList));
994
995 if (pbuf->prev == pUnitsDlg->pBeginActiveWidgetList) {
996 /* list entry not found - can this really happen? */
997 del_widget_from_vertical_scroll_widget_list(pUnitsDlg, pbuf->prev);
998 pWidget = pbuf->prev; /* pUnitsDlg->pBeginActiveWidgetList */
999 search_finished = TRUE;
1000 } else {
1001 /* found it */
1002 pbuf = pbuf->prev; /* first widget (icon) of list entry */
1003 }
1004 }
1005 }
1006 } else { /* player has no unit of this type */
1007 if (pbuf && pbuf->next != pUnitsDlg->pBeginActiveWidgetList) {
1008 if (utype_number(i) < (MAX_ID - pbuf->ID)) {
1009 continue;
1010 } else {
1011 pbuf = pbuf->next;
1012 do {
1013 del_widget_from_vertical_scroll_widget_list(pUnitsDlg,
1014 pbuf->prev);
1015 } while (((MAX_ID - pbuf->prev->ID) == utype_number(i))
1016 && (pbuf->prev != pUnitsDlg->pBeginActiveWidgetList));
1017 if (pbuf->prev == pUnitsDlg->pBeginActiveWidgetList) {
1018 del_widget_from_vertical_scroll_widget_list(pUnitsDlg,
1019 pbuf->prev);
1020 }
1021 pWidget = pbuf->prev;
1022 }
1023 }
1024 }
1025 } unit_type_iterate_end;
1026
1027 /* -------------------------------------- */
1028
1029 /* total active */
1030 pbuf = pUnitsDlg->pEndWidgetList->prev->prev;
1031 fc_snprintf(cbuf, sizeof(cbuf), "%d", units_total.active_count);
1032 copy_chars_to_utf8_str(pbuf->string_utf8, cbuf);
1033
1034 /* total shields cost */
1035 pbuf = pbuf->prev;
1036 fc_snprintf(cbuf, sizeof(cbuf), "%d", units_total.upkeep[O_SHIELD]);
1037 copy_chars_to_utf8_str(pbuf->string_utf8, cbuf);
1038
1039 /* total food cost widget */
1040 pbuf = pbuf->prev;
1041 fc_snprintf(cbuf, sizeof(cbuf), "%d", units_total.upkeep[O_FOOD]);
1042 copy_chars_to_utf8_str(pbuf->string_utf8, cbuf);
1043
1044 /* total gold cost widget */
1045 pbuf = pbuf->prev;
1046 fc_snprintf(cbuf, sizeof(cbuf), "%d", units_total.upkeep[O_GOLD]);
1047 copy_chars_to_utf8_str(pbuf->string_utf8, cbuf);
1048
1049 /* total building count */
1050 pbuf = pbuf->prev;
1051 fc_snprintf(cbuf, sizeof(cbuf), "%d", units_total.building_count);
1052 copy_chars_to_utf8_str(pbuf->string_utf8, cbuf);
1053
1054 /* -------------------------------------- */
1055 redraw_group(pUnitsDlg->pBeginWidgetList, pUnitsDlg->pEndWidgetList, 0);
1056 widget_mark_dirty(pUnitsDlg->pEndWidgetList);
1057
1058 flush_dirty();
1059 }
1060 }
1061
1062 /**************************************************************************
1063 Popup (or raise) the units report (F2). It may or may not be modal.
1064 **************************************************************************/
units_report_dialog_popup(bool make_modal)1065 void units_report_dialog_popup(bool make_modal)
1066 {
1067 struct units_entry units[U_LAST];
1068 struct units_entry units_total;
1069
1070 if (pUnitsDlg) {
1071 return;
1072 }
1073
1074 get_units_report_data(units, &units_total);
1075 real_activeunits_report_dialog_update(units, &units_total);
1076 }
1077
1078 /**************************************************************************
1079 Popdown the units report.
1080 **************************************************************************/
units_report_dialog_popdown(void)1081 void units_report_dialog_popdown(void)
1082 {
1083 if (pUnitsDlg) {
1084 if (pUnits_Upg_Dlg) {
1085 del_group_of_widgets_from_gui_list(pUnits_Upg_Dlg->pBeginWidgetList,
1086 pUnits_Upg_Dlg->pEndWidgetList);
1087 FC_FREE(pUnits_Upg_Dlg);
1088 }
1089 popdown_window_group_dialog(pUnitsDlg->pBeginWidgetList,
1090 pUnitsDlg->pEndWidgetList);
1091 FC_FREE(pUnitsDlg->pScroll);
1092 FC_FREE(pUnitsDlg);
1093 }
1094 }
1095
1096 /* ===================================================================== */
1097 /* ======================== Economy Report ============================= */
1098 /* ===================================================================== */
1099 static struct ADVANCED_DLG *pEconomyDlg = NULL;
1100 static struct SMALL_DLG *pEconomy_Sell_Dlg = NULL;
1101
1102 struct rates_move {
1103 int min, max, tax, x, gov_max;
1104 int *src_rate, *dst_rate;
1105 struct widget *pHoriz_Src, *pHoriz_Dst;
1106 struct widget *pLabel_Src, *pLabel_Dst;
1107 };
1108
1109 /**************************************************************************
1110 User interacted with Economy Report window.
1111 **************************************************************************/
economy_dialog_callback(struct widget * pWindow)1112 static int economy_dialog_callback(struct widget *pWindow)
1113 {
1114 if (PRESSED_EVENT(Main.event)) {
1115 move_window_group(pEconomyDlg->pBeginWidgetList, pWindow);
1116 }
1117
1118 return -1;
1119 }
1120
1121 /**************************************************************************
1122 User interacted with Economy dialog Close Dialog button.
1123 **************************************************************************/
exit_economy_dialog_callback(struct widget * pWidget)1124 static int exit_economy_dialog_callback(struct widget *pWidget)
1125 {
1126 if (PRESSED_EVENT(Main.event)) {
1127 if (pEconomyDlg) {
1128 if (pEconomy_Sell_Dlg) {
1129 del_group_of_widgets_from_gui_list(pEconomy_Sell_Dlg->pBeginWidgetList,
1130 pEconomy_Sell_Dlg->pEndWidgetList);
1131 FC_FREE(pEconomy_Sell_Dlg);
1132 }
1133 popdown_window_group_dialog(pEconomyDlg->pBeginWidgetList,
1134 pEconomyDlg->pEndWidgetList);
1135 FC_FREE(pEconomyDlg->pScroll);
1136 FC_FREE(pEconomyDlg);
1137 set_wstate(get_tax_rates_widget(), FC_WS_NORMAL);
1138 widget_redraw(get_tax_rates_widget());
1139 widget_mark_dirty(get_tax_rates_widget());
1140 flush_dirty();
1141 }
1142 }
1143
1144 return -1;
1145 }
1146
1147 /**************************************************************************
1148 Toggle Rates dialog locking checkbox.
1149 **************************************************************************/
toggle_block_callback(struct widget * pCheckBox)1150 static int toggle_block_callback(struct widget *pCheckBox)
1151 {
1152 if (PRESSED_EVENT(Main.event)) {
1153 switch (pCheckBox->ID) {
1154 case ID_CHANGE_TAXRATE_DLG_LUX_BLOCK_CHECKBOX:
1155 SDL_Client_Flags ^= CF_CHANGE_TAXRATE_LUX_BLOCK;
1156 return -1;
1157
1158 case ID_CHANGE_TAXRATE_DLG_SCI_BLOCK_CHECKBOX:
1159 SDL_Client_Flags ^= CF_CHANGE_TAXRATE_SCI_BLOCK;
1160 return -1;
1161
1162 default:
1163 return -1;
1164 }
1165 }
1166
1167 return -1;
1168 }
1169
1170 /**************************************************************************
1171 User released mouse button while adjusting rates.
1172 **************************************************************************/
report_scroll_mouse_button_up(SDL_MouseButtonEvent * pButtonEvent,void * pData)1173 static Uint16 report_scroll_mouse_button_up(SDL_MouseButtonEvent *pButtonEvent,
1174 void *pData)
1175 {
1176 return (Uint16)ID_SCROLLBAR;
1177 }
1178
1179 /**************************************************************************
1180 User moved a mouse while adjusting rates.
1181 **************************************************************************/
report_scroll_mouse_motion_handler(SDL_MouseMotionEvent * pMotionEvent,void * pData)1182 static Uint16 report_scroll_mouse_motion_handler(SDL_MouseMotionEvent *pMotionEvent,
1183 void *pData)
1184 {
1185 struct rates_move *pMotion = (struct rates_move *)pData;
1186 struct widget *pTax_Label = pEconomyDlg->pEndWidgetList->prev->prev;
1187 struct widget *pbuf = NULL;
1188 char cbuf[8];
1189 int dir, inc, x, *buf_rate = NULL;
1190
1191 pMotionEvent->x -= pMotion->pHoriz_Src->dst->dest_rect.x;
1192
1193 if ((abs(pMotionEvent->x - pMotion->x) > 7)
1194 && (pMotionEvent->x >= pMotion->min)
1195 && (pMotionEvent->x <= pMotion->max)) {
1196
1197 /* set up directions */
1198 if (pMotionEvent->xrel > 0) {
1199 dir = 15;
1200 inc = 10;
1201 } else {
1202 dir = -15;
1203 inc = -10;
1204 }
1205
1206 /* make checks */
1207 x = pMotion->pHoriz_Src->size.x;
1208 if (((x + dir) <= pMotion->max) && ((x + dir) >= pMotion->min)) {
1209 /* src in range */
1210 if (pMotion->pHoriz_Dst) {
1211 x = pMotion->pHoriz_Dst->size.x;
1212 if (((x + (-1 * dir)) > pMotion->max) || ((x + (-1 * dir)) < pMotion->min)) {
1213 /* dst out of range */
1214 if (pMotion->tax + (-1 * inc) <= pMotion->gov_max
1215 && pMotion->tax + (-1 * inc) >= 0) {
1216 /* tax in range */
1217 pbuf = pMotion->pHoriz_Dst;
1218 pMotion->pHoriz_Dst = NULL;
1219 buf_rate = pMotion->dst_rate;
1220 pMotion->dst_rate = &pMotion->tax;
1221 pMotion->pLabel_Dst = pTax_Label;
1222 } else {
1223 pMotion->x = pMotion->pHoriz_Src->size.x;
1224 return ID_ERROR;
1225 }
1226 }
1227 } else {
1228 if (pMotion->tax + (-1 * inc) > pMotion->gov_max
1229 || pMotion->tax + (-1 * inc) < 0) {
1230 pMotion->x = pMotion->pHoriz_Src->size.x;
1231 return ID_ERROR;
1232 }
1233 }
1234
1235 /* undraw scrollbars */
1236 widget_undraw(pMotion->pHoriz_Src);
1237 widget_mark_dirty(pMotion->pHoriz_Src);
1238
1239 if (pMotion->pHoriz_Dst) {
1240 widget_undraw(pMotion->pHoriz_Dst);
1241 widget_mark_dirty(pMotion->pHoriz_Dst);
1242 }
1243
1244 pMotion->pHoriz_Src->size.x += dir;
1245 if (pMotion->pHoriz_Dst) {
1246 pMotion->pHoriz_Dst->size.x -= dir;
1247 }
1248
1249 *pMotion->src_rate += inc;
1250 *pMotion->dst_rate -= inc;
1251
1252 fc_snprintf(cbuf, sizeof(cbuf), "%d%%", *pMotion->src_rate);
1253 copy_chars_to_utf8_str(pMotion->pLabel_Src->string_utf8, cbuf);
1254 fc_snprintf(cbuf, sizeof(cbuf), "%d%%", *pMotion->dst_rate);
1255 copy_chars_to_utf8_str(pMotion->pLabel_Dst->string_utf8, cbuf);
1256
1257 /* redraw label */
1258 widget_redraw(pMotion->pLabel_Src);
1259 widget_mark_dirty(pMotion->pLabel_Src);
1260
1261 widget_redraw(pMotion->pLabel_Dst);
1262 widget_mark_dirty(pMotion->pLabel_Dst);
1263
1264 /* redraw scroolbar */
1265 if (get_wflags(pMotion->pHoriz_Src) & WF_RESTORE_BACKGROUND) {
1266 refresh_widget_background(pMotion->pHoriz_Src);
1267 }
1268 widget_redraw(pMotion->pHoriz_Src);
1269 widget_mark_dirty(pMotion->pHoriz_Src);
1270
1271 if (pMotion->pHoriz_Dst) {
1272 if (get_wflags(pMotion->pHoriz_Dst) & WF_RESTORE_BACKGROUND) {
1273 refresh_widget_background(pMotion->pHoriz_Dst);
1274 }
1275 widget_redraw(pMotion->pHoriz_Dst);
1276 widget_mark_dirty(pMotion->pHoriz_Dst);
1277 }
1278
1279 flush_dirty();
1280
1281 if (pbuf != NULL) {
1282 pMotion->pHoriz_Dst = pbuf;
1283 pMotion->pLabel_Dst = pMotion->pHoriz_Dst->prev;
1284 pMotion->dst_rate = buf_rate;
1285 pbuf = NULL;
1286 }
1287
1288 pMotion->x = pMotion->pHoriz_Src->size.x;
1289 }
1290 } /* if */
1291
1292 return ID_ERROR;
1293 }
1294
1295
1296 /**************************************************************************
1297 Handle Rates sliders.
1298 **************************************************************************/
horiz_taxrate_callback(struct widget * pHoriz_Src)1299 static int horiz_taxrate_callback(struct widget *pHoriz_Src)
1300 {
1301 if (PRESSED_EVENT(Main.event)) {
1302 struct rates_move pMotion;
1303
1304 pMotion.pHoriz_Src = pHoriz_Src;
1305 pMotion.pLabel_Src = pHoriz_Src->prev;
1306
1307 switch (pHoriz_Src->ID) {
1308 case ID_CHANGE_TAXRATE_DLG_LUX_SCROLLBAR:
1309 if (SDL_Client_Flags & CF_CHANGE_TAXRATE_LUX_BLOCK) {
1310 goto END;
1311 }
1312 pMotion.src_rate = (int *)pHoriz_Src->data.ptr;
1313 pMotion.pHoriz_Dst = pHoriz_Src->prev->prev->prev; /* sci */
1314 pMotion.dst_rate = (int *)pMotion.pHoriz_Dst->data.ptr;
1315 pMotion.tax = 100 - *pMotion.src_rate - *pMotion.dst_rate;
1316 if ((SDL_Client_Flags & CF_CHANGE_TAXRATE_SCI_BLOCK)) {
1317 if (pMotion.tax <= get_player_bonus(client.conn.playing, EFT_MAX_RATES)) {
1318 pMotion.pHoriz_Dst = NULL; /* tax */
1319 pMotion.dst_rate = &pMotion.tax;
1320 } else {
1321 goto END; /* all blocked */
1322 }
1323 }
1324
1325 break;
1326
1327 case ID_CHANGE_TAXRATE_DLG_SCI_SCROLLBAR:
1328 if ((SDL_Client_Flags & CF_CHANGE_TAXRATE_SCI_BLOCK)) {
1329 goto END;
1330 }
1331 pMotion.src_rate = (int *)pHoriz_Src->data.ptr;
1332 pMotion.pHoriz_Dst = pHoriz_Src->next->next->next; /* lux */
1333 pMotion.dst_rate = (int *)pMotion.pHoriz_Dst->data.ptr;
1334 pMotion.tax = 100 - *pMotion.src_rate - *pMotion.dst_rate;
1335 if (SDL_Client_Flags & CF_CHANGE_TAXRATE_LUX_BLOCK) {
1336 if (pMotion.tax <= get_player_bonus(client.conn.playing, EFT_MAX_RATES)) {
1337 /* tax */
1338 pMotion.pHoriz_Dst = NULL;
1339 pMotion.dst_rate = &pMotion.tax;
1340 } else {
1341 goto END; /* all blocked */
1342 }
1343 }
1344
1345 break;
1346
1347 default:
1348 return -1;
1349 }
1350
1351 if (pMotion.pHoriz_Dst) {
1352 pMotion.pLabel_Dst = pMotion.pHoriz_Dst->prev;
1353 } else {
1354 /* tax label */
1355 pMotion.pLabel_Dst = pEconomyDlg->pEndWidgetList->prev->prev;
1356 }
1357
1358 pMotion.min = pHoriz_Src->next->size.x + pHoriz_Src->next->size.w + adj_size(2);
1359 pMotion.gov_max = get_player_bonus(client.conn.playing, EFT_MAX_RATES);
1360 pMotion.max = pMotion.min + pMotion.gov_max * 1.5;
1361 pMotion.x = pHoriz_Src->size.x;
1362
1363 MOVE_STEP_Y = 0;
1364 /* Filter mouse motion events */
1365 SDL_SetEventFilter(FilterMouseMotionEvents, NULL);
1366 gui_event_loop((void *)(&pMotion), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1367 report_scroll_mouse_button_up,
1368 report_scroll_mouse_motion_handler);
1369 /* Turn off Filter mouse motion events */
1370 SDL_SetEventFilter(NULL, NULL);
1371 MOVE_STEP_Y = DEFAULT_MOVE_STEP;
1372
1373 END:
1374 unselect_widget_action();
1375 selected_widget = pHoriz_Src;
1376 set_wstate(pHoriz_Src, FC_WS_SELECTED);
1377 widget_redraw(pHoriz_Src);
1378 widget_flush(pHoriz_Src);
1379 }
1380
1381 return -1;
1382 }
1383
1384 /**************************************************************************
1385 User interacted with Update button of the Rates.
1386 **************************************************************************/
apply_taxrates_callback(struct widget * pButton)1387 static int apply_taxrates_callback(struct widget *pButton)
1388 {
1389 if (PRESSED_EVENT(Main.event)) {
1390 struct widget *pBuf;
1391 int science, luxury, tax;
1392
1393 if (C_S_RUNNING != client_state()) {
1394 return -1;
1395 }
1396
1397 /* Science Scrollbar */
1398 pBuf = pButton->next->next;
1399 science = *(int *)pBuf->data.ptr;
1400
1401 /* Luxuries Scrollbar */
1402 pBuf = pBuf->next->next->next;
1403 luxury = *(int *)pBuf->data.ptr;
1404
1405 /* Tax */
1406 tax = 100 - luxury - science;
1407
1408 if (tax != client.conn.playing->economic.tax
1409 || science != client.conn.playing->economic.science
1410 || luxury != client.conn.playing->economic.luxury) {
1411 dsend_packet_player_rates(&client.conn, tax, luxury, science);
1412 }
1413
1414 widget_redraw(pButton);
1415 widget_flush(pButton);
1416 }
1417
1418 return -1;
1419 }
1420
1421 /**************************************************************************
1422 Set economy dialog widgets enabled.
1423 **************************************************************************/
enable_economy_dlg(void)1424 static void enable_economy_dlg(void)
1425 {
1426 /* lux lock */
1427 struct widget *pBuf = pEconomyDlg->pEndWidgetList->prev->prev->prev->prev->prev->prev;
1428
1429 set_wstate(pBuf, FC_WS_NORMAL);
1430
1431 /* lux scrollbar */
1432 pBuf = pBuf->prev;
1433 set_wstate(pBuf, FC_WS_NORMAL);
1434
1435 /* sci lock */
1436 pBuf = pBuf->prev->prev;
1437 set_wstate(pBuf, FC_WS_NORMAL);
1438
1439 /* sci scrollbar */
1440 pBuf = pBuf->prev;
1441 set_wstate(pBuf, FC_WS_NORMAL);
1442
1443 /* update button */
1444 pBuf = pBuf->prev->prev;
1445 set_wstate(pBuf, FC_WS_NORMAL);
1446
1447 /* cancel button */
1448 pBuf = pBuf->prev;
1449 set_wstate(pBuf, FC_WS_NORMAL);
1450
1451 set_group_state(pEconomyDlg->pBeginActiveWidgetList,
1452 pEconomyDlg->pEndActiveWidgetList, FC_WS_NORMAL);
1453 if (pEconomyDlg->pScroll && pEconomyDlg->pActiveWidgetList) {
1454 set_wstate(pEconomyDlg->pScroll->pUp_Left_Button, FC_WS_NORMAL);
1455 set_wstate(pEconomyDlg->pScroll->pDown_Right_Button, FC_WS_NORMAL);
1456 set_wstate(pEconomyDlg->pScroll->pScrollBar, FC_WS_NORMAL);
1457 }
1458 }
1459
1460 /**************************************************************************
1461 Set economy dialog widgets disabled.
1462 **************************************************************************/
disable_economy_dlg(void)1463 static void disable_economy_dlg(void)
1464 {
1465 /* lux lock */
1466 struct widget *pBuf = pEconomyDlg->pEndWidgetList->prev->prev->prev->prev->prev->prev;
1467
1468 set_wstate(pBuf, FC_WS_DISABLED);
1469
1470 /* lux scrollbar */
1471 pBuf = pBuf->prev;
1472 set_wstate(pBuf, FC_WS_DISABLED);
1473
1474 /* sci lock */
1475 pBuf = pBuf->prev->prev;
1476 set_wstate(pBuf, FC_WS_DISABLED);
1477
1478 /* sci scrollbar */
1479 pBuf = pBuf->prev;
1480 set_wstate(pBuf, FC_WS_DISABLED);
1481
1482 /* update button */
1483 pBuf = pBuf->prev->prev;
1484 set_wstate(pBuf, FC_WS_DISABLED);
1485
1486 /* cancel button */
1487 pBuf = pBuf->prev;
1488 set_wstate(pBuf, FC_WS_DISABLED);
1489
1490 set_group_state(pEconomyDlg->pBeginActiveWidgetList,
1491 pEconomyDlg->pEndActiveWidgetList, FC_WS_DISABLED);
1492 if (pEconomyDlg->pScroll && pEconomyDlg->pActiveWidgetList) {
1493 set_wstate(pEconomyDlg->pScroll->pUp_Left_Button, FC_WS_DISABLED);
1494 set_wstate(pEconomyDlg->pScroll->pDown_Right_Button, FC_WS_DISABLED);
1495 set_wstate(pEconomyDlg->pScroll->pScrollBar, FC_WS_DISABLED);
1496 }
1497 }
1498
1499 /* --------------------------------------------------------------- */
1500
1501 /**************************************************************************
1502 User interacted with Yes button of the improvement selling dialog.
1503 **************************************************************************/
ok_sell_impr_callback(struct widget * pWidget)1504 static int ok_sell_impr_callback(struct widget *pWidget)
1505 {
1506 if (PRESSED_EVENT(Main.event)) {
1507 int imp, total_count, count = 0;
1508 struct widget *pImpr = (struct widget *)pWidget->data.ptr;
1509
1510 imp = pImpr->data.cont->id0;
1511 total_count = pImpr->data.cont->id1;
1512
1513 /* popdown sell dlg */
1514 popdown_window_group_dialog(pEconomy_Sell_Dlg->pBeginWidgetList,
1515 pEconomy_Sell_Dlg->pEndWidgetList);
1516 FC_FREE(pEconomy_Sell_Dlg);
1517 enable_economy_dlg();
1518
1519 /* send sell */
1520 city_list_iterate(client.conn.playing->cities, pCity) {
1521 if (!pCity->did_sell && city_has_building(pCity, improvement_by_number(imp))){
1522 count++;
1523
1524 city_sell_improvement(pCity, imp);
1525 }
1526 } city_list_iterate_end;
1527
1528 if (count == total_count) {
1529 del_widget_from_vertical_scroll_widget_list(pEconomyDlg, pImpr);
1530 }
1531 }
1532
1533 return -1;
1534 }
1535
1536 /**************************************************************************
1537 User interacted with the improvement selling window.
1538 **************************************************************************/
sell_impr_window_callback(struct widget * pWindow)1539 static int sell_impr_window_callback(struct widget *pWindow)
1540 {
1541 if (PRESSED_EVENT(Main.event)) {
1542 move_window_group(pEconomy_Sell_Dlg->pBeginWidgetList, pWindow);
1543 }
1544
1545 return -1;
1546 }
1547
1548 /**************************************************************************
1549 User interacted with Cancel button of the improvement selling dialog.
1550 **************************************************************************/
cancel_sell_impr_callback(struct widget * pWidget)1551 static int cancel_sell_impr_callback(struct widget *pWidget)
1552 {
1553 if (PRESSED_EVENT(Main.event)) {
1554 if (pEconomy_Sell_Dlg) {
1555 popdown_window_group_dialog(pEconomy_Sell_Dlg->pBeginWidgetList,
1556 pEconomy_Sell_Dlg->pEndWidgetList);
1557 FC_FREE(pEconomy_Sell_Dlg);
1558 enable_economy_dlg();
1559 flush_dirty();
1560 }
1561 }
1562
1563 return -1;
1564 }
1565
1566 /**************************************************************************
1567 Open improvement selling dialog.
1568 **************************************************************************/
popup_sell_impr_callback(struct widget * pWidget)1569 static int popup_sell_impr_callback(struct widget *pWidget)
1570 {
1571 if (PRESSED_EVENT(Main.event)) {
1572 int imp, total_count ,count = 0, gold = 0;
1573 int value;
1574 char cBuf[128];
1575 struct widget *pBuf = NULL, *pWindow;
1576 utf8_str *pstr;
1577 SDL_Surface *pText;
1578 SDL_Rect dst;
1579 SDL_Rect area;
1580
1581 if (pEconomy_Sell_Dlg) {
1582 return 1;
1583 }
1584
1585 set_wstate(pWidget, FC_WS_NORMAL);
1586 selected_widget = NULL;
1587 widget_redraw(pWidget);
1588 widget_mark_dirty(pWidget);
1589
1590 pEconomy_Sell_Dlg = fc_calloc(1, sizeof(struct SMALL_DLG));
1591
1592 imp = pWidget->data.cont->id0;
1593 total_count = pWidget->data.cont->id1;
1594 value = impr_sell_gold(improvement_by_number(imp));
1595
1596 city_list_iterate(client.conn.playing->cities, pCity) {
1597 if (!pCity->did_sell && city_has_building(pCity, improvement_by_number(imp))) {
1598 count++;
1599 gold += value;
1600 }
1601 } city_list_iterate_end;
1602
1603 if (count > 0) {
1604 fc_snprintf(cBuf, sizeof(cBuf),
1605 _("We have %d of %s\n(total value is : %d)\n"
1606 "We can sell %d of them for %d gold."),
1607 total_count,
1608 improvement_name_translation(improvement_by_number(imp)),
1609 total_count * value, count, gold);
1610 } else {
1611 fc_snprintf(cBuf, sizeof(cBuf),
1612 _("We can't sell any %s in this turn."),
1613 improvement_name_translation(improvement_by_number(imp)));
1614 }
1615
1616 pstr = create_utf8_from_char(_("Sell It?"), adj_font(12));
1617 pstr->style |= TTF_STYLE_BOLD;
1618
1619 pWindow = create_window_skeleton(NULL, pstr, 0);
1620
1621 pWindow->action = sell_impr_window_callback;
1622 set_wstate(pWindow, FC_WS_NORMAL);
1623
1624 pEconomy_Sell_Dlg->pEndWidgetList = pWindow;
1625
1626 add_to_gui_list(ID_WINDOW, pWindow);
1627
1628 area = pWindow->area;
1629
1630 /* ============================================================= */
1631
1632 /* create text label */
1633 pstr = create_utf8_from_char(cBuf, adj_font(10));
1634 pstr->style |= (TTF_STYLE_BOLD|SF_CENTER);
1635 pstr->fgcol = *get_theme_color(COLOR_THEME_SELLIMPR_TEXT);
1636
1637 pText = create_text_surf_from_utf8(pstr);
1638 FREEUTF8STR(pstr);
1639
1640 area.w = MAX(area.w, pText->w + adj_size(20));
1641 area.h += (pText->h + adj_size(10));
1642
1643 /* cancel button */
1644 pBuf = create_themeicon_button_from_chars(current_theme->CANCEL_Icon,
1645 pWindow->dst, _("No"),
1646 adj_font(12), 0);
1647
1648 pBuf->action = cancel_sell_impr_callback;
1649 set_wstate(pBuf, FC_WS_NORMAL);
1650
1651 area.h += (pBuf->size.h + adj_size(20));
1652
1653 add_to_gui_list(ID_BUTTON, pBuf);
1654
1655 if (count > 0) {
1656 pBuf = create_themeicon_button_from_chars(current_theme->OK_Icon, pWindow->dst,
1657 _("Sell"), adj_font(12), 0);
1658
1659 pBuf->action = ok_sell_impr_callback;
1660 set_wstate(pBuf, FC_WS_NORMAL);
1661 pBuf->data.ptr = (void *)pWidget;
1662
1663 add_to_gui_list(ID_BUTTON, pBuf);
1664 pBuf->size.w = MAX(pBuf->size.w, pBuf->next->size.w);
1665 pBuf->next->size.w = pBuf->size.w;
1666 area.w = MAX(area.w, adj_size(30) + pBuf->size.w * 2);
1667 } else {
1668 area.w = MAX(area.w, pBuf->size.w + adj_size(20));
1669 }
1670 /* ============================================ */
1671
1672 pEconomy_Sell_Dlg->pBeginWidgetList = pBuf;
1673
1674 resize_window(pWindow, NULL, get_theme_color(COLOR_THEME_BACKGROUND),
1675 (pWindow->size.w - pWindow->area.w) + area.w,
1676 (pWindow->size.h - pWindow->area.h) + area.h);
1677
1678 area = pWindow->area;
1679
1680 widget_set_position(pWindow,
1681 pEconomyDlg->pEndWidgetList->size.x +
1682 (pEconomyDlg->pEndWidgetList->size.w - pWindow->size.w) / 2,
1683 pEconomyDlg->pEndWidgetList->size.y +
1684 (pEconomyDlg->pEndWidgetList->size.h - pWindow->size.h) / 2);
1685
1686 /* setup rest of widgets */
1687 /* label */
1688 dst.x = area.x + (area.w - pText->w) / 2;
1689 dst.y = area.y + adj_size(10);
1690 alphablit(pText, NULL, pWindow->theme, &dst, 255);
1691 FREESURFACE(pText);
1692
1693 /* cancel button */
1694 pBuf = pWindow->prev;
1695 pBuf->size.y = area.y + area.h - pBuf->size.h - adj_size(10);
1696
1697 if (count > 0) {
1698 /* sell button */
1699 pBuf = pBuf->prev;
1700 pBuf->size.x = area.x + (area.w - (2 * pBuf->size.w + adj_size(10))) / 2;
1701 pBuf->size.y = pBuf->next->size.y;
1702
1703 /* cancel button */
1704 pBuf->next->size.x = pBuf->size.x + pBuf->size.w + adj_size(10);
1705 } else {
1706 /* x position of cancel button */
1707 pBuf->size.x = area.x + area.w - adj_size(10) - pBuf->size.w;
1708 }
1709
1710 /* ================================================== */
1711 /* redraw */
1712 redraw_group(pEconomy_Sell_Dlg->pBeginWidgetList, pWindow, 0);
1713 disable_economy_dlg();
1714
1715 widget_mark_dirty(pWindow);
1716 flush_dirty();
1717 }
1718
1719 return -1;
1720 }
1721
1722 /**************************************************************************
1723 Update the economy report.
1724 **************************************************************************/
real_economy_report_dialog_update(void * unused)1725 void real_economy_report_dialog_update(void *unused)
1726 {
1727 if (pEconomyDlg) {
1728 struct widget *pbuf = pEconomyDlg->pEndWidgetList;
1729 int tax, total, entries_used = 0;
1730 char cbuf[128];
1731 struct improvement_entry entries[B_LAST];
1732
1733 get_economy_report_data(entries, &entries_used, &total, &tax);
1734
1735 /* tresure */
1736 pbuf = pbuf->prev;
1737 fc_snprintf(cbuf, sizeof(cbuf), "%d", client.conn.playing->economic.gold);
1738 copy_chars_to_utf8_str(pbuf->string_utf8, cbuf);
1739 remake_label_size(pbuf);
1740
1741 /* Icome */
1742 pbuf = pbuf->prev->prev;
1743 fc_snprintf(cbuf, sizeof(cbuf), "%d", tax);
1744 copy_chars_to_utf8_str(pbuf->string_utf8, cbuf);
1745 remake_label_size(pbuf);
1746
1747 /* Cost */
1748 pbuf = pbuf->prev;
1749 fc_snprintf(cbuf, sizeof(cbuf), "%d", total);
1750 copy_chars_to_utf8_str(pbuf->string_utf8, cbuf);
1751 remake_label_size(pbuf);
1752
1753 /* Netto */
1754 pbuf = pbuf->prev;
1755 fc_snprintf(cbuf, sizeof(cbuf), "%d", tax - total);
1756 copy_chars_to_utf8_str(pbuf->string_utf8, cbuf);
1757 remake_label_size(pbuf);
1758 if (tax - total < 0) {
1759 pbuf->string_utf8->fgcol = *get_theme_color(COLOR_THEME_ECONOMYDLG_NEG_TEXT);
1760 } else {
1761 pbuf->string_utf8->fgcol = *get_theme_color(COLOR_THEME_ECONOMYDLG_TEXT);
1762 }
1763
1764 /* ---------------- */
1765 redraw_group(pEconomyDlg->pBeginWidgetList, pEconomyDlg->pEndWidgetList, 0);
1766 widget_flush(pEconomyDlg->pEndWidgetList);
1767 }
1768 }
1769
1770 /**************************************************************************
1771 Popdown the economy report.
1772 **************************************************************************/
economy_report_dialog_popdown(void)1773 void economy_report_dialog_popdown(void)
1774 {
1775 if (pEconomyDlg) {
1776 if (pEconomy_Sell_Dlg) {
1777 del_group_of_widgets_from_gui_list(pEconomy_Sell_Dlg->pBeginWidgetList,
1778 pEconomy_Sell_Dlg->pEndWidgetList);
1779 FC_FREE(pEconomy_Sell_Dlg);
1780 }
1781 popdown_window_group_dialog(pEconomyDlg->pBeginWidgetList,
1782 pEconomyDlg->pEndWidgetList);
1783 FC_FREE(pEconomyDlg->pScroll);
1784 FC_FREE(pEconomyDlg);
1785 set_wstate(get_tax_rates_widget(), FC_WS_NORMAL);
1786 widget_redraw(get_tax_rates_widget());
1787 widget_mark_dirty(get_tax_rates_widget());
1788 }
1789 }
1790
1791 #define TARGETS_ROW 2
1792 #define TARGETS_COL 4
1793
1794 /**************************************************************************
1795 Popup (or raise) the economy report (F5). It may or may not be modal.
1796 **************************************************************************/
economy_report_dialog_popup(bool make_modal)1797 void economy_report_dialog_popup(bool make_modal)
1798 {
1799 SDL_Color bg_color = {255,255,255,128};
1800 SDL_Color bg_color2 = {255,255,255,136};
1801 SDL_Color bg_color3 = {255,255,255,64};
1802 struct widget *pBuf;
1803 struct widget *pWindow , *pLast;
1804 utf8_str *pstr, *pstr2;
1805 SDL_Surface *pSurf, *pText_Name, *pText, *pZoom;
1806 SDL_Surface *pBackground;
1807 int i, count , h = 0;
1808 int w = 0; /* left column values */
1809 int w2 = 0; /* right column: lock + scrollbar + ... */
1810 int w3 = 0; /* left column text without values */
1811 int tax, total, entries_used = 0;
1812 char cbuf[128];
1813 struct improvement_entry entries[B_LAST];
1814 SDL_Rect dst;
1815 SDL_Rect area;
1816 struct government *pGov = government_of_player(client.conn.playing);
1817 SDL_Surface *pTreasuryText;
1818 SDL_Surface *pTaxRateText;
1819 SDL_Surface *pTotalIncomeText;
1820 SDL_Surface *pTotalCostText;
1821 SDL_Surface *pNetIncomeText;
1822 SDL_Surface *pMaxRateText;
1823
1824 if (pEconomyDlg) {
1825 return;
1826 }
1827
1828 /* disable "Economy" button */
1829 pBuf = get_tax_rates_widget();
1830 set_wstate(pBuf, FC_WS_DISABLED);
1831 widget_redraw(pBuf);
1832 widget_mark_dirty(pBuf);
1833
1834 pEconomyDlg = fc_calloc(1, sizeof(struct ADVANCED_DLG));
1835
1836 get_economy_report_data(entries, &entries_used, &total, &tax);
1837
1838 /* --------------- */
1839 pstr = create_utf8_from_char(_("Economy Report"), adj_font(12));
1840 pstr->style |= TTF_STYLE_BOLD;
1841
1842 pWindow = create_window_skeleton(NULL, pstr, 0);
1843 pEconomyDlg->pEndWidgetList = pWindow;
1844 set_wstate(pWindow, FC_WS_NORMAL);
1845 pWindow->action = economy_dialog_callback;
1846
1847 add_to_gui_list(ID_ECONOMY_DIALOG_WINDOW, pWindow);
1848
1849 area = pWindow->area;
1850
1851 /* ------------------------- */
1852
1853 /* "Treasury" text surface */
1854 fc_snprintf(cbuf, sizeof(cbuf), _("Treasury: "));
1855 pstr2 = create_utf8_from_char(cbuf, adj_font(12));
1856 pstr2->style |= TTF_STYLE_BOLD;
1857 pTreasuryText = create_text_surf_from_utf8(pstr2);
1858 w3 = MAX(w3, pTreasuryText->w);
1859
1860 /* "Treasury" value label*/
1861 fc_snprintf(cbuf, sizeof(cbuf), "%d", client.conn.playing->economic.gold);
1862 pstr = create_utf8_from_char(cbuf, adj_font(12));
1863 pstr->style |= (TTF_STYLE_BOLD|SF_CENTER);
1864
1865 pBuf = create_iconlabel(pIcons->pBIG_Coin, pWindow->dst, pstr,
1866 (WF_RESTORE_BACKGROUND|WF_ICON_CENTER_RIGHT));
1867
1868 add_to_gui_list(ID_LABEL, pBuf);
1869
1870 w = MAX(w, pBuf->size.w);
1871 h += pBuf->size.h;
1872
1873 /* "Tax Rate" text surface */
1874 fc_snprintf(cbuf, sizeof(cbuf), _("Tax Rate: "));
1875 copy_chars_to_utf8_str(pstr2, cbuf);
1876 pTaxRateText = create_text_surf_from_utf8(pstr2);
1877 w3 = MAX(w3, pTaxRateText->w);
1878
1879 /* "Tax Rate" value label */
1880 /* it is important to leave 1 space at ending of this string */
1881 fc_snprintf(cbuf, sizeof(cbuf), "%d%% ", client.conn.playing->economic.tax);
1882 pstr = create_utf8_from_char(cbuf, adj_font(12));
1883 pstr->style |= (TTF_STYLE_BOLD|SF_CENTER);
1884
1885 pBuf = create_iconlabel(NULL, pWindow->dst, pstr, WF_RESTORE_BACKGROUND);
1886
1887 add_to_gui_list(ID_LABEL, pBuf);
1888
1889 w = MAX(w, pBuf->size.w + pBuf->next->size.w);
1890 h += pBuf->size.h;
1891
1892 /* "Total Income" text surface */
1893 fc_snprintf(cbuf, sizeof(cbuf), _("Total Income: "));
1894 copy_chars_to_utf8_str(pstr2, cbuf);
1895 pTotalIncomeText = create_text_surf_from_utf8(pstr2);
1896 w3 = MAX(w3, pTotalIncomeText->w);
1897
1898 /* "Total Icome" value label */
1899 fc_snprintf(cbuf, sizeof(cbuf), "%d", tax);
1900 pstr = create_utf8_from_char(cbuf, adj_font(12));
1901 pstr->style |= TTF_STYLE_BOLD;
1902
1903 pBuf = create_iconlabel(NULL, pWindow->dst, pstr, WF_RESTORE_BACKGROUND);
1904
1905 add_to_gui_list(ID_LABEL, pBuf);
1906
1907 w = MAX(w, pBuf->size.w);
1908 h += pBuf->size.h;
1909
1910 /* "Total Cost" text surface */
1911 fc_snprintf(cbuf, sizeof(cbuf), _("Total Cost: "));
1912 copy_chars_to_utf8_str(pstr2, cbuf);
1913 pTotalCostText = create_text_surf_from_utf8(pstr2);
1914
1915 /* "Total Cost" value label */
1916 fc_snprintf(cbuf, sizeof(cbuf), "%d", total);
1917 pstr = create_utf8_from_char(cbuf, adj_font(12));
1918 pstr->style |= TTF_STYLE_BOLD;
1919
1920 pBuf = create_iconlabel(NULL, pWindow->dst, pstr, WF_RESTORE_BACKGROUND);
1921
1922 add_to_gui_list(ID_LABEL, pBuf);
1923
1924 w = MAX(w, pBuf->size.w);
1925 h += pBuf->size.h;
1926
1927 /* "Net Income" text surface */
1928 fc_snprintf(cbuf, sizeof(cbuf), _("Net Income: "));
1929 copy_chars_to_utf8_str(pstr2, cbuf);
1930 pNetIncomeText = create_text_surf_from_utf8(pstr2);
1931 w3 = MAX(w3, pNetIncomeText->w);
1932
1933 /* "Net Icome" value label */
1934 fc_snprintf(cbuf, sizeof(cbuf), "%d", tax - total);
1935 pstr = create_utf8_from_char(cbuf, adj_font(12));
1936 pstr->style |= (TTF_STYLE_BOLD|SF_CENTER);
1937
1938 if (tax - total < 0) {
1939 pstr->fgcol = *get_theme_color(COLOR_THEME_ECONOMYDLG_NEG_TEXT);
1940 }
1941
1942 pBuf = create_iconlabel(NULL, pWindow->dst, pstr, WF_RESTORE_BACKGROUND);
1943
1944 add_to_gui_list(ID_LABEL, pBuf);
1945
1946 w = MAX(w, pBuf->size.w);
1947 h += pBuf->size.h;
1948
1949 /* gov and taxrate */
1950 fc_snprintf(cbuf, sizeof(cbuf), _("%s max rate : %d%%"),
1951 government_name_translation(pGov),
1952 get_player_bonus(client.conn.playing, EFT_MAX_RATES));
1953 copy_chars_to_utf8_str(pstr2, cbuf);
1954 pMaxRateText = create_text_surf_from_utf8(pstr2);
1955
1956 FREEUTF8STR(pstr2);
1957
1958 /* ------------------------- */
1959 /* lux rate */
1960
1961 /* lux rate lock */
1962 fc_snprintf(cbuf, sizeof(cbuf), _("Lock"));
1963 pstr = create_utf8_from_char(cbuf, adj_font(10));
1964 pstr->style |= TTF_STYLE_BOLD;
1965
1966 pBuf = create_checkbox(pWindow->dst,
1967 SDL_Client_Flags & CF_CHANGE_TAXRATE_LUX_BLOCK,
1968 WF_RESTORE_BACKGROUND | WF_WIDGET_HAS_INFO_LABEL);
1969 set_new_checkbox_theme(pBuf, current_theme->LOCK_Icon, current_theme->UNLOCK_Icon);
1970 pBuf->info_label = pstr;
1971 pBuf->action = toggle_block_callback;
1972 set_wstate(pBuf, FC_WS_NORMAL);
1973
1974 add_to_gui_list(ID_CHANGE_TAXRATE_DLG_LUX_BLOCK_CHECKBOX, pBuf);
1975
1976 w2 = adj_size(10) + pBuf->size.w;
1977
1978 /* lux rate slider */
1979 pBuf = create_horizontal(current_theme->Horiz, pWindow->dst, adj_size(30),
1980 (WF_FREE_DATA | WF_RESTORE_BACKGROUND));
1981
1982 pBuf->action = horiz_taxrate_callback;
1983 pBuf->data.ptr = fc_calloc(1, sizeof(int));
1984 *(int *)pBuf->data.ptr = client.conn.playing->economic.luxury;
1985 set_wstate(pBuf, FC_WS_NORMAL);
1986
1987 add_to_gui_list(ID_CHANGE_TAXRATE_DLG_LUX_SCROLLBAR, pBuf);
1988
1989 w2 += adj_size(184);
1990
1991 /* lux rate iconlabel */
1992
1993 /* it is important to leave 1 space at ending of this string */
1994 fc_snprintf(cbuf, sizeof(cbuf), "%d%% ", client.conn.playing->economic.luxury);
1995 pstr = create_utf8_from_char(cbuf, adj_font(11));
1996 pstr->style |= TTF_STYLE_BOLD;
1997
1998 pBuf = create_iconlabel(pIcons->pBIG_Luxury, pWindow->dst, pstr,
1999 WF_RESTORE_BACKGROUND);
2000 add_to_gui_list(ID_CHANGE_TAXRATE_DLG_LUX_LABEL, pBuf);
2001
2002 w2 += (adj_size(5) + pBuf->size.w + adj_size(10));
2003
2004 /* ------------------------- */
2005 /* science rate */
2006
2007 /* science rate lock */
2008 fc_snprintf(cbuf, sizeof(cbuf), _("Lock"));
2009 pstr = create_utf8_from_char(cbuf, adj_font(10));
2010 pstr->style |= TTF_STYLE_BOLD;
2011
2012 pBuf = create_checkbox(pWindow->dst,
2013 SDL_Client_Flags & CF_CHANGE_TAXRATE_SCI_BLOCK,
2014 WF_RESTORE_BACKGROUND | WF_WIDGET_HAS_INFO_LABEL);
2015
2016 set_new_checkbox_theme(pBuf, current_theme->LOCK_Icon, current_theme->UNLOCK_Icon);
2017
2018 pBuf->info_label = pstr;
2019 pBuf->action = toggle_block_callback;
2020 set_wstate(pBuf, FC_WS_NORMAL);
2021
2022 add_to_gui_list(ID_CHANGE_TAXRATE_DLG_SCI_BLOCK_CHECKBOX, pBuf);
2023
2024 /* science rate slider */
2025 pBuf = create_horizontal(current_theme->Horiz, pWindow->dst, adj_size(30),
2026 (WF_FREE_DATA | WF_RESTORE_BACKGROUND));
2027
2028 pBuf->action = horiz_taxrate_callback;
2029 pBuf->data.ptr = fc_calloc(1, sizeof(int));
2030 *(int *)pBuf->data.ptr = client.conn.playing->economic.science;
2031
2032 set_wstate(pBuf, FC_WS_NORMAL);
2033
2034 add_to_gui_list(ID_CHANGE_TAXRATE_DLG_SCI_SCROLLBAR, pBuf);
2035
2036 /* science rate iconlabel */
2037 /* it is important to leave 1 space at ending of this string */
2038 fc_snprintf(cbuf, sizeof(cbuf), "%d%% ", client.conn.playing->economic.science);
2039 pstr = create_utf8_from_char(cbuf, adj_font(11));
2040 pstr->style |= TTF_STYLE_BOLD;
2041
2042 pBuf = create_iconlabel(pIcons->pBIG_Colb, pWindow->dst, pstr,
2043 WF_RESTORE_BACKGROUND);
2044
2045 add_to_gui_list(ID_CHANGE_TAXRATE_DLG_SCI_LABEL, pBuf);
2046
2047 /* ---- */
2048
2049 fc_snprintf(cbuf, sizeof(cbuf), _("Update"));
2050 pstr = create_utf8_from_char(cbuf, adj_font(12));
2051 pBuf = create_themeicon_button(current_theme->Small_OK_Icon, pWindow->dst, pstr, 0);
2052 pBuf->action = apply_taxrates_callback;
2053 set_wstate(pBuf, FC_WS_NORMAL);
2054
2055 add_to_gui_list(ID_CHANGE_TAXRATE_DLG_OK_BUTTON, pBuf);
2056
2057 /* ---- */
2058
2059 fc_snprintf(cbuf, sizeof(cbuf), _("Close Dialog (Esc)"));
2060 pstr = create_utf8_from_char(cbuf, adj_font(12));
2061 pBuf = create_themeicon(current_theme->Small_CANCEL_Icon, pWindow->dst,
2062 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
2063 pBuf->info_label = pstr;
2064 pBuf->action = exit_economy_dialog_callback;
2065 set_wstate(pBuf, FC_WS_NORMAL);
2066 pBuf->key = SDLK_ESCAPE;
2067
2068 add_to_gui_list(ID_CHANGE_TAXRATE_DLG_CANCEL_BUTTON, pBuf);
2069
2070 h += adj_size(5);
2071
2072 /* ------------------------- */
2073 pLast = pBuf;
2074 if (entries_used > 0) {
2075
2076 /* Create Imprv Background Icon */
2077 pBackground = create_surf(adj_size(116), adj_size(116), SDL_SWSURFACE);
2078
2079 SDL_FillRect(pBackground, NULL, map_rgba(pBackground->format, bg_color));
2080
2081 create_frame(pBackground,
2082 0, 0, pBackground->w - 1, pBackground->h - 1,
2083 get_theme_color(COLOR_THEME_ECONOMYDLG_FRAME));
2084
2085 pstr = create_utf8_str(NULL, 0, adj_font(10));
2086 pstr->style |= (SF_CENTER|TTF_STYLE_BOLD);
2087 pstr->bgcol = (SDL_Color) {0, 0, 0, 0};
2088
2089 for (i = 0; i < entries_used; i++) {
2090 struct improvement_entry *p = &entries[i];
2091 struct impr_type *pImprove = p->type;
2092
2093 pSurf = crop_rect_from_surface(pBackground, NULL);
2094
2095 fc_snprintf(cbuf, sizeof(cbuf), "%s", improvement_name_translation(pImprove));
2096
2097 copy_chars_to_utf8_str(pstr, cbuf);
2098 pstr->style |= TTF_STYLE_BOLD;
2099 pText_Name = create_text_surf_smaller_than_w(pstr, pSurf->w - adj_size(4));
2100
2101 fc_snprintf(cbuf, sizeof(cbuf), "%s %d\n%s %d",
2102 _("Built"), p->count, _("U Total"),p->total_cost);
2103 copy_chars_to_utf8_str(pstr, cbuf);
2104 pstr->style &= ~TTF_STYLE_BOLD;
2105
2106 pText = create_text_surf_from_utf8(pstr);
2107
2108 /*-----------------*/
2109
2110 pZoom = get_building_surface(pImprove);
2111 pZoom = zoomSurface(pZoom, DEFAULT_ZOOM * ((float)54 / pZoom->w), DEFAULT_ZOOM * ((float)54 / pZoom->w), 1);
2112
2113 dst.x = (pSurf->w - pZoom->w) / 2;
2114 dst.y = (pSurf->h / 2 - pZoom->h) / 2;
2115 alphablit(pZoom, NULL, pSurf, &dst, 255);
2116 dst.y += pZoom->h;
2117 FREESURFACE(pZoom);
2118
2119 dst.x = (pSurf->w - pText_Name->w)/2;
2120 dst.y += ((pSurf->h - dst.y) -
2121 (pText_Name->h + (pIcons->pBIG_Coin->h + 2) + pText->h)) / 2;
2122 alphablit(pText_Name, NULL, pSurf, &dst, 255);
2123
2124 dst.y += pText_Name->h;
2125 if (p->cost) {
2126 dst.x = (pSurf->w - p->cost * (pIcons->pBIG_Coin->w + 1))/2;
2127 for (count = 0; count < p->cost; count++) {
2128 alphablit(pIcons->pBIG_Coin, NULL, pSurf, &dst, 255);
2129 dst.x += pIcons->pBIG_Coin->w + 1;
2130 }
2131 } else {
2132
2133 if (!is_wonder(pImprove)) {
2134 copy_chars_to_utf8_str(pstr, _("Nation"));
2135 } else {
2136 copy_chars_to_utf8_str(pstr, _("Wonder"));
2137 }
2138 /*pstr->style &= ~TTF_STYLE_BOLD;*/
2139
2140 pZoom = create_text_surf_from_utf8(pstr);
2141
2142 dst.x = (pSurf->w - pZoom->w) / 2;
2143 alphablit(pZoom, NULL, pSurf, &dst, 255);
2144 FREESURFACE(pZoom);
2145 }
2146
2147 dst.y += (pIcons->pBIG_Coin->h + adj_size(2));
2148 dst.x = (pSurf->w - pText->w) / 2;
2149 alphablit(pText, NULL, pSurf, &dst, 255);
2150
2151 FREESURFACE(pText);
2152 FREESURFACE(pText_Name);
2153
2154 pBuf = create_icon2(pSurf, pWindow->dst,
2155 (WF_RESTORE_BACKGROUND|WF_FREE_THEME|WF_FREE_DATA));
2156
2157 set_wstate(pBuf, FC_WS_NORMAL);
2158
2159 pBuf->data.cont = fc_calloc(1, sizeof(struct CONTAINER));
2160 pBuf->data.cont->id0 = improvement_number(p->type);
2161 pBuf->data.cont->id1 = p->count;
2162 pBuf->action = popup_sell_impr_callback;
2163
2164 add_to_gui_list(MAX_ID - i, pBuf);
2165
2166 if (i > (TARGETS_ROW * TARGETS_COL - 1)) {
2167 set_wflag(pBuf, WF_HIDDEN);
2168 }
2169 }
2170
2171 FREEUTF8STR(pstr);
2172 FREESURFACE(pBackground);
2173
2174 pEconomyDlg->pEndActiveWidgetList = pLast->prev;
2175 pEconomyDlg->pBeginWidgetList = pBuf;
2176 pEconomyDlg->pBeginActiveWidgetList = pEconomyDlg->pBeginWidgetList;
2177
2178 if (entries_used > (TARGETS_ROW * TARGETS_COL)) {
2179 pEconomyDlg->pActiveWidgetList = pEconomyDlg->pEndActiveWidgetList;
2180 count = create_vertical_scrollbar(pEconomyDlg,
2181 TARGETS_COL, TARGETS_ROW, TRUE, TRUE);
2182 h += (TARGETS_ROW * pBuf->size.h + adj_size(10));
2183 } else {
2184 count = 0;
2185 if (entries_used > TARGETS_COL) {
2186 h += pBuf->size.h;
2187 }
2188 h += (adj_size(10) + pBuf->size.h);
2189 }
2190 count = TARGETS_COL * pBuf->size.w + count;
2191 } else {
2192 pEconomyDlg->pBeginWidgetList = pBuf;
2193 h += adj_size(10);
2194 count = 0;
2195 }
2196
2197 area.w = MAX(area.w, MAX(adj_size(10) + w3 + w + w2, count));
2198 area.h = h;
2199
2200 pBackground = theme_get_background(theme, BACKGROUND_ECONOMYDLG);
2201 if (resize_window(pWindow, pBackground, NULL,
2202 (pWindow->size.w - pWindow->area.w) + area.w,
2203 (pWindow->size.h - pWindow->area.h) + area.h)) {
2204 FREESURFACE(pBackground);
2205 }
2206
2207 area = pWindow->area;
2208
2209 widget_set_position(pWindow,
2210 (main_window_width() - pWindow->size.w) / 2,
2211 (main_window_height() - pWindow->size.h) / 2);
2212
2213 /* "Treasury" value label */
2214 pBuf = pWindow->prev;
2215 pBuf->size.x = area.x + adj_size(10) + pTreasuryText->w;
2216 pBuf->size.y = area.y + adj_size(5);
2217
2218 w = pTreasuryText->w + pBuf->size.w;
2219 h = pBuf->size.h;
2220
2221 /* "Tax Rate" value label */
2222 pBuf = pBuf->prev;
2223 pBuf->size.x = area.x + adj_size(10) + pTaxRateText->w;
2224 pBuf->size.y = pBuf->next->size.y + pBuf->next->size.h;
2225
2226 w = MAX(w, pTaxRateText->w + pBuf->size.w);
2227 h += pBuf->size.h;
2228
2229 /* "Total Income" value label */
2230 pBuf = pBuf->prev;
2231 pBuf->size.x = area.x + adj_size(10) + pTotalIncomeText->w;
2232 pBuf->size.y = pBuf->next->size.y + pBuf->next->size.h;
2233
2234 w = MAX(w, pTotalIncomeText->w + pBuf->size.w);
2235 h += pBuf->size.h;
2236
2237 /* "Total Cost" value label */
2238 pBuf = pBuf->prev;
2239 pBuf->size.x = area.x + adj_size(10) + pTotalCostText->w;
2240 pBuf->size.y = pBuf->next->size.y + pBuf->next->size.h;
2241
2242 w = MAX(w, pTotalCostText->w + pBuf->size.w);
2243 h += pBuf->size.h;
2244
2245 /* "Net Income" value label */
2246 pBuf = pBuf->prev;
2247 pBuf->size.x = area.x + adj_size(10) + pNetIncomeText->w;
2248 pBuf->size.y = pBuf->next->size.y + pBuf->next->size.h;
2249
2250 w = MAX(w, pNetIncomeText->w + pBuf->size.w);
2251 h += pBuf->size.h;
2252
2253 /* Backgrounds */
2254 dst.x = area.x;
2255 dst.y = area.y;
2256 dst.w = area.w;
2257 dst.h = h + adj_size(15);
2258 h = dst.h;
2259
2260 fill_rect_alpha(pWindow->theme, &dst, &bg_color2);
2261
2262 create_frame(pWindow->theme,
2263 dst.x, dst.y, dst.w - 1, dst.h - 1,
2264 get_theme_color(COLOR_THEME_ECONOMYDLG_FRAME));
2265
2266 /* draw statical strings */
2267 dst.x = area.x + adj_size(10);
2268 dst.y = area.y + adj_size(5);
2269
2270 /* "Treasury */
2271 alphablit(pTreasuryText, NULL, pWindow->theme, &dst, 255);
2272 dst.y += pTreasuryText->h;
2273 FREESURFACE(pTreasuryText);
2274
2275 /* Tax Rate */
2276 alphablit(pTaxRateText, NULL, pWindow->theme, &dst, 255);
2277 dst.y += pTaxRateText->h;
2278 FREESURFACE(pTaxRateText);
2279
2280 /* Total Income */
2281 alphablit(pTotalIncomeText, NULL, pWindow->theme, &dst, 255);
2282 dst.y += pTotalIncomeText->h;
2283 FREESURFACE(pTotalIncomeText);
2284
2285 /* Total Cost */
2286 alphablit(pTotalCostText, NULL, pWindow->theme, &dst, 255);
2287 dst.y += pTotalCostText->h;
2288 FREESURFACE(pTotalCostText);
2289
2290 /* Net Income */
2291 alphablit(pNetIncomeText, NULL, pWindow->theme, &dst, 255);
2292 dst.y += pNetIncomeText->h;
2293 FREESURFACE(pNetIncomeText);
2294
2295 /* gov and taxrate */
2296 dst.x = area.x + adj_size(10) + w + ((area.w - (w + adj_size(10)) - pMaxRateText->w) / 2);
2297 dst.y = area.y + adj_size(5);
2298
2299 alphablit(pMaxRateText, NULL, pWindow->theme, &dst, 255);
2300 dst.y += (pMaxRateText->h + 1);
2301 FREESURFACE(pMaxRateText);
2302
2303 /* Luxuries Horizontal Scrollbar Background */
2304 dst.x = area.x + adj_size(10) + w + (area.w - (w + adj_size(10)) - adj_size(184)) / 2;
2305 dst.w = adj_size(184);
2306 dst.h = current_theme->Horiz->h - adj_size(2);
2307
2308 fill_rect_alpha(pWindow->theme, &dst, &bg_color3);
2309
2310 create_frame(pWindow->theme,
2311 dst.x, dst.y, dst.w - 1, dst.h - 1,
2312 get_theme_color(COLOR_THEME_ECONOMYDLG_FRAME));
2313
2314 /* lock icon */
2315 pBuf = pBuf->prev;
2316 pBuf->size.x = dst.x - pBuf->size.w;
2317 pBuf->size.y = dst.y - adj_size(2);
2318
2319 /* lux scrollbar */
2320 pBuf = pBuf->prev;
2321 pBuf->size.x = dst.x + adj_size(2) + (client.conn.playing->economic.luxury * 3) / 2;
2322 pBuf->size.y = dst.y -1;
2323
2324 /* lux rate */
2325 pBuf = pBuf->prev;
2326 pBuf->size.x = dst.x + dst.w + adj_size(5);
2327 pBuf->size.y = dst.y + 1;
2328
2329 /* Science Horizontal Scrollbar Background */
2330 dst.y += current_theme->Horiz->h + 1;
2331 fill_rect_alpha(pWindow->theme, &dst, &bg_color3);
2332
2333 create_frame(pWindow->theme,
2334 dst.x, dst.y, dst.w - 1, dst.h - 1,
2335 get_theme_color(COLOR_THEME_ECONOMYDLG_FRAME));
2336
2337 /* science lock icon */
2338 pBuf = pBuf->prev;
2339 pBuf->size.x = dst.x - pBuf->size.w;
2340 pBuf->size.y = dst.y - adj_size(2);
2341
2342 /* science scrollbar */
2343 pBuf = pBuf->prev;
2344 pBuf->size.x = dst.x + adj_size(2) + (client.conn.playing->economic.science * 3) / 2;
2345 pBuf->size.y = dst.y -1;
2346
2347 /* science rate */
2348 pBuf = pBuf->prev;
2349 pBuf->size.x = dst.x + dst.w + adj_size(5);
2350 pBuf->size.y = dst.y + 1;
2351
2352 /* update */
2353 pBuf = pBuf->prev;
2354 pBuf->size.x = dst.x + (dst.w - pBuf->size.w) / 2;
2355 pBuf->size.y = dst.y + dst.h + adj_size(3);
2356
2357 /* cancel */
2358 pBuf = pBuf->prev;
2359 pBuf->size.x = area.x + area.w - pBuf->size.w - 1;
2360 pBuf->size.y = pWindow->size.y + adj_size(2);
2361 /* ------------------------------- */
2362
2363 if (entries_used > 0) {
2364 setup_vertical_widgets_position(TARGETS_COL,
2365 area.x,
2366 area.y + h,
2367 0, 0, pEconomyDlg->pBeginActiveWidgetList,
2368 pEconomyDlg->pEndActiveWidgetList);
2369 if (pEconomyDlg->pScroll) {
2370 setup_vertical_scrollbar_area(pEconomyDlg->pScroll,
2371 area.x + area.w - 1,
2372 area.y + h,
2373 area.h - h - 1, TRUE);
2374 }
2375 }
2376
2377 /* ------------------------ */
2378 redraw_group(pEconomyDlg->pBeginWidgetList, pWindow, 0);
2379 widget_mark_dirty(pWindow);
2380 flush_dirty();
2381 }
2382
2383 /* ===================================================================== */
2384 /* ======================== Science Report ============================= */
2385 /* ===================================================================== */
2386 static struct SMALL_DLG *pScienceDlg = NULL;
2387
2388 static struct ADVANCED_DLG *pChangeTechDlg = NULL;
2389
2390 /**************************************************************************
2391 Create icon surface for a tech.
2392 **************************************************************************/
create_select_tech_icon(utf8_str * pstr,Tech_type_id tech_id,enum tech_info_mode mode)2393 SDL_Surface *create_select_tech_icon(utf8_str *pstr, Tech_type_id tech_id,
2394 enum tech_info_mode mode)
2395 {
2396 struct unit_type *pUnit = NULL;
2397 SDL_Surface *pSurf, *pText, *pTmp, *pTmp2;
2398 SDL_Surface *Surf_Array[10], **pBuf_Array;
2399 SDL_Rect dst;
2400 SDL_Color color;
2401 int w, h;
2402
2403 color = *get_tech_color(tech_id);
2404 switch (mode)
2405 {
2406 case SMALL_MODE:
2407 h = adj_size(40);
2408 w = adj_size(135);
2409 break;
2410 case MED_MODE:
2411 color = *get_theme_color(COLOR_THEME_SCIENCEDLG_MED_TECHICON_BG);
2412 fc__fallthrough; /* No break, continue to setting default h & w */
2413 default:
2414 h = adj_size(200);
2415 w = adj_size(100);
2416 break;
2417 }
2418
2419 pText = create_text_surf_smaller_than_w(pstr, adj_size(100 - 4));
2420
2421 /* create label surface */
2422 pSurf = create_surf(w, h, SDL_SWSURFACE);
2423
2424 if (tech_id == research_get(client_player())->researching) {
2425 color.a = 180;
2426 } else {
2427 color.a = 128;
2428 }
2429
2430 SDL_FillRect(pSurf, NULL, map_rgba(pSurf->format, color));
2431
2432 create_frame(pSurf,
2433 0,0, pSurf->w - 1, pSurf->h - 1,
2434 get_theme_color(COLOR_THEME_SCIENCEDLG_FRAME));
2435
2436 pTmp = get_tech_icon(tech_id);
2437
2438 if (mode == SMALL_MODE) {
2439 /* draw name tech text */
2440 dst.x = adj_size(35) + (pSurf->w - pText->w - adj_size(35)) / 2;
2441 dst.y = (pSurf->h - pText->h) / 2;
2442 alphablit(pText, NULL, pSurf, &dst, 255);
2443 FREESURFACE(pText);
2444
2445 /* draw tech icon */
2446 pText = ResizeSurface(pTmp, adj_size(25), adj_size(25), 1);
2447 dst.x = (adj_size(35) - pText->w) / 2;
2448 dst.y = (pSurf->h - pText->h) / 2;
2449 alphablit(pText, NULL, pSurf, &dst, 255);
2450 FREESURFACE(pText);
2451
2452 } else {
2453
2454 /* draw name tech text */
2455 dst.x = (pSurf->w - pText->w) / 2;
2456 dst.y = adj_size(20);
2457 alphablit(pText, NULL, pSurf, &dst, 255);
2458 dst.y += pText->h + adj_size(10);
2459 FREESURFACE(pText);
2460
2461 /* draw tech icon */
2462 dst.x = (pSurf->w - pTmp->w) / 2;
2463 alphablit(pTmp, NULL, pSurf, &dst, 255);
2464 dst.y += pTmp->w + adj_size(10);
2465
2466 /* fill array with iprvm. icons */
2467 w = 0;
2468 improvement_iterate(pImprove) {
2469 requirement_vector_iterate(&pImprove->reqs, preq) {
2470 if (VUT_ADVANCE == preq->source.kind
2471 && advance_number(preq->source.value.advance) == tech_id) {
2472 pTmp2 = get_building_surface(pImprove);
2473 Surf_Array[w++] = zoomSurface(pTmp2, DEFAULT_ZOOM * ((float)36 / pTmp2->w), DEFAULT_ZOOM * ((float)36 / pTmp2->w), 1);
2474 }
2475 } requirement_vector_iterate_end;
2476 } improvement_iterate_end;
2477
2478 if (w) {
2479 if (w >= 2) {
2480 dst.x = (pSurf->w - 2 * Surf_Array[0]->w) / 2;
2481 } else {
2482 dst.x = (pSurf->w - Surf_Array[0]->w) / 2;
2483 }
2484
2485 /* draw iprvm. icons */
2486 pBuf_Array = Surf_Array;
2487 h = 0;
2488 while (w) {
2489 alphablit(*pBuf_Array, NULL, pSurf, &dst, 255);
2490 dst.x += (*pBuf_Array)->w;
2491 w--;
2492 h++;
2493 if (!(h % 2)) {
2494 if (w >= 2) {
2495 dst.x = (pSurf->w - 2 * (*pBuf_Array)->w) / 2;
2496 } else {
2497 dst.x = (pSurf->w - (*pBuf_Array)->w) / 2;
2498 }
2499 dst.y += (*pBuf_Array)->h;
2500 h = 0;
2501 } /* h == 2 */
2502 pBuf_Array++;
2503 } /* while */
2504 dst.y += Surf_Array[0]->h + adj_size(5);
2505 } /* if (w) */
2506 /* -------------------------------------------------------- */
2507 w = 0;
2508 unit_type_iterate(un) {
2509 pUnit = un;
2510 if (advance_number(pUnit->require_advance) == tech_id) {
2511 Surf_Array[w++] = adj_surf(get_unittype_surface(un, direction8_invalid()));
2512 }
2513 } unit_type_iterate_end;
2514
2515 if (w) {
2516 if (w < 2) {
2517 /* w == 1 */
2518 if (Surf_Array[0]->w > 64) {
2519 float zoom = DEFAULT_ZOOM * (64.0 / Surf_Array[0]->w);
2520 SDL_Surface *zoomed = zoomSurface(Surf_Array[0], zoom, zoom, 1);
2521
2522 dst.x = (pSurf->w - zoomed->w) / 2;
2523 alphablit(zoomed, NULL, pSurf, &dst, 255);
2524 FREESURFACE(zoomed);
2525 } else {
2526 dst.x = (pSurf->w - Surf_Array[0]->w) / 2;
2527 alphablit(Surf_Array[0], NULL, pSurf, &dst, 255);
2528 }
2529 } else {
2530 float zoom;
2531
2532 if (w > 2) {
2533 zoom = DEFAULT_ZOOM * (38.0 / Surf_Array[0]->w);
2534 } else {
2535 zoom = DEFAULT_ZOOM * (45.0 / Surf_Array[0]->w);
2536 }
2537 dst.x = (pSurf->w - (Surf_Array[0]->w * 2) * zoom - 2) / 2;
2538 pBuf_Array = Surf_Array;
2539 h = 0;
2540 while (w) {
2541 SDL_Surface *zoomed = zoomSurface((*pBuf_Array), zoom, zoom, 1);
2542
2543 alphablit(zoomed, NULL, pSurf, &dst, 255);
2544 dst.x += zoomed->w + 2;
2545 w--;
2546 h++;
2547 if (!(h % 2)) {
2548 if (w >= 2) {
2549 dst.x = (pSurf->w - 2 * zoomed->w - 2 ) / 2;
2550 } else {
2551 dst.x = (pSurf->w - zoomed->w) / 2;
2552 }
2553 dst.y += zoomed->h + 2;
2554 h = 0;
2555 } /* h == 2 */
2556 pBuf_Array++;
2557 FREESURFACE(zoomed);
2558 } /* while */
2559 } /* w > 1 */
2560 } /* if (w) */
2561 }
2562
2563 FREESURFACE(pTmp);
2564
2565 return pSurf;
2566 }
2567
2568 /**************************************************************************
2569 enable science dialog group ( without window )
2570 **************************************************************************/
enable_science_dialog(void)2571 static void enable_science_dialog(void)
2572 {
2573 set_group_state(pScienceDlg->pBeginWidgetList,
2574 pScienceDlg->pEndWidgetList->prev, FC_WS_NORMAL);
2575 }
2576
2577 /**************************************************************************
2578 disable science dialog group ( without window )
2579 **************************************************************************/
disable_science_dialog(void)2580 static void disable_science_dialog(void)
2581 {
2582 set_group_state(pScienceDlg->pBeginWidgetList,
2583 pScienceDlg->pEndWidgetList->prev, FC_WS_DISABLED);
2584 }
2585
2586 /**************************************************************************
2587 Update the science report.
2588 **************************************************************************/
real_science_report_dialog_update(void * unused)2589 void real_science_report_dialog_update(void *unused)
2590 {
2591 SDL_Color bg_color = {255, 255, 255, 136};
2592
2593 if (pScienceDlg) {
2594 const struct research *presearch = research_get(client_player());
2595 char cBuf[128];
2596 utf8_str *pStr;
2597 SDL_Surface *pSurf;
2598 SDL_Surface *pColb_Surface = pIcons->pBIG_Colb;
2599 int step, i, cost;
2600 SDL_Rect dest;
2601 struct unit_type *pUnit;
2602 struct widget *pChangeResearchButton;
2603 struct widget *pChangeResearchGoalButton;
2604 SDL_Rect area;
2605 struct widget *pWindow = pScienceDlg->pEndWidgetList;
2606
2607 area = pWindow->area;
2608 pChangeResearchButton = pWindow->prev;
2609 pChangeResearchGoalButton = pWindow->prev->prev;
2610
2611 if (A_UNSET != presearch->researching) {
2612 cost = presearch->client.researching_cost;
2613 } else {
2614 cost = 0;
2615 }
2616
2617 /* update current research icons */
2618 FREESURFACE(pChangeResearchButton->theme);
2619 pChangeResearchButton->theme = get_tech_icon(presearch->researching);
2620 FREESURFACE(pChangeResearchGoalButton->theme);
2621 pChangeResearchGoalButton->theme = get_tech_icon(presearch->tech_goal);
2622
2623 /* redraw Window */
2624 widget_redraw(pWindow);
2625
2626 /* ------------------------------------- */
2627
2628 /* research progress text */
2629 pStr = create_utf8_from_char(science_dialog_text(), adj_font(12));
2630 pStr->style |= SF_CENTER;
2631 pStr->fgcol = *get_theme_color(COLOR_THEME_SCIENCEDLG_TEXT);
2632
2633 pSurf = create_text_surf_from_utf8(pStr);
2634
2635 dest.x = area.x + (area.w - pSurf->w) / 2;
2636 dest.y = area.y + adj_size(2);
2637 alphablit(pSurf, NULL, pWindow->dst->surface, &dest, 255);
2638
2639 dest.y += pSurf->h + adj_size(4);
2640
2641 FREESURFACE(pSurf);
2642
2643 dest.x = area.x + adj_size(16);
2644
2645 /* separator */
2646 create_line(pWindow->dst->surface,
2647 dest.x, dest.y, (area.x + area.w - adj_size(16)), dest.y,
2648 get_theme_color(COLOR_THEME_SCIENCEDLG_FRAME));
2649
2650 dest.y += adj_size(6);
2651
2652 widget_set_position(pChangeResearchButton, dest.x, dest.y + adj_size(18));
2653
2654 /* current research text */
2655 fc_snprintf(cBuf, sizeof(cBuf), "%s: %s",
2656 research_advance_name_translation(presearch,
2657 presearch->researching),
2658 get_science_target_text(NULL));
2659
2660 copy_chars_to_utf8_str(pStr, cBuf);
2661
2662 pSurf = create_text_surf_from_utf8(pStr);
2663
2664 dest.x = pChangeResearchButton->size.x + pChangeResearchButton->size.w + adj_size(10);
2665
2666 alphablit(pSurf, NULL, pWindow->dst->surface, &dest, 255);
2667
2668 dest.y += pSurf->h + adj_size(4);
2669
2670 FREESURFACE(pSurf);
2671
2672 /* progress bar */
2673 if (cost > 0) {
2674 int cost_div_safe = cost - 1;
2675
2676 cost_div_safe = (cost_div_safe != 0 ? cost_div_safe : 1);
2677 dest.w = cost * pColb_Surface->w;
2678 step = pColb_Surface->w;
2679 if (dest.w > (area.w - dest.x - adj_size(16))) {
2680 dest.w = (area.w - dest.x - adj_size(16));
2681 step = ((area.w - dest.x - adj_size(16)) - pColb_Surface->w) / cost_div_safe;
2682
2683 if (step == 0) {
2684 step = 1;
2685 }
2686 }
2687
2688 dest.h = pColb_Surface->h + adj_size(4);
2689 fill_rect_alpha(pWindow->dst->surface, &dest, &bg_color);
2690
2691 create_frame(pWindow->dst->surface,
2692 dest.x - 1, dest.y - 1, dest.w, dest.h,
2693 get_theme_color(COLOR_THEME_SCIENCEDLG_FRAME));
2694
2695 if (cost > adj_size(286)) {
2696 cost = adj_size(286) * ((float) presearch->bulbs_researched / cost);
2697 } else {
2698 cost = (float) cost * ((float) presearch->bulbs_researched / cost);
2699 }
2700
2701 dest.y += adj_size(2);
2702 for (i = 0; i < cost; i++) {
2703 alphablit(pColb_Surface, NULL, pWindow->dst->surface, &dest, 255);
2704 dest.x += step;
2705 }
2706 }
2707
2708 /* improvement icons */
2709
2710 dest.y += dest.h + adj_size(4);
2711 dest.x = pChangeResearchButton->size.x + pChangeResearchButton->size.w + adj_size(10);
2712
2713 /* buildings */
2714 improvement_iterate(pImprove) {
2715 requirement_vector_iterate(&pImprove->reqs, preq) {
2716 if (VUT_ADVANCE == preq->source.kind
2717 && (advance_number(preq->source.value.advance)
2718 == presearch->researching)) {
2719 pSurf = adj_surf(get_building_surface(pImprove));
2720 alphablit(pSurf, NULL, pWindow->dst->surface, &dest, 255);
2721 dest.x += pSurf->w + 1;
2722 }
2723 } requirement_vector_iterate_end;
2724 } improvement_iterate_end;
2725
2726 dest.x += adj_size(5);
2727
2728 /* units */
2729 unit_type_iterate(un) {
2730 pUnit = un;
2731 if (advance_number(pUnit->require_advance) == presearch->researching) {
2732 SDL_Surface *surf = get_unittype_surface(un, direction8_invalid());
2733 int w = surf->w;
2734
2735 if (w > 64) {
2736 float zoom = DEFAULT_ZOOM * (64.0 / w);
2737
2738 pSurf = zoomSurface(surf, zoom, zoom, 1);
2739 alphablit(pSurf, NULL, pWindow->dst->surface, &dest, 255);
2740 dest.x += pSurf->w + adj_size(2);
2741 FREESURFACE(pSurf);
2742 } else {
2743 pSurf = adj_surf(surf);
2744 alphablit(pSurf, NULL, pWindow->dst->surface, &dest, 255);
2745 dest.x += pSurf->w + adj_size(2);
2746 }
2747 }
2748 } unit_type_iterate_end;
2749
2750 /* -------------------------------- */
2751 /* draw separator line */
2752 dest.x = area.x + adj_size(16);
2753 dest.y += adj_size(48) + adj_size(6);
2754
2755 create_line(pWindow->dst->surface,
2756 dest.x, dest.y, (area.x + area.w - adj_size(16)), dest.y,
2757 get_theme_color(COLOR_THEME_SCIENCEDLG_FRAME));
2758
2759 dest.x = pChangeResearchButton->size.x;
2760 dest.y += adj_size(6);
2761
2762 widget_set_position(pChangeResearchGoalButton, dest.x, dest.y + adj_size(16));
2763
2764 /* -------------------------------- */
2765
2766 /* Goals */
2767 if (A_UNSET != presearch->tech_goal) {
2768 /* current goal text */
2769 copy_chars_to_utf8_str(pStr, research_advance_name_translation
2770 (presearch, presearch->tech_goal));
2771 pSurf = create_text_surf_from_utf8(pStr);
2772
2773 dest.x = pChangeResearchGoalButton->size.x + pChangeResearchGoalButton->size.w + adj_size(10);
2774 alphablit(pSurf, NULL, pWindow->dst->surface, &dest, 255);
2775
2776 dest.y += pSurf->h;
2777
2778 FREESURFACE(pSurf);
2779
2780 copy_chars_to_utf8_str(pStr, get_science_goal_text
2781 (presearch->tech_goal));
2782 pSurf = create_text_surf_from_utf8(pStr);
2783
2784 dest.x = pChangeResearchGoalButton->size.x + pChangeResearchGoalButton->size.w + adj_size(10);
2785 alphablit(pSurf, NULL, pWindow->dst->surface, &dest, 255);
2786
2787 dest.y += pSurf->h + adj_size(6);
2788
2789 FREESURFACE(pSurf);
2790
2791 /* buildings */
2792 improvement_iterate(pImprove) {
2793 requirement_vector_iterate(&pImprove->reqs, preq) {
2794 if (VUT_ADVANCE == preq->source.kind
2795 && (advance_number(preq->source.value.advance)
2796 == presearch->tech_goal)) {
2797 pSurf = adj_surf(get_building_surface(pImprove));
2798 alphablit(pSurf, NULL, pWindow->dst->surface, &dest, 255);
2799 dest.x += pSurf->w + 1;
2800 }
2801 } requirement_vector_iterate_end;
2802 } improvement_iterate_end;
2803
2804 dest.x += adj_size(6);
2805
2806 /* units */
2807 unit_type_iterate(un) {
2808 pUnit = un;
2809 if (advance_number(pUnit->require_advance) == presearch->tech_goal) {
2810 SDL_Surface *surf = get_unittype_surface(un, direction8_invalid());
2811 int w = surf->w;
2812
2813 if (w > 64) {
2814 float zoom = DEFAULT_ZOOM * (64.0 / w);
2815
2816 pSurf = zoomSurface(surf, zoom, zoom, 1);
2817 alphablit(pSurf, NULL, pWindow->dst->surface, &dest, 255);
2818 dest.x += pSurf->w + adj_size(2);
2819 FREESURFACE(pSurf);
2820 } else {
2821 pSurf = adj_surf(surf);
2822 alphablit(pSurf, NULL, pWindow->dst->surface, &dest, 255);
2823 dest.x += pSurf->w + adj_size(2);
2824 }
2825 }
2826 } unit_type_iterate_end;
2827 }
2828
2829 /* -------------------------------- */
2830 widget_mark_dirty(pWindow);
2831 redraw_group(pScienceDlg->pBeginWidgetList, pWindow->prev, 1);
2832 flush_dirty();
2833
2834 FREEUTF8STR(pStr);
2835 }
2836 }
2837
2838 /**************************************************************************
2839 Close science report dialog.
2840 **************************************************************************/
science_report_dialog_popdown(void)2841 static void science_report_dialog_popdown(void)
2842 {
2843 if (pScienceDlg) {
2844 popdown_window_group_dialog(pScienceDlg->pBeginWidgetList,
2845 pScienceDlg->pEndWidgetList);
2846 FC_FREE(pScienceDlg);
2847 set_wstate(get_research_widget(), FC_WS_NORMAL);
2848 widget_redraw(get_research_widget());
2849 widget_mark_dirty(get_research_widget());
2850 flush_dirty();
2851 }
2852 }
2853
2854 /**************************************************************************
2855 Close research target changing dialog.
2856 **************************************************************************/
exit_change_tech_dlg_callback(struct widget * pWidget)2857 static int exit_change_tech_dlg_callback(struct widget *pWidget)
2858 {
2859 if (PRESSED_EVENT(Main.event)) {
2860 if (pChangeTechDlg) {
2861 popdown_window_group_dialog(pChangeTechDlg->pBeginWidgetList,
2862 pChangeTechDlg->pEndWidgetList);
2863 FC_FREE(pChangeTechDlg->pScroll);
2864 FC_FREE(pChangeTechDlg);
2865 enable_science_dialog();
2866 if (pWidget) {
2867 flush_dirty();
2868 }
2869 }
2870 }
2871
2872 return -1;
2873 }
2874
2875 /**************************************************************************
2876 User interacted with button of specific Tech.
2877 **************************************************************************/
change_research_callback(struct widget * pWidget)2878 static int change_research_callback(struct widget *pWidget)
2879 {
2880 if (PRESSED_EVENT(Main.event)) {
2881 dsend_packet_player_research(&client.conn, (MAX_ID - pWidget->ID));
2882 exit_change_tech_dlg_callback(NULL);
2883 } else if (Main.event.button.button == SDL_BUTTON_MIDDLE) {
2884 popup_tech_info((MAX_ID - pWidget->ID));
2885 }
2886
2887 return -1;
2888 }
2889
2890 /**************************************************************************
2891 This function is used by change research and change goals dlgs.
2892 **************************************************************************/
change_research_goal_dialog_callback(struct widget * pWindow)2893 static int change_research_goal_dialog_callback(struct widget *pWindow)
2894 {
2895 if (PRESSED_EVENT(Main.event)) {
2896 if (select_window_group_dialog(pChangeTechDlg->pBeginWidgetList, pWindow)) {
2897 widget_flush(pWindow);
2898 }
2899 }
2900
2901 return -1;
2902 }
2903
2904 /**************************************************************************
2905 Popup dialog to change current research.
2906 **************************************************************************/
popup_change_research_dialog(void)2907 static void popup_change_research_dialog(void)
2908 {
2909 const struct research *presearch = research_get(client_player());
2910 struct widget *pBuf = NULL;
2911 struct widget *pWindow;
2912 utf8_str *pstr;
2913 SDL_Surface *pSurf;
2914 int max_col, max_row, col, i, count = 0, h;
2915 SDL_Rect area;
2916
2917 if (is_future_tech(presearch->researching)) {
2918 return;
2919 }
2920
2921 advance_index_iterate(A_FIRST, aidx) {
2922 if (!research_invention_gettable(presearch, aidx, FALSE)) {
2923 continue;
2924 }
2925 count++;
2926 } advance_index_iterate_end;
2927
2928 if (count < 2) {
2929 return;
2930 }
2931
2932 pChangeTechDlg = fc_calloc(1, sizeof(struct ADVANCED_DLG));
2933
2934 pstr = create_utf8_from_char(_("What should we focus on now?"), adj_font(12));
2935 pstr->style |= TTF_STYLE_BOLD;
2936
2937 pWindow = create_window_skeleton(NULL, pstr, 0);
2938 pChangeTechDlg->pEndWidgetList = pWindow;
2939 set_wstate(pWindow, FC_WS_NORMAL);
2940 pWindow->action = change_research_goal_dialog_callback;
2941
2942 add_to_gui_list(ID_SCIENCE_DLG_CHANGE_REASARCH_WINDOW, pWindow);
2943
2944 area = pWindow->area;
2945
2946 /* ------------------------- */
2947 /* exit button */
2948 pBuf = create_themeicon(current_theme->Small_CANCEL_Icon, pWindow->dst,
2949 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
2950 pBuf->info_label = create_utf8_from_char(_("Close Dialog (Esc)"),
2951 adj_font(12));
2952 area.w += pBuf->size.w + adj_size(10);
2953 pBuf->action = exit_change_tech_dlg_callback;
2954 set_wstate(pBuf, FC_WS_NORMAL);
2955 pBuf->key = SDLK_ESCAPE;
2956
2957 add_to_gui_list(ID_TERRAIN_ADV_DLG_EXIT_BUTTON, pBuf);
2958
2959 /* ------------------------- */
2960 /* max col - 104 is select tech widget width */
2961 max_col = (main_window_width() - (pWindow->size.w - pWindow->area.w) - adj_size(2)) / adj_size(104);
2962 /* max row - 204 is select tech widget height */
2963 max_row = (main_window_height() - (pWindow->size.h - pWindow->area.h) - adj_size(2)) / adj_size(204);
2964
2965 /* make space on screen for scrollbar */
2966 if (max_col * max_row < count) {
2967 max_col--;
2968 }
2969
2970 if (count < max_col + 1) {
2971 col = count;
2972 } else {
2973 if (count < max_col + 3) {
2974 col = max_col - 2;
2975 } else {
2976 if (count < max_col + 5) {
2977 col = max_col - 1;
2978 } else {
2979 col = max_col;
2980 }
2981 }
2982 }
2983
2984 pstr = create_utf8_str(NULL, 0, adj_font(10));
2985 pstr->style |= (TTF_STYLE_BOLD | SF_CENTER);
2986
2987 count = 0;
2988 h = col * max_row;
2989 advance_index_iterate(A_FIRST, aidx) {
2990 if (!research_invention_gettable(presearch, aidx, FALSE)) {
2991 continue;
2992 }
2993
2994 count++;
2995
2996 copy_chars_to_utf8_str(pstr, advance_name_translation(advance_by_number(aidx)));
2997 pSurf = create_select_tech_icon(pstr, aidx, MED_MODE);
2998 pBuf = create_icon2(pSurf, pWindow->dst,
2999 WF_FREE_THEME | WF_RESTORE_BACKGROUND);
3000
3001 set_wstate(pBuf, FC_WS_NORMAL);
3002 pBuf->action = change_research_callback;
3003
3004 add_to_gui_list(MAX_ID - aidx, pBuf);
3005
3006 if (count > h) {
3007 set_wflag(pBuf, WF_HIDDEN);
3008 }
3009 } advance_index_iterate_end;
3010
3011 FREEUTF8STR(pstr);
3012
3013 pChangeTechDlg->pBeginWidgetList = pBuf;
3014 pChangeTechDlg->pBeginActiveWidgetList = pChangeTechDlg->pBeginWidgetList;
3015 pChangeTechDlg->pEndActiveWidgetList = pChangeTechDlg->pEndWidgetList->prev->prev;
3016
3017 /* -------------------------------------------------------------- */
3018
3019 i = 0;
3020 if (count > col) {
3021 count = (count + (col - 1)) / col;
3022 if (count > max_row) {
3023 pChangeTechDlg->pActiveWidgetList = pChangeTechDlg->pEndActiveWidgetList;
3024 count = max_row;
3025 i = create_vertical_scrollbar(pChangeTechDlg, col, count, TRUE, TRUE);
3026 }
3027 } else {
3028 count = 1;
3029 }
3030
3031 disable_science_dialog();
3032
3033 area.w = MAX(area.w, (col * pBuf->size.w + adj_size(2) + i));
3034 area.h = MAX(area.h, count * pBuf->size.h + adj_size(2));
3035
3036 /* alloca window theme and win background buffer */
3037 pSurf = theme_get_background(theme, BACKGROUND_CHANGERESEARCHDLG);
3038 resize_window(pWindow, pSurf, NULL,
3039 (pWindow->size.w - pWindow->area.w) + area.w,
3040 (pWindow->size.h - pWindow->area.h) + area.h);
3041 FREESURFACE(pSurf);
3042
3043 area = pWindow->area;
3044
3045 widget_set_position(pWindow,
3046 (main_window_width() - pWindow->size.w) / 2,
3047 (main_window_height() - pWindow->size.h) / 2);
3048
3049 /* exit button */
3050 pBuf = pWindow->prev;
3051 pBuf->size.x = area.x + area.w - pBuf->size.w - 1;
3052 pBuf->size.y = pWindow->size.y + adj_size(2);
3053
3054 setup_vertical_widgets_position(col, area.x + 1,
3055 area.y, 0, 0,
3056 pChangeTechDlg->pBeginActiveWidgetList,
3057 pChangeTechDlg->pEndActiveWidgetList);
3058
3059 if (pChangeTechDlg->pScroll) {
3060 setup_vertical_scrollbar_area(pChangeTechDlg->pScroll,
3061 area.x + area.w, area.y,
3062 area.h, TRUE);
3063 }
3064
3065 redraw_group(pChangeTechDlg->pBeginWidgetList, pWindow, FALSE);
3066
3067 widget_flush(pWindow);
3068 }
3069
3070 /**************************************************************************
3071 User chose spesic tech as research goal.
3072 **************************************************************************/
change_research_goal_callback(struct widget * pWidget)3073 static int change_research_goal_callback(struct widget *pWidget)
3074 {
3075 if (PRESSED_EVENT(Main.event)) {
3076 dsend_packet_player_tech_goal(&client.conn, (MAX_ID - pWidget->ID));
3077
3078 exit_change_tech_dlg_callback(NULL);
3079
3080 /* Following is to make the menu go back to the current goal;
3081 * there may be a better way to do this? --dwp */
3082 real_science_report_dialog_update(NULL);
3083 } else if (Main.event.button.button == SDL_BUTTON_MIDDLE) {
3084 popup_tech_info((MAX_ID - pWidget->ID));
3085 }
3086
3087 return -1;
3088 }
3089
3090 /**************************************************************************
3091 Popup dialog to change research goal.
3092 **************************************************************************/
popup_change_research_goal_dialog(void)3093 static void popup_change_research_goal_dialog(void)
3094 {
3095 const struct research *presearch = research_get(client_player());
3096 struct widget *pBuf = NULL;
3097 struct widget *pWindow;
3098 utf8_str *pstr;
3099 SDL_Surface *pSurf;
3100 char cBuf[128];
3101 int max_col, max_row, col, i, count = 0, h , num;
3102 SDL_Rect area;
3103
3104 /* collect all techs which are reachable in under 11 steps
3105 * hist will hold afterwards the techid of the current choice
3106 */
3107 advance_index_iterate(A_FIRST, aidx) {
3108 if (research_invention_reachable(presearch, aidx)
3109 && TECH_KNOWN != research_invention_state(presearch, aidx)
3110 && (11 > research_goal_unknown_techs(presearch, aidx)
3111 || aidx == presearch->tech_goal)) {
3112 count++;
3113 }
3114 } advance_index_iterate_end;
3115
3116 if (count < 1) {
3117 return;
3118 }
3119
3120 pChangeTechDlg = fc_calloc(1, sizeof(struct ADVANCED_DLG));
3121
3122 pstr = create_utf8_from_char(_("Select target :"), adj_font(12));
3123 pstr->style |= TTF_STYLE_BOLD;
3124
3125 pWindow = create_window_skeleton(NULL, pstr, 0);
3126 pChangeTechDlg->pEndWidgetList = pWindow;
3127 set_wstate(pWindow, FC_WS_NORMAL);
3128 pWindow->action = change_research_goal_dialog_callback;
3129
3130 add_to_gui_list(ID_SCIENCE_DLG_CHANGE_GOAL_WINDOW, pWindow);
3131
3132 area = pWindow->area;
3133
3134 /* ------------------------- */
3135 /* exit button */
3136 pBuf = create_themeicon(current_theme->Small_CANCEL_Icon, pWindow->dst,
3137 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
3138 pBuf->info_label = create_utf8_from_char(_("Close Dialog (Esc)"),
3139 adj_font(12));
3140 area.w += pBuf->size.w + adj_size(10);
3141 pBuf->action = exit_change_tech_dlg_callback;
3142 set_wstate(pBuf, FC_WS_NORMAL);
3143 pBuf->key = SDLK_ESCAPE;
3144
3145 add_to_gui_list(ID_SCIENCE_DLG_CHANGE_GOAL_CANCEL_BUTTON, pBuf);
3146
3147 /* ------------------------- */
3148 /* max col - 104 is goal tech widget width */
3149 max_col = (main_window_width() - (pWindow->size.w - pWindow->area.w) - adj_size(2)) / adj_size(104);
3150
3151 /* max row - 204 is goal tech widget height */
3152 max_row = (main_window_height() - (pWindow->size.h - pWindow->area.h) - adj_size(2)) / adj_size(204);
3153
3154 /* make space on screen for scrollbar */
3155 if (max_col * max_row < count) {
3156 max_col--;
3157 }
3158
3159 if (count < max_col + 1) {
3160 col = count;
3161 } else {
3162 if (count < max_col + 3) {
3163 col = max_col - 2;
3164 } else {
3165 if (count < max_col + 5) {
3166 col = max_col - 1;
3167 } else {
3168 col = max_col;
3169 }
3170 }
3171 }
3172
3173 pstr = create_utf8_str(NULL, 0, adj_font(10));
3174 pstr->style |= (TTF_STYLE_BOLD | SF_CENTER);
3175
3176 /* collect all techs which are reachable in under 11 steps
3177 * hist will hold afterwards the techid of the current choice
3178 */
3179 count = 0;
3180 h = col * max_row;
3181 advance_index_iterate(A_FIRST, aidx) {
3182 if (research_invention_reachable(presearch, aidx)
3183 && TECH_KNOWN != research_invention_state(presearch, aidx)
3184 && (11 > (num = research_goal_unknown_techs(presearch, aidx))
3185 || aidx == presearch->tech_goal)) {
3186
3187 count++;
3188 fc_snprintf(cBuf, sizeof(cBuf), "%s\n%d %s",
3189 advance_name_translation(advance_by_number(aidx)),
3190 num,
3191 PL_("step", "steps", num));
3192 copy_chars_to_utf8_str(pstr, cBuf);
3193 pSurf = create_select_tech_icon(pstr, aidx, FULL_MODE);
3194 pBuf = create_icon2(pSurf, pWindow->dst,
3195 WF_FREE_THEME | WF_RESTORE_BACKGROUND);
3196
3197 set_wstate(pBuf, FC_WS_NORMAL);
3198 pBuf->action = change_research_goal_callback;
3199
3200 add_to_gui_list(MAX_ID - aidx, pBuf);
3201
3202 if (count > h) {
3203 set_wflag(pBuf, WF_HIDDEN);
3204 }
3205 }
3206 } advance_index_iterate_end;
3207
3208 FREEUTF8STR(pstr);
3209
3210 pChangeTechDlg->pBeginWidgetList = pBuf;
3211 pChangeTechDlg->pBeginActiveWidgetList = pChangeTechDlg->pBeginWidgetList;
3212 pChangeTechDlg->pEndActiveWidgetList = pChangeTechDlg->pEndWidgetList->prev->prev;
3213
3214 /* -------------------------------------------------------------- */
3215
3216 i = 0;
3217 if (count > col) {
3218 count = (count + (col-1)) / col;
3219 if (count > max_row) {
3220 pChangeTechDlg->pActiveWidgetList = pChangeTechDlg->pEndActiveWidgetList;
3221 count = max_row;
3222 i = create_vertical_scrollbar(pChangeTechDlg, col, count, TRUE, TRUE);
3223 }
3224 } else {
3225 count = 1;
3226 }
3227
3228 disable_science_dialog();
3229
3230 area.w = MAX(area.w, (col * pBuf->size.w + adj_size(2) + i));
3231 area.h = MAX(area.h, count * pBuf->size.h + adj_size(2));
3232
3233 /* alloca window theme and win background buffer */
3234 pSurf = theme_get_background(theme, BACKGROUND_CHANGERESEARCHDLG);
3235 resize_window(pWindow, pSurf, NULL,
3236 (pWindow->size.w - pWindow->area.w) + area.w,
3237 (pWindow->size.h - pWindow->area.h) + area.h);
3238 FREESURFACE(pSurf);
3239
3240 area = pWindow->area;
3241
3242 widget_set_position(pWindow,
3243 (main_window_width() - pWindow->size.w) / 2,
3244 (main_window_height() - pWindow->size.h) / 2);
3245
3246 /* exit button */
3247 pBuf = pWindow->prev;
3248 pBuf->size.x = area.x + area.w - pBuf->size.w - 1;
3249 pBuf->size.y = pWindow->size.y + adj_size(2);
3250
3251 setup_vertical_widgets_position(col, area.x + 1,
3252 area.y, 0, 0,
3253 pChangeTechDlg->pBeginActiveWidgetList,
3254 pChangeTechDlg->pEndActiveWidgetList);
3255
3256 if (pChangeTechDlg->pScroll) {
3257 setup_vertical_scrollbar_area(pChangeTechDlg->pScroll,
3258 area.x + area.w, area.y,
3259 area.h, TRUE);
3260 }
3261
3262 redraw_group(pChangeTechDlg->pBeginWidgetList, pWindow, FALSE);
3263
3264 widget_flush(pWindow);
3265 }
3266
3267 /**************************************************************************
3268 User interacted with science dialog window.
3269 **************************************************************************/
science_dialog_callback(struct widget * pWindow)3270 static int science_dialog_callback(struct widget *pWindow)
3271 {
3272 if (PRESSED_EVENT(Main.event)) {
3273 if (!pChangeTechDlg) {
3274 if (select_window_group_dialog(pScienceDlg->pBeginWidgetList, pWindow)) {
3275 widget_flush(pWindow);
3276 }
3277 if (move_window_group_dialog(pScienceDlg->pBeginWidgetList, pWindow)) {
3278 real_science_report_dialog_update(NULL);
3279 }
3280 }
3281 }
3282
3283 return -1;
3284 }
3285
3286 /**************************************************************************
3287 Open research target changing dialog.
3288 **************************************************************************/
popup_change_research_dialog_callback(struct widget * pWidget)3289 static int popup_change_research_dialog_callback(struct widget *pWidget)
3290 {
3291 if (PRESSED_EVENT(Main.event)) {
3292 set_wstate(pWidget, FC_WS_NORMAL);
3293 selected_widget = NULL;
3294 widget_redraw(pWidget);
3295 widget_flush(pWidget);
3296
3297 popup_change_research_dialog();
3298 }
3299 return -1;
3300 }
3301
3302 /**************************************************************************
3303 Open research goal changing dialog.
3304 **************************************************************************/
popup_change_research_goal_dialog_callback(struct widget * pWidget)3305 static int popup_change_research_goal_dialog_callback(struct widget *pWidget)
3306 {
3307 if (PRESSED_EVENT(Main.event)) {
3308 set_wstate(pWidget, FC_WS_NORMAL);
3309 selected_widget = NULL;
3310 widget_redraw(pWidget);
3311 widget_flush(pWidget);
3312
3313 popup_change_research_goal_dialog();
3314 }
3315 return -1;
3316 }
3317
3318 /**************************************************************************
3319 Close science dialog.
3320 **************************************************************************/
popdown_science_dialog_callback(struct widget * pWidget)3321 static int popdown_science_dialog_callback(struct widget *pWidget)
3322 {
3323 if (PRESSED_EVENT(Main.event)) {
3324 science_report_dialog_popdown();
3325 }
3326
3327 return -1;
3328 }
3329
3330 /**************************************************************************
3331 Popup (or raise) the science report(F6). It may or may not be modal.
3332 **************************************************************************/
science_report_dialog_popup(bool raise)3333 void science_report_dialog_popup(bool raise)
3334 {
3335 const struct research *presearch;
3336 struct widget *pWidget, *pWindow;
3337 struct widget *pChangeResearchButton;
3338 struct widget *pChangeResearchGoalButton;
3339 struct widget *pExitButton;
3340 utf8_str *pstr;
3341 SDL_Surface *pBackground, *pTechIcon;
3342 int count;
3343 SDL_Rect area;
3344
3345 if (pScienceDlg) {
3346 return;
3347 }
3348
3349 presearch = research_get(client_player());
3350
3351 /* disable research button */
3352 pWidget = get_research_widget();
3353 set_wstate(pWidget, FC_WS_DISABLED);
3354 widget_redraw(pWidget);
3355 widget_mark_dirty(pWidget);
3356
3357 pScienceDlg = fc_calloc(1, sizeof(struct SMALL_DLG));
3358
3359 /* TRANS: Research report title */
3360 pstr = create_utf8_from_char(_("Research"), adj_font(12));
3361 pstr->style |= TTF_STYLE_BOLD;
3362
3363 #ifdef SMALL_SCREEN
3364 pWindow = create_window(NULL, pstr, 200, 132, 0);
3365 #else /* SMALL_SCREEN */
3366 pWindow = create_window(NULL, pstr, adj_size(400), adj_size(246), 0);
3367 #endif /* SMALL_SCREEN */
3368 set_wstate(pWindow, FC_WS_NORMAL);
3369 pWindow->action = science_dialog_callback;
3370
3371 pScienceDlg->pEndWidgetList = pWindow;
3372
3373 pBackground = theme_get_background(theme, BACKGROUND_SCIENCEDLG);
3374 pWindow->theme = ResizeSurface(pBackground, pWindow->size.w, pWindow->size.h, 1);
3375 FREESURFACE(pBackground);
3376
3377 area = pWindow->area;
3378
3379 widget_set_position(pWindow,
3380 (main_window_width() - pWindow->size.w) / 2,
3381 (main_window_height() - pWindow->size.h) / 2);
3382
3383 add_to_gui_list(ID_SCIENCE_DLG_WINDOW, pWindow);
3384
3385 /* count number of researchable techs */
3386 count = 0;
3387 advance_index_iterate(A_FIRST, i) {
3388 if (research_invention_reachable(presearch, i)
3389 && TECH_KNOWN != research_invention_state(presearch, i)) {
3390 count++;
3391 }
3392 } advance_index_iterate_end;
3393
3394 /* current research icon */
3395 pTechIcon = get_tech_icon(presearch->researching);
3396 pChangeResearchButton = create_icon2(pTechIcon, pWindow->dst, WF_RESTORE_BACKGROUND | WF_FREE_THEME);
3397
3398 pChangeResearchButton->action = popup_change_research_dialog_callback;
3399 if (count > 0) {
3400 set_wstate(pChangeResearchButton, FC_WS_NORMAL);
3401 }
3402
3403 add_to_gui_list(ID_SCIENCE_DLG_CHANGE_REASARCH_BUTTON, pChangeResearchButton);
3404
3405 /* current research goal icon */
3406 pTechIcon = get_tech_icon(presearch->tech_goal);
3407 pChangeResearchGoalButton = create_icon2(pTechIcon, pWindow->dst, WF_RESTORE_BACKGROUND | WF_FREE_THEME);
3408
3409 pChangeResearchGoalButton->action = popup_change_research_goal_dialog_callback;
3410 if (count > 0) {
3411 set_wstate(pChangeResearchGoalButton, FC_WS_NORMAL);
3412 }
3413
3414 add_to_gui_list(ID_SCIENCE_DLG_CHANGE_GOAL_BUTTON, pChangeResearchGoalButton);
3415
3416 /* ------ */
3417 /* exit button */
3418 pExitButton = create_themeicon(current_theme->Small_CANCEL_Icon, pWindow->dst,
3419 WF_WIDGET_HAS_INFO_LABEL
3420 | WF_RESTORE_BACKGROUND);
3421 pExitButton->info_label = create_utf8_from_char(_("Close Dialog (Esc)"),
3422 adj_font(12));
3423 pExitButton->action = popdown_science_dialog_callback;
3424 set_wstate(pExitButton, FC_WS_NORMAL);
3425 pExitButton->key = SDLK_ESCAPE;
3426
3427 add_to_gui_list(ID_SCIENCE_CANCEL_DLG_BUTTON, pExitButton);
3428
3429 widget_set_position(pExitButton,
3430 area.x + area.w - pExitButton->size.w - adj_size(1),
3431 pWindow->size.y + adj_size(2));
3432
3433 /* ======================== */
3434 pScienceDlg->pBeginWidgetList = pExitButton;
3435
3436 real_science_report_dialog_update(NULL);
3437 }
3438
3439 /**************************************************************************
3440 Popdown all the science reports (report, change tech, change goals).
3441 **************************************************************************/
science_report_dialogs_popdown_all(void)3442 void science_report_dialogs_popdown_all(void)
3443 {
3444 if (pChangeTechDlg) {
3445 popdown_window_group_dialog(pChangeTechDlg->pBeginWidgetList,
3446 pChangeTechDlg->pEndWidgetList);
3447 FC_FREE(pChangeTechDlg->pScroll);
3448 FC_FREE(pChangeTechDlg);
3449 }
3450 if (pScienceDlg) {
3451 popdown_window_group_dialog(pScienceDlg->pBeginWidgetList,
3452 pScienceDlg->pEndWidgetList);
3453 FC_FREE(pScienceDlg);
3454 set_wstate(get_research_widget(), FC_WS_NORMAL);
3455 widget_redraw(get_research_widget());
3456 widget_mark_dirty(get_research_widget());
3457 }
3458 }
3459
3460 /****************************************************************************
3461 Resize and redraw the requirement tree.
3462 ****************************************************************************/
science_report_dialog_redraw(void)3463 void science_report_dialog_redraw(void)
3464 {
3465 /* No requirement tree yet. */
3466 }
3467
3468 /* ===================================================================== */
3469 /* ======================== Endgame Report ============================= */
3470 /* ===================================================================== */
3471
3472 static char eg_buffer[150 * MAX_NUM_PLAYERS];
3473 static int eg_player_count = 0;
3474 static int eg_players_received = 0;
3475
3476 /****************************************************************
3477 Show a dialog with player statistics at endgame.
3478 TODO: Display all statistics in packet_endgame_report.
3479 *****************************************************************/
endgame_report_dialog_start(const struct packet_endgame_report * packet)3480 void endgame_report_dialog_start(const struct packet_endgame_report *packet)
3481 {
3482 eg_buffer[0] = '\0';
3483 eg_player_count = packet->player_num;
3484 eg_players_received = 0;
3485 }
3486
3487 /****************************************************************
3488 Received endgame report information about single player
3489 *****************************************************************/
endgame_report_dialog_player(const struct packet_endgame_player * packet)3490 void endgame_report_dialog_player(const struct packet_endgame_player *packet)
3491 {
3492 const struct player *pplayer = player_by_number(packet->player_id);
3493
3494 eg_players_received++;
3495
3496 cat_snprintf(eg_buffer, sizeof(eg_buffer),
3497 PL_("%2d: The %s ruler %s scored %d point\n",
3498 "%2d: The %s ruler %s scored %d points\n",
3499 packet->score),
3500 eg_players_received, nation_adjective_for_player(pplayer),
3501 player_name(pplayer), packet->score);
3502
3503 if (eg_players_received == eg_player_count) {
3504 popup_notify_dialog(_("Final Report:"),
3505 _("The Greatest Civilizations in the world."),
3506 eg_buffer);
3507 }
3508 }
3509