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 <errno.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21
22 #include <X11/Intrinsic.h>
23 #include <X11/StringDefs.h>
24 #include <X11/Xaw/Form.h>
25 #include <X11/Xaw/Label.h>
26 #include <X11/Xaw/SimpleMenu.h>
27 #include <X11/Xaw/Command.h>
28 #include <X11/Xaw/AsciiText.h>
29 #include <X11/Xaw/List.h>
30 #include <X11/Xaw/Viewport.h>
31
32 /* common & utility */
33 #include "fcintl.h"
34 #include "log.h"
35 #include "mem.h" /* fc_strdup() */
36 #include "support.h"
37 #include "version.h"
38
39 /* client */
40 #include "client_main.h"
41 #include "clinet.h" /* connect_to_server() */
42 #include "packhand.h"
43 #include "servers.h"
44
45 #include "chatline.h"
46 #include "gui_main.h"
47 #include "gui_stuff.h"
48 #include "pages.h"
49
50 #include "connectdlg_common.h"
51 #include "connectdlg.h"
52
53
54 enum connection_state {
55 LOGIN_TYPE,
56 NEW_PASSWORD_TYPE,
57 ENTER_PASSWORD_TYPE,
58 WAITING_TYPE
59 };
60
61 static enum connection_state connection_status;
62
63
64 static Widget connectdlg_shell;
65 static Widget connectdlg_form;
66 #if IS_BETA_VERSION
67 static Widget connectdlg_beta_label;
68 #endif
69 static Widget connectdlg_select_label;
70 static Widget connectdlg_host_label;
71 static Widget connectdlg_host_text;
72 static Widget connectdlg_port_label;
73 static Widget connectdlg_port_text;
74 static Widget connectdlg_login_label;
75 static Widget connectdlg_login_text;
76 static Widget connectdlg_password_label;
77 static Widget connectdlg_password_text;
78 static Widget connectdlg_verify_label;
79 static Widget connectdlg_verify_text;
80 static Widget connectdlg_message_label;
81 static Widget connectdlg_connect_button;
82 static Widget connectdlg_lan_button;
83 static Widget connectdlg_meta_button;
84 static Widget connectdlg_quit_button;
85
86 void connectdlg_connect_callback(Widget w, XtPointer client_data,
87 XtPointer call_data);
88 void connectdlg_lan_callback(Widget w, XtPointer client_data,
89 XtPointer call_data);
90 void connectdlg_meta_callback(Widget w, XtPointer client_data,
91 XtPointer call_data);
92 void connectdlg_quit_callback(Widget w, XtPointer client_data,
93 XtPointer call_data);
94
95 /****************************************************************/
96
97 /* Serverlist */
98 static Widget connectdlg_serverlist_shell;
99
100 static Widget connectdlg_serverlist_form;
101 static Widget connectdlg_serverlist_legend_label;
102 static Widget connectdlg_serverlist_viewport;
103 static Widget connectdlg_serverlist_list;
104 static Widget connectdlg_serverlist_update_button;
105 static Widget connectdlg_serverlist_close_button;
106
107 static struct server_scan *lan_scan, *meta_scan;
108
109 void connectdlg_serverlist_popup(void);
110 void server_scan_error(struct server_scan *scan, const char *message);
111 void connectdlg_serverlist_update_callback(Widget w, XtPointer client_data,
112 XtPointer call_data);
113 void connectdlg_serverlist_close_callback(Widget w, XtPointer client_data,
114 XtPointer call_data);
115 void connectdlg_serverlist_list_callback(Widget w, XtPointer client_data,
116 XtPointer call_data);
117
118 /* FIXME: Replace magic 64 with proper constant. */
119 static char *servers_list[64]={NULL};
120
121 static void server_list_timer(XtPointer client_data, XtIntervalId * id);
122 static int get_server_list(char **list, char *errbuf, int n_errbuf);
123
124 static bool lan_mode; /* true for LAN mode, false when Meta mode */
125 static int num_lanservers_timer = 0;
126
127
128 /****************************************************************************
129 Aligns widths of connect dialog labels and texts.
130 ****************************************************************************/
connectdlg_align_labels(void)131 static void connectdlg_align_labels(void)
132 {
133 Dimension width, s_width, t_width, max_width = 0;
134
135 #if IS_BETA_VERSION
136 XtVaGetValues(connectdlg_beta_label, XtNwidth, &width, NULL);
137 max_width = width;
138 #endif
139
140 XtVaGetValues(connectdlg_select_label, XtNwidth, &width, NULL);
141 if (width > max_width) {
142 max_width = width;
143 }
144 XtVaGetValues(connectdlg_message_label, XtNwidth, &width, NULL);
145 if (width > max_width) {
146 max_width = width;
147 }
148
149 /* FIXME: Replace 7 with proper XtN* variable value */
150 XtVaGetValues(connectdlg_host_label, XtNwidth, &width, NULL);
151 XtVaGetValues(connectdlg_host_text, XtNwidth, &t_width, NULL);
152 s_width = width;
153 if (width + 7 + t_width > max_width) {
154 max_width = width + 7 + t_width;
155 }
156 XtVaGetValues(connectdlg_port_label, XtNwidth, &width, NULL);
157 XtVaGetValues(connectdlg_port_text, XtNwidth, &t_width, NULL);
158 if (width > s_width) {
159 s_width = width;
160 }
161 if (width + 7 + t_width > max_width) {
162 max_width = width + 7 + t_width;
163 }
164 XtVaGetValues(connectdlg_login_label, XtNwidth, &width, NULL);
165 XtVaGetValues(connectdlg_login_text, XtNwidth, &t_width, NULL);
166 if (width > s_width) {
167 s_width = width;
168 }
169 if (width + 7 + t_width > max_width) {
170 max_width = width + 7 + t_width;
171 }
172 XtVaGetValues(connectdlg_password_label, XtNwidth, &width, NULL);
173 XtVaGetValues(connectdlg_password_text, XtNwidth, &t_width, NULL);
174 if (width > s_width) {
175 s_width = width;
176 }
177 if (width + 7 + t_width > max_width) {
178 max_width = width + 7 + t_width;
179 }
180 XtVaGetValues(connectdlg_verify_label, XtNwidth, &width, NULL);
181 XtVaGetValues(connectdlg_verify_text, XtNwidth, &t_width, NULL);
182 if (width > s_width) {
183 s_width = width;
184 }
185 if (width + 7 + t_width > max_width) {
186 max_width = width + 7 + t_width;
187 }
188
189 #if IS_BETA_VERSION
190 XtVaSetValues(connectdlg_beta_label, XtNwidth, max_width, NULL);
191 #endif
192 XtVaSetValues(connectdlg_select_label, XtNwidth, max_width, NULL);
193 XtVaSetValues(connectdlg_message_label, XtNwidth, max_width, NULL);
194 XtVaSetValues(connectdlg_message_label, XtNresizable, False, NULL);
195
196 XtVaSetValues(connectdlg_host_label, XtNwidth, s_width, NULL);
197 XtVaSetValues(connectdlg_port_label, XtNwidth, s_width, NULL);
198 XtVaSetValues(connectdlg_login_label, XtNwidth, s_width, NULL);
199 XtVaSetValues(connectdlg_password_label, XtNwidth, s_width, NULL);
200 XtVaSetValues(connectdlg_verify_label, XtNwidth, s_width, NULL);
201
202 XtVaSetValues(connectdlg_host_text, XtNresizable, True, NULL);
203 XtVaSetValues(connectdlg_host_text, XtNwidth, max_width - s_width - 7,
204 NULL);
205 XtVaSetValues(connectdlg_host_text, XtNresizable, False, NULL);
206 XtVaSetValues(connectdlg_port_text, XtNresizable, True, NULL);
207 XtVaSetValues(connectdlg_port_text, XtNwidth, max_width - s_width - 7,
208 NULL);
209 XtVaSetValues(connectdlg_port_text, XtNresizable, False, NULL);
210 XtVaSetValues(connectdlg_login_text, XtNresizable, True, NULL);
211 XtVaSetValues(connectdlg_login_text, XtNwidth, max_width - s_width - 7,
212 NULL);
213 XtVaSetValues(connectdlg_login_text, XtNresizable, False, NULL);
214 XtVaSetValues(connectdlg_password_text, XtNresizable, True, NULL);
215 XtVaSetValues(connectdlg_password_text, XtNwidth, max_width - s_width - 7,
216 NULL);
217 XtVaSetValues(connectdlg_password_text, XtNresizable, False, NULL);
218 XtVaSetValues(connectdlg_verify_text, XtNresizable, True, NULL);
219 XtVaSetValues(connectdlg_verify_text, XtNwidth, max_width - s_width - 7,
220 NULL);
221 XtVaSetValues(connectdlg_verify_text, XtNresizable, False, NULL);
222 }
223
224 /**************************************************************************
225 Creates connect dialog.
226 **************************************************************************/
connectdlg_create(void)227 static void connectdlg_create(void)
228 {
229 char buf[64];
230
231 if (connectdlg_shell) {
232 return;
233 }
234
235 connectdlg_shell =
236 I_IN(I_T(XtCreatePopupShell("connectdialog", topLevelShellWidgetClass,
237 toplevel, NULL, 0)));
238 connectdlg_form =
239 XtVaCreateManagedWidget("connectform", formWidgetClass,
240 connectdlg_shell, NULL);
241
242 #if IS_BETA_VERSION
243 connectdlg_beta_label =
244 I_L(XtVaCreateManagedWidget("connbetalabel", labelWidgetClass,
245 connectdlg_form,
246 XtNresizable, True,
247 XtNjustify, XtJustifyCenter,
248 XtNlabel, beta_message(),
249 NULL));
250 #endif
251
252 connectdlg_select_label =
253 I_L(XtVaCreateManagedWidget("connselectlabel", labelWidgetClass,
254 connectdlg_form,
255 XtNresizable, True,
256 #if IS_BETA_VERSION
257 XtNfromVert, connectdlg_beta_label,
258 #endif
259 NULL));
260
261 connectdlg_host_label =
262 I_L(XtVaCreateManagedWidget("connhostlabel", labelWidgetClass,
263 connectdlg_form,
264 XtNresizable, True,
265 NULL));
266 connectdlg_host_text =
267 XtVaCreateManagedWidget("connhosttext", asciiTextWidgetClass,
268 connectdlg_form,
269 XtNeditType, XawtextEdit,
270 XtNstring, server_host,
271 NULL);
272 connectdlg_port_label =
273 I_L(XtVaCreateManagedWidget("connportlabel", labelWidgetClass,
274 connectdlg_form,
275 XtNresizable, True,
276 NULL));
277 fc_snprintf(buf, sizeof(buf), "%d", server_port);
278 connectdlg_port_text =
279 XtVaCreateManagedWidget("connporttext", asciiTextWidgetClass,
280 connectdlg_form,
281 XtNeditType, XawtextEdit,
282 XtNstring, buf,
283 NULL);
284 connectdlg_login_label =
285 I_L(XtVaCreateManagedWidget("connloginlabel", labelWidgetClass,
286 connectdlg_form,
287 XtNresizable, True,
288 NULL));
289 connectdlg_login_text =
290 XtVaCreateManagedWidget("connlogintext", asciiTextWidgetClass,
291 connectdlg_form,
292 XtNeditType, XawtextEdit,
293 XtNstring, user_name,
294 NULL);
295 connectdlg_password_label =
296 I_L(XtVaCreateManagedWidget("connpasswordlabel", labelWidgetClass,
297 connectdlg_form,
298 XtNresizable, True,
299 NULL));
300 connectdlg_password_text =
301 XtVaCreateManagedWidget("connpasswordtext", asciiTextWidgetClass,
302 connectdlg_form,
303 XtNecho, False,
304 XtNsensitive, False,
305 NULL);
306 connectdlg_verify_label =
307 I_L(XtVaCreateManagedWidget("connverifylabel", labelWidgetClass,
308 connectdlg_form,
309 XtNresizable, True,
310 NULL));
311 connectdlg_verify_text =
312 XtVaCreateManagedWidget("connverifytext", asciiTextWidgetClass,
313 connectdlg_form,
314 XtNecho, False,
315 XtNsensitive, False,
316 NULL);
317 connectdlg_message_label =
318 I_L(XtVaCreateManagedWidget("connmessagelabel", labelWidgetClass,
319 connectdlg_form,
320 XtNresizable, True,
321 NULL));
322
323 connectdlg_connect_button =
324 I_L(XtVaCreateManagedWidget("connconnectbutton", commandWidgetClass,
325 connectdlg_form,
326 XtNlabel, _("Connect"),
327 NULL));
328 connectdlg_lan_button =
329 I_L(XtVaCreateManagedWidget("connlanbutton", commandWidgetClass,
330 connectdlg_form,
331 XtNlabel, _("LAN Servers"),
332 NULL));
333 connectdlg_meta_button =
334 I_L(XtVaCreateManagedWidget("connmetabutton", commandWidgetClass,
335 connectdlg_form,
336 XtNlabel, _("Metaserver"),
337 NULL));
338 connectdlg_quit_button =
339 I_L(XtVaCreateManagedWidget("connquitbutton", commandWidgetClass,
340 connectdlg_form,
341 XtNlabel, _("Quit"),
342 NULL));
343
344 XtAddCallback(connectdlg_connect_button, XtNcallback,
345 connectdlg_connect_callback, NULL);
346 XtAddCallback(connectdlg_lan_button, XtNcallback,
347 connectdlg_lan_callback, NULL);
348 XtAddCallback(connectdlg_meta_button, XtNcallback,
349 connectdlg_meta_callback, NULL);
350 XtAddCallback(connectdlg_quit_button, XtNcallback,
351 connectdlg_quit_callback, NULL);
352
353 XtRealizeWidget(connectdlg_shell);
354 }
355
356 /**************************************************************************
357 Popdowns connect dialog.
358 **************************************************************************/
connectdlg_popdown(void)359 static void connectdlg_popdown(void)
360 {
361 if (lan_scan) {
362 server_scan_finish(lan_scan);
363 lan_scan = NULL;
364 }
365 if (meta_scan) {
366 server_scan_finish(meta_scan);
367 meta_scan = NULL;
368 }
369 if (connectdlg_shell) {
370 XtPopdown(connectdlg_shell);
371 }
372 }
373
374 /**************************************************************************
375 Destroys connect dialog.
376 **************************************************************************/
connectdlg_destroy(void)377 static void connectdlg_destroy(void)
378 {
379 if (connectdlg_shell) {
380 connectdlg_popdown();
381 XtDestroyWidget(connectdlg_shell);
382 connectdlg_shell = NULL;
383 }
384 }
385
386 /**************************************************************************
387 Popups connect dialog.
388 **************************************************************************/
connectdlg_popup(void)389 static void connectdlg_popup(void)
390 {
391 if (!connectdlg_shell) {
392 connectdlg_create();
393 }
394
395 connectdlg_align_labels();
396 xaw_set_relative_position(toplevel, connectdlg_shell, 20, 20);
397 XtPopup(connectdlg_shell, XtGrabNone);
398 }
399
400 /****************************************************************************
401 Callback for Connect button.
402 ****************************************************************************/
connectdlg_connect_callback(Widget w,XtPointer client_data,XtPointer call_data)403 void connectdlg_connect_callback(Widget w, XtPointer client_data,
404 XtPointer call_data)
405 {
406 XtPointer pxp;
407 char errbuf[512];
408 struct packet_authentication_reply reply;
409
410 switch (connection_status) {
411 case LOGIN_TYPE:
412 XtVaGetValues(connectdlg_host_text, XtNstring, &pxp, NULL);
413 sz_strlcpy(server_host, (char *)pxp);
414 XtVaGetValues(connectdlg_port_text, XtNstring, &pxp, NULL);
415 sscanf((char *)pxp, "%d", &server_port);
416 XtVaGetValues(connectdlg_login_text, XtNstring, &pxp, NULL);
417 sz_strlcpy(user_name, (char *)pxp);
418 if (connect_to_server(user_name, server_host, server_port,
419 errbuf, sizeof(errbuf)) != -1) {
420 popup_start_page();
421 connectdlg_destroy();
422 XtSetSensitive(toplevel, True);
423 return;
424 } else {
425 XtVaSetValues(connectdlg_message_label, XtNlabel, errbuf, NULL);
426 output_window_append(ftc_client, errbuf);
427 }
428 break;
429 case NEW_PASSWORD_TYPE:
430 XtVaGetValues(connectdlg_password_text, XtNstring, &pxp, NULL);
431 sz_strlcpy(fc_password, (char *)pxp);
432 XtVaGetValues(connectdlg_verify_text, XtNstring, &pxp, NULL);
433 sz_strlcpy(reply.password, (char *)pxp);
434 if (strncmp(reply.password, fc_password, MAX_LEN_NAME) == 0) {
435 fc_password[0] = '\0';
436 send_packet_authentication_reply(&client.conn, &reply);
437 XtVaSetValues(connectdlg_message_label, XtNlabel, "", NULL);
438 XtVaSetValues(connectdlg_password_text, XtNsensitive, False, NULL);
439 XtVaSetValues(connectdlg_verify_text, XtNsensitive, False, NULL);
440 } else {
441 XtVaSetValues(connectdlg_password_text, XtNstring, "", NULL);
442 XtVaSetValues(connectdlg_verify_text, XtNstring, "", NULL);
443 XtVaSetValues(connectdlg_message_label, XtNlabel,
444 _("Passwords don't match, enter password."), NULL);
445 output_window_append(ftc_client,
446 _("Passwords don't match, enter password."));
447 }
448 break;
449 case ENTER_PASSWORD_TYPE:
450 XtVaGetValues(connectdlg_verify_text, XtNstring, &pxp, NULL);
451 sz_strlcpy(reply.password, (char *)pxp);
452 send_packet_authentication_reply(&client.conn, &reply);
453
454 XtVaSetValues(connectdlg_message_label, XtNlabel, "", NULL);
455 XtVaSetValues(connectdlg_password_text, XtNsensitive, False, NULL);
456 XtVaSetValues(connectdlg_verify_text, XtNsensitive, False, NULL);
457 break;
458 case WAITING_TYPE:
459 break;
460 }
461 }
462
463 /****************************************************************************
464 Callback fir LAN Servers button.
465 ****************************************************************************/
connectdlg_lan_callback(Widget w,XtPointer client_data,XtPointer call_data)466 void connectdlg_lan_callback(Widget w, XtPointer client_data,
467 XtPointer call_data)
468 {
469 lan_mode = true;
470 if (!lan_scan) {
471 lan_scan = server_scan_begin(SERVER_SCAN_LOCAL, server_scan_error);
472 }
473 connectdlg_serverlist_popup();
474 }
475
476 /****************************************************************************
477 Callback for Metaserver button.
478 ****************************************************************************/
connectdlg_meta_callback(Widget w,XtPointer client_data,XtPointer call_data)479 void connectdlg_meta_callback(Widget w, XtPointer client_data,
480 XtPointer call_data)
481 {
482 lan_mode = false;
483 if (!meta_scan) {
484 meta_scan = server_scan_begin(SERVER_SCAN_GLOBAL, server_scan_error);
485 }
486 connectdlg_serverlist_popup();
487 }
488
489 /****************************************************************************
490 Callback for Quit button.
491 ****************************************************************************/
connectdlg_quit_callback(Widget w,XtPointer client_data,XtPointer call_data)492 void connectdlg_quit_callback(Widget w, XtPointer client_data,
493 XtPointer call_data)
494 {
495 connectdlg_destroy();
496 xaw_ui_exit();
497 }
498
499 /**************************************************************************
500 configure the dialog depending on what type of authentication request the
501 server is making.
502 **************************************************************************/
handle_authentication_req(enum authentication_type type,const char * message)503 void handle_authentication_req(enum authentication_type type,
504 const char *message)
505 {
506 XtVaSetValues(connectdlg_message_label, XtNlabel, message, NULL);
507
508 switch (type) {
509 case AUTH_NEWUSER_FIRST:
510 case AUTH_NEWUSER_RETRY:
511 XtVaSetValues(connectdlg_password_text, XtNsensitive, True, NULL);
512 XtVaSetValues(connectdlg_verify_text, XtNsensitive, True, NULL);
513 connection_status = NEW_PASSWORD_TYPE;
514 break;
515 case AUTH_LOGIN_FIRST:
516 /* if we magically have a password already present in 'fc_password'
517 * then, use that and skip the password entry dialog */
518 if (fc_password[0] != '\0') {
519 struct packet_authentication_reply reply;
520
521 sz_strlcpy(reply.password, fc_password);
522 send_packet_authentication_reply(&client.conn, &reply);
523 return;
524 } else {
525 XtVaSetValues(connectdlg_password_text, XtNsensitive, True, NULL);
526 XtVaSetValues(connectdlg_verify_text, XtNsensitive, False, NULL);
527 connection_status = ENTER_PASSWORD_TYPE;
528 }
529 break;
530 case AUTH_LOGIN_RETRY:
531 XtVaSetValues(connectdlg_password_text, XtNsensitive, True, NULL);
532 XtVaSetValues(connectdlg_verify_text, XtNsensitive, False, NULL);
533 connection_status = ENTER_PASSWORD_TYPE;
534 break;
535 default:
536 log_error("Unsupported authentication type %d: %s.", type, message);
537 break;
538 }
539 }
540
541 /****************************************************************
542 Provide an interface for connecting to a Freeciv server.
543 *****************************************************************/
server_connect(void)544 void server_connect(void)
545 {
546 connection_status = LOGIN_TYPE;
547
548 XtSetSensitive(turn_done_button, FALSE);
549 /* XtSetSensitive(toplevel, FALSE);*/
550
551 if (auto_connect) {
552 /* FIXME */
553 } else {
554 connectdlg_popup();
555 /*
556 XtPopup(connectdlg_shell, XtGrabNone);
557 XtSetKeyboardFocus(toplevel, connectdlg_shell);
558 */
559 }
560 }
561
562 /**************************************************************************
563 this regenerates the player information from a loaded game on the server.
564 currently a stub. TODO
565 **************************************************************************/
handle_game_load(bool load_successful,const char * filename)566 void handle_game_load(bool load_successful, const char *filename)
567 {
568 /* PORTME */
569 }
570
571 /****************************************************************
572 ...
573 *****************************************************************/
connectdlg_key_connect(Widget w)574 void connectdlg_key_connect(Widget w)
575 {
576 x_simulate_button_click(connectdlg_connect_button);
577 }
578
579 /****************************************************************************
580 SERVERS LIST DIALOG
581 ****************************************************************************/
582
583 /****************************************************************************
584 Callback function for when there's an error in the server scan.
585 ****************************************************************************/
server_scan_error(struct server_scan * scan,const char * message)586 void server_scan_error(struct server_scan *scan, const char *message)
587 {
588 output_window_append(ftc_client, message);
589 log_normal("%s", message);
590 switch (server_scan_get_type(scan)) {
591 case SERVER_SCAN_LOCAL:
592 server_scan_finish(lan_scan);
593 lan_scan = NULL;
594 break;
595 case SERVER_SCAN_GLOBAL:
596 server_scan_finish(meta_scan);
597 meta_scan = NULL;
598 break;
599 case SERVER_SCAN_LAST:
600 break;
601 }
602 }
603
604 /****************************************************************************
605 This function updates the list of servers after the server dialog has been
606 displayed. LAN servers updated every 250 ms for 5 seconds, metaserver
607 updated every 500 ms for 2 seconds.
608 ****************************************************************************/
server_list_timer(XtPointer meta_list,XtIntervalId * id)609 static void server_list_timer(XtPointer meta_list, XtIntervalId * id)
610 {
611 char errbuf[128];
612
613 if (!connectdlg_serverlist_shell) {
614 return;
615 }
616
617 if (get_server_list(servers_list, errbuf, sizeof(errbuf)) != -1) {
618 XawListChange(meta_list, (CONST_FOR_XAW_LIST_CHANGE char **)servers_list, 0, 0, True);
619 }
620 /*
621 else if (!lan_mode) {
622 output_window_append(ftc_client, errbuf);
623 }
624 */
625 num_lanservers_timer++;
626
627 if (lan_mode) {
628 if (num_lanservers_timer == 20) {
629 server_scan_finish(lan_scan);
630 lan_scan = NULL;
631 num_lanservers_timer = 0;
632 return;
633 }
634 (void)XtAppAddTimeOut(app_context, 250, server_list_timer,
635 (XtPointer)meta_list);
636 } else {
637 if (num_lanservers_timer == 4) {
638 server_scan_finish(meta_scan);
639 meta_scan = NULL;
640 num_lanservers_timer = 0;
641 return;
642 }
643 (void)XtAppAddTimeOut(app_context, 500, server_list_timer,
644 (XtPointer)meta_list);
645 }
646 }
647
648 /****************************************************************************
649 Creates Servers List dialog.
650 ****************************************************************************/
connectdlg_serverlist_create(void)651 static void connectdlg_serverlist_create(void)
652 {
653 connectdlg_serverlist_shell =
654 I_IN(I_T(XtCreatePopupShell("serverlistdialog",
655 topLevelShellWidgetClass,
656 toplevel, NULL, 0)));
657
658 connectdlg_serverlist_form =
659 XtVaCreateManagedWidget("serverlistform", formWidgetClass,
660 connectdlg_serverlist_shell, NULL);
661 connectdlg_serverlist_legend_label =
662 I_L(XtVaCreateManagedWidget("legendlabel", labelWidgetClass,
663 connectdlg_serverlist_form,
664 XtNresizable, True,
665 NULL));
666 connectdlg_serverlist_viewport =
667 XtVaCreateManagedWidget("viewport", viewportWidgetClass,
668 connectdlg_serverlist_form, NULL);
669 connectdlg_serverlist_list =
670 XtVaCreateManagedWidget("serverlist", listWidgetClass,
671 connectdlg_serverlist_viewport, NULL);
672 connectdlg_serverlist_update_button =
673 XtVaCreateManagedWidget("updatebutton", commandWidgetClass,
674 connectdlg_serverlist_form,
675 XtNlabel, _("Update"),
676 NULL);
677 connectdlg_serverlist_close_button =
678 XtVaCreateManagedWidget("closebutton", commandWidgetClass,
679 connectdlg_serverlist_form,
680 XtNlabel, _("Close"),
681 NULL);
682
683 XtAddCallback(connectdlg_serverlist_update_button, XtNcallback,
684 connectdlg_serverlist_update_callback, NULL);
685 XtAddCallback(connectdlg_serverlist_close_button, XtNcallback,
686 connectdlg_serverlist_close_callback, NULL);
687 XtAddCallback(connectdlg_serverlist_list, XtNcallback,
688 connectdlg_serverlist_list_callback, NULL);
689
690 (void)XtAppAddTimeOut(app_context, 1, server_list_timer,
691 (XtPointer)connectdlg_serverlist_list);
692
693 XtRealizeWidget(connectdlg_serverlist_shell);
694 }
695
696 /****************************************************************************
697 Popups Servers List dialog.
698 ****************************************************************************/
connectdlg_serverlist_popup(void)699 void connectdlg_serverlist_popup(void)
700 {
701 if (!connectdlg_serverlist_shell) {
702 connectdlg_serverlist_create();
703 }
704
705 xaw_set_relative_position(toplevel, connectdlg_serverlist_shell, 15, 15);
706 XtPopup(connectdlg_serverlist_shell, XtGrabNone);
707 }
708
709 /****************************************************************************
710 Destroys Servers List dialog.
711 ****************************************************************************/
connectdlg_serverlist_destroy(void)712 static void connectdlg_serverlist_destroy(void)
713 {
714 int i;
715
716 if (lan_scan) {
717 server_scan_finish(lan_scan);
718 lan_scan = NULL;
719 }
720 if (meta_scan) {
721 server_scan_finish(meta_scan);
722 meta_scan = NULL;
723 }
724 /* FIXME: Replace magic 64 with proper constant. */
725 for (i = 0; i < 64; i++) {
726 if (servers_list[i]) {
727 free(servers_list[i]);
728 servers_list[i] = NULL;
729 }
730 }
731 if (connectdlg_serverlist_shell) {
732 XtDestroyWidget(connectdlg_serverlist_shell);
733 connectdlg_serverlist_shell = NULL;
734 }
735 }
736
737 /****************************************************************************
738 Callback for Update button.
739 ****************************************************************************/
connectdlg_serverlist_update_callback(Widget w,XtPointer client_data,XtPointer call_data)740 void connectdlg_serverlist_update_callback(Widget w, XtPointer client_data,
741 XtPointer call_data)
742 {
743 if (lan_mode) {
744 if (!lan_scan) {
745 lan_scan = server_scan_begin(SERVER_SCAN_LOCAL, server_scan_error);
746 }
747 if (num_lanservers_timer == 0) {
748 server_list_timer(connectdlg_serverlist_list, NULL);
749 }
750 } else {
751 if (!meta_scan) {
752 meta_scan = server_scan_begin(SERVER_SCAN_GLOBAL, server_scan_error);
753 }
754 if (num_lanservers_timer == 0) {
755 server_list_timer(connectdlg_serverlist_list, NULL);
756 }
757 }
758 }
759
760 /****************************************************************************
761 Callback for Close button.
762 ****************************************************************************/
connectdlg_serverlist_close_callback(Widget w,XtPointer client_data,XtPointer call_data)763 void connectdlg_serverlist_close_callback(Widget w, XtPointer client_data,
764 XtPointer call_data)
765 {
766 connectdlg_serverlist_destroy();
767 }
768
769 /****************************************************************************
770 Callback for choosing server from serverlist.
771 ****************************************************************************/
connectdlg_serverlist_list_callback(Widget w,XtPointer client_data,XtPointer call_data)772 void connectdlg_serverlist_list_callback(Widget w, XtPointer client_data,
773 XtPointer call_data)
774 {
775 XawListReturnStruct *ret = XawListShowCurrent(w);
776 char name[64], port[16];
777
778 sscanf(ret->string, "%s %s\n", name, port);
779 XtVaSetValues(connectdlg_host_text, XtNstring, name, NULL);
780 XtVaSetValues(connectdlg_port_text, XtNstring, port, NULL);
781 }
782
783 /**************************************************************************
784 Get the list of servers from the metaserver or LAN servers
785 depending on lan_mode.
786 **************************************************************************/
get_server_list(char ** list,char * errbuf,int n_errbuf)787 static int get_server_list(char **list, char *errbuf, int n_errbuf)
788 {
789 char line[256];
790 struct srv_list *srvrs = NULL;
791 enum server_scan_status scan_stat;
792
793 if (lan_mode) {
794 if (lan_scan) {
795 server_scan_poll(lan_scan);
796 srvrs = server_scan_get_list(lan_scan);
797 fc_allocate_mutex(&srvrs->mutex);
798 if (srvrs->servers == NULL) {
799 int retval;
800
801 if (num_lanservers_timer == 0) {
802 if (*list) {
803 free(*list);
804 }
805 *list = fc_strdup(" ");
806 retval = 0;
807 } else {
808 retval = -1;
809 }
810 fc_release_mutex(&srvrs->mutex);
811
812 return retval;
813 }
814 } else {
815 return -1;
816 }
817 } else {
818 if (meta_scan) {
819 scan_stat = server_scan_poll(meta_scan);
820 if (scan_stat >= SCAN_STATUS_PARTIAL) {
821 srvrs = server_scan_get_list(meta_scan);
822 fc_allocate_mutex(&srvrs->mutex);
823 if (!srvrs->servers) {
824 fc_release_mutex(&srvrs->mutex);
825 if (num_lanservers_timer == 0) {
826 if (*list) {
827 free(*list);
828 }
829 *list = fc_strdup(" ");
830 return 0;
831 } else {
832 return -1;
833 }
834 }
835 } else {
836 return -1;
837 }
838 } else {
839 return -1;
840 }
841 }
842
843 server_list_iterate(srvrs->servers, pserver) {
844 if (pserver == NULL) {
845 continue;
846 }
847 fc_snprintf(line, sizeof(line), "%-35s %-5d %-11s %-11s %2d %s",
848 pserver->host, pserver->port, pserver->version,
849 _(pserver->state), pserver->nplayers, pserver->message);
850 if (*list) {
851 free(*list);
852 }
853 *list = fc_strdup(line);
854 list++;
855 } server_list_iterate_end;
856
857 fc_release_mutex(&srvrs->mutex);
858
859 /*
860 if (!lan_mode) {
861 delete_server_list(server_list);
862 }
863 */
864 *list = NULL;
865
866 return 0;
867 }
868
869 /**************************************************************************
870 Really closes and destroys the dialog.
871 **************************************************************************/
really_close_connection_dialog(void)872 void really_close_connection_dialog(void)
873 {
874 /* PORTME */
875 }
876
877 /**************************************************************************
878 Closes and destroys the dialog.
879 **************************************************************************/
close_connection_dialog(void)880 void close_connection_dialog(void)
881 {
882 connectdlg_serverlist_destroy();
883 connectdlg_destroy();
884 }
885
886