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 <X11/Intrinsic.h>
22 #include <X11/StringDefs.h>
23 #include <X11/Xaw/Form.h>
24 #include <X11/Xaw/Label.h>
25 #include <X11/Xaw/Command.h>
26 #include <X11/Xaw/List.h>
27 #include <X11/Xaw/SimpleMenu.h>
28 #include <X11/Xaw/MenuButton.h>
29 #include <X11/Xaw/SmeBSB.h>
30 #include <X11/Xaw/SmeLine.h>
31 #include <X11/Xaw/AsciiText.h>
32 #include <X11/Xaw/Viewport.h>
33 
34 /* utility */
35 #include "fcintl.h"
36 #include "log.h"
37 #include "mem.h"
38 #include "shared.h"
39 #include "support.h"
40 
41 /* common */
42 #include "diptreaty.h"
43 #include "game.h"
44 #include "government.h"
45 #include "map.h"
46 #include "packets.h"
47 #include "player.h"
48 #include "research.h"
49 
50 /* client */
51 #include "client_main.h"
52 #include "climisc.h"
53 
54 /* gui-xaw */
55 #include "chatline.h"
56 #include "gui_main.h"
57 #include "gui_stuff.h"
58 #include "mapview.h"
59 
60 #include "diplodlg.h"
61 
62 #define MAX_NUM_CLAUSES 64
63 
64 struct Diplomacy_dialog {
65   struct Treaty treaty;
66 
67   Widget dip_dialog_shell;
68   Widget dip_form, dip_main_form, dip_form0, dip_formm, dip_form1;
69   Widget dip_view;
70 
71   Widget dip_headline0;
72   Widget dip_headlinem;
73   Widget dip_headline1;
74 
75   Widget dip_map_menubutton0;
76   Widget dip_map_menubutton1;
77   Widget dip_tech_menubutton0;
78   Widget dip_tech_menubutton1;
79   Widget dip_city_menubutton0;
80   Widget dip_city_menubutton1;
81   Widget dip_gold_label0;
82   Widget dip_gold_label1;
83   Widget dip_gold_input0;
84   Widget dip_gold_input1;
85   Widget dip_vision_button0;
86   Widget dip_vision_button1;
87   Widget dip_pact_menubutton;
88 
89   Widget dip_label;
90   Widget dip_clauselabel;
91   Widget dip_clauselist;
92   Widget dip_acceptlabel0;
93   Widget dip_acceptthumb0;
94   Widget dip_acceptlabel1;
95   Widget dip_acceptthumb1;
96 
97   Widget dip_accept_command;
98   Widget dip_close_command;
99 
100   Widget dip_erase_clause_command;
101 
102   char clauselist_strings[MAX_NUM_CLAUSES+1][128];
103   CONST_FOR_XAW_LIST_CHANGE char *clauselist_strings_ptrs[MAX_NUM_CLAUSES + 1];
104 };
105 
106 static char *dummy_clause_list_strings[]
107     = { "\n", "\n", "\n", "\n", "\n", "\n", 0 };
108 
109 #define SPECLIST_TAG dialog
110 #define SPECLIST_TYPE struct Diplomacy_dialog
111 #include "speclist.h"
112 
113 #define dialog_list_iterate(dialoglist, pdialog) \
114     TYPED_LIST_ITERATE(struct Diplomacy_dialog, dialoglist, pdialog)
115 #define dialog_list_iterate_end  LIST_ITERATE_END
116 
117 static struct dialog_list *dialog_list = NULL;
118 static bool dialog_list_list_has_been_initialised = FALSE;
119 
120 struct Diplomacy_dialog *create_diplomacy_dialog(struct player *plr0,
121 						 struct player *plr1);
122 
123 static struct Diplomacy_dialog *find_diplomacy_dialog(int other_player_id);
124 static void popup_diplomacy_dialog(int other_player_id);
125 void diplomacy_dialog_close_callback(Widget w, XtPointer client_data,
126 				    XtPointer call_data);
127 void diplomacy_dialog_map_callback(Widget w, XtPointer client_data,
128 				   XtPointer call_data);
129 void diplomacy_dialog_seamap_callback(Widget w, XtPointer client_data,
130 				      XtPointer call_data);
131 void diplomacy_dialog_erase_clause_callback(Widget w, XtPointer client_data,
132 					    XtPointer call_data);
133 void diplomacy_dialog_accept_callback(Widget w, XtPointer client_data,
134 				      XtPointer call_data);
135 void diplomacy_dialog_tech_callback(Widget w, XtPointer client_data,
136 				    XtPointer call_data);
137 void diplomacy_dialog_city_callback(Widget w, XtPointer client_data,
138 				    XtPointer call_data);
139 void diplomacy_dialog_ceasefire_callback(Widget w, XtPointer client_data,
140 					 XtPointer call_data);
141 void diplomacy_dialog_peace_callback(Widget w, XtPointer client_data,
142 					XtPointer call_data);
143 void diplomacy_dialog_alliance_callback(Widget w, XtPointer client_data,
144 					XtPointer call_data);
145 void diplomacy_dialog_vision_callback(Widget w, XtPointer client_data,
146 				      XtPointer call_data);
147 void close_diplomacy_dialog(struct Diplomacy_dialog *pdialog);
148 void update_diplomacy_dialog(struct Diplomacy_dialog *pdialog);
149 
150 
151 /****************************************************************
152 ...
153 *****************************************************************/
handle_diplomacy_accept_treaty(int counterpart,bool I_accepted,bool other_accepted)154 void handle_diplomacy_accept_treaty(int counterpart, bool I_accepted,
155 				    bool other_accepted)
156 {
157   struct Diplomacy_dialog *pdialog = find_diplomacy_dialog(counterpart);
158 
159   if (!pdialog) {
160     return;
161   }
162 
163   pdialog->treaty.accept0 = I_accepted;
164   pdialog->treaty.accept1 = other_accepted;
165 
166   update_diplomacy_dialog(pdialog);
167 }
168 
169 /****************************************************************
170 ...
171 *****************************************************************/
handle_diplomacy_init_meeting(int counterpart,int initiated_from)172 void handle_diplomacy_init_meeting(int counterpart, int initiated_from)
173 {
174   popup_diplomacy_dialog(counterpart);
175 }
176 
177 /****************************************************************
178 ...
179 *****************************************************************/
handle_diplomacy_cancel_meeting(int counterpart,int initiated_from)180 void handle_diplomacy_cancel_meeting(int counterpart, int initiated_from)
181 {
182   struct Diplomacy_dialog *pdialog = find_diplomacy_dialog(counterpart);
183 
184   if (!pdialog) {
185     return;
186   }
187 
188   close_diplomacy_dialog(pdialog);
189 }
190 
191 /****************************************************************
192 ...
193 *****************************************************************/
handle_diplomacy_create_clause(int counterpart,int giver,enum clause_type type,int value)194 void handle_diplomacy_create_clause(int counterpart, int giver,
195 				    enum clause_type type, int value)
196 {
197   struct Diplomacy_dialog *pdialog = find_diplomacy_dialog(counterpart);
198 
199   if (!pdialog) {
200     return;
201   }
202 
203   add_clause(&pdialog->treaty, player_by_number(giver), type, value);
204   update_diplomacy_dialog(pdialog);
205 }
206 
207 /****************************************************************
208 ...
209 *****************************************************************/
handle_diplomacy_remove_clause(int counterpart,int giver,enum clause_type type,int value)210 void handle_diplomacy_remove_clause(int counterpart, int giver,
211 				    enum clause_type type, int value)
212 {
213   struct Diplomacy_dialog *pdialog = find_diplomacy_dialog(counterpart);
214 
215   if (!pdialog) {
216     return;
217   }
218 
219   remove_clause(&pdialog->treaty, player_by_number(giver), type, value);
220   update_diplomacy_dialog(pdialog);
221 }
222 
223 /****************************************************************
224 popup the dialog 10% inside the main-window
225 *****************************************************************/
popup_diplomacy_dialog(int other_player_id)226 static void popup_diplomacy_dialog(int other_player_id)
227 {
228   struct Diplomacy_dialog *pdialog = find_diplomacy_dialog(other_player_id);
229 
230   if (NULL == client.conn.playing || client.conn.playing->ai_controlled) {
231     return;			/* Don't show if we are AI controlled. */
232   }
233 
234   if (!pdialog) {
235     Position x, y;
236     Dimension width, height;
237 
238     pdialog = create_diplomacy_dialog(client.conn.playing,
239 				      player_by_number(other_player_id));
240     XtVaGetValues(toplevel, XtNwidth, &width, XtNheight, &height, NULL);
241     XtTranslateCoords(toplevel, (Position) width / 10,
242 		      (Position) height / 10, &x, &y);
243     XtVaSetValues(pdialog->dip_dialog_shell, XtNx, x, XtNy, y, NULL);
244   }
245 
246   XtPopup(pdialog->dip_dialog_shell, XtGrabNone);
247 }
248 
249 
250 /****************************************************************
251 ...
252 *****************************************************************/
fill_diplomacy_tech_menu(Widget popupmenu,struct player * plr0,struct player * plr1)253 static int fill_diplomacy_tech_menu(Widget popupmenu,
254 				    struct player *plr0, struct player *plr1)
255 {
256   const struct research *presearch0, *presearch1;
257   int flag = 0;
258 
259   if (!game.info.trading_tech) {
260     /* Trading advances deactivated. */
261     return 0;
262   }
263 
264   presearch0 = research_get(plr0);
265   presearch1 = research_get(plr1);
266   advance_index_iterate(A_FIRST, i) {
267     if (research_invention_state(presearch0, i) == TECH_KNOWN
268         && research_invention_gettable(presearch1, i,
269                                        game.info.tech_trade_allow_holes)
270         && research_invention_state(presearch1, i) != TECH_KNOWN) {
271       Widget entry=
272 	XtVaCreateManagedWidget(advance_name_translation(advance_by_number(i)),
273 				smeBSBObjectClass,
274 				popupmenu,
275 				NULL);
276       XtAddCallback(entry, XtNcallback, diplomacy_dialog_tech_callback,
277 			 INT_TO_XTPOINTER((player_number(plr0) << 24) |
278 					 (player_number(plr1) << 16) |
279 					 i));
280       flag=1;
281     }
282   } advance_index_iterate_end;
283   return flag;
284 }
285 
286 /****************************************************************
287 Creates a sorted list of plr0's cities, excluding the capital and
288 any cities not visible to plr1.  This means that you can only trade
289 cities visible to requesting player.
290 
291                             - Kris Bubendorfer
292 *****************************************************************/
fill_diplomacy_city_menu(Widget popupmenu,struct player * plr0,struct player * plr1)293 static int fill_diplomacy_city_menu(Widget popupmenu,
294 				    struct player *plr0, struct player *plr1)
295 {
296   int i = 0, j = 0, n = city_list_size(plr0->cities);
297 
298   if (game.info.trading_city) {
299     /* Trading cities deactivated. */
300     return 0;
301   }
302 
303   struct city **city_list_ptrs;
304   if (n>0) {
305     city_list_ptrs = fc_malloc(sizeof(struct city*)*n);
306   } else {
307     city_list_ptrs = NULL;
308   }
309 
310   city_list_iterate(plr0->cities, pcity) {
311     if (!is_capital(pcity)) {
312       city_list_ptrs[i] = pcity;
313       i++;
314     }
315   } city_list_iterate_end;
316 
317   qsort(city_list_ptrs, i, sizeof(struct city*), city_name_compare);
318 
319   for (j = 0; j < i; j++) {
320     Widget entry =
321       XtVaCreateManagedWidget(city_name_get(city_list_ptrs[j]), smeBSBObjectClass,
322                               popupmenu, NULL);
323     XtAddCallback(entry, XtNcallback, diplomacy_dialog_city_callback,
324                   INT_TO_XTPOINTER((player_number(plr0) << 24) |
325                                    (player_number(plr1) << 16) |
326                                    city_list_ptrs[j]->id));
327   }
328   free(city_list_ptrs);
329 
330   return i;
331 }
332 
333 /****************************************************************
334 ...
335 *****************************************************************/
create_diplomacy_dialog(struct player * plr0,struct player * plr1)336 struct Diplomacy_dialog *create_diplomacy_dialog(struct player *plr0,
337 						 struct player *plr1)
338 {
339   char plr0_buf[4 * MAX_LEN_NAME], plr1_buf[4 * MAX_LEN_NAME];
340   char buf[512], *pheadlinem;
341   struct Diplomacy_dialog *pdialog;
342   Dimension width, height, maxwidth;
343   Widget popupmenu;
344   Widget entry;
345 
346   pdialog=fc_malloc(sizeof(struct Diplomacy_dialog));
347   dialog_list_prepend(dialog_list, pdialog);
348 
349   init_treaty(&pdialog->treaty, plr0, plr1);
350 
351   pdialog->dip_dialog_shell =
352     I_T(XtCreatePopupShell("dippopupshell", topLevelShellWidgetClass,
353 			   toplevel, NULL, 0));
354 
355   pdialog->dip_form = XtVaCreateManagedWidget("dipform",
356 					      formWidgetClass,
357 					      pdialog->dip_dialog_shell,
358 					      NULL);
359 
360   pdialog->dip_main_form = XtVaCreateManagedWidget("dipmainform",
361 						   formWidgetClass,
362 						   pdialog->dip_form,
363 						   NULL);
364 
365   pdialog->dip_form0 = XtVaCreateManagedWidget("dipform0",
366 					       formWidgetClass,
367 					       pdialog->dip_main_form,
368 					       NULL);
369 
370   pdialog->dip_formm = XtVaCreateManagedWidget("dipformm",
371 					       formWidgetClass,
372 					       pdialog->dip_main_form,
373 					       NULL);
374 
375   pdialog->dip_form1 = XtVaCreateManagedWidget("dipform1",
376 					       formWidgetClass,
377 					       pdialog->dip_main_form,
378 					       NULL);
379 
380   fc_snprintf(buf, sizeof(buf), _("The %s offerings"),
381 	      nation_adjective_for_player(plr0));
382   pdialog->dip_headline0=XtVaCreateManagedWidget("dipheadline0",
383 						 labelWidgetClass,
384 						 pdialog->dip_form0,
385 						 XtNlabel, buf,
386 						 NULL);
387 
388   fc_snprintf(buf, sizeof(buf), _("The %s offerings"),
389 	      nation_adjective_for_player(plr1));
390   pdialog->dip_headline1=XtVaCreateManagedWidget("dipheadline1",
391 						 labelWidgetClass,
392 						 pdialog->dip_form1,
393 						 XtNlabel, buf,
394 						 NULL);
395 
396 
397   pdialog->dip_map_menubutton0 =
398     I_L(XtVaCreateManagedWidget("dipmapmenubutton0",
399 				menuButtonWidgetClass,
400 				pdialog->dip_form0,
401 				NULL));
402   popupmenu=XtVaCreatePopupShell("menu",
403 				 simpleMenuWidgetClass,
404 				 pdialog->dip_map_menubutton0,
405 				 NULL);
406 
407   entry=XtVaCreateManagedWidget(_("World-map"), smeBSBObjectClass,
408 				popupmenu, NULL);
409   XtAddCallback(entry, XtNcallback, diplomacy_dialog_map_callback,
410 		(XtPointer)pdialog);
411   entry=XtVaCreateManagedWidget(_("Sea-map"), smeBSBObjectClass,
412 				popupmenu, NULL);
413   XtAddCallback(entry, XtNcallback, diplomacy_dialog_seamap_callback,
414 		(XtPointer)pdialog);
415 
416   pdialog->dip_map_menubutton1 =
417     I_L(XtVaCreateManagedWidget("dipmapmenubutton1",
418 				menuButtonWidgetClass,
419 				pdialog->dip_form1,
420 				NULL));
421   popupmenu=XtVaCreatePopupShell("menu",
422 				 simpleMenuWidgetClass,
423 				 pdialog->dip_map_menubutton1,
424 				 NULL);
425   entry=XtVaCreateManagedWidget(_("World-map"), smeBSBObjectClass,
426 				popupmenu, NULL);
427   XtAddCallback(entry, XtNcallback, diplomacy_dialog_map_callback,
428 		(XtPointer)pdialog);
429   entry=XtVaCreateManagedWidget(_("Sea-map"), smeBSBObjectClass,
430 				popupmenu, NULL);
431   XtAddCallback(entry, XtNcallback, diplomacy_dialog_seamap_callback,
432 		(XtPointer)pdialog);
433 
434 
435   pdialog->dip_tech_menubutton0 =
436     I_L(XtVaCreateManagedWidget("diptechmenubutton0",
437 				menuButtonWidgetClass,
438 				pdialog->dip_form0,
439 				NULL));
440   popupmenu=XtVaCreatePopupShell("menu",
441 				 simpleMenuWidgetClass,
442 				 pdialog->dip_tech_menubutton0,
443 				 NULL);
444 
445   if(!fill_diplomacy_tech_menu(popupmenu, plr0, plr1))
446     XtSetSensitive(pdialog->dip_tech_menubutton0, FALSE);
447 
448 
449   pdialog->dip_tech_menubutton1 =
450     I_L(XtVaCreateManagedWidget("diptechmenubutton1",
451 				menuButtonWidgetClass,
452 				pdialog->dip_form1,
453 				NULL));
454   popupmenu=XtVaCreatePopupShell("menu",
455 				 simpleMenuWidgetClass,
456 				 pdialog->dip_tech_menubutton1,
457 				 NULL);
458   if(!fill_diplomacy_tech_menu(popupmenu, plr1, plr0))
459     XtSetSensitive(pdialog->dip_tech_menubutton1, FALSE);
460 
461   /* Start of trade city code - Kris Bubendorfer */
462 
463   pdialog->dip_city_menubutton0 =
464     I_L(XtVaCreateManagedWidget("dipcitymenubutton0",
465 				menuButtonWidgetClass,
466 				pdialog->dip_form0,
467 				NULL));
468   popupmenu=XtVaCreatePopupShell("menu",
469 				 simpleMenuWidgetClass,
470 				 pdialog->dip_city_menubutton0,
471 				 NULL);
472 
473   XtSetSensitive(pdialog->dip_city_menubutton0,
474 		 fill_diplomacy_city_menu(popupmenu, plr0, plr1));
475 
476 
477   pdialog->dip_city_menubutton1 =
478     I_L(XtVaCreateManagedWidget("dipcitymenubutton1",
479 				menuButtonWidgetClass,
480 				pdialog->dip_form1,
481 				NULL));
482   popupmenu=XtVaCreatePopupShell("menu",
483 				 simpleMenuWidgetClass,
484 				 pdialog->dip_city_menubutton1,
485 				 NULL);
486 
487   XtSetSensitive(pdialog->dip_city_menubutton1,
488 		 fill_diplomacy_city_menu(popupmenu, plr1, plr0));
489 
490   /* End of trade city code */
491 
492   /* Trading gold */
493   if (game.info.trading_gold) {
494     pdialog->dip_gold_input0 = XtVaCreateManagedWidget("dipgoldinput0",
495                                                        asciiTextWidgetClass,
496                                                        pdialog->dip_form0, NULL);
497     fc_snprintf(buf, sizeof(buf), _("Gold(max %d)"), plr0->economic.gold);
498     pdialog->dip_gold_label0 = XtVaCreateManagedWidget("dipgoldlabel0",
499                                                        labelWidgetClass,
500                                                        pdialog->dip_form0,
501                                                        XtNlabel, buf, NULL);
502 
503 
504     pdialog->dip_gold_input1 = XtVaCreateManagedWidget("dipgoldinput1",
505                                                        asciiTextWidgetClass,
506                                                        pdialog->dip_form1, NULL);
507     fc_snprintf(buf, sizeof(buf), _("Gold(max %d)"), plr1->economic.gold);
508     pdialog->dip_gold_label1 = XtVaCreateManagedWidget("dipgoldlabel1",
509                                                        labelWidgetClass,
510                                                        pdialog->dip_form1,
511                                                        XtNlabel, buf, NULL);
512   } else {
513     pdialog->dip_gold_input0 = NULL;
514     pdialog->dip_gold_input1 = NULL;
515     pdialog->dip_gold_label0 = NULL;
516     pdialog->dip_gold_label1 = NULL;
517   }
518 
519   pdialog->dip_vision_button0 =
520     I_L(XtVaCreateManagedWidget("dipvisionbutton0",
521 				commandWidgetClass,
522 				pdialog->dip_form0,
523 				NULL));
524   if (gives_shared_vision(plr0, plr1))
525     XtSetSensitive(pdialog->dip_vision_button0, FALSE);
526 
527   pdialog->dip_vision_button1 =
528     I_L(XtVaCreateManagedWidget("dipvisionbutton1",
529 				commandWidgetClass,
530 				pdialog->dip_form1,
531 				NULL));
532   if (gives_shared_vision(plr1, plr0))
533     XtSetSensitive(pdialog->dip_vision_button1, FALSE);
534 
535   XtAddCallback(pdialog->dip_vision_button0, XtNcallback,
536 		diplomacy_dialog_vision_callback, (XtPointer)pdialog);
537   XtAddCallback(pdialog->dip_vision_button1, XtNcallback,
538 		diplomacy_dialog_vision_callback, (XtPointer)pdialog);
539 
540 
541   pdialog->dip_pact_menubutton=
542     I_L(XtVaCreateManagedWidget("dippactmenubutton",
543 				menuButtonWidgetClass,
544 				pdialog->dip_form0,
545 				NULL));
546   popupmenu=XtVaCreatePopupShell("menu",
547 				 simpleMenuWidgetClass,
548 				 pdialog->dip_pact_menubutton,
549 				 NULL);
550   entry=XtVaCreateManagedWidget(Q_("?diplomatic_state:Cease-fire"),
551 				smeBSBObjectClass, popupmenu, NULL);
552   XtAddCallback(entry, XtNcallback, diplomacy_dialog_ceasefire_callback,
553 		(XtPointer)pdialog);
554   entry=XtVaCreateManagedWidget(Q_("?diplomatic_state:Peace"),
555 				smeBSBObjectClass, popupmenu, NULL);
556   XtAddCallback(entry, XtNcallback, diplomacy_dialog_peace_callback,
557 		(XtPointer)pdialog);
558   entry=XtVaCreateManagedWidget(Q_("?diplomatic_state:Alliance"),
559 				smeBSBObjectClass, popupmenu, NULL);
560   XtAddCallback(entry, XtNcallback, diplomacy_dialog_alliance_callback,
561 		(XtPointer)pdialog);
562 
563   fc_snprintf(buf, sizeof(buf),
564               /* TRANS: The <nation adjective> <ruler-title + player-name>
565                * E.g. "The Czech President Vaclav Havel". */
566               _("This Eternal Treaty\n"
567                 "marks the results of the diplomatic work between\n"
568                 "The %s %s\nand\nThe %s %s"),
569               nation_adjective_for_player(plr0),
570               ruler_title_for_player(plr0, plr0_buf, sizeof(plr0_buf)),
571               nation_adjective_for_player(plr1),
572               ruler_title_for_player(plr1, plr1_buf, sizeof(plr1_buf)));
573 
574   pheadlinem=create_centered_string(buf);
575   pdialog->dip_headline1=XtVaCreateManagedWidget("dipheadlinem",
576 						 labelWidgetClass,
577 						 pdialog->dip_formm,
578 						 XtNlabel, pheadlinem,
579 						 NULL);
580 
581   pdialog->dip_clauselabel =
582     I_L(XtVaCreateManagedWidget("dipclauselabel",
583 				labelWidgetClass,
584 				pdialog->dip_formm,
585 				NULL));
586 
587   pdialog->dip_view =  XtVaCreateManagedWidget("dipview",
588 					       viewportWidgetClass,
589 					       pdialog->dip_formm,
590 					       NULL);
591 
592 
593   pdialog->dip_clauselist = XtVaCreateManagedWidget("dipclauselist",
594 						    listWidgetClass,
595 						    pdialog->dip_view,
596 						    XtNlist,
597 						    (XtArgVal)dummy_clause_list_strings,
598 						    NULL);
599 
600   XtVaGetValues(pdialog->dip_headline1, XtNwidth, &width, NULL);
601   XtVaSetValues(pdialog->dip_view, XtNwidth, width, NULL);
602   XtVaSetValues(pdialog->dip_clauselist, XtNwidth, width, NULL);
603 
604   fc_snprintf(buf, sizeof(buf), _("%s view:"),
605               nation_adjective_for_player(plr0));
606   pdialog->dip_acceptlabel0=XtVaCreateManagedWidget("dipacceptlabel0",
607 						    labelWidgetClass,
608 						    pdialog->dip_formm,
609 						    XtNlabel, buf,
610 						    NULL);
611   pdialog->dip_acceptthumb0=XtVaCreateManagedWidget("dipacceptthumb0",
612 						    labelWidgetClass,
613 						    pdialog->dip_formm,
614 						    XtNbitmap, get_thumb_pixmap(0),
615 						    NULL);
616   fc_snprintf(buf, sizeof(buf), _("%s view:"),
617               nation_adjective_for_player(plr1));
618   pdialog->dip_acceptlabel1=XtVaCreateManagedWidget("dipacceptlabel1",
619 						    labelWidgetClass,
620 						    pdialog->dip_formm,
621 						    XtNlabel, buf,
622 						    NULL);
623   pdialog->dip_acceptthumb1=XtVaCreateManagedWidget("dipacceptthumb1",
624 						    labelWidgetClass,
625 						    pdialog->dip_formm,
626 						    NULL);
627 
628 
629   pdialog->dip_erase_clause_command =
630     I_L(XtVaCreateManagedWidget("diperaseclausecommand",
631 				commandWidgetClass,
632 				pdialog->dip_main_form,
633 				NULL));
634 
635   pdialog->dip_accept_command =
636     I_L(XtVaCreateManagedWidget("dipacceptcommand",
637 				commandWidgetClass,
638 				pdialog->dip_form,
639 				NULL));
640 
641   pdialog->dip_close_command =
642     I_L(XtVaCreateManagedWidget("dipclosecommand",
643 				commandWidgetClass,
644 				pdialog->dip_form,
645 				NULL));
646 
647   XtAddCallback(pdialog->dip_close_command, XtNcallback,
648 		diplomacy_dialog_close_callback, (XtPointer)pdialog);
649   XtAddCallback(pdialog->dip_erase_clause_command, XtNcallback,
650 		diplomacy_dialog_erase_clause_callback, (XtPointer)pdialog);
651   XtAddCallback(pdialog->dip_accept_command, XtNcallback,
652 		diplomacy_dialog_accept_callback, (XtPointer)pdialog);
653 
654 
655   XtRealizeWidget(pdialog->dip_dialog_shell);
656 
657 
658   XtVaGetValues(pdialog->dip_map_menubutton0, XtNwidth, &maxwidth, NULL);
659   XtVaGetValues(pdialog->dip_tech_menubutton0, XtNwidth, &width, NULL);
660   XtVaGetValues(pdialog->dip_city_menubutton0, XtNwidth, &width, NULL);
661   maxwidth=MAX(width, maxwidth);
662   if (pdialog->dip_gold_input0) {
663     XtVaGetValues(pdialog->dip_gold_input0, XtNwidth, &width, NULL);
664   }
665   maxwidth=MAX(width, maxwidth);
666   XtVaSetValues(pdialog->dip_map_menubutton0, XtNwidth, maxwidth, NULL);
667   XtVaSetValues(pdialog->dip_tech_menubutton0, XtNwidth, maxwidth, NULL);
668   XtVaSetValues(pdialog->dip_city_menubutton0, XtNwidth, maxwidth, NULL);
669   if (pdialog->dip_gold_input0) {
670     XtVaSetValues(pdialog->dip_gold_input0,  XtNwidth, maxwidth, NULL);
671   }
672 
673   XtVaGetValues(pdialog->dip_formm, XtNheight, &height, NULL);
674   XtVaSetValues(pdialog->dip_form0, XtNheight, height, NULL);
675   XtVaSetValues(pdialog->dip_form1, XtNheight, height, NULL);
676 
677 
678   free(pheadlinem);
679 
680   update_diplomacy_dialog(pdialog);
681 
682   return pdialog;
683 }
684 
685 
686 /**************************************************************************
687 ...
688 **************************************************************************/
update_diplomacy_dialog(struct Diplomacy_dialog * pdialog)689 void update_diplomacy_dialog(struct Diplomacy_dialog *pdialog)
690 {
691   int i = 0;
692   const int n = sizeof(pdialog->clauselist_strings[0]);
693 
694   clause_list_iterate(pdialog->treaty.clauses, pclause) {
695     client_diplomacy_clause_string(pdialog->clauselist_strings[i], n, pclause);
696     pdialog->clauselist_strings_ptrs[i]=pdialog->clauselist_strings[i];
697     i++;
698   } clause_list_iterate_end;
699 
700   pdialog->clauselist_strings_ptrs[i]=0;
701   XawListChange(pdialog->dip_clauselist, pdialog->clauselist_strings_ptrs,
702 		0, 0, False);
703 
704 /* force refresh of viewport so that scrollbar is added
705    sun seems to need this */
706   XtVaSetValues(pdialog->dip_view, XtNforceBars, False, NULL);
707   XtVaSetValues(pdialog->dip_view, XtNforceBars, True, NULL);
708 
709   xaw_set_bitmap(pdialog->dip_acceptthumb0,
710 		 get_thumb_pixmap(pdialog->treaty.accept0));
711   xaw_set_bitmap(pdialog->dip_acceptthumb1,
712 		 get_thumb_pixmap(pdialog->treaty.accept1));
713 }
714 
715 /****************************************************************
716   Callback for trading techs
717 *****************************************************************/
diplomacy_dialog_tech_callback(Widget w,XtPointer client_data,XtPointer call_data)718 void diplomacy_dialog_tech_callback(Widget w, XtPointer client_data,
719 				    XtPointer call_data)
720 {
721   size_t choice = (size_t) client_data;
722   int giver = (choice >> 24) & 0xff, dest = (choice >> 16) & 0xff, other;
723   int tech = choice & 0xffff;
724 
725   if (player_by_number(giver) == client.conn.playing) {
726     other = dest;
727   } else {
728     other = giver;
729   }
730 
731   dsend_packet_diplomacy_create_clause_req(&client.conn, other, giver,
732 					   CLAUSE_ADVANCE, tech);
733 }
734 
735 /****************************************************************
736 Callback for trading cities
737                               - Kris Bubendorfer
738 *****************************************************************/
diplomacy_dialog_city_callback(Widget w,XtPointer client_data,XtPointer call_data)739 void diplomacy_dialog_city_callback(Widget w, XtPointer client_data,
740 				    XtPointer call_data)
741 {
742   size_t choice = (size_t) client_data;
743   int giver = (choice >> 24) & 0xff, dest = (choice >> 16) & 0xff, other;
744   int city = choice & 0xffff;
745 
746   if (player_by_number(giver) == client.conn.playing) {
747     other = dest;
748   } else {
749     other = giver;
750   }
751 
752   dsend_packet_diplomacy_create_clause_req(&client.conn, other, giver,
753 					   CLAUSE_CITY, city);
754 }
755 
756 /****************************************************************
757 ...
758 *****************************************************************/
diplomacy_dialog_erase_clause_callback(Widget w,XtPointer client_data,XtPointer call_data)759 void diplomacy_dialog_erase_clause_callback(Widget w, XtPointer client_data,
760 					    XtPointer call_data)
761 {
762   struct Diplomacy_dialog *pdialog = (struct Diplomacy_dialog *) client_data;
763   XawListReturnStruct *ret = XawListShowCurrent(pdialog->dip_clauselist);
764 
765   if (ret->list_index != XAW_LIST_NONE) {
766     int i = 0;
767 
768     clause_list_iterate(pdialog->treaty.clauses, pclause) {
769       if (i == ret->list_index) {
770 	dsend_packet_diplomacy_remove_clause_req(&client.conn,
771 						 player_number(pdialog->treaty.plr1),
772 						 player_number(pclause->from),
773 						 pclause->type,
774 						 pclause->value);
775 	return;
776       }
777       i++;
778     } clause_list_iterate_end;
779   }
780 }
781 
782 /****************************************************************
783   Callback for trading map
784 *****************************************************************/
diplomacy_dialog_map_callback(Widget w,XtPointer client_data,XtPointer call_data)785 void diplomacy_dialog_map_callback(Widget w, XtPointer client_data,
786 				   XtPointer call_data)
787 {
788   struct Diplomacy_dialog *pdialog = (struct Diplomacy_dialog *) client_data;
789   struct player *pgiver =
790       (XtParent(XtParent(w)) ==
791        pdialog->dip_map_menubutton0) ? pdialog->treaty.plr0 : pdialog->
792       treaty.plr1;
793 
794   dsend_packet_diplomacy_create_clause_req(&client.conn,
795 					   player_number(pdialog->treaty.plr1),
796 					   player_number(pgiver), CLAUSE_MAP, 0);
797 }
798 
799 /****************************************************************
800   Callback for trading seamap
801 *****************************************************************/
diplomacy_dialog_seamap_callback(Widget w,XtPointer client_data,XtPointer call_data)802 void diplomacy_dialog_seamap_callback(Widget w, XtPointer client_data,
803 				      XtPointer call_data)
804 {
805   struct Diplomacy_dialog *pdialog = (struct Diplomacy_dialog *) client_data;
806   struct player *pgiver =
807       (XtParent(XtParent(w)) ==
808        pdialog->dip_map_menubutton0) ? pdialog->treaty.plr0 : pdialog->
809       treaty.plr1;
810 
811   dsend_packet_diplomacy_create_clause_req(&client.conn,
812 					   player_number(pdialog->treaty.plr1),
813 					   player_number(pgiver), CLAUSE_SEAMAP,
814 					   0);
815 }
816 
817 /****************************************************************
818 ...
819 *****************************************************************/
diplomacy_dialog_vision_callback(Widget w,XtPointer client_data,XtPointer call_data)820 void diplomacy_dialog_vision_callback(Widget w, XtPointer client_data,
821 				   XtPointer call_data)
822 {
823   struct Diplomacy_dialog *pdialog = (struct Diplomacy_dialog *) client_data;
824   struct player *pgiver = (w == pdialog->dip_vision_button0) ?
825       pdialog->treaty.plr0 : pdialog->treaty.plr1;
826 
827   dsend_packet_diplomacy_create_clause_req(&client.conn,
828 					   player_number(pdialog->treaty.plr1),
829 					   player_number(pgiver), CLAUSE_VISION,
830 					   0);
831 }
832 
833 /****************************************************************
834 Generic add-a-clause function for adding pact types
835 *****************************************************************/
diplomacy_dialog_add_pact_clause(Widget w,XtPointer client_data,XtPointer call_data,int type)836 static void diplomacy_dialog_add_pact_clause(Widget w, XtPointer client_data,
837 					     XtPointer call_data, int type)
838 {
839   struct Diplomacy_dialog *pdialog = (struct Diplomacy_dialog *) client_data;
840   struct player *pgiver = (w == pdialog->dip_vision_button0) ?
841       pdialog->treaty.plr0 : pdialog->treaty.plr1;
842 
843   dsend_packet_diplomacy_create_clause_req(&client.conn,
844 					   player_number(pdialog->treaty.plr1),
845 					   player_number(pgiver), type, 0);
846 }
847 
848 /****************************************************************
849 The cease-fire widget was selected; add a cease-fire to the
850 clauses
851 *****************************************************************/
diplomacy_dialog_ceasefire_callback(Widget w,XtPointer client_data,XtPointer call_data)852 void diplomacy_dialog_ceasefire_callback(Widget w, XtPointer client_data,
853 					 XtPointer call_data)
854 {
855   diplomacy_dialog_add_pact_clause(w, client_data, call_data,
856 				   CLAUSE_CEASEFIRE);
857 }
858 
859 /****************************************************************
860 The peace widget was selected; add a peace treaty to the
861 clauses
862 *****************************************************************/
diplomacy_dialog_peace_callback(Widget w,XtPointer client_data,XtPointer call_data)863 void diplomacy_dialog_peace_callback(Widget w, XtPointer client_data,
864 				     XtPointer call_data)
865 {
866   diplomacy_dialog_add_pact_clause(w, client_data, call_data,
867 				   CLAUSE_PEACE);
868 }
869 
870 /****************************************************************
871 The alliance widget was selected; add an alliance to the
872 clauses
873 *****************************************************************/
diplomacy_dialog_alliance_callback(Widget w,XtPointer client_data,XtPointer call_data)874 void diplomacy_dialog_alliance_callback(Widget w, XtPointer client_data,
875 					XtPointer call_data)
876 {
877   diplomacy_dialog_add_pact_clause(w, client_data, call_data,
878 				   CLAUSE_ALLIANCE);
879 }
880 
881 
882 /****************************************************************
883 ...
884 *****************************************************************/
diplomacy_dialog_close_callback(Widget w,XtPointer client_data,XtPointer call_data)885 void diplomacy_dialog_close_callback(Widget w, XtPointer client_data,
886 				     XtPointer call_data)
887 {
888   struct Diplomacy_dialog *pdialog = (struct Diplomacy_dialog *) client_data;
889 
890   dsend_packet_diplomacy_cancel_meeting_req(&client.conn,
891 					    player_number(pdialog->treaty.plr1));
892   close_diplomacy_dialog(pdialog);
893 }
894 
895 
896 /****************************************************************
897 ...
898 *****************************************************************/
diplomacy_dialog_accept_callback(Widget w,XtPointer client_data,XtPointer call_data)899 void diplomacy_dialog_accept_callback(Widget w, XtPointer client_data,
900 				      XtPointer call_data)
901 {
902   struct Diplomacy_dialog *pdialog = (struct Diplomacy_dialog *) client_data;
903 
904   dsend_packet_diplomacy_accept_treaty_req(&client.conn,
905 					   player_number(pdialog->treaty.plr1));
906 }
907 
908 
909 /*****************************************************************
910 ...
911 *****************************************************************/
close_diplomacy_dialog(struct Diplomacy_dialog * pdialog)912 void close_diplomacy_dialog(struct Diplomacy_dialog *pdialog)
913 {
914   XtDestroyWidget(pdialog->dip_dialog_shell);
915 
916   dialog_list_remove(dialog_list, pdialog);
917   free(pdialog);
918 }
919 
920 /*****************************************************************
921 ...
922 *****************************************************************/
find_diplomacy_dialog(int other_player_id)923 static struct Diplomacy_dialog *find_diplomacy_dialog(int other_player_id)
924 {
925   struct player *plr0 = client.conn.playing;
926   struct player *plr1 = player_by_number(other_player_id);
927 
928   if (!dialog_list_list_has_been_initialised) {
929     dialog_list = dialog_list_new();
930     dialog_list_list_has_been_initialised = TRUE;
931   }
932 
933   dialog_list_iterate(dialog_list, pdialog) {
934     if ((pdialog->treaty.plr0 == plr0 && pdialog->treaty.plr1 == plr1) ||
935 	(pdialog->treaty.plr0 == plr1 && pdialog->treaty.plr1 == plr0)) {
936       return pdialog;
937     }
938   } dialog_list_iterate_end;
939 
940   return NULL;
941 }
942 
943 /*****************************************************************
944 ...
945 *****************************************************************/
find_diplomacy_by_input(Widget w)946 static struct Diplomacy_dialog *find_diplomacy_by_input(Widget w)
947 {
948   dialog_list_iterate(dialog_list, pdialog) {
949     if ((pdialog->dip_gold_input0 == w) || (pdialog->dip_gold_input1 == w)) {
950       return pdialog;
951     }
952   } dialog_list_iterate_end;
953 
954   return NULL;
955 }
956 
957 /*****************************************************************
958 ...
959 *****************************************************************/
diplodlg_key_gold(Widget w)960 void diplodlg_key_gold(Widget w)
961 {
962   struct Diplomacy_dialog *pdialog = find_diplomacy_by_input(w);
963 
964   if (pdialog) {
965     struct player *pgiver = (w == pdialog->dip_gold_input0) ?
966 	pdialog->treaty.plr0 : pdialog->treaty.plr1;
967     XtPointer dp;
968     int amount;
969 
970     XtVaGetValues(w, XtNstring, &dp, NULL);
971     if (str_to_int(dp, &amount) && 0 <= amount
972 	&& amount <= pgiver->economic.gold) {
973       dsend_packet_diplomacy_create_clause_req(&client.conn,
974 					       player_number(pdialog->treaty.plr1),
975 					       player_number(pgiver),
976 					       CLAUSE_GOLD, amount);
977       XtVaSetValues(w, XtNstring, "", NULL);
978     } else {
979       output_window_append(ftc_client,
980                            _("Invalid amount of gold specified."));
981     }
982   }
983 }
984 
985 /*****************************************************************
986   Close all dialogs, for when client disconnects from game.
987 *****************************************************************/
close_all_diplomacy_dialogs(void)988 void close_all_diplomacy_dialogs(void)
989 {
990   if (!dialog_list_list_has_been_initialised) {
991     return;
992   }
993 
994   while (dialog_list_size(dialog_list) > 0) {
995     close_diplomacy_dialog(dialog_list_get(dialog_list, 0));
996   }
997 }
998