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 #ifdef HAVE_CONFIG_H
15 #include <fc_config.h>
16 #endif
17
18 /* SDL */
19 #include <SDL/SDL.h>
20
21 /* utility */
22 #include "fcintl.h"
23 #include "log.h"
24
25 /* common */
26 #include "diptreaty.h"
27 #include "game.h"
28 #include "research.h"
29
30 /* client */
31 #include "client_main.h"
32 #include "climisc.h"
33 #include "packhand.h"
34
35 /* gui-sdl */
36 #include "chatline.h"
37 #include "colors.h"
38 #include "dialogs.h"
39 #include "graphics.h"
40 #include "gui_iconv.h"
41 #include "gui_id.h"
42 #include "gui_main.h"
43 #include "gui_tilespec.h"
44 #include "mapview.h"
45 #include "themespec.h"
46 #include "widget.h"
47
48 #include "diplodlg.h"
49
50 #define MAX_NUM_CLAUSES 64
51
52 struct diplomacy_dialog {
53 struct Treaty treaty;
54 struct ADVANCED_DLG *pdialog;
55 struct ADVANCED_DLG *pwants;
56 struct ADVANCED_DLG *poffers;
57 };
58
59 #define SPECLIST_TAG dialog
60 #define SPECLIST_TYPE struct diplomacy_dialog
61 #include "speclist.h"
62
63 #define dialog_list_iterate(dialoglist, pdialog) \
64 TYPED_LIST_ITERATE(struct diplomacy_dialog, dialoglist, pdialog)
65 #define dialog_list_iterate_end LIST_ITERATE_END
66
67 static struct dialog_list *dialog_list;
68
69 static void update_diplomacy_dialog(struct diplomacy_dialog *pdialog);
70 static void update_acceptance_icons(struct diplomacy_dialog *pdialog);
71 static void update_clauses_list(struct diplomacy_dialog *pdialog);
72 static void remove_clause_widget_from_list(int counterpart, int giver,
73 enum clause_type type, int value);
74 static void popdown_diplomacy_dialog(int counterpart);
75 static void popdown_diplomacy_dialogs(void);
76 static void popdown_sdip_dialog(void);
77
78 /****************************************************************
79 Initialialize diplomacy dialog system.
80 *****************************************************************/
diplomacy_dialog_init(void)81 void diplomacy_dialog_init(void)
82 {
83 dialog_list = dialog_list_new();
84 }
85
86 /****************************************************************
87 Free resources allocated for diplomacy dialog system.
88 *****************************************************************/
diplomacy_dialog_done(void)89 void diplomacy_dialog_done(void)
90 {
91 dialog_list_destroy(dialog_list);
92 }
93
94 /****************************************************************
95 Get diplomacy dialog between client user and other player.
96 *****************************************************************/
get_diplomacy_dialog(int other_player_id)97 static struct diplomacy_dialog *get_diplomacy_dialog(int other_player_id)
98 {
99 struct player *plr0 = client.conn.playing;
100 struct player *plr1 = player_by_number(other_player_id);
101
102 dialog_list_iterate(dialog_list, pdialog) {
103 if ((pdialog->treaty.plr0 == plr0 && pdialog->treaty.plr1 == plr1) ||
104 (pdialog->treaty.plr0 == plr1 && pdialog->treaty.plr1 == plr0)) {
105 return pdialog;
106 }
107 } dialog_list_iterate_end;
108
109 return NULL;
110 }
111
112 /**************************************************************************
113 Update a player's acceptance status of a treaty (traditionally shown
114 with the thumbs-up/thumbs-down sprite).
115 **************************************************************************/
handle_diplomacy_accept_treaty(int counterpart,bool I_accepted,bool other_accepted)116 void handle_diplomacy_accept_treaty(int counterpart, bool I_accepted,
117 bool other_accepted)
118 {
119 struct diplomacy_dialog *pdialog = get_diplomacy_dialog(counterpart);
120
121 if (!pdialog) {
122 return;
123 }
124
125 pdialog->treaty.accept0 = I_accepted;
126 pdialog->treaty.accept1 = other_accepted;
127
128 update_acceptance_icons(pdialog);
129 }
130
131 /**************************************************************************
132 Update the diplomacy dialog when the meeting is canceled (the dialog
133 should be closed).
134 **************************************************************************/
handle_diplomacy_cancel_meeting(int counterpart,int initiated_from)135 void handle_diplomacy_cancel_meeting(int counterpart, int initiated_from)
136 {
137 popdown_diplomacy_dialog(counterpart);
138 flush_dirty();
139 }
140 /* ----------------------------------------------------------------------- */
141
142 /**************************************************************************
143 User interacted with remove clause -widget.
144 **************************************************************************/
remove_clause_callback(struct widget * pWidget)145 static int remove_clause_callback(struct widget *pWidget)
146 {
147 if (Main.event.button.button == SDL_BUTTON_LEFT) {
148 struct diplomacy_dialog *pdialog;
149
150 if (!(pdialog = get_diplomacy_dialog(pWidget->data.cont->id1))) {
151 pdialog = get_diplomacy_dialog(pWidget->data.cont->id0);
152 }
153
154 dsend_packet_diplomacy_remove_clause_req(&client.conn,
155 player_number(pdialog->treaty.plr1),
156 pWidget->data.cont->id0,
157 (enum clause_type) ((pWidget->data.
158 cont->value >> 16) & 0xFFFF),
159 pWidget->data.cont->value & 0xFFFF);
160 }
161 return -1;
162 }
163
164 /**************************************************************************
165 Update the diplomacy dialog by adding a clause.
166 **************************************************************************/
handle_diplomacy_create_clause(int counterpart,int giver,enum clause_type type,int value)167 void handle_diplomacy_create_clause(int counterpart, int giver,
168 enum clause_type type, int value)
169 {
170 struct diplomacy_dialog *pdialog = get_diplomacy_dialog(counterpart);
171
172 if (!pdialog) {
173 return;
174 }
175
176 clause_list_iterate(pdialog->treaty.clauses, pclause) {
177 remove_clause_widget_from_list(player_number(pdialog->treaty.plr1),
178 player_number(pclause->from),
179 pclause->type,
180 pclause->value);
181 } clause_list_iterate_end;
182
183 add_clause(&pdialog->treaty, player_by_number(giver), type, value);
184
185 update_clauses_list(pdialog);
186 update_acceptance_icons(pdialog);
187 }
188
189 /**************************************************************************
190 Update the diplomacy dialog by removing a clause.
191 **************************************************************************/
handle_diplomacy_remove_clause(int counterpart,int giver,enum clause_type type,int value)192 void handle_diplomacy_remove_clause(int counterpart, int giver,
193 enum clause_type type, int value)
194 {
195 struct diplomacy_dialog *pdialog = get_diplomacy_dialog(counterpart);
196
197 if (!pdialog) {
198 return;
199 }
200
201 clause_list_iterate(pdialog->treaty.clauses, pclause) {
202 remove_clause_widget_from_list(player_number(pdialog->treaty.plr1),
203 player_number(pclause->from),
204 pclause->type,
205 pclause->value);
206 } clause_list_iterate_end;
207
208 remove_clause(&pdialog->treaty, player_by_number(giver), type, value);
209
210 update_clauses_list(pdialog);
211 update_acceptance_icons(pdialog);
212 }
213
214 /* ================================================================= */
215
216 /**************************************************************************
217 User interacted with cancel meeting -widget.
218 **************************************************************************/
cancel_meeting_callback(struct widget * pWidget)219 static int cancel_meeting_callback(struct widget *pWidget)
220 {
221 if (Main.event.button.button == SDL_BUTTON_LEFT) {
222 dsend_packet_diplomacy_cancel_meeting_req(&client.conn,
223 pWidget->data.cont->id1);
224 }
225 return -1;
226 }
227
228 /**************************************************************************
229 User interacted with accept treaty -widget.
230 **************************************************************************/
accept_treaty_callback(struct widget * pWidget)231 static int accept_treaty_callback(struct widget *pWidget)
232 {
233 if (Main.event.button.button == SDL_BUTTON_LEFT) {
234 dsend_packet_diplomacy_accept_treaty_req(&client.conn,
235 pWidget->data.cont->id1);
236 }
237 return -1;
238 }
239
240 /* ------------------------------------------------------------------------ */
241
242 /**************************************************************************
243 User interacted with pact selection -widget.
244 **************************************************************************/
pact_callback(struct widget * pWidget)245 static int pact_callback(struct widget *pWidget)
246 {
247 if (Main.event.button.button == SDL_BUTTON_LEFT) {
248 int clause_type;
249
250 struct diplomacy_dialog *pdialog;
251
252 if (!(pdialog = get_diplomacy_dialog(pWidget->data.cont->id1))) {
253 pdialog = get_diplomacy_dialog(pWidget->data.cont->id0);
254 }
255
256 switch(MAX_ID - pWidget->ID) {
257 case 2:
258 clause_type = CLAUSE_CEASEFIRE;
259 break;
260 case 1:
261 clause_type = CLAUSE_PEACE;
262 break;
263 default:
264 clause_type = CLAUSE_ALLIANCE;
265 break;
266 }
267
268 dsend_packet_diplomacy_create_clause_req(&client.conn,
269 player_number(pdialog->treaty.plr1),
270 pWidget->data.cont->id0,
271 clause_type, 0);
272 }
273 return -1;
274 }
275
276 /**************************************************************************
277 User interacted with shared vision -widget.
278 **************************************************************************/
vision_callback(struct widget * pWidget)279 static int vision_callback(struct widget *pWidget)
280 {
281 if (Main.event.button.button == SDL_BUTTON_LEFT) {
282 struct diplomacy_dialog *pdialog;
283
284 if (!(pdialog = get_diplomacy_dialog(pWidget->data.cont->id1))) {
285 pdialog = get_diplomacy_dialog(pWidget->data.cont->id0);
286 }
287
288 dsend_packet_diplomacy_create_clause_req(&client.conn,
289 player_number(pdialog->treaty.plr1),
290 pWidget->data.cont->id0,
291 CLAUSE_VISION, 0);
292 }
293 return -1;
294 }
295
296 /**************************************************************************
297 User interacted with embassy -widget.
298 **************************************************************************/
embassy_callback(struct widget * pWidget)299 static int embassy_callback(struct widget *pWidget)
300 {
301 if (Main.event.button.button == SDL_BUTTON_LEFT) {
302 struct diplomacy_dialog *pdialog;
303
304 if (!(pdialog = get_diplomacy_dialog(pWidget->data.cont->id1))) {
305 pdialog = get_diplomacy_dialog(pWidget->data.cont->id0);
306 }
307
308 dsend_packet_diplomacy_create_clause_req(&client.conn,
309 player_number(pdialog->treaty.plr1),
310 pWidget->data.cont->id0,
311 CLAUSE_EMBASSY, 0);
312 }
313 return -1;
314 }
315
316 /**************************************************************************
317 User interacted with map -widget.
318 **************************************************************************/
maps_callback(struct widget * pWidget)319 static int maps_callback(struct widget *pWidget)
320 {
321 if (Main.event.button.button == SDL_BUTTON_LEFT) {
322 int clause_type;
323
324 struct diplomacy_dialog *pdialog;
325
326 if (!(pdialog = get_diplomacy_dialog(pWidget->data.cont->id1))) {
327 pdialog = get_diplomacy_dialog(pWidget->data.cont->id0);
328 }
329
330 switch(MAX_ID - pWidget->ID) {
331 case 1:
332 clause_type = CLAUSE_MAP;
333 break;
334 default:
335 clause_type = CLAUSE_SEAMAP;
336 break;
337 }
338
339 dsend_packet_diplomacy_create_clause_req(&client.conn,
340 player_number(pdialog->treaty.plr1),
341 pWidget->data.cont->id0,
342 clause_type, 0);
343 }
344 return -1;
345 }
346
347 /**************************************************************************
348 User interacted with tech -widget.
349 **************************************************************************/
techs_callback(struct widget * pWidget)350 static int techs_callback(struct widget *pWidget)
351 {
352 if (Main.event.button.button == SDL_BUTTON_LEFT) {
353 struct diplomacy_dialog *pdialog;
354
355 if (!(pdialog = get_diplomacy_dialog(pWidget->data.cont->id1))) {
356 pdialog = get_diplomacy_dialog(pWidget->data.cont->id0);
357 }
358
359 dsend_packet_diplomacy_create_clause_req(&client.conn,
360 player_number(pdialog->treaty.plr1),
361 pWidget->data.cont->id0,
362 CLAUSE_ADVANCE,
363 (MAX_ID - pWidget->ID));
364 }
365 return -1;
366 }
367
368 /**************************************************************************
369 User interacted with gold -widget.
370 **************************************************************************/
gold_callback(struct widget * pWidget)371 static int gold_callback(struct widget *pWidget)
372 {
373 if (Main.event.button.button == SDL_BUTTON_LEFT) {
374 int amount;
375
376 struct diplomacy_dialog *pdialog;
377
378 if (!(pdialog = get_diplomacy_dialog(pWidget->data.cont->id1))) {
379 pdialog = get_diplomacy_dialog(pWidget->data.cont->id0);
380 }
381
382 if(pWidget->string16->text) {
383 char cBuf[16];
384
385 convertcopy_to_chars(cBuf, sizeof(cBuf), pWidget->string16->text);
386 sscanf(cBuf, "%d", &amount);
387
388 if(amount > pWidget->data.cont->value) {
389 /* max player gold */
390 amount = pWidget->data.cont->value;
391 }
392
393 } else {
394 amount = 0;
395 }
396
397 if (amount > 0) {
398 dsend_packet_diplomacy_create_clause_req(&client.conn,
399 player_number(pdialog->treaty.plr1),
400 pWidget->data.cont->id0,
401 CLAUSE_GOLD, amount);
402
403 } else {
404 output_window_append(ftc_client,
405 _("Invalid amount of gold specified."));
406 }
407
408 if(amount || !pWidget->string16->text) {
409 copy_chars_to_string16(pWidget->string16, "0");
410 widget_redraw(pWidget);
411 widget_flush(pWidget);
412 }
413 }
414 return -1;
415 }
416
417 /**************************************************************************
418 User interacted with city -widget.
419 **************************************************************************/
cities_callback(struct widget * pWidget)420 static int cities_callback(struct widget *pWidget)
421 {
422 if (Main.event.button.button == SDL_BUTTON_LEFT) {
423 struct diplomacy_dialog *pdialog;
424
425 if (!(pdialog = get_diplomacy_dialog(pWidget->data.cont->id1))) {
426 pdialog = get_diplomacy_dialog(pWidget->data.cont->id0);
427 }
428
429 dsend_packet_diplomacy_create_clause_req(&client.conn,
430 player_number(pdialog->treaty.plr1),
431 pWidget->data.cont->id0,
432 CLAUSE_CITY,
433 (MAX_ID - pWidget->ID));
434 }
435 return -1;
436 }
437
438 /**************************************************************************
439 User interacted with Diplomacy meeting -window.
440 **************************************************************************/
dipomatic_window_callback(struct widget * pWindow)441 static int dipomatic_window_callback(struct widget *pWindow)
442 {
443 return -1;
444 }
445
446 /**************************************************************************
447 Create treaty widgets. Pact (that will always be both ways) related
448 widgets are created only when pPlayer0 is client user.
449 **************************************************************************/
popup_diplomatic_objects(struct player * pPlayer0,struct player * pPlayer1,struct widget * pMainWindow,bool L_R)450 static struct ADVANCED_DLG * popup_diplomatic_objects(struct player *pPlayer0,
451 struct player *pPlayer1,
452 struct widget *pMainWindow, bool L_R)
453 {
454 struct ADVANCED_DLG *pDlg = fc_calloc(1, sizeof(struct ADVANCED_DLG));
455 struct CONTAINER *pCont = fc_calloc(1, sizeof(struct CONTAINER));
456 int width, height, count = 0, scroll_w = 0;
457 char cBuf[128];
458 struct widget *pBuf = NULL, *pWindow;
459 SDL_String16 *pStr;
460 int window_x = 0, window_y = 0;
461 SDL_Rect area;
462
463 enum diplstate_type type
464 = player_diplstate_get(pPlayer0, pPlayer1)->type;
465
466 pCont->id0 = player_number(pPlayer0);
467 pCont->id1 = player_number(pPlayer1);
468
469 pStr = create_str16_from_char(nation_adjective_for_player(pPlayer0), adj_font(12));
470 pStr->style |= TTF_STYLE_BOLD;
471
472 pWindow = create_window_skeleton(NULL, pStr, WF_FREE_DATA);
473
474 pWindow->action = dipomatic_window_callback;
475 set_wstate(pWindow, FC_WS_NORMAL);
476
477 pDlg->pEndWidgetList = pWindow;
478 pWindow->data.cont = pCont;
479 add_to_gui_list(ID_WINDOW, pWindow);
480
481 area = pWindow->area;
482
483 /* ============================================================= */
484 width = 0;
485 height = 0;
486
487 /* Pacts. */
488 if (pPlayer0 == client.conn.playing && DS_ALLIANCE != type) {
489
490 pBuf = create_iconlabel_from_chars(NULL, pWindow->dst,
491 _("Pacts"), adj_font(12), WF_RESTORE_BACKGROUND);
492 pBuf->string16->fgcol = *get_theme_color(COLOR_THEME_DIPLODLG_MEETING_HEADING_TEXT);
493 width = pBuf->size.w;
494 height = pBuf->size.h;
495 add_to_gui_list(ID_LABEL, pBuf);
496 count++;
497
498 if (type != DS_CEASEFIRE && type != DS_TEAM) {
499 fc_snprintf(cBuf, sizeof(cBuf), " %s", Q_("?diplomatic_state:Cease-fire"));
500 pBuf = create_iconlabel_from_chars(NULL, pWindow->dst,
501 cBuf, adj_font(12), (WF_RESTORE_BACKGROUND|WF_DRAW_TEXT_LABEL_WITH_SPACE));
502 pBuf->string16->fgcol = *get_theme_color(COLOR_THEME_DIPLODLG_MEETING_TEXT);
503 width = MAX(width, pBuf->size.w);
504 height = MAX(height, pBuf->size.h);
505 pBuf->action = pact_callback;
506 pBuf->data.cont = pCont;
507 set_wstate(pBuf, FC_WS_NORMAL);
508 add_to_gui_list(MAX_ID - 2, pBuf);
509 count++;
510 }
511
512 if (type != DS_PEACE && type != DS_TEAM) {
513 fc_snprintf(cBuf, sizeof(cBuf), " %s", Q_("?diplomatic_state:Peace"));
514
515 pBuf = create_iconlabel_from_chars(NULL, pWindow->dst,
516 cBuf, adj_font(12), (WF_RESTORE_BACKGROUND|WF_DRAW_TEXT_LABEL_WITH_SPACE));
517 pBuf->string16->fgcol = *get_theme_color(COLOR_THEME_DIPLODLG_MEETING_TEXT);
518 width = MAX(width, pBuf->size.w);
519 height = MAX(height, pBuf->size.h);
520 pBuf->action = pact_callback;
521 pBuf->data.cont = pCont;
522 set_wstate(pBuf, FC_WS_NORMAL);
523 add_to_gui_list(MAX_ID - 1, pBuf);
524 count++;
525 }
526
527 if (pplayer_can_make_treaty(pPlayer0, pPlayer1, DS_ALLIANCE)) {
528 fc_snprintf(cBuf, sizeof(cBuf), " %s", Q_("?diplomatic_state:Alliance"));
529
530 pBuf = create_iconlabel_from_chars(NULL, pWindow->dst,
531 cBuf, adj_font(12), (WF_RESTORE_BACKGROUND|WF_DRAW_TEXT_LABEL_WITH_SPACE));
532 pBuf->string16->fgcol = *get_theme_color(COLOR_THEME_DIPLODLG_MEETING_TEXT);
533 width = MAX(width, pBuf->size.w);
534 height = MAX(height, pBuf->size.h);
535 pBuf->action = pact_callback;
536 pBuf->data.cont = pCont;
537 set_wstate(pBuf, FC_WS_NORMAL);
538 add_to_gui_list(MAX_ID, pBuf);
539 count++;
540 }
541
542 }
543
544 /* ---------------------------- */
545 if (!gives_shared_vision(pPlayer0, pPlayer1)) {
546
547 pBuf = create_iconlabel_from_chars(NULL, pWindow->dst,
548 _("Give shared vision"), adj_font(12),
549 (WF_RESTORE_BACKGROUND|WF_DRAW_TEXT_LABEL_WITH_SPACE));
550 pBuf->string16->fgcol = *get_theme_color(COLOR_THEME_DIPLODLG_MEETING_TEXT);
551 width = MAX(width, pBuf->size.w);
552 height = MAX(height, pBuf->size.h);
553 pBuf->action = vision_callback;
554 pBuf->data.cont = pCont;
555 set_wstate(pBuf, FC_WS_NORMAL);
556 add_to_gui_list(ID_LABEL, pBuf);
557 count++;
558
559 /* ---------------------------- */
560 /* you can't give maps if you give shared vision */
561 pBuf = create_iconlabel_from_chars(NULL, pWindow->dst,
562 _("Maps"), adj_font(12), WF_RESTORE_BACKGROUND);
563 pBuf->string16->fgcol = *get_theme_color(COLOR_THEME_DIPLODLG_MEETING_HEADING_TEXT);
564 width = MAX(width, pBuf->size.w);
565 height = MAX(height, pBuf->size.h);
566 add_to_gui_list(ID_LABEL, pBuf);
567 count++;
568
569 /* ----- */
570 fc_snprintf(cBuf, sizeof(cBuf), " %s", _("World map"));
571
572 pBuf = create_iconlabel_from_chars(NULL, pWindow->dst,
573 cBuf, adj_font(12), (WF_RESTORE_BACKGROUND|WF_DRAW_TEXT_LABEL_WITH_SPACE));
574 pBuf->string16->fgcol = *get_theme_color(COLOR_THEME_DIPLODLG_MEETING_TEXT);
575 width = MAX(width, pBuf->size.w);
576 height = MAX(height, pBuf->size.h);
577 pBuf->action = maps_callback;
578 pBuf->data.cont = pCont;
579 set_wstate(pBuf, FC_WS_NORMAL);
580 add_to_gui_list(MAX_ID - 1, pBuf);
581 count++;
582
583 /* ----- */
584 fc_snprintf(cBuf, sizeof(cBuf), " %s", _("Sea map"));
585
586 pBuf = create_iconlabel_from_chars(NULL, pWindow->dst,
587 cBuf, adj_font(12), (WF_RESTORE_BACKGROUND|WF_DRAW_TEXT_LABEL_WITH_SPACE));
588 pBuf->string16->fgcol = *get_theme_color(COLOR_THEME_DIPLODLG_MEETING_TEXT);
589 width = MAX(width, pBuf->size.w);
590 height = MAX(height, pBuf->size.h);
591 pBuf->action = maps_callback;
592 pBuf->data.cont = pCont;
593 set_wstate(pBuf, FC_WS_NORMAL);
594 add_to_gui_list(MAX_ID, pBuf);
595 count++;
596 }
597
598 /* Don't take in account the embassy effects. */
599 if (!player_has_real_embassy(pPlayer1, pPlayer0)) {
600 pBuf = create_iconlabel_from_chars(NULL, pWindow->dst,
601 _("Give embassy"), adj_font(12),
602 (WF_RESTORE_BACKGROUND|WF_DRAW_TEXT_LABEL_WITH_SPACE));
603 pBuf->string16->fgcol = *get_theme_color(COLOR_THEME_DIPLODLG_MEETING_TEXT);
604 width = MAX(width, pBuf->size.w);
605 height = MAX(height, pBuf->size.h);
606 pBuf->action = embassy_callback;
607 pBuf->data.cont = pCont;
608 set_wstate(pBuf, FC_WS_NORMAL);
609 add_to_gui_list(ID_LABEL, pBuf);
610 count++;
611 }
612
613 /* ---------------------------- */
614 if(game.info.trading_gold && pPlayer0->economic.gold > 0) {
615 pCont->value = pPlayer0->economic.gold;
616
617 fc_snprintf(cBuf, sizeof(cBuf), _("Gold(max %d)"), pPlayer0->economic.gold);
618 pBuf = create_iconlabel_from_chars(NULL, pWindow->dst,
619 cBuf, adj_font(12), WF_RESTORE_BACKGROUND);
620 pBuf->string16->fgcol = *get_theme_color(COLOR_THEME_DIPLODLG_MEETING_HEADING_TEXT);
621 width = MAX(width, pBuf->size.w);
622 height = MAX(height, pBuf->size.h);
623 add_to_gui_list(ID_LABEL, pBuf);
624 count++;
625
626 pBuf = create_edit(NULL, pWindow->dst,
627 create_str16_from_char("0", adj_font(10)), 0,
628 (WF_RESTORE_BACKGROUND|WF_FREE_STRING));
629 pBuf->data.cont = pCont;
630 pBuf->action = gold_callback;
631 set_wstate(pBuf, FC_WS_NORMAL);
632 width = MAX(width, pBuf->size.w);
633 height = MAX(height, pBuf->size.h);
634 add_to_gui_list(ID_LABEL, pBuf);
635 count++;
636 }
637 /* ---------------------------- */
638
639 /* Trading: advances */
640 if (game.info.trading_tech) {
641 const struct research *presearch0 = research_get(pPlayer0);
642 const struct research *presearch1 = research_get(pPlayer1);
643 int flag = A_NONE;
644
645 advance_index_iterate(A_FIRST, i) {
646 if (research_invention_state(presearch0, i) == TECH_KNOWN
647 && research_invention_gettable(presearch1, i,
648 game.info.tech_trade_allow_holes)
649 && (research_invention_state(presearch1, i) == TECH_UNKNOWN
650 || research_invention_state(presearch1, i)
651 == TECH_PREREQS_KNOWN)) {
652
653 pBuf = create_iconlabel_from_chars(NULL, pWindow->dst,
654 _("Advances"), adj_font(12), WF_RESTORE_BACKGROUND);
655 pBuf->string16->fgcol = *get_theme_color(COLOR_THEME_DIPLODLG_MEETING_HEADING_TEXT);
656 width = MAX(width, pBuf->size.w);
657 height = MAX(height, pBuf->size.h);
658 add_to_gui_list(ID_LABEL, pBuf);
659 count++;
660
661 fc_snprintf(cBuf, sizeof(cBuf), " %s", advance_name_translation(advance_by_number(i)));
662
663 pBuf = create_iconlabel_from_chars(NULL, pWindow->dst, cBuf, adj_font(12),
664 (WF_RESTORE_BACKGROUND|WF_DRAW_TEXT_LABEL_WITH_SPACE));
665 pBuf->string16->fgcol = *get_theme_color(COLOR_THEME_DIPLODLG_MEETING_TEXT);
666 width = MAX(width, pBuf->size.w);
667 height = MAX(height, pBuf->size.h);
668 pBuf->action = techs_callback;
669 set_wstate(pBuf, FC_WS_NORMAL);
670 pBuf->data.cont = pCont;
671 add_to_gui_list(MAX_ID - i, pBuf);
672 count++;
673 flag = ++i;
674 break;
675 }
676 } advance_index_iterate_end;
677
678 if (flag > A_NONE) {
679 advance_index_iterate(flag, i) {
680 if (research_invention_state(presearch0, i) == TECH_KNOWN
681 && research_invention_gettable(presearch1, i,
682 game.info.tech_trade_allow_holes)
683 && (research_invention_state(presearch1, i) == TECH_UNKNOWN
684 || research_invention_state(presearch1, i)
685 == TECH_PREREQS_KNOWN)) {
686
687 fc_snprintf(cBuf, sizeof(cBuf), " %s", advance_name_translation(advance_by_number(i)));
688
689 pBuf = create_iconlabel_from_chars(NULL, pWindow->dst, cBuf, adj_font(12),
690 (WF_RESTORE_BACKGROUND|WF_DRAW_TEXT_LABEL_WITH_SPACE));
691 pBuf->string16->fgcol = *get_theme_color(COLOR_THEME_DIPLODLG_MEETING_TEXT);
692 width = MAX(width, pBuf->size.w);
693 height = MAX(height, pBuf->size.h);
694 pBuf->action = techs_callback;
695 set_wstate(pBuf, FC_WS_NORMAL);
696 pBuf->data.cont = pCont;
697 add_to_gui_list(MAX_ID - i, pBuf);
698 count++;
699 }
700 }
701 } advance_index_iterate_end;
702
703 } /* Advances */
704
705 /* Trading: cities */
706 /****************************************************************
707 Creates a sorted list of pPlayer0's cities, excluding the capital and
708 any cities not visible to pPlayer1. This means that you can only trade
709 cities visible to requesting player.
710
711 - Kris Bubendorfer
712 *****************************************************************/
713 if (game.info.trading_city) {
714 int i = 0, j = 0, n = city_list_size(pPlayer0->cities);
715 struct city **city_list_ptrs;
716
717 if (n > 0) {
718 city_list_ptrs = fc_calloc(1, sizeof(struct city *) * n);
719 city_list_iterate(pPlayer0->cities, pCity) {
720 if (!is_capital(pCity)) {
721 city_list_ptrs[i] = pCity;
722 i++;
723 }
724 } city_list_iterate_end;
725 } else {
726 city_list_ptrs = NULL;
727 }
728
729
730 if(i > 0) {
731
732 pBuf = create_iconlabel_from_chars(NULL, pWindow->dst,
733 _("Cities"), adj_font(12), WF_RESTORE_BACKGROUND);
734 pBuf->string16->fgcol = *get_theme_color(COLOR_THEME_DIPLODLG_MEETING_HEADING_TEXT);
735 pBuf->string16->style &= ~SF_CENTER;
736 width = MAX(width, pBuf->size.w);
737 height = MAX(height, pBuf->size.h);
738 add_to_gui_list(ID_LABEL, pBuf);
739 count++;
740
741 qsort(city_list_ptrs, i, sizeof(struct city *), city_name_compare);
742
743 for (j = 0; j < i; j++) {
744 fc_snprintf(cBuf, sizeof(cBuf), " %s", city_name_get(city_list_ptrs[j]));
745
746 pBuf = create_iconlabel_from_chars(NULL, pWindow->dst, cBuf, adj_font(12),
747 (WF_RESTORE_BACKGROUND|WF_DRAW_TEXT_LABEL_WITH_SPACE));
748 pBuf->string16->fgcol = *get_theme_color(COLOR_THEME_DIPLODLG_MEETING_TEXT);
749 width = MAX(width, pBuf->size.w);
750 height = MAX(height, pBuf->size.h);
751 pBuf->data.cont = pCont;
752 pBuf->action = cities_callback;
753 set_wstate(pBuf, FC_WS_NORMAL);
754 /* MAX_ID is unigned short type range and city id must be in this range */
755 fc_assert(city_list_ptrs[j]->id <= MAX_ID);
756 add_to_gui_list(MAX_ID - city_list_ptrs[j]->id, pBuf);
757 count++;
758 }
759 }
760 FC_FREE(city_list_ptrs);
761 } /* Cities */
762
763 pDlg->pBeginWidgetList = pBuf;
764 pDlg->pBeginActiveWidgetList = pDlg->pBeginWidgetList;
765 pDlg->pEndActiveWidgetList = pDlg->pEndWidgetList->prev;
766 pDlg->pScroll = NULL;
767
768 area.h = (Main.screen->h - adj_size(100) - (pWindow->size.h - pWindow->area.h));
769
770 if (area.h < (count * height)) {
771 pDlg->pActiveWidgetList = pDlg->pEndActiveWidgetList;
772 count = area.h / height;
773 scroll_w = create_vertical_scrollbar(pDlg, 1, count, TRUE, TRUE);
774 pBuf = pWindow;
775 /* hide not seen widgets */
776 do {
777 pBuf = pBuf->prev;
778 if(count) {
779 count--;
780 } else {
781 set_wflag(pBuf, WF_HIDDEN);
782 }
783 } while(pBuf != pDlg->pBeginActiveWidgetList);
784 }
785
786 area.w = MAX(width + adj_size(4) + scroll_w, adj_size(150) - (pWindow->size.w - pWindow->area.w));
787
788 resize_window(pWindow, NULL, get_theme_color(COLOR_THEME_BACKGROUND),
789 (pWindow->size.w - pWindow->area.w) + area.w,
790 (pWindow->size.h - pWindow->area.h) + area.h);
791
792 area = pWindow->area;
793
794 if(L_R) {
795 window_x = pMainWindow->dst->dest_rect.x + pMainWindow->size.w + adj_size(20);
796 } else {
797 window_x = pMainWindow->dst->dest_rect.x - adj_size(20) - pWindow->size.w;
798 }
799 window_y = (Main.screen->h - pWindow->size.h) / 2;
800
801 widget_set_position(pWindow, window_x, window_y);
802
803 setup_vertical_widgets_position(1,
804 area.x + adj_size(2), area.y + 1,
805 width, height, pDlg->pBeginActiveWidgetList, pDlg->pEndActiveWidgetList);
806
807 if(pDlg->pScroll) {
808 setup_vertical_scrollbar_area(pDlg->pScroll,
809 area.x + area.w,
810 area.y,
811 area.h, TRUE);
812 }
813
814 return pDlg;
815 }
816
817 /**************************************************************************
818 Open new diplomacy dialog between players.
819 **************************************************************************/
create_diplomacy_dialog(struct player * plr0,struct player * plr1)820 static struct diplomacy_dialog *create_diplomacy_dialog(struct player *plr0,
821 struct player *plr1)
822 {
823 struct diplomacy_dialog *pdialog = fc_calloc(1, sizeof(struct diplomacy_dialog));
824
825 init_treaty(&pdialog->treaty, plr0, plr1);
826
827 pdialog->pdialog = fc_calloc(1, sizeof(struct ADVANCED_DLG));
828
829 dialog_list_prepend(dialog_list, pdialog);
830
831 return pdialog;
832 }
833
834 /****************************************************************
835 Update diplomacy dialog information.
836 *****************************************************************/
update_diplomacy_dialog(struct diplomacy_dialog * pdialog)837 static void update_diplomacy_dialog(struct diplomacy_dialog *pdialog)
838 {
839 SDL_Color bg_color = {255, 255, 255, 136};
840
841 struct player *pPlayer0, *pPlayer1;
842 struct CONTAINER *pCont = fc_calloc(1, sizeof(struct CONTAINER));
843 char cBuf[128];
844 struct widget *pBuf = NULL, *pWindow;
845 SDL_String16 *pStr;
846 SDL_Rect dst;
847 SDL_Rect area;
848
849 if(pdialog) {
850
851 /* delete old content */
852 if (pdialog->pdialog->pEndWidgetList) {
853 popdown_window_group_dialog(pdialog->poffers->pBeginWidgetList,
854 pdialog->poffers->pEndWidgetList);
855 FC_FREE(pdialog->poffers->pScroll);
856 FC_FREE(pdialog->poffers);
857
858 popdown_window_group_dialog(pdialog->pwants->pBeginWidgetList,
859 pdialog->pwants->pEndWidgetList);
860 FC_FREE(pdialog->pwants->pScroll);
861 FC_FREE(pdialog->pwants);
862
863 popdown_window_group_dialog(pdialog->pdialog->pBeginWidgetList,
864 pdialog->pdialog->pEndWidgetList);
865 }
866
867 pPlayer0 = pdialog->treaty.plr0;
868 pPlayer1 = pdialog->treaty.plr1;
869
870 pCont->id0 = player_number(pPlayer0);
871 pCont->id1 = player_number(pPlayer1);
872
873 fc_snprintf(cBuf, sizeof(cBuf), _("Diplomacy meeting"));
874
875 pStr = create_str16_from_char(cBuf, adj_font(12));
876 pStr->style |= TTF_STYLE_BOLD;
877
878 pWindow = create_window_skeleton(NULL, pStr, 0);
879
880 pWindow->action = dipomatic_window_callback;
881 set_wstate(pWindow, FC_WS_NORMAL);
882 pWindow->data.cont = pCont;
883 pdialog->pdialog->pEndWidgetList = pWindow;
884
885 add_to_gui_list(ID_WINDOW, pWindow);
886
887 /* ============================================================= */
888
889 pStr = create_str16_from_char(nation_adjective_for_player(pPlayer0), adj_font(12));
890 pStr->style |= (TTF_STYLE_BOLD|SF_CENTER);
891 pStr->fgcol = *get_theme_color(COLOR_THEME_DIPLODLG_MEETING_TEXT);
892
893 pBuf = create_iconlabel(
894 create_icon_from_theme(current_theme->CANCEL_PACT_Icon, 0),
895 pWindow->dst, pStr,
896 (WF_ICON_ABOVE_TEXT|WF_FREE_PRIVATE_DATA|WF_FREE_THEME|
897 WF_RESTORE_BACKGROUND));
898
899 pBuf->private_data.cbox = fc_calloc(1, sizeof(struct CHECKBOX));
900 pBuf->private_data.cbox->state = FALSE;
901 pBuf->private_data.cbox->pTRUE_Theme = current_theme->OK_PACT_Icon;
902 pBuf->private_data.cbox->pFALSE_Theme = current_theme->CANCEL_PACT_Icon;
903
904 add_to_gui_list(ID_ICON, pBuf);
905
906 pStr = create_str16_from_char(nation_adjective_for_player(pPlayer1), adj_font(12));
907 pStr->style |= (TTF_STYLE_BOLD|SF_CENTER);
908 pStr->fgcol = *get_theme_color(COLOR_THEME_DIPLODLG_MEETING_TEXT);
909
910 pBuf = create_iconlabel(
911 create_icon_from_theme(current_theme->CANCEL_PACT_Icon, 0),
912 pWindow->dst, pStr,
913 (WF_ICON_ABOVE_TEXT|WF_FREE_PRIVATE_DATA|WF_FREE_THEME|
914 WF_RESTORE_BACKGROUND));
915 pBuf->private_data.cbox = fc_calloc(1, sizeof(struct CHECKBOX));
916 pBuf->private_data.cbox->state = FALSE;
917 pBuf->private_data.cbox->pTRUE_Theme = current_theme->OK_PACT_Icon;
918 pBuf->private_data.cbox->pFALSE_Theme = current_theme->CANCEL_PACT_Icon;
919 add_to_gui_list(ID_ICON, pBuf);
920 /* ============================================================= */
921
922 pBuf = create_themeicon(current_theme->CANCEL_PACT_Icon, pWindow->dst,
923 WF_WIDGET_HAS_INFO_LABEL
924 | WF_RESTORE_BACKGROUND);
925 pBuf->info_label = create_str16_from_char(_("Cancel meeting"),
926 adj_font(12));
927 pBuf->action = cancel_meeting_callback;
928 pBuf->data.cont = pCont;
929 set_wstate(pBuf, FC_WS_NORMAL);
930
931 add_to_gui_list(ID_ICON, pBuf);
932
933 pBuf = create_themeicon(current_theme->OK_PACT_Icon, pWindow->dst,
934 WF_FREE_DATA | WF_WIDGET_HAS_INFO_LABEL
935 | WF_RESTORE_BACKGROUND);
936 pBuf->info_label = create_str16_from_char(_("Accept treaty"),
937 adj_font(12));
938 pBuf->action = accept_treaty_callback;
939 pBuf->data.cont = pCont;
940 set_wstate(pBuf, FC_WS_NORMAL);
941
942 add_to_gui_list(ID_ICON, pBuf);
943 /* ============================================================= */
944
945 pdialog->pdialog->pBeginWidgetList = pBuf;
946
947 create_vertical_scrollbar(pdialog->pdialog, 1, 7, TRUE, TRUE);
948 hide_scrollbar(pdialog->pdialog->pScroll);
949
950 /* ============================================================= */
951
952 resize_window(pWindow, NULL, get_theme_color(COLOR_THEME_BACKGROUND),
953 adj_size(250), adj_size(300));
954
955 area = pWindow->area;
956
957 widget_set_position(pWindow,
958 (Main.screen->w - pWindow->size.w) / 2,
959 (Main.screen->h - pWindow->size.h) / 2);
960
961 pBuf = pWindow->prev;
962 pBuf->size.x = area.x + adj_size(17);
963 pBuf->size.y = area.y + adj_size(6);
964
965 dst.y = area.y + adj_size(6) + pBuf->size.h + adj_size(10);
966 dst.x = adj_size(10);
967 dst.w = area.w - adj_size(14);
968
969 pBuf = pBuf->prev;
970 pBuf->size.x = area.x + area.w - pBuf->size.w - adj_size(20);
971 pBuf->size.y = area.y + adj_size(6);
972
973 pBuf = pBuf->prev;
974 pBuf->size.x = area.x + (area.w - (2 * pBuf->size.w + adj_size(40))) / 2;
975 pBuf->size.y = area.y + area.h - pBuf->size.w - adj_size(17);
976
977 pBuf = pBuf->prev;
978 pBuf->size.x = pBuf->next->size.x + pBuf->next->size.w + adj_size(40);
979 pBuf->size.y = area.y + area.h - pBuf->size.w - adj_size(17);
980
981 dst.h = area.h - pBuf->size.w - adj_size(3) - dst.y;
982 /* ============================================================= */
983
984 SDL_FillRectAlpha(pWindow->theme, &dst, &bg_color);
985
986 /* ============================================================= */
987 setup_vertical_scrollbar_area(pdialog->pdialog->pScroll,
988 area.x + dst.x + dst.w,
989 dst.y,
990 dst.h, TRUE);
991 /* ============================================================= */
992 pdialog->poffers = popup_diplomatic_objects(pPlayer0, pPlayer1, pWindow, FALSE);
993
994 pdialog->pwants = popup_diplomatic_objects(pPlayer1, pPlayer0, pWindow, TRUE);
995 /* ============================================================= */
996 /* redraw */
997 redraw_group(pdialog->pdialog->pBeginWidgetList, pWindow, 0);
998 widget_mark_dirty(pWindow);
999
1000 redraw_group(pdialog->poffers->pBeginWidgetList, pdialog->poffers->pEndWidgetList, 0);
1001 widget_mark_dirty(pdialog->poffers->pEndWidgetList);
1002
1003 redraw_group(pdialog->pwants->pBeginWidgetList, pdialog->pwants->pEndWidgetList, 0);
1004 widget_mark_dirty(pdialog->pwants->pEndWidgetList);
1005
1006 flush_dirty();
1007 }
1008 }
1009
1010 /****************************************************************
1011 Update treaty acceptance icons (accepted / rejected)
1012 *****************************************************************/
update_acceptance_icons(struct diplomacy_dialog * pdialog)1013 static void update_acceptance_icons(struct diplomacy_dialog *pdialog)
1014 {
1015 struct widget *pLabel;
1016 SDL_Surface *pThm;
1017 SDL_Rect src = {0, 0, 0, 0};
1018
1019 /* updates your own acceptance status */
1020 pLabel = pdialog->pdialog->pEndWidgetList->prev;
1021
1022 pLabel->private_data.cbox->state = pdialog->treaty.accept0;
1023 if (pLabel->private_data.cbox->state) {
1024 pThm = pLabel->private_data.cbox->pTRUE_Theme;
1025 } else {
1026 pThm = pLabel->private_data.cbox->pFALSE_Theme;
1027 }
1028
1029 src.w = pThm->w / 4;
1030 src.h = pThm->h;
1031
1032 alphablit(pThm, &src, pLabel->theme, NULL);
1033 SDL_SetAlpha(pThm, SDL_SRCALPHA, 255);
1034
1035 widget_redraw(pLabel);
1036 widget_flush(pLabel);
1037
1038 /* updates other player's acceptance status */
1039 pLabel = pdialog->pdialog->pEndWidgetList->prev->prev;
1040
1041 pLabel->private_data.cbox->state = pdialog->treaty.accept1;
1042 if (pLabel->private_data.cbox->state) {
1043 pThm = pLabel->private_data.cbox->pTRUE_Theme;
1044 } else {
1045 pThm = pLabel->private_data.cbox->pFALSE_Theme;
1046 }
1047
1048 src.w = pThm->w / 4;
1049 src.h = pThm->h;
1050
1051 alphablit(pThm, &src, pLabel->theme, NULL);
1052
1053 widget_redraw(pLabel);
1054 widget_flush(pLabel);
1055 }
1056
1057 /****************************************************************
1058 Refresh diplomacy dialog when list of clauses has been changed.
1059 *****************************************************************/
update_clauses_list(struct diplomacy_dialog * pdialog)1060 static void update_clauses_list(struct diplomacy_dialog *pdialog) {
1061 SDL_String16 *pStr;
1062 struct widget *pBuf, *pWindow = pdialog->pdialog->pEndWidgetList;
1063 char cBuf[128];
1064 bool redraw_all, scroll = (pdialog->pdialog->pActiveWidgetList != NULL);
1065 int len = pdialog->pdialog->pScroll->pUp_Left_Button->size.w;
1066
1067 clause_list_iterate(pdialog->treaty.clauses, pclause) {
1068
1069 client_diplomacy_clause_string(cBuf, sizeof(cBuf), pclause);
1070
1071 pStr = create_str16_from_char(cBuf, adj_font(12));
1072 pBuf = create_iconlabel(NULL, pWindow->dst, pStr,
1073 (WF_FREE_DATA|WF_DRAW_TEXT_LABEL_WITH_SPACE|WF_RESTORE_BACKGROUND));
1074
1075 if (pclause->from != client.conn.playing) {
1076 pBuf->string16->style |= SF_CENTER_RIGHT;
1077 }
1078
1079 pBuf->data.cont = fc_calloc(1, sizeof(struct CONTAINER));
1080 pBuf->data.cont->id0 = player_number(pclause->from);
1081 pBuf->data.cont->id1 = player_number(pdialog->treaty.plr1);
1082 pBuf->data.cont->value = ((int)pclause->type << 16) + pclause->value;
1083
1084 pBuf->action = remove_clause_callback;
1085 set_wstate(pBuf, FC_WS_NORMAL);
1086
1087 pBuf->size.w = pWindow->size.w - adj_size(24) - (scroll ? len : 0);
1088
1089 redraw_all = add_widget_to_vertical_scroll_widget_list(pdialog->pdialog,
1090 pBuf, pdialog->pdialog->pBeginWidgetList,
1091 FALSE,
1092 pWindow->size.x + adj_size(12),
1093 pdialog->pdialog->pScroll->pUp_Left_Button->size.y + adj_size(2));
1094
1095 if(!scroll && (pdialog->pdialog->pActiveWidgetList != NULL)) {
1096 /* -> the scrollbar has been activated */
1097 pBuf = pdialog->pdialog->pEndActiveWidgetList->next;
1098 do {
1099 pBuf = pBuf->prev;
1100 pBuf->size.w -= len;
1101 /* we need to save a new background because the width has changed */
1102 FREESURFACE(pBuf->gfx);
1103 } while(pBuf != pdialog->pdialog->pBeginActiveWidgetList);
1104 scroll = TRUE;
1105 }
1106
1107 /* redraw */
1108 if(redraw_all) {
1109 redraw_group(pdialog->pdialog->pBeginWidgetList, pWindow, 0);
1110 widget_mark_dirty(pWindow);
1111 } else {
1112 widget_redraw(pBuf);
1113 widget_mark_dirty(pBuf);
1114 }
1115
1116 } clause_list_iterate_end;
1117
1118 flush_dirty();
1119 }
1120
1121 /****************************************************************
1122 Remove widget related to clause from list of widgets.
1123 *****************************************************************/
remove_clause_widget_from_list(int counterpart,int giver,enum clause_type type,int value)1124 static void remove_clause_widget_from_list(int counterpart, int giver,
1125 enum clause_type type, int value)
1126 {
1127 struct widget *pBuf;
1128 SDL_Rect src = {0, 0, 0, 0};
1129 bool scroll = TRUE;
1130
1131 struct diplomacy_dialog *pdialog = get_diplomacy_dialog(counterpart);
1132
1133 /* find widget with clause */
1134 pBuf = pdialog->pdialog->pEndActiveWidgetList->next;
1135
1136 do {
1137 pBuf = pBuf->prev;
1138 } while(!((pBuf->data.cont->id0 == giver) &&
1139 (((pBuf->data.cont->value >> 16) & 0xFFFF) == (int)type) &&
1140 ((pBuf->data.cont->value & 0xFFFF) == value)) &&
1141 (pBuf != pdialog->pdialog->pBeginActiveWidgetList));
1142
1143 if(!(pBuf->data.cont->id0 == giver &&
1144 ((pBuf->data.cont->value >> 16) & 0xFFFF) == (int)type &&
1145 (pBuf->data.cont->value & 0xFFFF) == value)) {
1146 return;
1147 }
1148
1149 scroll = (pdialog->pdialog->pActiveWidgetList != NULL);
1150 del_widget_from_vertical_scroll_widget_list(pdialog->pdialog, pBuf);
1151
1152 if(scroll && (pdialog->pdialog->pActiveWidgetList == NULL)) {
1153 /* -> the scrollbar has been deactivated */
1154
1155 int len = pdialog->pdialog->pScroll->pUp_Left_Button->size.w;
1156 pBuf = pdialog->pdialog->pEndActiveWidgetList->next;
1157 do {
1158 pBuf = pBuf->prev;
1159 widget_undraw(pBuf);
1160 pBuf->size.w += len;
1161 /* we need to save a new background because the width has changed */
1162 FREESURFACE(pBuf->gfx);
1163 } while(pBuf != pdialog->pdialog->pBeginActiveWidgetList);
1164 scroll = FALSE;
1165 }
1166
1167 /* update state icons */
1168 pBuf = pdialog->pdialog->pEndWidgetList->prev;
1169 if(pBuf->private_data.cbox->state) {
1170 pBuf->private_data.cbox->state = FALSE;
1171 src.w = pBuf->private_data.cbox->pFALSE_Theme->w / 4;
1172 src.h = pBuf->private_data.cbox->pFALSE_Theme->h;
1173
1174 alphablit(pBuf->private_data.cbox->pFALSE_Theme, &src, pBuf->theme, NULL);
1175 }
1176
1177 }
1178
1179 /**************************************************************************
1180 Handle the start of a diplomacy meeting - usually by poping up a
1181 diplomacy dialog.
1182 **************************************************************************/
handle_diplomacy_init_meeting(int counterpart,int initiated_from)1183 void handle_diplomacy_init_meeting(int counterpart, int initiated_from)
1184 {
1185 struct diplomacy_dialog *pdialog;
1186
1187 if (!can_client_issue_orders()) {
1188 return;
1189 }
1190
1191 if (client.conn.playing->ai_controlled) {
1192 return; /* Don't show if we are AI controlled. */
1193 }
1194
1195 if (!(pdialog = get_diplomacy_dialog(counterpart))) {
1196 pdialog = create_diplomacy_dialog(client.conn.playing,
1197 player_by_number(counterpart));
1198 } else {
1199 /* bring existing dialog to front */
1200 sellect_window_group_dialog(pdialog->pdialog->pBeginWidgetList,
1201 pdialog->pdialog->pEndWidgetList);
1202 }
1203
1204 update_diplomacy_dialog(pdialog);
1205 }
1206
1207 /**************************************************************************
1208 Close diplomacy dialog between client user and given counterpart.
1209 **************************************************************************/
popdown_diplomacy_dialog(int counterpart)1210 static void popdown_diplomacy_dialog(int counterpart)
1211 {
1212 struct diplomacy_dialog *pdialog = get_diplomacy_dialog(counterpart);
1213
1214 if (pdialog) {
1215 popdown_window_group_dialog(pdialog->poffers->pBeginWidgetList,
1216 pdialog->poffers->pEndWidgetList);
1217 FC_FREE(pdialog->poffers->pScroll);
1218 FC_FREE(pdialog->poffers);
1219
1220 popdown_window_group_dialog(pdialog->pwants->pBeginWidgetList,
1221 pdialog->pwants->pEndWidgetList);
1222 FC_FREE(pdialog->pwants->pScroll);
1223 FC_FREE(pdialog->pwants);
1224
1225 popdown_window_group_dialog(pdialog->pdialog->pBeginWidgetList,
1226 pdialog->pdialog->pEndWidgetList);
1227
1228 dialog_list_remove(dialog_list, pdialog);
1229
1230 FC_FREE(pdialog->pdialog->pScroll);
1231 FC_FREE(pdialog->pdialog);
1232 FC_FREE(pdialog);
1233 }
1234 }
1235
1236 /**************************************************************************
1237 Popdown all diplomacy dialogs
1238 **************************************************************************/
popdown_diplomacy_dialogs(void)1239 static void popdown_diplomacy_dialogs(void)
1240 {
1241 dialog_list_iterate(dialog_list, pdialog) {
1242 popdown_diplomacy_dialog(player_number(pdialog->treaty.plr1));
1243 } dialog_list_iterate_end;
1244 }
1245
1246 /**************************************************************************
1247 Close all open diplomacy dialogs, for when client disconnects from game.
1248 **************************************************************************/
close_all_diplomacy_dialogs(void)1249 void close_all_diplomacy_dialogs(void)
1250 {
1251 popdown_sdip_dialog();
1252 popdown_diplomacy_dialogs();
1253 }
1254
1255 /* ================================================================= */
1256 /* ========================== Small Diplomat Dialog ================ */
1257 /* ================================================================= */
1258 static struct SMALL_DLG *pSDip_Dlg = NULL;
1259
1260 /**************************************************************************
1261 Close small diplomacy dialog.
1262 **************************************************************************/
popdown_sdip_dialog(void)1263 static void popdown_sdip_dialog(void)
1264 {
1265 if (pSDip_Dlg) {
1266 popdown_window_group_dialog(pSDip_Dlg->pBeginWidgetList,
1267 pSDip_Dlg->pEndWidgetList);
1268 FC_FREE(pSDip_Dlg);
1269 }
1270 }
1271
1272 /**************************************************************************
1273 User interacted with small diplomacy window.
1274 **************************************************************************/
sdip_window_callback(struct widget * pWindow)1275 static int sdip_window_callback(struct widget *pWindow)
1276 {
1277 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1278 move_window_group(pSDip_Dlg->pBeginWidgetList, pWindow);
1279 }
1280 return -1;
1281 }
1282
1283 /**************************************************************************
1284 User interacted with withdraw vision -widget.
1285 **************************************************************************/
withdraw_vision_dlg_callback(struct widget * pWidget)1286 static int withdraw_vision_dlg_callback(struct widget *pWidget)
1287 {
1288 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1289 popdown_sdip_dialog();
1290
1291 dsend_packet_diplomacy_cancel_pact(&client.conn,
1292 player_number(pWidget->data.player),
1293 CLAUSE_VISION);
1294
1295 flush_dirty();
1296 }
1297 return -1;
1298 }
1299
1300 /**************************************************************************
1301 User interacted with cancel pact -widget.
1302 **************************************************************************/
cancel_pact_dlg_callback(struct widget * pWidget)1303 static int cancel_pact_dlg_callback(struct widget *pWidget)
1304 {
1305 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1306 popdown_sdip_dialog();
1307
1308 dsend_packet_diplomacy_cancel_pact(&client.conn,
1309 player_number(pWidget->data.player),
1310 CLAUSE_CEASEFIRE);
1311
1312 flush_dirty();
1313 }
1314 return -1;
1315 }
1316
1317 /**************************************************************************
1318 User interacted with call meeting -widget.
1319 **************************************************************************/
call_meeting_dlg_callback(struct widget * pWidget)1320 static int call_meeting_dlg_callback(struct widget *pWidget)
1321 {
1322 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1323 popdown_sdip_dialog();
1324
1325 if (can_meet_with_player(pWidget->data.player)) {
1326 dsend_packet_diplomacy_init_meeting_req(&client.conn,
1327 player_number
1328 (pWidget->data.player));
1329 }
1330
1331 flush_dirty();
1332 }
1333 return -1;
1334 }
1335
1336 /**************************************************************************
1337 User interacted with cancel small diplomacy dialog -widget.
1338 **************************************************************************/
cancel_sdip_dlg_callback(struct widget * pWidget)1339 static int cancel_sdip_dlg_callback(struct widget *pWidget)
1340 {
1341 if (Main.event.button.button == SDL_BUTTON_LEFT) {
1342 popdown_sdip_dialog();
1343 flush_dirty();
1344 }
1345 return -1;
1346 }
1347
1348 /**************************************************************************
1349 Open war declaring dialog after some incident caused by pPlayer.
1350 **************************************************************************/
popup_war_dialog(struct player * pPlayer)1351 static void popup_war_dialog(struct player *pPlayer)
1352 {
1353 char cBuf[128];
1354 struct widget *pBuf = NULL, *pWindow;
1355 SDL_String16 *pStr;
1356 SDL_Surface *pText;
1357 SDL_Rect dst;
1358 SDL_Rect area;
1359
1360 if (pSDip_Dlg) {
1361 return;
1362 }
1363
1364 pSDip_Dlg = fc_calloc(1, sizeof(struct SMALL_DLG));
1365
1366 fc_snprintf(cBuf, sizeof(cBuf),
1367 /* TRANS: "Polish incident !" FIXME!!! */
1368 _("%s incident !"),
1369 nation_adjective_for_player(pPlayer));
1370 pStr = create_str16_from_char(cBuf, adj_font(12));
1371 pStr->style |= TTF_STYLE_BOLD;
1372
1373 pWindow = create_window_skeleton(NULL, pStr, 0);
1374
1375 pWindow->action = sdip_window_callback;
1376 set_wstate(pWindow, FC_WS_NORMAL);
1377
1378 add_to_gui_list(ID_WINDOW, pWindow);
1379
1380 pSDip_Dlg->pEndWidgetList = pWindow;
1381
1382 area = pWindow->area;
1383
1384 /* ============================================================= */
1385 /* label */
1386 fc_snprintf(cBuf, sizeof(cBuf), _("Shall we declare WAR on them?"));
1387
1388 pStr = create_str16_from_char(cBuf, adj_font(14));
1389 pStr->style |= (TTF_STYLE_BOLD|SF_CENTER);
1390 pStr->fgcol = *get_theme_color(COLOR_THEME_WARDLG_TEXT);
1391
1392 pText = create_text_surf_from_str16(pStr);
1393 FREESTRING16(pStr);
1394 area.w = MAX(area.w, pText->w);
1395 area.h += pText->h + adj_size(10);
1396
1397
1398 pBuf = create_themeicon_button_from_chars(current_theme->CANCEL_Icon,
1399 pWindow->dst, _("No"),
1400 adj_font(12), 0);
1401
1402 pBuf->action = cancel_sdip_dlg_callback;
1403 set_wstate(pBuf, FC_WS_NORMAL);
1404 pBuf->key = SDLK_ESCAPE;
1405 area.h += pBuf->size.h;
1406
1407 add_to_gui_list(ID_BUTTON, pBuf);
1408
1409 pBuf = create_themeicon_button_from_chars(current_theme->OK_Icon, pWindow->dst,
1410 _("Yes"), adj_font(12), 0);
1411
1412 pBuf->action = cancel_pact_dlg_callback;
1413 set_wstate(pBuf, FC_WS_NORMAL);
1414 pBuf->data.player = pPlayer;
1415 pBuf->key = SDLK_RETURN;
1416 add_to_gui_list(ID_BUTTON, pBuf);
1417 pBuf->size.w = MAX(pBuf->next->size.w, pBuf->size.w);
1418 pBuf->next->size.w = pBuf->size.w;
1419 area.w = MAX(area.w , 2 * pBuf->size.w + adj_size(20));
1420
1421 pSDip_Dlg->pBeginWidgetList = pBuf;
1422
1423 /* setup window size and start position */
1424 area.w += adj_size(10);
1425
1426 pBuf = pWindow->prev;
1427
1428 area.h += adj_size(5);
1429
1430 resize_window(pWindow, NULL, get_theme_color(COLOR_THEME_BACKGROUND),
1431 (pWindow->size.w - pWindow->area.w) + area.w,
1432 (pWindow->size.h - pWindow->area.h) + area.h);
1433
1434 area = pWindow->area;
1435
1436 widget_set_position(pWindow,
1437 (Main.screen->w - pWindow->size.w) / 2,
1438 (Main.screen->h - pWindow->size.h) / 2);
1439
1440 /* setup rest of widgets */
1441 /* label */
1442 dst.x = area.x + (area.w - pText->w) / 2;
1443 dst.y = area.y + 1;
1444 alphablit(pText, NULL, pWindow->theme, &dst);
1445 dst.y += pText->h + adj_size(5);
1446 FREESURFACE(pText);
1447
1448 /* no */
1449 pBuf = pWindow->prev;
1450 pBuf->size.y = dst.y;
1451
1452 /* yes */
1453 pBuf = pBuf->prev;
1454 pBuf->size.x = area.x + (area.w - (2 * pBuf->size.w + adj_size(20))) / 2;
1455 pBuf->size.y = dst.y;
1456
1457 /* no */
1458 pBuf->next->size.x = pBuf->size.x + pBuf->size.w + adj_size(20);
1459
1460 /* ================================================== */
1461 /* redraw */
1462 redraw_group(pSDip_Dlg->pBeginWidgetList, pWindow, 0);
1463 widget_mark_dirty(pWindow);
1464 flush_dirty();
1465 }
1466
1467 /* ===================================================================== */
1468
1469 /**************************************************************************
1470 Open diplomacy dialog between client user and given player.
1471 **************************************************************************/
popup_diplomacy_dialog(struct player * pPlayer)1472 void popup_diplomacy_dialog(struct player *pPlayer)
1473 {
1474 enum diplstate_type type =
1475 player_diplstate_get(client.conn.playing, pPlayer)->type;
1476
1477 if (!can_meet_with_player(pPlayer)) {
1478 if (DS_WAR == type || pPlayer == client.conn.playing) {
1479 flush_dirty();
1480 return;
1481 } else {
1482 popup_war_dialog(pPlayer);
1483 return;
1484 }
1485 } else {
1486 int button_w = 0, button_h = 0;
1487 char cBuf[128];
1488 struct widget *pBuf = NULL, *pWindow;
1489 SDL_String16 *pStr;
1490 SDL_Surface *pText;
1491 SDL_Rect dst;
1492 bool shared;
1493 SDL_Rect area;
1494 int buttons = 0;
1495 bool can_toward_war;
1496
1497 if (pSDip_Dlg) {
1498 return;
1499 }
1500
1501 pSDip_Dlg = fc_calloc(1, sizeof(struct SMALL_DLG));
1502
1503 fc_snprintf(cBuf, sizeof(cBuf), _("Foreign Minister"));
1504 pStr = create_str16_from_char(cBuf, adj_font(12));
1505 pStr->style |= TTF_STYLE_BOLD;
1506
1507 pWindow = create_window_skeleton(NULL, pStr, 0);
1508
1509 pWindow->action = sdip_window_callback;
1510 set_wstate(pWindow, FC_WS_NORMAL);
1511 pSDip_Dlg->pEndWidgetList = pWindow;
1512
1513 add_to_gui_list(ID_WINDOW, pWindow);
1514
1515 area = pWindow->area;
1516
1517 /* ============================================================= */
1518 /* label */
1519 if (client.conn.playing == NULL || client.conn.playing->is_male) {
1520 fc_snprintf(cBuf, sizeof(cBuf), _("Sir!, the %s ambassador has arrived\n"
1521 "What are your wishes?"),
1522 nation_adjective_for_player(pPlayer));
1523 } else {
1524 fc_snprintf(cBuf, sizeof(cBuf), _("Ma'am!, the %s ambassador has arrived\n"
1525 "What are your wishes?"),
1526 nation_adjective_for_player(pPlayer));
1527 }
1528
1529 pStr = create_str16_from_char(cBuf, adj_font(14));
1530 pStr->style |= (TTF_STYLE_BOLD|SF_CENTER);
1531 pStr->fgcol = *get_theme_color(COLOR_THEME_DIPLODLG_TEXT);
1532
1533 pText = create_text_surf_from_str16(pStr);
1534 FREESTRING16(pStr);
1535 area.w = MAX(area.w , pText->w);
1536 area.h += pText->h + adj_size(15);
1537
1538 can_toward_war = can_client_issue_orders()
1539 && pplayer_can_cancel_treaty(client_player(), pPlayer) == DIPL_OK;
1540
1541 if (can_toward_war) {
1542 if (type == DS_ARMISTICE) {
1543 fc_snprintf(cBuf, sizeof(cBuf), _("Declare WAR"));
1544 } else {
1545 fc_snprintf(cBuf, sizeof(cBuf), _("Cancel Treaty"));
1546 }
1547
1548 /* cancel treaty */
1549 pBuf = create_themeicon_button_from_chars(current_theme->UNITS2_Icon,
1550 pWindow->dst, cBuf, adj_font(12), 0);
1551
1552 pBuf->action = cancel_pact_dlg_callback;
1553 set_wstate(pBuf, FC_WS_NORMAL);
1554 pBuf->string16->fgcol = *get_theme_color(COLOR_THEME_DIPLODLG_MEETING_TEXT);
1555 pBuf->data.player = pPlayer;
1556 pBuf->key = SDLK_c;
1557 add_to_gui_list(ID_BUTTON, pBuf);
1558 pBuf->size.w = MAX(pBuf->next->size.w, pBuf->size.w);
1559 pBuf->next->size.w = pBuf->size.w;
1560 button_w = MAX(button_w , pBuf->size.w);
1561 button_h = MAX(button_h , pBuf->size.h);
1562 buttons++;
1563 }
1564
1565 shared = gives_shared_vision(client.conn.playing, pPlayer);
1566
1567 if (shared) {
1568 /* shared vision */
1569 pBuf = create_themeicon_button_from_chars(current_theme->UNITS2_Icon,
1570 pWindow->dst, _("Withdraw vision"),
1571 adj_font(12), 0);
1572
1573 pBuf->action = withdraw_vision_dlg_callback;
1574 set_wstate(pBuf, FC_WS_NORMAL);
1575 pBuf->data.player = pPlayer;
1576 pBuf->key = SDLK_w;
1577 pBuf->string16->fgcol = *get_theme_color(COLOR_THEME_DIPLODLG_MEETING_TEXT);
1578 add_to_gui_list(ID_BUTTON, pBuf);
1579 pBuf->size.w = MAX(pBuf->next->size.w, pBuf->size.w);
1580 pBuf->next->size.w = pBuf->size.w;
1581 button_w = MAX(button_w , pBuf->size.w);
1582 button_h = MAX(button_h , pBuf->size.h);
1583 buttons++;
1584 }
1585
1586 /* meet */
1587 pBuf = create_themeicon_button_from_chars(current_theme->PLAYERS_Icon,
1588 pWindow->dst,
1589 _("Call Diplomatic Meeting"),
1590 adj_font(12), 0);
1591
1592 pBuf->action = call_meeting_dlg_callback;
1593 set_wstate(pBuf, FC_WS_NORMAL);
1594 pBuf->data.player = pPlayer;
1595 pBuf->key = SDLK_m;
1596 pBuf->string16->fgcol = *get_theme_color(COLOR_THEME_DIPLODLG_MEETING_TEXT);
1597 add_to_gui_list(ID_BUTTON, pBuf);
1598 pBuf->size.w = MAX(pBuf->next->size.w, pBuf->size.w);
1599 pBuf->next->size.w = pBuf->size.w;
1600 button_w = MAX(button_w , pBuf->size.w);
1601 button_h = MAX(button_h , pBuf->size.h);
1602 buttons++;
1603
1604 pBuf = create_themeicon_button_from_chars(current_theme->CANCEL_Icon,
1605 pWindow->dst, _("Send him back"),
1606 adj_font(12), 0);
1607
1608 pBuf->action = cancel_sdip_dlg_callback;
1609 set_wstate(pBuf, FC_WS_NORMAL);
1610 pBuf->string16->fgcol = *get_theme_color(COLOR_THEME_DIPLODLG_MEETING_TEXT);
1611 pBuf->key = SDLK_ESCAPE;
1612 button_w = MAX(button_w , pBuf->size.w);
1613 button_h = MAX(button_h , pBuf->size.h);
1614 buttons++;
1615
1616 button_h += adj_size(4);
1617 area.w = MAX(area.w, button_w + adj_size(20));
1618
1619 area.h += buttons * (button_h + adj_size(10));
1620
1621 add_to_gui_list(ID_BUTTON, pBuf);
1622
1623
1624 pSDip_Dlg->pBeginWidgetList = pBuf;
1625
1626 /* setup window size and start position */
1627 area.w += adj_size(10);
1628
1629 pBuf = pWindow->prev;
1630
1631 area.h += adj_size(2);
1632
1633 resize_window(pWindow, NULL, get_theme_color(COLOR_THEME_BACKGROUND),
1634 (pWindow->size.w - pWindow->area.w) + area.w,
1635 (pWindow->size.h - pWindow->area.h) + area.h);
1636
1637 area = pWindow->area;
1638
1639 widget_set_position(pWindow,
1640 (Main.screen->w - pWindow->size.w) / 2,
1641 (Main.screen->h - pWindow->size.h) / 2);
1642
1643 /* setup rest of widgets */
1644 /* label */
1645 dst.x = area.x + (area.w - pText->w) / 2;
1646 dst.y = area.y + 1;
1647 alphablit(pText, NULL, pWindow->theme, &dst);
1648 dst.y += pText->h + adj_size(15);
1649 FREESURFACE(pText);
1650
1651 pBuf = pWindow;
1652
1653 /* war: meet, peace: cancel treaty */
1654 pBuf = pBuf->prev;
1655 pBuf->size.w = button_w;
1656 pBuf->size.h = button_h;
1657 pBuf->size.x = area.x + (area.w - (pBuf->size.w)) / 2;
1658 pBuf->size.y = dst.y;
1659
1660 if (shared) {
1661 /* vision */
1662 pBuf = pBuf->prev;
1663 pBuf->size.w = button_w;
1664 pBuf->size.h = button_h;
1665 pBuf->size.y = pBuf->next->size.y + pBuf->next->size.h + adj_size(10);
1666 pBuf->size.x = pBuf->next->size.x;
1667 }
1668
1669 if (type != DS_WAR) {
1670 /* meet */
1671 pBuf = pBuf->prev;
1672 pBuf->size.w = button_w;
1673 pBuf->size.h = button_h;
1674 pBuf->size.y = pBuf->next->size.y + pBuf->next->size.h + adj_size(10);
1675 pBuf->size.x = pBuf->next->size.x;
1676 }
1677
1678 /* cancel */
1679 if (can_toward_war) {
1680 pBuf = pBuf->prev;
1681 pBuf->size.w = button_w;
1682 pBuf->size.h = button_h;
1683 pBuf->size.y = pBuf->next->size.y + pBuf->next->size.h + adj_size(10);
1684 pBuf->size.x = pBuf->next->size.x;
1685 }
1686
1687 /* ================================================== */
1688 /* redraw */
1689 redraw_group(pSDip_Dlg->pBeginWidgetList, pWindow, 0);
1690 widget_mark_dirty(pWindow);
1691
1692 flush_dirty();
1693 }
1694 }
1695