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