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