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/SimpleMenu.h>
26 #include <X11/Xaw/Command.h>
27 #include <X11/Xaw/List.h>
28 
29 /* common & utility */
30 #include "diptreaty.h"
31 #include "fcintl.h"
32 #include "packets.h"
33 #include "player.h"
34 #include "support.h"
35 
36 /* client */
37 #include "chatline.h"
38 #include "client_main.h"
39 #include "climisc.h"
40 #include "diplodlg.h"
41 #include "gui_main.h"
42 #include "gui_stuff.h"
43 #include "inteldlg.h"
44 #include "spaceshipdlg.h"
45 
46 #include "plrdlg.h"
47 
48 static Widget players_dialog_shell;
49 static Widget players_form;
50 static Widget players_label;
51 static Widget players_list;
52 static Widget players_close_command;
53 static Widget players_int_command;
54 static Widget players_meet_command;
55 static Widget players_war_command;
56 static Widget players_vision_command;
57 static Widget players_sship_command;
58 static bool players_dialog_shell_is_raised;
59 
60 static int list_index_to_player_index[MAX_NUM_PLAYERS];
61 
62 
63 static void create_players_dialog(bool raise);
64 static void players_close_callback(Widget w, XtPointer client_data,
65 				   XtPointer call_data);
66 static void players_meet_callback(Widget w, XtPointer client_data,
67 				  XtPointer call_data);
68 static void players_intel_callback(Widget w, XtPointer client_data,
69 				   XtPointer call_data);
70 static void players_list_callback(Widget w, XtPointer client_data,
71 				  XtPointer call_data);
72 static void players_war_callback(Widget w, XtPointer client_data,
73 				 XtPointer call_data);
74 static void players_vision_callback(Widget w, XtPointer client_data,
75 				 XtPointer call_data);
76 static void players_sship_callback(Widget w, XtPointer client_data,
77 				   XtPointer call_data);
78 
79 
80 /******************************************************************/
81 
82 /****************************************************************
83 popup the dialog somewhat inside the main-window
84 *****************************************************************/
popup_players_dialog(bool raise)85 void popup_players_dialog(bool raise)
86 {
87   players_dialog_shell_is_raised = raise;
88 
89   if(!players_dialog_shell)
90     create_players_dialog(raise);
91 
92   if (raise) {
93     XtSetSensitive(main_form, FALSE);
94   }
95 
96   xaw_set_relative_position(toplevel, players_dialog_shell, 5, 25);
97   XtPopup(players_dialog_shell, XtGrabNone);
98 }
99 
100 /****************************************************************
101   Closes the player list dialog.
102 *****************************************************************/
popdown_players_dialog(void)103 void popdown_players_dialog(void)
104 {
105   if (players_dialog_shell) {
106     if (players_dialog_shell_is_raised) {
107       XtSetSensitive(main_form, TRUE);
108     }
109     XtDestroyWidget(players_dialog_shell);
110     players_dialog_shell = 0;
111   }
112 }
113 
114 /****************************************************************
115 ...
116 *****************************************************************/
create_players_dialog(bool raise)117 void create_players_dialog(bool raise)
118 {
119   players_dialog_shell =
120     I_IN(I_T(XtCreatePopupShell("playerspopup",
121 				raise ? transientShellWidgetClass
122 				: topLevelShellWidgetClass,
123 				toplevel, NULL, 0)));
124 
125   players_form = XtVaCreateManagedWidget("playersform",
126 				       formWidgetClass,
127 				       players_dialog_shell, NULL);
128 
129   players_label = I_L(XtVaCreateManagedWidget("playerslabel",
130 					labelWidgetClass,
131 					players_form, NULL));
132 
133 
134   players_list = XtVaCreateManagedWidget("playerslist",
135 					 listWidgetClass,
136 					 players_form,
137 					 NULL);
138 
139   players_close_command =
140     I_L(XtVaCreateManagedWidget("playersclosecommand", commandWidgetClass,
141 				players_form, NULL));
142 
143   players_int_command =
144     I_L(XtVaCreateManagedWidget("playersintcommand", commandWidgetClass,
145 				players_form,
146 				XtNsensitive, False,
147 				NULL));
148 
149   players_meet_command =
150     I_L(XtVaCreateManagedWidget("playersmeetcommand", commandWidgetClass,
151 				players_form,
152 				XtNsensitive, False,
153 				NULL));
154 
155   players_war_command =
156     I_L(XtVaCreateManagedWidget("playerswarcommand", commandWidgetClass,
157 				players_form,
158 				XtNsensitive, False,
159 				NULL));
160 
161   players_vision_command =
162     I_L(XtVaCreateManagedWidget("playersvisioncommand", commandWidgetClass,
163 				players_form,
164 				XtNsensitive, False,
165 				NULL));
166 
167   players_sship_command =
168     I_L(XtVaCreateManagedWidget("playerssshipcommand", commandWidgetClass,
169 				players_form,
170 				XtNsensitive, False,
171 				NULL));
172 
173   XtAddCallback(players_list, XtNcallback, players_list_callback,
174 		NULL);
175 
176   XtAddCallback(players_close_command, XtNcallback, players_close_callback,
177 		NULL);
178 
179   XtAddCallback(players_meet_command, XtNcallback, players_meet_callback,
180 		NULL);
181 
182   XtAddCallback(players_int_command, XtNcallback, players_intel_callback,
183 		NULL);
184 
185   XtAddCallback(players_war_command, XtNcallback, players_war_callback,
186 		NULL);
187 
188   XtAddCallback(players_vision_command, XtNcallback, players_vision_callback,
189 		NULL);
190 
191   XtAddCallback(players_sship_command, XtNcallback, players_sship_callback,
192 		NULL);
193 
194   players_dialog_update();
195 
196   XtRealizeWidget(players_dialog_shell);
197 
198   XSetWMProtocols(display, XtWindow(players_dialog_shell),
199 		  &wm_delete_window, 1);
200   XtOverrideTranslations(players_dialog_shell,
201     XtParseTranslationTable("<Message>WM_PROTOCOLS: msg-close-players()"));
202 }
203 
204 
205 /**************************************************************************
206   Updates the player list dialog.
207 
208   FIXME: use plrdlg_common.c
209 **************************************************************************/
real_players_dialog_update(void * unused)210 void real_players_dialog_update(void *unused)
211 {
212   if (players_dialog_shell) {
213     int j = 0;
214     Dimension width;
215     static CONST_FOR_XAW_LIST_CHANGE char *namelist_ptrs[MAX_NUM_PLAYERS];
216     static char namelist_text[MAX_NUM_PLAYERS][256];
217     const struct player_diplstate *pds;
218 
219     players_iterate(pplayer) {
220       char idlebuf[32], statebuf[32], namebuf[32], dsbuf[32];
221 
222       /* skip barbarians */
223       if(is_barbarian(pplayer))
224         continue;
225 
226       /* text for state */
227       sz_strlcpy(statebuf, plrdlg_col_state(pplayer));
228 
229       /* text for idleness */
230       if(pplayer->nturns_idle>3) {
231 	fc_snprintf(idlebuf, sizeof(idlebuf),
232 		    PL_("(idle %d turn)",
233 			"(idle %d turns)",
234 			pplayer->nturns_idle - 1),
235 		    pplayer->nturns_idle - 1);
236       } else {
237 	idlebuf[0]='\0';
238       }
239 
240       /* text for name, plus AI marker */
241       if (pplayer->ai_controlled) {
242         fc_snprintf(namebuf, sizeof(namebuf), "*%-15s",player_name(pplayer));
243       } else {
244         fc_snprintf(namebuf, sizeof(namebuf), "%-16s",player_name(pplayer));
245       }
246       namebuf[16] = '\0';
247 
248       /* text for diplstate type and turns -- not applicable if this is me */
249       if (NULL == client.conn.playing
250           || pplayer == client.conn.playing) {
251 	strcpy(dsbuf, "-");
252       } else {
253 	pds = player_diplstate_get(client.conn.playing, pplayer);
254 	if (pds->type == DS_CEASEFIRE) {
255 	  fc_snprintf(dsbuf, sizeof(dsbuf), "%s (%d)",
256 		      diplstate_type_translated_name(pds->type),
257 		      pds->turns_left);
258 	} else {
259 	  fc_snprintf(dsbuf, sizeof(dsbuf), "%s",
260 		      diplstate_type_translated_name(pds->type));
261 	}
262       }
263 
264       /* assemble the whole lot */
265       fc_snprintf(namelist_text[j], sizeof(namelist_text[j]),
266 	      "%-16s %-12s %-8s %-15s %-8s %-6s   %-15s%s",
267 	      namebuf,
268 	      nation_adjective_for_player(pplayer),
269 	      get_embassy_status(client.conn.playing, pplayer),
270 	      dsbuf,
271 	      get_vision_status(client.conn.playing, pplayer),
272 	      statebuf,
273 	      player_addr_hack(pplayer),  /* Fixme for multi-conn */
274 	      idlebuf);
275 
276       namelist_ptrs[j]=namelist_text[j];
277       list_index_to_player_index[j] = player_number(pplayer);
278       j++;
279     } players_iterate_end;
280 
281     XawListChange(players_list, namelist_ptrs, j, 0, True);
282 
283     XtVaGetValues(players_list, XtNwidth, &width, NULL);
284     XtVaSetValues(players_label, XtNwidth, width, NULL);
285   }
286 }
287 
288 /**************************************************************************
289 ...
290 **************************************************************************/
players_list_callback(Widget w,XtPointer client_data,XtPointer call_data)291 void players_list_callback(Widget w, XtPointer client_data,
292 			   XtPointer call_data)
293 
294 {
295   XawListReturnStruct *ret;
296 
297   ret = XawListShowCurrent(players_list);
298 
299   XtSetSensitive(players_meet_command, FALSE);
300   XtSetSensitive(players_int_command, FALSE);
301   if (ret->list_index != XAW_LIST_NONE) {
302     struct player *pplayer =
303       player_by_number(list_index_to_player_index[ret->list_index]);
304 
305     if (pplayer->spaceship.state != SSHIP_NONE)
306       XtSetSensitive(players_sship_command, TRUE);
307     else
308       XtSetSensitive(players_sship_command, FALSE);
309 
310     if (NULL != client.conn.playing && pplayer->is_alive) {
311       XtSetSensitive(players_war_command,
312 		     client.conn.playing != pplayer
313 		     && !pplayers_at_war(client.conn.playing, pplayer));
314     }
315 
316     if (NULL != client.conn.playing) {
317       XtSetSensitive(players_vision_command,
318 		     gives_shared_vision(client.conn.playing, pplayer));
319 
320       XtSetSensitive(players_meet_command, can_meet_with_player(pplayer));
321     }
322     XtSetSensitive(players_int_command, can_intel_with_player(pplayer));
323   }
324 }
325 
326 
327 /**************************************************************************
328 ...
329 **************************************************************************/
players_close_callback(Widget w,XtPointer client_data,XtPointer call_data)330 void players_close_callback(Widget w, XtPointer client_data,
331 			      XtPointer call_data)
332 {
333   popdown_players_dialog();
334 }
335 
336 /****************************************************************
337 ...
338 *****************************************************************/
plrdlg_msg_close(Widget w)339 void plrdlg_msg_close(Widget w)
340 {
341   players_close_callback(w, NULL, NULL);
342 }
343 
344 /**************************************************************************
345 ...
346 **************************************************************************/
players_meet_callback(Widget w,XtPointer client_data,XtPointer call_data)347 void players_meet_callback(Widget w, XtPointer client_data,
348 			      XtPointer call_data)
349 {
350   XawListReturnStruct *ret = XawListShowCurrent(players_list);
351 
352   if (ret->list_index != XAW_LIST_NONE) {
353     int player_index = list_index_to_player_index[ret->list_index];
354     struct player *pplayer = player_by_number(player_index);
355 
356     if (can_meet_with_player(pplayer)) {
357       dsend_packet_diplomacy_init_meeting_req(&client.conn, player_index);
358     } else {
359       output_window_append(ftc_client,
360                            _("You need an embassy to establish"
361                              " a diplomatic meeting."));
362     }
363   }
364 }
365 
366 /**************************************************************************
367 ...
368 **************************************************************************/
players_intel_callback(Widget w,XtPointer client_data,XtPointer call_data)369 void players_intel_callback(Widget w, XtPointer client_data,
370 			    XtPointer call_data)
371 {
372   XawListReturnStruct *ret = XawListShowCurrent(players_list);
373 
374   if (ret->list_index != XAW_LIST_NONE) {
375     int player_index = list_index_to_player_index[ret->list_index];
376     struct player *pplayer = player_by_number(player_index);
377 
378     if (can_intel_with_player(pplayer)) {
379       popup_intel_dialog(pplayer);
380     }
381   }
382 }
383 
384 /**************************************************************************
385 ...
386 **************************************************************************/
players_war_callback(Widget w,XtPointer client_data,XtPointer call_data)387 void players_war_callback(Widget w, XtPointer client_data,
388                           XtPointer call_data)
389 {
390   XawListReturnStruct *ret = XawListShowCurrent(players_list);
391 
392   if (ret->list_index != XAW_LIST_NONE) {
393     int player_index = list_index_to_player_index[ret->list_index];
394 
395     /* can be any pact clause */
396     dsend_packet_diplomacy_cancel_pact(&client.conn, player_index,
397 				       CLAUSE_CEASEFIRE);
398   }
399 }
400 
401 /**************************************************************************
402 ...
403 **************************************************************************/
players_vision_callback(Widget w,XtPointer client_data,XtPointer call_data)404 void players_vision_callback(Widget w, XtPointer client_data,
405                           XtPointer call_data)
406 {
407   XawListReturnStruct *ret = XawListShowCurrent(players_list);
408 
409   if (ret->list_index != XAW_LIST_NONE) {
410     int player_index = list_index_to_player_index[ret->list_index];
411 
412     dsend_packet_diplomacy_cancel_pact(&client.conn, player_index,
413 				       CLAUSE_VISION);
414   }
415 }
416 
417 /**************************************************************************
418 ...
419 **************************************************************************/
players_sship_callback(Widget w,XtPointer client_data,XtPointer call_data)420 void players_sship_callback(Widget w, XtPointer client_data,
421 			    XtPointer call_data)
422 {
423   XawListReturnStruct *ret = XawListShowCurrent(players_list);
424 
425   if (ret->list_index != XAW_LIST_NONE) {
426     int player_index = list_index_to_player_index[ret->list_index];
427     struct player *pplayer = player_by_number(player_index);
428 
429     popup_spaceship_dialog(pplayer);
430   }
431 }
432