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-3.22 */
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 g_object_set(dipl_sw, "margin", 2, NULL);
494 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(dipl_sw),
495 GTK_POLICY_AUTOMATIC,
496 GTK_POLICY_AUTOMATIC);
497 gtk_container_add(GTK_CONTAINER(dipl_sw), dipl_main->notebook);
498
499 /* Buttons */
500 gui_dialog_add_button(dipl_main->dialog, NULL,
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_container_add(GTK_CONTAINER(dipl_box), dipl_sw);
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, *mainbox;
628 GtkWidget *label, *sw, *view, *image, *spin;
629 GtkWidget *menubar, *menuitem, *menu, *notebook;
630 struct sprite *flag_spr;
631 GdkPixbuf *pb;
632 GtkListStore *store;
633 GtkCellRenderer *rend;
634 int i;
635
636 struct Diplomacy_dialog *pdialog;
637 char plr_buf[4 * MAX_LEN_NAME];
638 gchar *buf;
639
640 pdialog = fc_malloc(sizeof(*pdialog));
641
642 dialog_list_prepend(dialog_list, pdialog);
643 init_treaty(&pdialog->treaty, plr0, plr1);
644
645 /* Get main diplomacy tab. */
646 dipl_dialog = diplomacy_main_create();
647
648 buf = g_strdup_printf(_("Diplomacy [%d]"), dialog_list_size(dialog_list));
649 gui_dialog_set_title(dipl_dialog->dialog, buf);
650 g_free(buf);
651
652 notebook = dipl_dialog->notebook;
653
654 gui_dialog_new(&(pdialog->dialog), GTK_NOTEBOOK(notebook), pdialog, FALSE);
655
656 /* Buttons */
657 gui_dialog_add_button(pdialog->dialog, NULL,
658 _("Accept treaty"), GTK_RESPONSE_ACCEPT);
659 gui_dialog_add_button(pdialog->dialog, NULL,
660 _("Cancel meeting"), RESPONSE_CANCEL_MEETING);
661
662 /* Responces for one meeting. */
663 gui_dialog_response_set_callback(pdialog->dialog, diplomacy_response);
664 gui_dialog_set_default_response(pdialog->dialog, RESPONSE_CANCEL_MEETING);
665
666 /* Label for the new meeting. */
667 buf = g_strdup_printf("%s", nation_plural_for_player(plr1));
668 gui_dialog_set_title(pdialog->dialog, buf);
669
670 /* Sort meeting tabs alphabetically by the tab label. */
671 for (i = 0; i < gtk_notebook_get_n_pages(GTK_NOTEBOOK(notebook)); i++) {
672 GtkWidget *prev_page
673 = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), i);
674 struct gui_dialog *prev_dialog
675 = g_object_get_data(G_OBJECT(prev_page), "gui-dialog-data");
676 const char *prev_label
677 = gtk_label_get_text(GTK_LABEL(prev_dialog->v.tab.label));
678
679 if (fc_strcasecmp(buf, prev_label) < 0) {
680 gtk_notebook_reorder_child(GTK_NOTEBOOK(notebook),
681 pdialog->dialog->vbox, i);
682 break;
683 }
684 }
685 g_free(buf);
686
687 /* Content. */
688 mainbox = pdialog->dialog->vbox;
689
690 /* us. */
691 vbox = gtk_grid_new();
692 gtk_orientable_set_orientation(GTK_ORIENTABLE(vbox),
693 GTK_ORIENTATION_VERTICAL);
694 gtk_grid_set_row_spacing(GTK_GRID(vbox), 5);
695 gtk_container_set_border_width(GTK_CONTAINER(vbox), 2);
696 gtk_container_add(GTK_CONTAINER(mainbox), vbox);
697
698 /* Our nation. */
699 label = gtk_label_new(NULL);
700 gtk_widget_set_halign(label, GTK_ALIGN_CENTER);
701 gtk_widget_set_valign(label, GTK_ALIGN_CENTER);
702 buf = g_strdup_printf("<span size=\"large\"><u>%s</u></span>",
703 nation_plural_for_player(plr0));
704 gtk_label_set_markup(GTK_LABEL(label), buf);
705 g_free(buf);
706 gtk_container_add(GTK_CONTAINER(vbox), label);
707
708 hbox = gtk_grid_new();
709 gtk_grid_set_column_spacing(GTK_GRID(hbox), 5);
710 gtk_container_add(GTK_CONTAINER(vbox), hbox);
711
712 /* Our flag */
713 flag_spr = get_nation_flag_sprite(tileset, nation_of_player(plr0));
714
715 pb = sprite_get_pixbuf(flag_spr);
716 image = gtk_image_new_from_pixbuf(pb);
717 g_object_unref(pb);
718 gtk_container_add(GTK_CONTAINER(hbox), image);
719
720 /* Our name. */
721 label = gtk_label_new(NULL);
722 gtk_widget_set_hexpand(label, TRUE);
723 gtk_widget_set_halign(label, GTK_ALIGN_CENTER);
724 gtk_widget_set_valign(label, GTK_ALIGN_CENTER);
725 buf = g_strdup_printf("<span size=\"large\" weight=\"bold\">%s</span>",
726 ruler_title_for_player(plr0, plr_buf, sizeof(plr_buf)));
727 gtk_label_set_markup(GTK_LABEL(label), buf);
728 g_free(buf);
729 gtk_container_add(GTK_CONTAINER(hbox), label);
730
731 image = gtk_image_new();
732 pdialog->image0 = image;
733 gtk_container_add(GTK_CONTAINER(hbox), image);
734
735 /* Menu for clauses: we. */
736 menubar = gtk_aux_menu_bar_new();
737
738 menu = gtk_menu_new();
739 pdialog->menu0 = menu;
740
741 menuitem = gtk_menu_item_new_with_label(_("Add Clause..."));
742 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), menu);
743 gtk_menu_shell_append(GTK_MENU_SHELL(menubar), menuitem);
744 g_object_set_data(G_OBJECT(menu), "plr", plr0);
745 g_signal_connect(menu, "show", G_CALLBACK(popup_add_menu), pdialog);
746
747 /* Main table for clauses and (if activated) gold trading: we. */
748 table = gtk_grid_new();
749 gtk_widget_set_halign(table, GTK_ALIGN_CENTER);
750 gtk_widget_set_valign(table, GTK_ALIGN_CENTER);
751 gtk_grid_set_column_spacing(GTK_GRID(table), 16);
752 gtk_container_add(GTK_CONTAINER(vbox), table);
753
754 if (game.info.trading_gold) {
755 spin = gtk_spin_button_new_with_range(0.0, plr0->economic.gold + 0.1,
756 1.0);
757 gtk_spin_button_set_digits(GTK_SPIN_BUTTON(spin), 0);
758 gtk_entry_set_width_chars(GTK_ENTRY(spin), 16);
759 gtk_grid_attach(GTK_GRID(table), spin, 1, 0, 1, 1);
760 g_object_set_data(G_OBJECT(spin), "plr", plr0);
761 g_signal_connect_after(spin, "value-changed",
762 G_CALLBACK(diplo_dialog_returnkey), pdialog);
763
764 label = g_object_new(GTK_TYPE_LABEL, "use-underline", TRUE,
765 "mnemonic-widget", spin, "label", _("Gold:"),
766 "xalign", 0.0, "yalign", 0.5, NULL);
767 gtk_grid_attach(GTK_GRID(table), label, 0, 0, 1, 1);
768
769 gtk_grid_attach(GTK_GRID(table), menubar, 2, 0, 1, 1);
770 } else {
771 gtk_grid_attach(GTK_GRID(table), menubar, 0, 0, 1, 1);
772 }
773
774 /* them. */
775 vbox = gtk_grid_new();
776 gtk_orientable_set_orientation(GTK_ORIENTABLE(vbox),
777 GTK_ORIENTATION_VERTICAL);
778 gtk_grid_set_row_spacing(GTK_GRID(vbox), 5);
779 gtk_container_set_border_width(GTK_CONTAINER(vbox), 2);
780 gtk_container_add(GTK_CONTAINER(mainbox), vbox);
781
782 /* Their nation. */
783 label = gtk_label_new(NULL);
784 gtk_widget_set_halign(label, GTK_ALIGN_CENTER);
785 gtk_widget_set_valign(label, GTK_ALIGN_CENTER);
786 buf = g_strdup_printf("<span size=\"large\"><u>%s</u></span>",
787 nation_plural_for_player(plr1));
788 gtk_label_set_markup(GTK_LABEL(label), buf);
789 g_free(buf);
790 gtk_container_add(GTK_CONTAINER(vbox), label);
791
792 hbox = gtk_grid_new();
793 gtk_grid_set_column_spacing(GTK_GRID(hbox), 5);
794 gtk_container_add(GTK_CONTAINER(vbox), hbox);
795
796 /* Their flag */
797 flag_spr = get_nation_flag_sprite(tileset, nation_of_player(plr1));
798
799 pb = sprite_get_pixbuf(flag_spr);
800 image = gtk_image_new_from_pixbuf(pb);
801 g_object_unref(pb);
802 gtk_container_add(GTK_CONTAINER(hbox), image);
803
804 /* Their name. */
805 label = gtk_label_new(NULL);
806 gtk_widget_set_hexpand(label, TRUE);
807 gtk_widget_set_halign(label, GTK_ALIGN_CENTER);
808 gtk_widget_set_valign(label, GTK_ALIGN_CENTER);
809 buf = g_strdup_printf("<span size=\"large\" weight=\"bold\">%s</span>",
810 ruler_title_for_player(plr1, plr_buf, sizeof(plr_buf)));
811 gtk_label_set_markup(GTK_LABEL(label), buf);
812 g_free(buf);
813 gtk_container_add(GTK_CONTAINER(hbox), label);
814
815 image = gtk_image_new();
816 pdialog->image1 = image;
817 gtk_container_add(GTK_CONTAINER(hbox), image);
818
819 /* Menu for clauses: they. */
820 menubar = gtk_aux_menu_bar_new();
821
822 menu = gtk_menu_new();
823 pdialog->menu1 = menu;
824
825 menuitem = gtk_menu_item_new_with_label(_("Add Clause..."));
826 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), menu);
827 gtk_menu_shell_append(GTK_MENU_SHELL(menubar), menuitem);
828 g_object_set_data(G_OBJECT(menu), "plr", plr1);
829 g_signal_connect(menu, "show", G_CALLBACK(popup_add_menu), pdialog);
830
831 /* Main table for clauses and (if activated) gold trading: they. */
832 table = gtk_grid_new();
833 gtk_widget_set_halign(table, GTK_ALIGN_CENTER);
834 gtk_widget_set_valign(table, GTK_ALIGN_CENTER);
835 gtk_grid_set_column_spacing(GTK_GRID(table), 16);
836 gtk_container_add(GTK_CONTAINER(vbox), table);
837
838 if (game.info.trading_gold) {
839 spin = gtk_spin_button_new_with_range(0.0, plr1->economic.gold + 0.1,
840 1.0);
841 gtk_spin_button_set_digits(GTK_SPIN_BUTTON(spin), 0);
842 gtk_entry_set_width_chars(GTK_ENTRY(spin), 16);
843 gtk_grid_attach(GTK_GRID(table), spin, 1, 0, 1, 1);
844 g_object_set_data(G_OBJECT(spin), "plr", plr1);
845 g_signal_connect_after(spin, "value-changed",
846 G_CALLBACK(diplo_dialog_returnkey), pdialog);
847
848 label = g_object_new(GTK_TYPE_LABEL, "use-underline", TRUE,
849 "mnemonic-widget", spin, "label", _("Gold:"),
850 "xalign", 0.0, "yalign", 0.5, NULL);
851 gtk_grid_attach(GTK_GRID(table), label, 0, 0, 1, 1);
852
853 gtk_grid_attach(GTK_GRID(table), menubar, 2, 0, 1, 1);
854 } else {
855 gtk_grid_attach(GTK_GRID(table), menubar, 0, 0, 1, 1);
856 }
857
858 /* Clauses. */
859 mainbox = gtk_grid_new();
860 gtk_orientable_set_orientation(GTK_ORIENTABLE(mainbox),
861 GTK_ORIENTATION_VERTICAL);
862 gtk_container_add(GTK_CONTAINER(pdialog->dialog->vbox), mainbox);
863
864 store = gtk_list_store_new(1, G_TYPE_STRING);
865 pdialog->store = store;
866
867 view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
868 gtk_widget_set_hexpand(view, TRUE);
869 gtk_widget_set_vexpand(view, TRUE);
870 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), FALSE);
871 g_object_unref(store);
872 gtk_widget_set_size_request(view, 320, 100);
873
874 rend = gtk_cell_renderer_text_new();
875 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view), -1, NULL,
876 rend, "text", 0, NULL);
877
878 sw = gtk_scrolled_window_new(NULL, NULL);
879 g_object_set(sw, "margin", 2, NULL);
880 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw),
881 GTK_SHADOW_ETCHED_IN);
882 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
883 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
884 gtk_container_add(GTK_CONTAINER(sw), view);
885
886 label = g_object_new(GTK_TYPE_LABEL,
887 "use-underline", TRUE,
888 "mnemonic-widget", view,
889 "label", _("C_lauses:"),
890 "xalign", 0.0,
891 "yalign", 0.5,
892 NULL);
893
894 vbox = gtk_grid_new();
895 gtk_orientable_set_orientation(GTK_ORIENTABLE(vbox),
896 GTK_ORIENTATION_VERTICAL);
897 gtk_container_add(GTK_CONTAINER(mainbox), vbox);
898 gtk_container_add(GTK_CONTAINER(vbox), label);
899 gtk_container_add(GTK_CONTAINER(vbox), sw);
900
901 gtk_widget_show_all(mainbox);
902
903 g_signal_connect(view, "row_activated", G_CALLBACK(row_callback), pdialog);
904
905 update_diplomacy_dialog(pdialog);
906 gui_dialog_show_all(pdialog->dialog);
907
908 return pdialog;
909 }
910
911 /**************************************************************************
912 Update diplomacy dialog
913 **************************************************************************/
update_diplomacy_dialog(struct Diplomacy_dialog * pdialog)914 static void update_diplomacy_dialog(struct Diplomacy_dialog *pdialog)
915 {
916 GtkListStore *store;
917 GtkTreeIter it;
918 bool blank = TRUE;
919 GdkPixbuf *pixbuf;
920
921 store = pdialog->store;
922
923 gtk_list_store_clear(store);
924 clause_list_iterate(pdialog->treaty.clauses, pclause) {
925 char buf[128];
926
927 client_diplomacy_clause_string(buf, sizeof(buf), pclause);
928
929 gtk_list_store_append(store, &it);
930 gtk_list_store_set(store, &it, 0, buf, -1);
931 blank = FALSE;
932 } clause_list_iterate_end;
933
934 if (blank) {
935 gtk_list_store_append(store, &it);
936 gtk_list_store_set(store, &it, 0,
937 _("--- This treaty is blank. "
938 "Please add some clauses. ---"), -1);
939 }
940
941 pixbuf = get_thumb_pixbuf(pdialog->treaty.accept0);
942 gtk_image_set_from_pixbuf(GTK_IMAGE(pdialog->image0), pixbuf);
943 g_object_unref(G_OBJECT(pixbuf));
944 pixbuf = get_thumb_pixbuf(pdialog->treaty.accept1);
945 gtk_image_set_from_pixbuf(GTK_IMAGE(pdialog->image1), pixbuf);
946 g_object_unref(G_OBJECT(pixbuf));
947 }
948
949 /****************************************************************************
950 Callback for the diplomatic dialog: give tech.
951 ****************************************************************************/
diplomacy_dialog_tech_callback(GtkWidget * w,gpointer data)952 static void diplomacy_dialog_tech_callback(GtkWidget *w, gpointer data)
953 {
954 int giver, dest, other, tech;
955
956 giver = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w), "player_from"));
957 dest = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w), "player_to"));
958 tech = GPOINTER_TO_INT(data);
959 if (player_by_number(giver) == client_player()) {
960 other = dest;
961 } else {
962 other = giver;
963 }
964
965 if (A_LAST == tech) {
966 /* All techs. */
967 struct player *pgiver = player_by_number(giver);
968 struct player *pdest = player_by_number(dest);
969 const struct research *dresearch, *gresearch;
970
971 fc_assert_ret(NULL != pgiver);
972 fc_assert_ret(NULL != pdest);
973
974 dresearch = research_get(pdest);
975 gresearch = research_get(pgiver);
976 advance_iterate(A_FIRST, padvance) {
977 Tech_type_id i = advance_number(padvance);
978
979 if (research_invention_state(gresearch, i) == TECH_KNOWN
980 && research_invention_gettable(dresearch, i,
981 game.info.tech_trade_allow_holes)
982 && (research_invention_state(dresearch, i) == TECH_UNKNOWN
983 || research_invention_state(dresearch, i)
984 == TECH_PREREQS_KNOWN)) {
985 dsend_packet_diplomacy_create_clause_req(&client.conn, other, giver,
986 CLAUSE_ADVANCE, i);
987 }
988 } advance_iterate_end;
989 } else {
990 /* Only one tech. */
991 dsend_packet_diplomacy_create_clause_req(&client.conn, other, giver,
992 CLAUSE_ADVANCE, tech);
993 }
994 }
995
996 /****************************************************************
997 Callback for trading cities
998 - Kris Bubendorfer
999 *****************************************************************/
diplomacy_dialog_city_callback(GtkWidget * w,gpointer data)1000 static void diplomacy_dialog_city_callback(GtkWidget * w, gpointer data)
1001 {
1002 size_t choice = GPOINTER_TO_UINT(data);
1003 int giver = (choice >> 24) & 0xff, dest = (choice >> 16) & 0xff, other;
1004 int city = choice & 0xffff;
1005
1006 if (player_by_number(giver) == client.conn.playing) {
1007 other = dest;
1008 } else {
1009 other = giver;
1010 }
1011
1012 dsend_packet_diplomacy_create_clause_req(&client.conn, other, giver,
1013 CLAUSE_CITY, city);
1014 }
1015
1016 /****************************************************************
1017 Map menu item activated
1018 *****************************************************************/
diplomacy_dialog_map_callback(GtkWidget * w,gpointer data)1019 static void diplomacy_dialog_map_callback(GtkWidget *w, gpointer data)
1020 {
1021 struct Diplomacy_dialog *pdialog = (struct Diplomacy_dialog *)data;
1022 struct player *pgiver;
1023
1024 pgiver = (struct player *)g_object_get_data(G_OBJECT(w), "plr");
1025
1026 dsend_packet_diplomacy_create_clause_req(&client.conn,
1027 player_number(pdialog->treaty.plr1),
1028 player_number(pgiver), CLAUSE_MAP, 0);
1029 }
1030
1031 /****************************************************************
1032 Seamap menu item activated
1033 *****************************************************************/
diplomacy_dialog_seamap_callback(GtkWidget * w,gpointer data)1034 static void diplomacy_dialog_seamap_callback(GtkWidget *w, gpointer data)
1035 {
1036 struct Diplomacy_dialog *pdialog = (struct Diplomacy_dialog *)data;
1037 struct player *pgiver;
1038
1039 pgiver = (struct player *)g_object_get_data(G_OBJECT(w), "plr");
1040
1041 dsend_packet_diplomacy_create_clause_req(&client.conn,
1042 player_number(pdialog->treaty.plr1),
1043 player_number(pgiver), CLAUSE_SEAMAP,
1044 0);
1045 }
1046
1047 /****************************************************************
1048 Adding pact clause
1049 *****************************************************************/
diplomacy_dialog_add_pact_clause(GtkWidget * w,gpointer data,int type)1050 static void diplomacy_dialog_add_pact_clause(GtkWidget *w, gpointer data,
1051 int type)
1052 {
1053 struct Diplomacy_dialog *pdialog = (struct Diplomacy_dialog *)data;
1054
1055 dsend_packet_diplomacy_create_clause_req(&client.conn,
1056 player_number(pdialog->treaty.plr1),
1057 player_number(pdialog->treaty.plr0),
1058 type, 0);
1059 }
1060
1061 /****************************************************************
1062 Ceasefire pact menu item activated
1063 *****************************************************************/
diplomacy_dialog_ceasefire_callback(GtkWidget * w,gpointer data)1064 static void diplomacy_dialog_ceasefire_callback(GtkWidget *w, gpointer data)
1065 {
1066 diplomacy_dialog_add_pact_clause(w, data, CLAUSE_CEASEFIRE);
1067 }
1068
1069 /****************************************************************
1070 Peace pact menu item activated
1071 *****************************************************************/
diplomacy_dialog_peace_callback(GtkWidget * w,gpointer data)1072 static void diplomacy_dialog_peace_callback(GtkWidget *w, gpointer data)
1073 {
1074 diplomacy_dialog_add_pact_clause(w, data, CLAUSE_PEACE);
1075 }
1076
1077 /****************************************************************
1078 Alliance pact menu item activated
1079 *****************************************************************/
diplomacy_dialog_alliance_callback(GtkWidget * w,gpointer data)1080 static void diplomacy_dialog_alliance_callback(GtkWidget *w, gpointer data)
1081 {
1082 diplomacy_dialog_add_pact_clause(w, data, CLAUSE_ALLIANCE);
1083 }
1084
1085 /****************************************************************
1086 Shared vision menu item activated
1087 *****************************************************************/
diplomacy_dialog_vision_callback(GtkWidget * w,gpointer data)1088 static void diplomacy_dialog_vision_callback(GtkWidget *w, gpointer data)
1089 {
1090 struct Diplomacy_dialog *pdialog = (struct Diplomacy_dialog *) data;
1091 struct player *pgiver =
1092 (struct player *) g_object_get_data(G_OBJECT(w), "plr");
1093
1094 dsend_packet_diplomacy_create_clause_req(&client.conn,
1095 player_number(pdialog->treaty.plr1),
1096 player_number(pgiver), CLAUSE_VISION,
1097 0);
1098 }
1099
1100 /****************************************************************
1101 Embassy menu item activated
1102 *****************************************************************/
diplomacy_dialog_embassy_callback(GtkWidget * w,gpointer data)1103 static void diplomacy_dialog_embassy_callback(GtkWidget *w, gpointer data)
1104 {
1105 struct Diplomacy_dialog *pdialog = (struct Diplomacy_dialog *) data;
1106 struct player *pgiver =
1107 (struct player *) g_object_get_data(G_OBJECT(w), "plr");
1108
1109 dsend_packet_diplomacy_create_clause_req(&client.conn,
1110 player_number(pdialog->treaty.plr1),
1111 player_number(pgiver), CLAUSE_EMBASSY,
1112 0);
1113 }
1114
1115
1116 /*****************************************************************
1117 Close diplomacy dialog
1118 *****************************************************************/
close_diplomacy_dialog(struct Diplomacy_dialog * pdialog)1119 void close_diplomacy_dialog(struct Diplomacy_dialog *pdialog)
1120 {
1121 diplomacy_destroy(pdialog);
1122 }
1123
1124 /*****************************************************************
1125 Initialize diplomacy dialog
1126 *****************************************************************/
diplomacy_dialog_init(void)1127 void diplomacy_dialog_init(void)
1128 {
1129 dialog_list = dialog_list_new();
1130 dipl_main = NULL;
1131 }
1132
1133 /*****************************************************************
1134 Free resources allocated for diplomacy dialog
1135 *****************************************************************/
diplomacy_dialog_done(void)1136 void diplomacy_dialog_done(void)
1137 {
1138 dialog_list_destroy(dialog_list);
1139 }
1140
1141 /*****************************************************************
1142 Find diplomacy dialog between player and other player
1143 *****************************************************************/
find_diplomacy_dialog(int other_player_id)1144 static struct Diplomacy_dialog *find_diplomacy_dialog(int other_player_id)
1145 {
1146 struct player *plr0 = client.conn.playing;
1147 struct player *plr1 = player_by_number(other_player_id);
1148
1149 dialog_list_iterate(dialog_list, pdialog) {
1150 if ((pdialog->treaty.plr0 == plr0 && pdialog->treaty.plr1 == plr1) ||
1151 (pdialog->treaty.plr0 == plr1 && pdialog->treaty.plr1 == plr0)) {
1152 return pdialog;
1153 }
1154 } dialog_list_iterate_end;
1155
1156 return NULL;
1157 }
1158
1159 /*****************************************************************
1160 User hit enter after entering gold amount
1161 *****************************************************************/
diplo_dialog_returnkey(GtkWidget * w,gpointer data)1162 static void diplo_dialog_returnkey(GtkWidget *w, gpointer data)
1163 {
1164 struct Diplomacy_dialog *pdialog = (struct Diplomacy_dialog *) data;
1165 struct player *pgiver =
1166 (struct player *) g_object_get_data(G_OBJECT(w), "plr");
1167 int amount = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(w));
1168
1169 if (amount >= 0 && amount <= pgiver->economic.gold) {
1170 dsend_packet_diplomacy_create_clause_req(&client.conn,
1171 player_number(pdialog->treaty.plr1),
1172 player_number(pgiver),
1173 CLAUSE_GOLD, amount);
1174 } else {
1175 output_window_append(ftc_client, _("Invalid amount of gold specified."));
1176 }
1177 }
1178
1179 /*****************************************************************
1180 Close all dialogs, for when client disconnects from game.
1181 *****************************************************************/
close_all_diplomacy_dialogs(void)1182 void close_all_diplomacy_dialogs(void)
1183 {
1184 while (dialog_list_size(dialog_list) > 0) {
1185 close_diplomacy_dialog(dialog_list_get(dialog_list, 0));
1186 }
1187 }
1188