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 #include <stdio.h>
19 #include <stdlib.h>
20 
21 #include <gtk/gtk.h>
22 
23 /* utility */
24 #include "log.h"
25 #include "mem.h"
26 #include "shared.h"
27 #include "support.h"
28 
29 /* common */
30 #include "diptreaty.h"
31 #include "fcintl.h"
32 #include "game.h"
33 #include "government.h"
34 #include "map.h"
35 #include "packets.h"
36 #include "player.h"
37 #include "research.h"
38 
39 /* client */
40 #include "chatline.h"
41 #include "client_main.h"
42 #include "climisc.h"
43 #include "options.h"
44 
45 /* client/gui-gtk-2.0 */
46 #include "diplodlg.h"
47 #include "gui_main.h"
48 #include "gui_stuff.h"
49 #include "mapview.h"
50 #include "plrdlg.h"
51 
52 #define MAX_NUM_CLAUSES 64
53 
54 struct Diplomacy_dialog {
55   struct Treaty treaty;
56   struct gui_dialog* dialog;
57 
58   GtkWidget *menu0;
59   GtkWidget *menu1;
60 
61   GtkWidget *image0;
62   GtkWidget *image1;
63 
64   GtkListStore *store;
65 };
66 
67 struct Diplomacy_notebook {
68   struct gui_dialog* dialog;
69   GtkWidget *notebook;
70 };
71 
72 #define SPECLIST_TAG dialog
73 #define SPECLIST_TYPE struct Diplomacy_dialog
74 #include "speclist.h"
75 
76 #define dialog_list_iterate(dialoglist, pdialog) \
77     TYPED_LIST_ITERATE(struct Diplomacy_dialog, dialoglist, pdialog)
78 #define dialog_list_iterate_end  LIST_ITERATE_END
79 
80 static struct dialog_list *dialog_list;
81 static struct Diplomacy_notebook *dipl_main;
82 
83 static struct Diplomacy_dialog *create_diplomacy_dialog(struct player *plr0,
84 						 struct player *plr1);
85 
86 static struct Diplomacy_dialog *find_diplomacy_dialog(int other_player_id);
87 static void popup_diplomacy_dialog(int other_player_id, int initiated_from);
88 static void diplomacy_dialog_map_callback(GtkWidget *w, gpointer data);
89 static void diplomacy_dialog_seamap_callback(GtkWidget *w, gpointer data);
90 static void diplomacy_dialog_tech_callback(GtkWidget *w, gpointer data);
91 static void diplomacy_dialog_city_callback(GtkWidget *w, gpointer data);
92 static void diplomacy_dialog_ceasefire_callback(GtkWidget *w, gpointer data);
93 static void diplomacy_dialog_peace_callback(GtkWidget *w, gpointer data);
94 static void diplomacy_dialog_alliance_callback(GtkWidget *w, gpointer data);
95 static void diplomacy_dialog_vision_callback(GtkWidget *w, gpointer data);
96 static void diplomacy_dialog_embassy_callback(GtkWidget *w, gpointer data);
97 static void close_diplomacy_dialog(struct Diplomacy_dialog *pdialog);
98 static void update_diplomacy_dialog(struct Diplomacy_dialog *pdialog);
99 static void diplo_dialog_returnkey(GtkWidget *w, gpointer data);
100 
101 static struct Diplomacy_notebook *diplomacy_main_create(void);
102 static void diplomacy_main_destroy(void);
103 static void diplomacy_main_response(struct gui_dialog *dlg, int response,
104                                     gpointer data);
105 
106 #define RESPONSE_CANCEL_MEETING 100
107 #define RESPONSE_CANCEL_MEETING_ALL 101
108 
109 /****************************************************************
110   Server tells us that either party has accepted treaty
111 *****************************************************************/
handle_diplomacy_accept_treaty(int counterpart,bool I_accepted,bool other_accepted)112 void handle_diplomacy_accept_treaty(int counterpart, bool I_accepted,
113 				    bool other_accepted)
114 {
115   struct Diplomacy_dialog *pdialog = find_diplomacy_dialog(counterpart);
116 
117   if (!pdialog) {
118     return;
119   }
120 
121   pdialog->treaty.accept0 = I_accepted;
122   pdialog->treaty.accept1 = other_accepted;
123 
124   update_diplomacy_dialog(pdialog);
125   gui_dialog_alert(pdialog->dialog);
126 }
127 
128 /****************************************************************
129   Someone is initiating meeting with us.
130 *****************************************************************/
handle_diplomacy_init_meeting(int counterpart,int initiated_from)131 void handle_diplomacy_init_meeting(int counterpart, int initiated_from)
132 {
133   popup_diplomacy_dialog(counterpart, initiated_from);
134 }
135 
136 
137 /****************************************************************
138   Meeting has been cancelled.
139 *****************************************************************/
handle_diplomacy_cancel_meeting(int counterpart,int initiated_from)140 void handle_diplomacy_cancel_meeting(int counterpart, int initiated_from)
141 {
142   struct Diplomacy_dialog *pdialog = find_diplomacy_dialog(counterpart);
143 
144   if (!pdialog) {
145     return;
146   }
147 
148   close_diplomacy_dialog(pdialog);
149 }
150 
151 /****************************************************************
152   Added clause to the meeting
153 *****************************************************************/
handle_diplomacy_create_clause(int counterpart,int giver,enum clause_type type,int value)154 void handle_diplomacy_create_clause(int counterpart, int giver,
155 				    enum clause_type type, int value)
156 {
157   struct Diplomacy_dialog *pdialog = find_diplomacy_dialog(counterpart);
158 
159   if (!pdialog) {
160     return;
161   }
162 
163   add_clause(&pdialog->treaty, player_by_number(giver), type, value);
164   update_diplomacy_dialog(pdialog);
165   gui_dialog_alert(pdialog->dialog);
166 }
167 
168 /****************************************************************
169   Removed clause from meeting.
170 *****************************************************************/
handle_diplomacy_remove_clause(int counterpart,int giver,enum clause_type type,int value)171 void handle_diplomacy_remove_clause(int counterpart, int giver,
172 				    enum clause_type type, int value)
173 {
174   struct Diplomacy_dialog *pdialog = find_diplomacy_dialog(counterpart);
175 
176   if (!pdialog) {
177     return;
178   }
179 
180   remove_clause(&pdialog->treaty, player_by_number(giver), type, value);
181   update_diplomacy_dialog(pdialog);
182   gui_dialog_alert(pdialog->dialog);
183 }
184 
185 /****************************************************************
186   Popup the dialog 10% inside the main-window
187 *****************************************************************/
popup_diplomacy_dialog(int other_player_id,int initiated_from)188 static void popup_diplomacy_dialog(int other_player_id, int initiated_from)
189 {
190   struct Diplomacy_dialog *pdialog = find_diplomacy_dialog(other_player_id);
191 
192   if (!can_client_issue_orders()) {
193     return;
194   }
195 
196   if (client.conn.playing->ai_controlled) {
197     return;			/* Don't show if we are AI controlled. */
198   }
199 
200   if (!pdialog) {
201     pdialog = create_diplomacy_dialog(client.conn.playing,
202 				      player_by_number(other_player_id));
203   }
204 
205   gui_dialog_present(pdialog->dialog);
206   /* We initated the meeting - Make the tab active */
207   if (player_by_number(initiated_from) == client.conn.playing) {
208     /* we have to raise the diplomacy meeting tab as well as the selected
209      * meeting. */
210     fc_assert_ret(dipl_main != NULL);
211     gui_dialog_raise(dipl_main->dialog);
212     gui_dialog_raise(pdialog->dialog);
213 
214     if (players_dialog_shell != NULL) {
215       gui_dialog_set_return_dialog(pdialog->dialog, players_dialog_shell);
216     }
217   }
218 }
219 
220 /****************************************************************************
221   Utility for g_list_sort(). See below.
222 ****************************************************************************/
sort_advance_names(gconstpointer a,gconstpointer b)223 static gint sort_advance_names(gconstpointer a, gconstpointer b)
224 {
225   const struct advance *padvance1 = (const struct advance *) a;
226   const struct advance *padvance2 = (const struct advance *) b;
227 
228   return fc_strcoll(advance_name_translation(padvance1),
229                     advance_name_translation(padvance2));
230 }
231 
232 /****************************************************************
233   Popup menu about adding clauses
234 *****************************************************************/
popup_add_menu(GtkMenuShell * parent,gpointer data)235 static void popup_add_menu(GtkMenuShell *parent, gpointer data)
236 {
237   struct Diplomacy_dialog *pdialog;
238   struct player *pgiver, *pother;
239   GtkWidget *item, *menu;
240 
241 
242   /* init. */
243   gtk_container_foreach(GTK_CONTAINER(parent),
244                         (GtkCallback) gtk_widget_destroy, NULL);
245 
246   pdialog = (struct Diplomacy_dialog *) data;
247   pgiver = (struct player *) g_object_get_data(G_OBJECT(parent), "plr");
248   pother = (pgiver == pdialog->treaty.plr0
249             ? pdialog->treaty.plr1 : pdialog->treaty.plr0);
250 
251 
252   /* Maps. */
253   menu = gtk_menu_new();
254   item = gtk_menu_item_new_with_mnemonic(_("World-map"));
255   gtk_menu_shell_append(GTK_MENU_SHELL(menu),item);
256   g_object_set_data(G_OBJECT(item), "plr", pgiver);
257   g_signal_connect(item, "activate",
258 		   G_CALLBACK(diplomacy_dialog_map_callback), pdialog);
259 
260   item = gtk_menu_item_new_with_mnemonic(_("Sea-map"));
261   gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
262   g_object_set_data(G_OBJECT(item), "plr", pgiver);
263   g_signal_connect(item, "activate",
264 		   G_CALLBACK(diplomacy_dialog_seamap_callback), pdialog);
265 
266   item = gtk_menu_item_new_with_mnemonic(_("_Maps"));
267   gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), menu);
268   gtk_menu_shell_append(GTK_MENU_SHELL(parent), item);
269   gtk_widget_show_all(item);
270 
271   /* Trading: advances */
272   if (game.info.trading_tech) {
273     const struct research *gresearch = research_get(pgiver);
274     const struct research *oresearch = research_get(pother);
275     GtkWidget *advance_item;
276     GList *sorting_list = NULL;
277 
278     advance_item = gtk_menu_item_new_with_mnemonic(_("_Advances"));
279     gtk_menu_shell_append(GTK_MENU_SHELL(parent), advance_item);
280 
281     advance_iterate(A_FIRST, padvance) {
282       Tech_type_id i = advance_number(padvance);
283 
284       if (research_invention_state(gresearch, i) == TECH_KNOWN
285           && research_invention_gettable(oresearch, i,
286                                          game.info.tech_trade_allow_holes)
287           && (research_invention_state(oresearch, i) == TECH_UNKNOWN
288               || research_invention_state(oresearch, i)
289                  == TECH_PREREQS_KNOWN)) {
290         sorting_list = g_list_prepend(sorting_list, padvance);
291       }
292     } advance_iterate_end;
293 
294     if (NULL == sorting_list) {
295       /* No advance. */
296       gtk_widget_set_sensitive(advance_item, FALSE);
297     } else {
298       GList *list_item;
299       const struct advance *padvance;
300 
301       sorting_list = g_list_sort(sorting_list, sort_advance_names);
302       menu = gtk_menu_new();
303 
304       /* TRANS: All technologies menu item in the diplomatic dialog. */
305       item = gtk_menu_item_new_with_label(_("All advances"));
306       gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
307       g_object_set_data(G_OBJECT(item), "player_from",
308                         GINT_TO_POINTER(player_number(pgiver)));
309       g_object_set_data(G_OBJECT(item), "player_to",
310                         GINT_TO_POINTER(player_number(pother)));
311       g_signal_connect(item, "activate",
312                        G_CALLBACK(diplomacy_dialog_tech_callback),
313                        GINT_TO_POINTER(A_LAST));
314       gtk_menu_shell_append(GTK_MENU_SHELL(menu),
315                             gtk_separator_menu_item_new());
316 
317       for (list_item = sorting_list; NULL != list_item;
318            list_item = g_list_next(list_item)) {
319         padvance = (const struct advance *) list_item->data;
320         item =
321             gtk_menu_item_new_with_label(advance_name_translation(padvance));
322         gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
323         g_object_set_data(G_OBJECT(item), "player_from",
324                           GINT_TO_POINTER(player_number(pgiver)));
325         g_object_set_data(G_OBJECT(item), "player_to",
326                           GINT_TO_POINTER(player_number(pother)));
327         g_signal_connect(item, "activate",
328                          G_CALLBACK(diplomacy_dialog_tech_callback),
329                          GINT_TO_POINTER(advance_number(padvance)));
330       }
331 
332       gtk_menu_item_set_submenu(GTK_MENU_ITEM(advance_item), menu);
333       g_list_free(sorting_list);
334     }
335 
336     gtk_widget_show_all(advance_item);
337   }
338 
339 
340   /* Trading: cities. */
341 
342   /****************************************************************
343   Creates a sorted list of plr0's cities, excluding the capital and
344   any cities not visible to plr1.  This means that you can only trade
345   cities visible to requesting player.
346 
347 			      - Kris Bubendorfer
348   *****************************************************************/
349   if (game.info.trading_city) {
350     int i = 0, j = 0, n = city_list_size(pgiver->cities);
351     struct city **city_list_ptrs;
352 
353     if (n > 0) {
354       city_list_ptrs = fc_malloc(sizeof(struct city *) * n);
355     } else {
356       city_list_ptrs = NULL;
357     }
358 
359     city_list_iterate(pgiver->cities, pcity) {
360       if (!is_capital(pcity)) {
361 	city_list_ptrs[i] = pcity;
362 	i++;
363       }
364     } city_list_iterate_end;
365 
366     qsort(city_list_ptrs, i, sizeof(struct city *), city_name_compare);
367 
368     menu = gtk_menu_new();
369 
370     for (j = 0; j < i; j++) {
371       item = gtk_menu_item_new_with_label(city_name_get(city_list_ptrs[j]));
372 
373       gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
374       g_signal_connect(item, "activate",
375 		       G_CALLBACK(diplomacy_dialog_city_callback),
376 			 GINT_TO_POINTER((player_number(pgiver) << 24) |
377 					 (player_number(pother) << 16) |
378 					 city_list_ptrs[j]->id));
379     }
380     free(city_list_ptrs);
381 
382     item = gtk_menu_item_new_with_mnemonic(_("_Cities"));
383     gtk_widget_set_sensitive(item, (i > 0));
384     gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), menu);
385     gtk_menu_shell_append(GTK_MENU_SHELL(parent), item);
386     gtk_widget_show_all(item);
387   }
388 
389 
390   /* Give shared vision. */
391   item = gtk_menu_item_new_with_mnemonic(_("_Give shared vision"));
392   g_object_set_data(G_OBJECT(item), "plr", pgiver);
393   g_signal_connect(item, "activate",
394 		   G_CALLBACK(diplomacy_dialog_vision_callback), pdialog);
395 
396   if (gives_shared_vision(pgiver, pother)) {
397     gtk_widget_set_sensitive(item, FALSE);
398   }
399   gtk_menu_shell_append(GTK_MENU_SHELL(parent), item);
400   gtk_widget_show(item);
401 
402 
403   /* Give embassy. */
404   item = gtk_menu_item_new_with_mnemonic(_("Give _embassy"));
405   g_object_set_data(G_OBJECT(item), "plr", pgiver);
406   g_signal_connect(item, "activate",
407 		   G_CALLBACK(diplomacy_dialog_embassy_callback), pdialog);
408 
409   /* Don't take in account the embassy effects. */
410   if (player_has_real_embassy(pother, pgiver)) {
411     gtk_widget_set_sensitive(item, FALSE);
412   }
413   gtk_menu_shell_append(GTK_MENU_SHELL(parent), item);
414   gtk_widget_show(item);
415 
416 
417   /* Pacts. */
418   if (pgiver == pdialog->treaty.plr0) {
419     enum diplstate_type ds;
420 
421     ds = player_diplstate_get(pgiver, pother)->type;
422 
423     menu = gtk_menu_new();
424     item = gtk_menu_item_new_with_mnemonic(Q_("?diplomatic_state:Cease-fire"));
425     gtk_menu_shell_append(GTK_MENU_SHELL(menu),item);
426     g_signal_connect(item, "activate",
427 		     G_CALLBACK(diplomacy_dialog_ceasefire_callback), pdialog);
428     gtk_widget_set_sensitive(item, ds != DS_CEASEFIRE && ds != DS_TEAM);
429 
430     item = gtk_menu_item_new_with_mnemonic(Q_("?diplomatic_state:Peace"));
431     gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
432     g_signal_connect(item, "activate",
433 		     G_CALLBACK(diplomacy_dialog_peace_callback), pdialog);
434     gtk_widget_set_sensitive(item, ds != DS_PEACE && ds != DS_TEAM);
435 
436     item = gtk_menu_item_new_with_mnemonic(Q_("?diplomatic_state:Alliance"));
437     gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
438     g_signal_connect(item, "activate",
439 		     G_CALLBACK(diplomacy_dialog_alliance_callback), pdialog);
440     gtk_widget_set_sensitive(item, ds != DS_ALLIANCE && ds != DS_TEAM);
441 
442     item = gtk_menu_item_new_with_mnemonic(_("_Pacts"));
443     gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), menu);
444     gtk_menu_shell_append(GTK_MENU_SHELL(parent), item);
445     gtk_widget_show_all(item);
446   }
447 }
448 
449 /****************************************************************
450   Some clause activated
451 *****************************************************************/
row_callback(GtkTreeView * view,GtkTreePath * path,GtkTreeViewColumn * col,gpointer data)452 static void row_callback(GtkTreeView *view, GtkTreePath *path,
453 			 GtkTreeViewColumn *col, gpointer data)
454 {
455   struct Diplomacy_dialog *pdialog = (struct Diplomacy_dialog *)data;
456   gint i;
457   gint *index;
458 
459   index = gtk_tree_path_get_indices(path);
460 
461   i = 0;
462   clause_list_iterate(pdialog->treaty.clauses, pclause) {
463     if (i == index[0]) {
464       dsend_packet_diplomacy_remove_clause_req(&client.conn,
465 					       player_number(pdialog->treaty.plr1),
466 					       player_number(pclause->from),
467 					       pclause->type,
468 					       pclause->value);
469       return;
470     }
471     i++;
472   } clause_list_iterate_end;
473 }
474 
475 /*****************************************************************************
476   Create the main tab for diplomatic meetings.
477 *****************************************************************************/
diplomacy_main_create(void)478 static struct Diplomacy_notebook *diplomacy_main_create(void)
479 {
480   /* Collect all meetings in one main tab. */
481   if (!dipl_main) {
482     GtkWidget *dipl_box, *dipl_sw;
483 
484     dipl_main = fc_malloc(sizeof(*dipl_main));
485     gui_dialog_new(&(dipl_main->dialog), GTK_NOTEBOOK(top_notebook),
486                   dipl_main->dialog, TRUE);
487     dipl_main->notebook = gtk_notebook_new();
488     gtk_notebook_set_tab_pos(GTK_NOTEBOOK(dipl_main->notebook),
489                              GTK_POS_RIGHT);
490     gtk_notebook_set_scrollable(GTK_NOTEBOOK(dipl_main->notebook), TRUE);
491 
492     dipl_sw = gtk_scrolled_window_new(NULL, NULL);
493     gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(dipl_sw),
494                                    GTK_POLICY_AUTOMATIC,
495                                    GTK_POLICY_AUTOMATIC);
496     gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(dipl_sw),
497                                           dipl_main->notebook);
498 
499     /* Buttons */
500     gui_dialog_add_stockbutton(dipl_main->dialog, GTK_STOCK_CANCEL,
501                                _("Cancel _all meetings"),
502                                RESPONSE_CANCEL_MEETING_ALL);
503 
504     /* Responces for _all_ meetings. */
505     gui_dialog_response_set_callback(dipl_main->dialog,
506                                      diplomacy_main_response);
507     gui_dialog_set_default_response(dipl_main->dialog,
508                                     RESPONSE_CANCEL_MEETING_ALL);
509 
510     dipl_box = dipl_main->dialog->vbox;
511     gtk_box_pack_start(GTK_BOX(dipl_box), dipl_sw, TRUE, TRUE, 2);
512 
513     gui_dialog_show_all(dipl_main->dialog);
514     gui_dialog_present(dipl_main->dialog);
515   }
516 
517   return dipl_main;
518 }
519 
520 /*****************************************************************************
521   Destroy main diplomacy dialog.
522 *****************************************************************************/
diplomacy_main_destroy(void)523 static void diplomacy_main_destroy(void)
524 {
525   if (dipl_main->dialog) {
526     gui_dialog_destroy(dipl_main->dialog);
527   }
528   free(dipl_main);
529   dipl_main = NULL;
530 }
531 
532 /*****************************************************************************
533   User has responded to whole diplomacy dialog (main tab).
534 *****************************************************************************/
diplomacy_main_response(struct gui_dialog * dlg,int response,gpointer data)535 static void diplomacy_main_response(struct gui_dialog *dlg, int response,
536                                     gpointer data)
537 {
538   if (!dipl_main) {
539     return;
540   }
541 
542   switch (response) {
543   default:
544     log_error("unhandled response in %s: %d", __FUNCTION__, response);
545     fc__fallthrough; /* No break. */
546   case GTK_RESPONSE_DELETE_EVENT:   /* GTK: delete the widget. */
547   case RESPONSE_CANCEL_MEETING_ALL: /* Cancel all meetings. */
548     dialog_list_iterate(dialog_list, adialog) {
549       /* This will do a round trip to the server ans close the diolag in the
550        * client. Closing the last dialog will also close the main tab.*/
551       dsend_packet_diplomacy_cancel_meeting_req(&client.conn,
552                                                 player_number(
553                                                   adialog->treaty.plr1));
554     } dialog_list_iterate_end;
555     break;
556   }
557 }
558 
559 /****************************************************************
560   Destroy diplomacy dialog
561 *****************************************************************/
diplomacy_destroy(struct Diplomacy_dialog * pdialog)562 static void diplomacy_destroy(struct Diplomacy_dialog* pdialog)
563 {
564   if (NULL != pdialog->dialog) {
565     /* pdialog->dialog may be NULL if the tab have been destroyed
566      * by an other way. */
567     gui_dialog_destroy(pdialog->dialog);
568   }
569   dialog_list_remove(dialog_list, pdialog);
570   free(pdialog);
571 
572   if (dialog_list) {
573     /* Diplomatic meetings in one main tab. */
574     if (dialog_list_size(dialog_list) > 0) {
575       if (dipl_main && dipl_main->dialog) {
576         gchar *buf;
577 
578         buf = g_strdup_printf(_("Diplomacy [%d]"), dialog_list_size(dialog_list));
579         gui_dialog_set_title(dipl_main->dialog, buf);
580         g_free(buf);
581       }
582     } else if (dipl_main) {
583       /* No meeting left - destroy main tab. */
584       diplomacy_main_destroy();
585     }
586   }
587 }
588 
589 /*****************************************************************************
590   User has responded to whole diplomacy dialog (one meeting).
591 *****************************************************************************/
diplomacy_response(struct gui_dialog * dlg,int response,gpointer data)592 static void diplomacy_response(struct gui_dialog *dlg, int response,
593                                gpointer data)
594 {
595   struct Diplomacy_dialog *pdialog = NULL;
596 
597   fc_assert_ret(data);
598   pdialog = (struct Diplomacy_dialog *)data;
599 
600   switch (response) {
601   case GTK_RESPONSE_ACCEPT:         /* Accept treaty. */
602     dsend_packet_diplomacy_accept_treaty_req(&client.conn,
603                                              player_number(
604                                                pdialog->treaty.plr1));
605     break;
606 
607   default:
608     log_error("unhandled response in %s: %d", __FUNCTION__, response);
609     fc__fallthrough; /* No break. */
610   case GTK_RESPONSE_DELETE_EVENT:   /* GTK: delete the widget. */
611   case GTK_RESPONSE_CANCEL:         /* GTK: cancel button. */
612   case RESPONSE_CANCEL_MEETING:     /* Cancel meetings. */
613     dsend_packet_diplomacy_cancel_meeting_req(&client.conn,
614                                               player_number(
615                                                 pdialog->treaty.plr1));
616     break;
617   }
618 }
619 
620 /*****************************************************************************
621   Setups diplomacy dialog widgets.
622 *****************************************************************************/
create_diplomacy_dialog(struct player * plr0,struct player * plr1)623 static struct Diplomacy_dialog *create_diplomacy_dialog(struct player *plr0,
624                                                         struct player *plr1)
625 {
626   struct Diplomacy_notebook *dipl_dialog;
627   GtkWidget *vbox, *hbox, *table, *align, *mainbox;
628   GtkWidget *label, *sw, *view, *image, *spin;
629   GtkWidget *menubar, *menuitem, *menu, *notebook;
630   GtkListStore *store;
631   GtkCellRenderer *rend;
632   int i;
633 
634   struct Diplomacy_dialog *pdialog;
635   char plr_buf[4 * MAX_LEN_NAME];
636   gchar *buf;
637 
638   pdialog = fc_malloc(sizeof(*pdialog));
639 
640   dialog_list_prepend(dialog_list, pdialog);
641   init_treaty(&pdialog->treaty, plr0, plr1);
642 
643   /* Get main diplomacy tab. */
644   dipl_dialog = diplomacy_main_create();
645 
646   buf = g_strdup_printf(_("Diplomacy [%d]"), dialog_list_size(dialog_list));
647   gui_dialog_set_title(dipl_dialog->dialog, buf);
648   g_free(buf);
649 
650   notebook = dipl_dialog->notebook;
651 
652   gui_dialog_new(&(pdialog->dialog), GTK_NOTEBOOK(notebook), pdialog, FALSE);
653 
654   /* Buttons */
655   gui_dialog_add_stockbutton(pdialog->dialog, GTK_STOCK_CANCEL,
656                              _("Cancel meeting"), RESPONSE_CANCEL_MEETING);
657   gui_dialog_add_stockbutton(pdialog->dialog, GTK_STOCK_DND,
658                              _("Accept treaty"), GTK_RESPONSE_ACCEPT);
659 
660   /* Responces for one meeting. */
661   gui_dialog_response_set_callback(pdialog->dialog, diplomacy_response);
662   gui_dialog_set_default_response(pdialog->dialog, RESPONSE_CANCEL_MEETING);
663 
664   /* Label for the new meeting. */
665   buf = g_strdup_printf("%s", nation_plural_for_player(plr1));
666   gui_dialog_set_title(pdialog->dialog, buf);
667 
668   /* Sort meeting tabs alphabetically by the tab label. */
669   for (i = 0; i < gtk_notebook_get_n_pages(GTK_NOTEBOOK(notebook)); i++) {
670     GtkWidget *prev_page
671       = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), i);
672     struct gui_dialog *prev_dialog
673       = g_object_get_data(G_OBJECT(prev_page), "gui-dialog-data");
674     const char *prev_label
675       = gtk_label_get_text(GTK_LABEL(prev_dialog->v.tab.label));
676 
677     if (fc_strcasecmp(buf, prev_label) < 0) {
678       gtk_notebook_reorder_child(GTK_NOTEBOOK(notebook),
679                                  pdialog->dialog->vbox, i);
680       break;
681     }
682   }
683   g_free(buf);
684 
685   /* Content. */
686   mainbox = pdialog->dialog->vbox;
687 
688   /* us. */
689   vbox = gtk_vbox_new(FALSE, 5);
690   gtk_container_set_border_width(GTK_CONTAINER(vbox), 2);
691   gtk_box_pack_start(GTK_BOX(mainbox), vbox, FALSE, FALSE, 0);
692 
693   /* Our nation. */
694   label = gtk_label_new(NULL);
695   gtk_misc_set_alignment(GTK_MISC(label), 0.5, 0.5);
696   buf = g_strdup_printf("<span size=\"large\"><u>%s</u></span>",
697                         nation_plural_for_player(plr0));
698   gtk_label_set_markup(GTK_LABEL(label), buf);
699   g_free(buf);
700   gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
701 
702   hbox = gtk_hbox_new(FALSE, 5);
703   gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
704 
705   /* Our flag */
706   image =
707       gtk_image_new_from_pixbuf(sprite_get_pixbuf
708 				(get_nation_flag_sprite
709 				 (tileset, nation_of_player(plr0))));
710   gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0);
711 
712   /* Our name. */
713   label = gtk_label_new(NULL);
714   gtk_misc_set_alignment(GTK_MISC(label), 0.5, 0.5);
715   buf = g_strdup_printf("<span size=\"large\" weight=\"bold\">%s</span>",
716                         ruler_title_for_player(plr0, plr_buf, sizeof(plr_buf)));
717   gtk_label_set_markup(GTK_LABEL(label), buf);
718   g_free(buf);
719   gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
720 
721   image = gtk_image_new();
722   pdialog->image0 = image;
723   gtk_box_pack_end(GTK_BOX(hbox), image, FALSE, FALSE, 0);
724 
725   /* Menu for clauses: we. */
726   menubar = gtk_aux_menu_bar_new();
727 
728   menu = gtk_menu_new();
729   pdialog->menu0 = menu;
730 
731   menuitem = gtk_image_menu_item_new_with_label(_("Add Clause..."));
732   gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem),
733                                 gtk_image_new_from_stock(GTK_STOCK_ADD,
734                                                          GTK_ICON_SIZE_MENU));
735   gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), menu);
736   gtk_menu_shell_append(GTK_MENU_SHELL(menubar), menuitem);
737   g_object_set_data(G_OBJECT(menu), "plr", plr0);
738   g_signal_connect(menu, "show", G_CALLBACK(popup_add_menu), pdialog);
739 
740   /* Main table for clauses and (if activated) gold trading: we. */
741   align = gtk_alignment_new (0.5, 0.5, 0, 0);
742   gtk_box_pack_start(GTK_BOX(vbox), align, FALSE, TRUE, 0);
743 
744   if (game.info.trading_gold) {
745     table = gtk_table_new(1, 3, FALSE);
746     gtk_table_set_col_spacings(GTK_TABLE(table), 16);
747     gtk_container_add(GTK_CONTAINER(align), table);
748 
749     spin = gtk_spin_button_new_with_range(0.0, plr0->economic.gold + 0.1,
750                                           1.0);
751     gtk_spin_button_set_digits(GTK_SPIN_BUTTON(spin), 0);
752     gtk_entry_set_width_chars(GTK_ENTRY(spin), 16);
753     gtk_table_attach_defaults(GTK_TABLE(table), spin, 1, 2, 0, 1);
754     g_object_set_data(G_OBJECT(spin), "plr", plr0);
755     g_signal_connect_after(spin, "value-changed",
756                            G_CALLBACK(diplo_dialog_returnkey), pdialog);
757 
758     label = g_object_new(GTK_TYPE_LABEL, "use-underline", TRUE,
759                          "mnemonic-widget", spin, "label", _("Gold:"),
760                          "xalign", 0.0, "yalign", 0.5, NULL);
761     gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 0, 1);
762 
763     gtk_table_attach_defaults(GTK_TABLE(table), menubar, 2, 3, 0, 1);
764   } else {
765     table = gtk_table_new(1, 1, FALSE);
766     gtk_table_set_col_spacings(GTK_TABLE(table), 16);
767     gtk_container_add(GTK_CONTAINER(align), table);
768 
769     gtk_table_attach_defaults(GTK_TABLE(table), menubar, 0, 1, 0, 1);
770   }
771 
772   /* them. */
773   vbox = gtk_vbox_new(FALSE, 5);
774   gtk_container_set_border_width(GTK_CONTAINER(vbox), 2);
775   gtk_box_pack_start(GTK_BOX(mainbox), vbox, FALSE, FALSE, 0);
776 
777   /* Their nation. */
778   label = gtk_label_new(NULL);
779   gtk_misc_set_alignment(GTK_MISC(label), 0.5, 0.5);
780   buf = g_strdup_printf("<span size=\"large\"><u>%s</u></span>",
781                         nation_plural_for_player(plr1));
782   gtk_label_set_markup(GTK_LABEL(label), buf);
783   g_free(buf);
784   gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
785 
786   hbox = gtk_hbox_new(FALSE, 5);
787   gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
788 
789   /* Their flag */
790   image =
791       gtk_image_new_from_pixbuf(sprite_get_pixbuf
792 				(get_nation_flag_sprite
793 				 (tileset, nation_of_player(plr1))));
794   gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0);
795 
796   /* Their name. */
797   label = gtk_label_new(NULL);
798   gtk_misc_set_alignment(GTK_MISC(label), 0.5, 0.5);
799   buf = g_strdup_printf("<span size=\"large\" weight=\"bold\">%s</span>",
800                         ruler_title_for_player(plr1, plr_buf, sizeof(plr_buf)));
801   gtk_label_set_markup(GTK_LABEL(label), buf);
802   g_free(buf);
803   gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
804 
805   image = gtk_image_new();
806   pdialog->image1 = image;
807   gtk_box_pack_end(GTK_BOX(hbox), image, FALSE, FALSE, 0);
808 
809   /* Menu for clauses: they. */
810   menubar = gtk_aux_menu_bar_new();
811 
812   menu = gtk_menu_new();
813   pdialog->menu1 = menu;
814 
815   menuitem = gtk_image_menu_item_new_with_label(_("Add Clause..."));
816   gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem),
817                                 gtk_image_new_from_stock(GTK_STOCK_ADD,
818                                                          GTK_ICON_SIZE_MENU));
819   gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), menu);
820   gtk_menu_shell_append(GTK_MENU_SHELL(menubar), menuitem);
821   g_object_set_data(G_OBJECT(menu), "plr", plr1);
822   g_signal_connect(menu, "show", G_CALLBACK(popup_add_menu), pdialog);
823 
824   /* Main table for clauses and (if activated) gold trading: they. */
825   align = gtk_alignment_new (0.5, 0.5, 0, 0);
826   gtk_box_pack_start(GTK_BOX(vbox), align, FALSE, TRUE, 0);
827 
828   if (game.info.trading_gold) {
829     table = gtk_table_new(1, 3, FALSE);
830     gtk_table_set_col_spacings(GTK_TABLE(table), 16);
831     gtk_container_add(GTK_CONTAINER(align), table);
832 
833     spin = gtk_spin_button_new_with_range(0.0, plr1->economic.gold + 0.1,
834                                           1.0);
835     gtk_spin_button_set_digits(GTK_SPIN_BUTTON(spin), 0);
836     gtk_entry_set_width_chars(GTK_ENTRY(spin), 16);
837     gtk_table_attach_defaults(GTK_TABLE(table), spin, 1, 2, 0, 1);
838     g_object_set_data(G_OBJECT(spin), "plr", plr1);
839     g_signal_connect_after(spin, "value-changed",
840                            G_CALLBACK(diplo_dialog_returnkey), pdialog);
841 
842     label = g_object_new(GTK_TYPE_LABEL, "use-underline", TRUE,
843                          "mnemonic-widget", spin, "label", _("Gold:"),
844                          "xalign", 0.0, "yalign", 0.5, NULL);
845     gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 0, 1);
846 
847     gtk_table_attach_defaults(GTK_TABLE(table), menubar, 2, 3, 0, 1);
848   } else {
849     table = gtk_table_new(1, 1, FALSE);
850     gtk_table_set_col_spacings(GTK_TABLE(table), 16);
851     gtk_container_add(GTK_CONTAINER(align), table);
852 
853     gtk_table_attach_defaults(GTK_TABLE(table), menubar, 0, 1, 0, 1);
854   }
855 
856   /* Clauses. */
857   mainbox = gtk_vbox_new(FALSE, 0);
858   gtk_box_pack_start(GTK_BOX(pdialog->dialog->vbox), mainbox, TRUE, TRUE, 0);
859 
860   store = gtk_list_store_new(1, G_TYPE_STRING);
861   pdialog->store = store;
862 
863   view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
864   gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), FALSE);
865   g_object_unref(store);
866   gtk_widget_set_size_request(view, 320, 100);
867 
868   rend = gtk_cell_renderer_text_new();
869   gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view), -1, NULL,
870     rend, "text", 0, NULL);
871 
872   sw = gtk_scrolled_window_new(NULL, NULL);
873   gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw),
874                                       GTK_SHADOW_ETCHED_IN);
875   gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
876                                  GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
877   gtk_container_add(GTK_CONTAINER(sw), view);
878 
879   label = g_object_new(GTK_TYPE_LABEL,
880     "use-underline", TRUE,
881     "mnemonic-widget", view,
882     "label", _("C_lauses:"),
883     "xalign", 0.0,
884     "yalign", 0.5,
885     NULL);
886 
887   vbox = gtk_vbox_new(FALSE, 0);
888   gtk_box_pack_start(GTK_BOX(mainbox), vbox, TRUE, TRUE, 0);
889   gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
890   gtk_box_pack_start(GTK_BOX(vbox), sw, TRUE, TRUE, 2);
891 
892   gtk_widget_show_all(mainbox);
893 
894   g_signal_connect(view, "row_activated", G_CALLBACK(row_callback), pdialog);
895 
896   update_diplomacy_dialog(pdialog);
897   gui_dialog_show_all(pdialog->dialog);
898 
899   return pdialog;
900 }
901 
902 /**************************************************************************
903   Update diplomacy dialog
904 **************************************************************************/
update_diplomacy_dialog(struct Diplomacy_dialog * pdialog)905 static void update_diplomacy_dialog(struct Diplomacy_dialog *pdialog)
906 {
907   GtkListStore *store;
908   GtkTreeIter it;
909   bool blank = TRUE;
910 
911   store = pdialog->store;
912 
913   gtk_list_store_clear(store);
914   clause_list_iterate(pdialog->treaty.clauses, pclause) {
915     char buf[128];
916 
917     client_diplomacy_clause_string(buf, sizeof(buf), pclause);
918 
919     gtk_list_store_append(store, &it);
920     gtk_list_store_set(store, &it, 0, buf, -1);
921     blank = FALSE;
922   } clause_list_iterate_end;
923 
924   if (blank) {
925     gtk_list_store_append(store, &it);
926     gtk_list_store_set(store, &it, 0,
927 		       _("--- This treaty is blank. "
928 		 	 "Please add some clauses. ---"), -1);
929   }
930 
931   gtk_image_set_from_pixbuf(GTK_IMAGE(pdialog->image0),
932 			    get_thumb_pixbuf(pdialog->treaty.accept0));
933   gtk_image_set_from_pixbuf(GTK_IMAGE(pdialog->image1),
934 			    get_thumb_pixbuf(pdialog->treaty.accept1));
935 }
936 
937 /****************************************************************************
938   Callback for the diplomatic dialog: give tech.
939 ****************************************************************************/
diplomacy_dialog_tech_callback(GtkWidget * w,gpointer data)940 static void diplomacy_dialog_tech_callback(GtkWidget *w, gpointer data)
941 {
942   int giver, dest, other, tech;
943 
944   giver = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w), "player_from"));
945   dest = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w), "player_to"));
946   tech = GPOINTER_TO_INT(data);
947   if (player_by_number(giver) == client_player()) {
948     other = dest;
949   } else {
950     other = giver;
951   }
952 
953   if (A_LAST == tech) {
954     /* All techs. */
955     struct player *pgiver = player_by_number(giver);
956     struct player *pdest = player_by_number(dest);
957     const struct research *dresearch, *gresearch;
958 
959     fc_assert_ret(NULL != pgiver);
960     fc_assert_ret(NULL != pdest);
961 
962     dresearch = research_get(pdest);
963     gresearch = research_get(pgiver);
964     advance_iterate(A_FIRST, padvance) {
965       Tech_type_id i = advance_number(padvance);
966 
967       if (research_invention_state(gresearch, i) == TECH_KNOWN
968           && research_invention_gettable(dresearch, i,
969                                          game.info.tech_trade_allow_holes)
970           && (research_invention_state(dresearch, i) == TECH_UNKNOWN
971               || research_invention_state(dresearch, i)
972                  == TECH_PREREQS_KNOWN)) {
973         dsend_packet_diplomacy_create_clause_req(&client.conn, other, giver,
974                                                  CLAUSE_ADVANCE, i);
975       }
976     } advance_iterate_end;
977   } else {
978     /* Only one tech. */
979     dsend_packet_diplomacy_create_clause_req(&client.conn, other, giver,
980                                              CLAUSE_ADVANCE, tech);
981   }
982 }
983 
984 /****************************************************************
985 Callback for trading cities
986 			      - Kris Bubendorfer
987 *****************************************************************/
diplomacy_dialog_city_callback(GtkWidget * w,gpointer data)988 static void diplomacy_dialog_city_callback(GtkWidget * w, gpointer data)
989 {
990   size_t choice = GPOINTER_TO_UINT(data);
991   int giver = (choice >> 24) & 0xff, dest = (choice >> 16) & 0xff, other;
992   int city = choice & 0xffff;
993 
994   if (player_by_number(giver) == client.conn.playing) {
995     other = dest;
996   } else {
997     other = giver;
998   }
999 
1000   dsend_packet_diplomacy_create_clause_req(&client.conn, other, giver,
1001 					   CLAUSE_CITY, city);
1002 }
1003 
1004 /****************************************************************
1005   Map menu item activated
1006 *****************************************************************/
diplomacy_dialog_map_callback(GtkWidget * w,gpointer data)1007 static void diplomacy_dialog_map_callback(GtkWidget *w, gpointer data)
1008 {
1009   struct Diplomacy_dialog *pdialog = (struct Diplomacy_dialog *)data;
1010   struct player *pgiver;
1011 
1012   pgiver = (struct player *)g_object_get_data(G_OBJECT(w), "plr");
1013 
1014   dsend_packet_diplomacy_create_clause_req(&client.conn,
1015 					   player_number(pdialog->treaty.plr1),
1016 					   player_number(pgiver), CLAUSE_MAP, 0);
1017 }
1018 
1019 /****************************************************************
1020  Seamap menu item activated
1021 *****************************************************************/
diplomacy_dialog_seamap_callback(GtkWidget * w,gpointer data)1022 static void diplomacy_dialog_seamap_callback(GtkWidget *w, gpointer data)
1023 {
1024   struct Diplomacy_dialog *pdialog = (struct Diplomacy_dialog *)data;
1025   struct player *pgiver;
1026 
1027   pgiver = (struct player *)g_object_get_data(G_OBJECT(w), "plr");
1028 
1029   dsend_packet_diplomacy_create_clause_req(&client.conn,
1030 					   player_number(pdialog->treaty.plr1),
1031 					   player_number(pgiver), CLAUSE_SEAMAP,
1032 					   0);
1033 }
1034 
1035 /****************************************************************
1036   Adding pact clause
1037 *****************************************************************/
diplomacy_dialog_add_pact_clause(GtkWidget * w,gpointer data,int type)1038 static void diplomacy_dialog_add_pact_clause(GtkWidget *w, gpointer data,
1039 					     int type)
1040 {
1041   struct Diplomacy_dialog *pdialog = (struct Diplomacy_dialog *)data;
1042 
1043   dsend_packet_diplomacy_create_clause_req(&client.conn,
1044 					   player_number(pdialog->treaty.plr1),
1045 					   player_number(pdialog->treaty.plr0),
1046 					   type, 0);
1047 }
1048 
1049 /****************************************************************
1050   Ceasefire pact menu item activated
1051 *****************************************************************/
diplomacy_dialog_ceasefire_callback(GtkWidget * w,gpointer data)1052 static void diplomacy_dialog_ceasefire_callback(GtkWidget *w, gpointer data)
1053 {
1054   diplomacy_dialog_add_pact_clause(w, data, CLAUSE_CEASEFIRE);
1055 }
1056 
1057 /****************************************************************
1058   Peace pact menu item activated
1059 *****************************************************************/
diplomacy_dialog_peace_callback(GtkWidget * w,gpointer data)1060 static void diplomacy_dialog_peace_callback(GtkWidget *w, gpointer data)
1061 {
1062   diplomacy_dialog_add_pact_clause(w, data, CLAUSE_PEACE);
1063 }
1064 
1065 /****************************************************************
1066   Alliance pact menu item activated
1067 *****************************************************************/
diplomacy_dialog_alliance_callback(GtkWidget * w,gpointer data)1068 static void diplomacy_dialog_alliance_callback(GtkWidget *w, gpointer data)
1069 {
1070   diplomacy_dialog_add_pact_clause(w, data, CLAUSE_ALLIANCE);
1071 }
1072 
1073 /****************************************************************
1074   Shared vision menu item activated
1075 *****************************************************************/
diplomacy_dialog_vision_callback(GtkWidget * w,gpointer data)1076 static void diplomacy_dialog_vision_callback(GtkWidget *w, gpointer data)
1077 {
1078   struct Diplomacy_dialog *pdialog = (struct Diplomacy_dialog *) data;
1079   struct player *pgiver =
1080       (struct player *) g_object_get_data(G_OBJECT(w), "plr");
1081 
1082   dsend_packet_diplomacy_create_clause_req(&client.conn,
1083 					   player_number(pdialog->treaty.plr1),
1084 					   player_number(pgiver), CLAUSE_VISION,
1085 					   0);
1086 }
1087 
1088 /****************************************************************
1089   Embassy menu item activated
1090 *****************************************************************/
diplomacy_dialog_embassy_callback(GtkWidget * w,gpointer data)1091 static void diplomacy_dialog_embassy_callback(GtkWidget *w, gpointer data)
1092 {
1093   struct Diplomacy_dialog *pdialog = (struct Diplomacy_dialog *) data;
1094   struct player *pgiver =
1095       (struct player *) g_object_get_data(G_OBJECT(w), "plr");
1096 
1097   dsend_packet_diplomacy_create_clause_req(&client.conn,
1098 					   player_number(pdialog->treaty.plr1),
1099 					   player_number(pgiver), CLAUSE_EMBASSY,
1100 					   0);
1101 }
1102 
1103 
1104 /*****************************************************************
1105   Close diplomacy dialog
1106 *****************************************************************/
close_diplomacy_dialog(struct Diplomacy_dialog * pdialog)1107 void close_diplomacy_dialog(struct Diplomacy_dialog *pdialog)
1108 {
1109   diplomacy_destroy(pdialog);
1110 }
1111 
1112 /*****************************************************************
1113   Initialize diplomacy dialog
1114 *****************************************************************/
diplomacy_dialog_init(void)1115 void diplomacy_dialog_init(void)
1116 {
1117   dialog_list = dialog_list_new();
1118   dipl_main = NULL;
1119 }
1120 
1121 /*****************************************************************
1122   Free resources allocated for diplomacy dialog
1123 *****************************************************************/
diplomacy_dialog_done(void)1124 void diplomacy_dialog_done(void)
1125 {
1126   dialog_list_destroy(dialog_list);
1127 }
1128 
1129 /*****************************************************************
1130   Find diplomacy dialog between player and other player
1131 *****************************************************************/
find_diplomacy_dialog(int other_player_id)1132 static struct Diplomacy_dialog *find_diplomacy_dialog(int other_player_id)
1133 {
1134   struct player *plr0 = client.conn.playing;
1135   struct player *plr1 = player_by_number(other_player_id);
1136 
1137   dialog_list_iterate(dialog_list, pdialog) {
1138     if ((pdialog->treaty.plr0 == plr0 && pdialog->treaty.plr1 == plr1) ||
1139 	(pdialog->treaty.plr0 == plr1 && pdialog->treaty.plr1 == plr0)) {
1140       return pdialog;
1141     }
1142   } dialog_list_iterate_end;
1143 
1144   return NULL;
1145 }
1146 
1147 /*****************************************************************
1148   User hit enter after entering gold amount
1149 *****************************************************************/
diplo_dialog_returnkey(GtkWidget * w,gpointer data)1150 static void diplo_dialog_returnkey(GtkWidget *w, gpointer data)
1151 {
1152   struct Diplomacy_dialog *pdialog = (struct Diplomacy_dialog *) data;
1153   struct player *pgiver =
1154       (struct player *) g_object_get_data(G_OBJECT(w), "plr");
1155   int amount = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(w));
1156 
1157   if (amount >= 0 && amount <= pgiver->economic.gold) {
1158     dsend_packet_diplomacy_create_clause_req(&client.conn,
1159 					     player_number(pdialog->treaty.plr1),
1160 					     player_number(pgiver),
1161 					     CLAUSE_GOLD, amount);
1162   } else {
1163     output_window_append(ftc_client, _("Invalid amount of gold specified."));
1164   }
1165 }
1166 
1167 /*****************************************************************
1168   Close all dialogs, for when client disconnects from game.
1169 *****************************************************************/
close_all_diplomacy_dialogs(void)1170 void close_all_diplomacy_dialogs(void)
1171 {
1172   while (dialog_list_size(dialog_list) > 0) {
1173     close_diplomacy_dialog(dialog_list_get(dialog_list, 0));
1174   }
1175 }
1176