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/SimpleMenu.h>
27 #include <X11/Xaw/List.h>
28 
29 /* utility */
30 #include "fcintl.h"
31 #include "log.h"
32 #include "shared.h"
33 #include "support.h"
34 
35 /* common */
36 #include "government.h"
37 #include "packets.h"
38 #include "player.h"
39 #include "research.h"
40 
41 /* client */
42 #include "client_main.h"
43 
44 /* gui-xaw */
45 #include "gui_main.h"
46 #include "gui_stuff.h"
47 #include "mapview.h"
48 #include "optiondlg.h"
49 
50 #include "inteldlg.h"
51 
52 /******************************************************************/
53 struct intel_dialog {
54   struct player *pplayer;
55 
56   Widget intel_dialog_shell;
57   Widget intel_form;
58   Widget intel_label;
59   Widget intel_close_command;
60   Widget intel_diplo_command;
61   bool intel_dialog_shell_is_raised;
62 
63   Widget intel_diplo_dialog_shell;
64   Widget intel_diplo_form;
65   Widget intel_diplo_label;
66   Widget intel_diplo_list;
67   Widget intel_diplo_close_command;
68   bool intel_diplo_dialog_shell_is_raised;
69 };
70 
71 #define SPECLIST_TAG dialog
72 #define SPECLIST_TYPE struct intel_dialog
73 #include "speclist.h"
74 
75 #define dialog_list_iterate(dialoglist, pdialog) \
76     TYPED_LIST_ITERATE(struct intel_dialog, dialoglist, pdialog)
77 #define dialog_list_iterate_end  LIST_ITERATE_END
78 
79 static struct dialog_list *dialog_list = NULL;
80 static bool dialog_list_has_been_initialised = FALSE;
81 
82 /******************************************************************/
83 
84 struct intel_dialog *get_intel_dialog(struct player *pplayer);
85 void popdown_intel_dialog(struct intel_dialog *pdialog);
86 void create_intel_dialog(struct intel_dialog *pdialog, bool raise);
87 
88 void intel_close_callback(Widget w, XtPointer client_data,
89 			  XtPointer call_data);
90 void intel_diplo_callback(Widget w, XtPointer client_data,
91 			  XtPointer call_data);
92 
93 void popup_intel_diplo_dialog(struct player *pplayer, bool raise);
94 void popdown_intel_diplo_dialog(struct intel_dialog *pdialog);
95 void create_intel_diplo_dialog(struct intel_dialog *pdialog, bool raise);
96 void update_intel_diplo_dialog(struct intel_dialog *pdialog);
97 void intel_diplo_close_callback(Widget w, XtPointer client_data,
98 				XtPointer call_data);
99 
100 /****************************************************************
101   Get an intelligence dialog for the given player.
102 *****************************************************************/
get_intel_dialog(struct player * pplayer)103 struct intel_dialog *get_intel_dialog(struct player *pplayer)
104 {
105   if (!dialog_list_has_been_initialised) {
106     dialog_list = dialog_list_new();
107     dialog_list_has_been_initialised = TRUE;
108   }
109 
110   dialog_list_iterate(dialog_list, pdialog) {
111     if (pdialog->pplayer == pplayer) {
112       return pdialog;
113     }
114   } dialog_list_iterate_end;
115 
116   return NULL;
117 }
118 
119 /****************************************************************
120   Popup an intelligence dialog for the given player.
121 *****************************************************************/
popup_intel_dialog(struct player * pplayer)122 void popup_intel_dialog(struct player *pplayer)
123 {
124   struct intel_dialog *pdialog;
125   bool raise = FALSE; /* Drop when we'll have raise-parametered popup */
126 
127   if (!(pdialog = get_intel_dialog(pplayer))) {
128     pdialog = fc_malloc(sizeof(struct intel_dialog));
129     pdialog->pplayer = pplayer;
130     pdialog->intel_dialog_shell = 0;
131     pdialog->intel_diplo_dialog_shell = 0;
132     dialog_list_prepend(dialog_list, pdialog);
133   }
134 
135   if (!(pdialog->intel_dialog_shell)) {
136     create_intel_dialog(pdialog, raise);
137   }
138 
139   xaw_set_relative_position(toplevel, pdialog->intel_dialog_shell, 25, 25);
140   XtPopup(pdialog->intel_dialog_shell, XtGrabNone);
141   if (pdialog->intel_dialog_shell_is_raised) {
142     XtSetSensitive(main_form, FALSE);
143   }
144 }
145 
146 /****************************************************************
147   Close an intelligence dialog.
148 *****************************************************************/
popdown_intel_dialog(struct intel_dialog * pdialog)149 void popdown_intel_dialog(struct intel_dialog *pdialog)
150 {
151   if (pdialog->intel_dialog_shell_is_raised) {
152     XtSetSensitive(main_form, TRUE);
153   }
154   XtDestroyWidget(pdialog->intel_dialog_shell);
155   pdialog->intel_dialog_shell = 0;
156 
157   if (!(pdialog->intel_diplo_dialog_shell)) {
158     dialog_list_remove(dialog_list, pdialog);
159     free(pdialog);
160   }
161 }
162 
163 /**************************************************************************
164   Close an intelligence dialog for the given player.
165 **************************************************************************/
close_intel_dialog(struct player * p)166 void close_intel_dialog(struct player *p)
167 {
168   struct intel_dialog *pdialog = get_intel_dialog(p);
169   popdown_intel_dialog(pdialog);
170 }
171 
172 /****************************************************************
173 ...
174 *****************************************************************/
create_intel_dialog(struct intel_dialog * pdialog,bool raise)175 void create_intel_dialog(struct intel_dialog *pdialog, bool raise)
176 {
177   char buf[4 * MAX_LEN_NAME], plr_buf[4 * MAX_LEN_NAME];
178   struct city *pcity;
179   const struct research *presearch = research_get(pdialog->pplayer);
180 
181   static char *tech_list_names_ptrs[A_LAST+1];
182   static char tech_list_names[A_LAST+1][200];
183   int j = 0;
184 
185   pdialog->intel_dialog_shell_is_raised = raise;
186 
187   I_T(pdialog->intel_dialog_shell =
188     XtCreatePopupShell("intelpopup",
189 		       raise ? transientShellWidgetClass
190 		       : topLevelShellWidgetClass,
191 		       toplevel, NULL, 0));
192 
193   pdialog->intel_form = XtVaCreateManagedWidget("intelform",
194 						formWidgetClass,
195 						pdialog->intel_dialog_shell,
196 						NULL);
197 
198   fc_snprintf(buf, sizeof(buf),
199 	      _("Intelligence Information for the %s Empire"),
200 	      nation_adjective_for_player(pdialog->pplayer));
201 
202   pdialog->intel_label = I_L(XtVaCreateManagedWidget("inteltitlelabel",
203 						     labelWidgetClass,
204 						     pdialog->intel_form,
205 						     XtNlabel, buf,
206 						     NULL));
207 
208   fc_snprintf(buf, sizeof(buf), _("Ruler: %s"),
209               ruler_title_for_player(pdialog->pplayer,
210                                      plr_buf, sizeof(plr_buf)));
211   XtVaCreateManagedWidget("intelnamelabel",
212 			  labelWidgetClass,
213 			  pdialog->intel_form,
214 			  XtNlabel, buf,
215 			  NULL);
216 
217   fc_snprintf(buf, sizeof(buf), _("Government: %s"),
218 	      government_name_for_player(pdialog->pplayer));
219   XtVaCreateManagedWidget("intelgovlabel",
220 			  labelWidgetClass,
221 			  pdialog->intel_form,
222 			  XtNlabel, buf,
223 			  NULL);
224 
225   fc_snprintf(buf, sizeof(buf), _("Gold: %d"),
226 	      pdialog->pplayer->economic.gold);
227   XtVaCreateManagedWidget("intelgoldlabel",
228 			  labelWidgetClass,
229 			  pdialog->intel_form,
230 			  XtNlabel, buf,
231 			  NULL);
232 
233   fc_snprintf(buf, sizeof(buf), _("Tax: %d%%"),
234 	      pdialog->pplayer->economic.tax);
235   XtVaCreateManagedWidget("inteltaxlabel",
236 			  labelWidgetClass,
237 			  pdialog->intel_form,
238 			  XtNlabel, buf,
239 			  NULL);
240 
241   fc_snprintf(buf, sizeof(buf), _("Science: %d%%"),
242 	      pdialog->pplayer->economic.science);
243   XtVaCreateManagedWidget("intelscilabel",
244 			  labelWidgetClass,
245 			  pdialog->intel_form,
246 			  XtNlabel, buf,
247 			  NULL);
248 
249   fc_snprintf(buf, sizeof(buf), _("Luxury: %d%%"),
250 	      pdialog->pplayer->economic.luxury);
251   XtVaCreateManagedWidget("intelluxlabel",
252 			  labelWidgetClass,
253 			  pdialog->intel_form,
254 			  XtNlabel, buf,
255 			  NULL);
256 
257   switch (presearch->researching) {
258   case A_UNKNOWN:
259     fc_snprintf(buf, sizeof(buf), _("Researching: (Unknown)"));
260     break;
261   case A_UNSET:
262     fc_snprintf(buf, sizeof(buf), _("Researching: Unknown(%d/-)"),
263                 presearch->bulbs_researched);
264     break;
265   default:
266     fc_snprintf(buf, sizeof(buf), _("Researching: %s(%d/%d)"),
267                 research_advance_name_translation(presearch,
268                                                   presearch->researching),
269                 presearch->bulbs_researched,
270                 presearch->client.researching_cost);
271     break;
272   };
273 
274   XtVaCreateManagedWidget("intelreslabel",
275 			  labelWidgetClass,
276 			  pdialog->intel_form,
277 			  XtNlabel, buf,
278 			  NULL);
279 
280   pcity = player_capital(pdialog->pplayer);
281   fc_snprintf(buf, sizeof(buf), _("Capital: %s"),
282               /* TRANS: "unknown" location */
283               (!pcity) ? _("(unknown)") : city_name_get(pcity));
284   XtVaCreateManagedWidget("intelcapitallabel",
285                           labelWidgetClass,
286                           pdialog->intel_form,
287                           XtNlabel, buf,
288                           NULL);
289 
290   advance_index_iterate(A_FIRST, i) {
291     if (research_invention_state(presearch, i)
292         == TECH_KNOWN) {
293       if (research_invention_state(research_get(client_player()), i)
294           == TECH_KNOWN) {
295 	sz_strlcpy(tech_list_names[j], advance_name_translation(advance_by_number(i)));
296       } else {
297 	fc_snprintf(tech_list_names[j], sizeof(tech_list_names[j]),
298 		    "%s*", advance_name_translation(advance_by_number(i)));
299       }
300       tech_list_names_ptrs[j]=tech_list_names[j];
301       j++;
302     }
303   } advance_index_iterate_end;
304   tech_list_names_ptrs[j]=0;
305 
306   XtVaCreateManagedWidget("inteltechlist",
307 			  listWidgetClass,
308 			  pdialog->intel_form,
309 			  XtNlist, tech_list_names_ptrs,
310 			  NULL);
311 
312   pdialog->intel_close_command =
313     I_L(XtVaCreateManagedWidget("intelclosecommand",
314 				commandWidgetClass,
315 				pdialog->intel_form, NULL));
316 
317   pdialog->intel_diplo_command =
318     I_L(XtVaCreateManagedWidget("inteldiplocommand",
319 				commandWidgetClass,
320 				pdialog->intel_form, NULL));
321 
322   XtAddCallback(pdialog->intel_close_command, XtNcallback,
323 		intel_close_callback, (XtPointer)pdialog);
324   XtAddCallback(pdialog->intel_diplo_command, XtNcallback,
325 		intel_diplo_callback,
326 		INT_TO_XTPOINTER(player_number(pdialog->pplayer)));
327   XtRealizeWidget(pdialog->intel_dialog_shell);
328 
329   xaw_horiz_center(pdialog->intel_label);
330 
331   XSetWMProtocols(display, XtWindow(pdialog->intel_dialog_shell),
332 		  &wm_delete_window, 1);
333   XtOverrideTranslations(pdialog->intel_dialog_shell,
334     XtParseTranslationTable("<Message>WM_PROTOCOLS: msg-close-intel()"));
335 }
336 
337 /****************************************************************************
338   Update the intelligence dialog for the given player.  This is called by
339   the core client code when that player's information changes.
340 ****************************************************************************/
update_intel_dialog(struct player * p)341 void update_intel_dialog(struct player *p)
342 {
343   /* PORTME */
344 }
345 
346 /**************************************************************************
347 ...
348 **************************************************************************/
intel_close_callback(Widget w,XtPointer client_data,XtPointer call_data)349 void intel_close_callback(Widget w, XtPointer client_data,
350 			  XtPointer call_data)
351 {
352   popdown_intel_dialog((struct intel_dialog *)client_data);
353 }
354 
355 /**************************************************************************
356 ...
357 **************************************************************************/
intel_diplo_callback(Widget w,XtPointer client_data,XtPointer call_data)358 void intel_diplo_callback(Widget w, XtPointer client_data,
359 			  XtPointer call_data)
360 {
361   popup_intel_diplo_dialog(player_by_number(XTPOINTER_TO_INT(client_data)),
362 			   FALSE);
363 }
364 
365 /**************************************************************************
366 ...
367 **************************************************************************/
intel_dialog_msg_close(Widget w)368 void intel_dialog_msg_close(Widget w)
369 {
370   dialog_list_iterate(dialog_list, pdialog) {
371     if (pdialog->intel_dialog_shell == w) {
372       popdown_intel_dialog(pdialog);
373       return;
374     }
375   } dialog_list_iterate_end;
376 }
377 
378 /****************************************************************
379   Popup a player's relations dialog for the given player.
380 *****************************************************************/
popup_intel_diplo_dialog(struct player * pplayer,bool raise)381 void popup_intel_diplo_dialog(struct player *pplayer, bool raise)
382 {
383   struct intel_dialog *pdialog;
384 
385   if (!(pdialog = get_intel_dialog(pplayer))) {
386     pdialog = fc_malloc(sizeof(struct intel_dialog));
387     pdialog->pplayer = pplayer;
388     pdialog->intel_dialog_shell = 0;
389     pdialog->intel_diplo_dialog_shell = 0;
390     dialog_list_prepend(dialog_list, pdialog);
391   }
392 
393   if (!(pdialog->intel_diplo_dialog_shell)) {
394     create_intel_diplo_dialog(pdialog, raise);
395   }
396 
397   xaw_set_relative_position(toplevel,
398 			    pdialog->intel_diplo_dialog_shell, 25, 25);
399   XtPopup(pdialog->intel_diplo_dialog_shell, XtGrabNone);
400   if (pdialog->intel_diplo_dialog_shell_is_raised) {
401     XtSetSensitive(main_form, FALSE);
402   }
403 }
404 
405 /****************************************************************
406   Close a player's relations dialog.
407 *****************************************************************/
popdown_intel_diplo_dialog(struct intel_dialog * pdialog)408 void popdown_intel_diplo_dialog(struct intel_dialog *pdialog)
409 {
410   if (pdialog->intel_diplo_dialog_shell_is_raised) {
411     XtSetSensitive(main_form, TRUE);
412   }
413   XtDestroyWidget(pdialog->intel_diplo_dialog_shell);
414   pdialog->intel_diplo_dialog_shell = 0;
415 
416   if (!(pdialog->intel_dialog_shell)) {
417     dialog_list_remove(dialog_list, pdialog);
418     free(pdialog);
419   }
420 }
421 
422 /****************************************************************
423   Create a player's relations dialog for the given player.
424 *****************************************************************/
create_intel_diplo_dialog(struct intel_dialog * pdialog,bool raise)425 void create_intel_diplo_dialog(struct intel_dialog *pdialog, bool raise)
426 {
427   char buf[4 * MAX_LEN_NAME], plr_buf[4 * MAX_LEN_NAME];
428 
429   pdialog->intel_diplo_dialog_shell_is_raised = raise;
430 
431   pdialog->intel_diplo_dialog_shell =
432     I_IN(I_T(XtCreatePopupShell("inteldiplopopup",
433 				raise ? transientShellWidgetClass
434 				: topLevelShellWidgetClass,
435 				toplevel, NULL, 0)));
436 
437   pdialog->intel_diplo_form =
438     XtVaCreateManagedWidget("inteldiploform",
439 			    formWidgetClass,
440 			    pdialog->intel_diplo_dialog_shell,
441 			    NULL);
442 
443   fc_snprintf(buf, sizeof(buf),
444 	      _("Intelligence Diplomacy Information for the %s Empire"),
445 	      nation_adjective_for_player(pdialog->pplayer));
446 
447   pdialog->intel_diplo_label =
448     I_L(XtVaCreateManagedWidget("inteldiplolabel",
449 				labelWidgetClass,
450 				pdialog->intel_diplo_form,
451 				XtNlabel, buf,
452 				NULL));
453 
454   fc_snprintf(buf, sizeof(buf), _("Ruler: %s"),
455               ruler_title_for_player(pdialog->pplayer,
456                                      plr_buf, sizeof(plr_buf)));
457   XtVaCreateManagedWidget("inteldiplonamelabel",
458 			  labelWidgetClass,
459 			  pdialog->intel_diplo_form,
460 			  XtNlabel, buf,
461 			  NULL);
462 
463   pdialog->intel_diplo_list =
464     XtVaCreateManagedWidget("inteldiplolist",
465 			    listWidgetClass,
466 			    pdialog->intel_diplo_form,
467 			    NULL);
468 
469   pdialog->intel_diplo_close_command =
470     I_L(XtVaCreateManagedWidget("inteldiploclosecommand",
471 				commandWidgetClass,
472 				pdialog->intel_diplo_form,
473 				NULL));
474 
475   XtAddCallback(pdialog->intel_diplo_close_command, XtNcallback,
476 		intel_diplo_close_callback, (XtPointer)pdialog);
477 
478   update_intel_diplo_dialog(pdialog);
479 
480   XtRealizeWidget(pdialog->intel_diplo_dialog_shell);
481 
482   XSetWMProtocols(display, XtWindow(pdialog->intel_diplo_dialog_shell),
483 		  &wm_delete_window, 1);
484   XtOverrideTranslations(pdialog->intel_diplo_dialog_shell,
485     XtParseTranslationTable("<Message>WM_PROTOCOLS: msg-close-intel-diplo()"));
486 }
487 
488 /****************************************************************
489   Update a player's relations dialog for the given player.
490 *****************************************************************/
update_intel_diplo_dialog(struct intel_dialog * pdialog)491 void update_intel_diplo_dialog(struct intel_dialog *pdialog)
492 {
493   int i;
494   Dimension width;
495   static CONST_FOR_XAW_LIST_CHANGE char *namelist_ptrs[MAX_NUM_PLAYERS];
496   static char namelist_text[MAX_NUM_PLAYERS][72];
497   const struct player_diplstate *state;
498 
499   if (pdialog->intel_diplo_dialog_shell) {
500     i = 0;
501     players_iterate(other) {
502       if (other == pdialog->pplayer) {
503 	continue;
504       }
505       state = player_diplstate_get(pdialog->pplayer, other);
506       fc_snprintf(namelist_text[i], sizeof(namelist_text[i]),
507 		  "%-32s %-16s %-16s",
508 		  player_name(other),
509 		  nation_adjective_for_player(other),
510 		  diplstate_type_translated_name(state->type));
511       namelist_ptrs[i] = namelist_text[i];
512       i++;
513     } players_iterate_end;
514 
515     XawListChange(pdialog->intel_diplo_list, namelist_ptrs, i, 0, True);
516 
517     XtVaGetValues(pdialog->intel_diplo_list, XtNwidth, &width, NULL);
518     XtVaSetValues(pdialog->intel_diplo_label, XtNwidth, width, NULL);
519   }
520 }
521 
522 /**************************************************************************
523 ...
524 **************************************************************************/
intel_diplo_close_callback(Widget w,XtPointer client_data,XtPointer call_data)525 void intel_diplo_close_callback(Widget w, XtPointer client_data,
526 			  XtPointer call_data)
527 {
528   popdown_intel_diplo_dialog((struct intel_dialog *)client_data);
529 }
530 
531 /**************************************************************************
532 ...
533 **************************************************************************/
intel_diplo_dialog_msg_close(Widget w)534 void intel_diplo_dialog_msg_close(Widget w)
535 {
536   dialog_list_iterate(dialog_list, pdialog) {
537     if (pdialog->intel_diplo_dialog_shell == w) {
538       popdown_intel_diplo_dialog(pdialog);
539       return;
540     }
541   } dialog_list_iterate_end;
542 }
543