1 /*
2  * Biloba
3  * Copyright (C) 2004-2008 Guillaume Demougeot, Colin Leroy
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
18  */
19 
20 /**
21  * Biloba - Q1 2005
22  * Game by Guillaume Demougeot <dmgt@wanadoo.fr>
23  * Code by Colin Leroy <colin@colino.net>
24  *
25  * This file contains the options code used at startup.
26  */
27 
28 #include <stdlib.h>
29 #include <SDL.h>
30 #include <SDL_image.h>
31 #include <string.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <unistd.h>
35 #include <time.h>
36 #include <errno.h>
37 #include <limits.h>
38 #include <libgen.h>
39 
40 #include "options.h"
41 #include "utils.h"
42 #include "arrow.h"
43 #include "font.h"
44 #include "player.h"
45 #include "net.h"
46 #include "game.h"
47 #include "help.h"
48 #include "msg.h"
49 #include "widget.h"
50 #include "replay.h"
51 
52 #define BILOBA_MIN_X 		 (300)
53 #define NUM_PLAYERS_MIN_X 	 (100)
54 #define PLAYERS_MIN_X 		 (50)
55 #define GAMENAME_MIN_X 		 (50)
56 #define SERVER_MIN_X 		 (50)
57 #define CHOOSE_SERVER_MIN_X 	 (410)
58 #define CREATEGAME_MIN_X 	 (50)
59 #define JOINGAME_MIN_X 		 (300)
60 #define START_MIN_X 		 (550)
61 #define HELP_MIN_X 		 (720)
62 #define LANG_MIN_X 		 (688)
63 #define PLAYERPAWN_MIN_X(i) 	 (100)
64 #define PLAYERNAME_MIN_X(i) 	 (140)
65 #define PLAYERTYPE_MIN_X(i) 	 (340)
66 #define NETWORK_GAMES_LIST_MIN_X (550)
67 #define GAMELIST_MIN_X(i) 	 (550)
68 #define SAVE_LAST_MIN_X 	 (550)
69 #define SAVED_MIN_X		 (100)
70 
71 #ifndef MAEMO
72 #define BILOBA_MIN_Y		 (20)
73 #define PLAYERS_MIN_Y		 (100)
74 #define GAMENAME_MIN_Y		 (400)
75 #define SERVER_MIN_Y		 (350)
76 #define CHOOSE_SERVER_MIN_Y	 (350)
77 #define CREATEGAME_MIN_Y	 (500)
78 #define JOINGAME_MIN_Y		 (500)
79 #define START_MIN_Y		 (500)
80 #define HELP_MIN_Y		 (40)
81 #define LANG_MIN_Y		 (40)
82 #define PLAYERPAWN_MIN_Y(i)	 (200 + (40*(i-2)))
83 #define PLAYERNAME_MIN_Y(i)	 (200 + (40*(i-2)))
84 #define PLAYERTYPE_MIN_Y(i)	 (200 + (40*(i-2)))
85 #define NETWORK_GAMES_LIST_MIN_Y (100)
86 #define GAMELIST_MIN_Y(i)	 (151 + (40*(i)))
87 #define SAVE_LAST_MIN_Y		 (400)
88 #define SAVED_MIN_Y		 (275)
89 #else
90 #define BILOBA_MIN_Y		 (10)
91 #define PLAYERS_MIN_Y		 (70)
92 #define GAMENAME_MIN_Y		 (367)
93 #define SERVER_MIN_Y		 (320)
94 #define CHOOSE_SERVER_MIN_Y	 (320)
95 #define CREATEGAME_MIN_Y	 (420)
96 #define JOINGAME_MIN_Y		 (420)
97 #define START_MIN_Y		 (420)
98 #define HELP_MIN_Y		 (30)
99 #define LANG_MIN_Y		 (30)
100 #define PLAYERPAWN_MIN_Y(i)	 (170 + (40*(i-2)))
101 #define PLAYERNAME_MIN_Y(i)	 (170 + (40*(i-2)))
102 #define PLAYERTYPE_MIN_Y(i)	 (170 + (40*(i-2)))
103 #define NETWORK_GAMES_LIST_MIN_Y (70)
104 #define GAMELIST_MIN_Y(i)	 (121 + (40*(i)))
105 #define SAVE_LAST_MIN_Y		 (367)
106 #define SAVED_MIN_Y		 (215)
107 #endif
108 
109 /* GUI widgets */
110 static Widget *numplayers = NULL;
111 static Widget *numplayers_icon = NULL;
112 static Widget *title = NULL;
113 static Widget *player_pawn_box[4] = { NULL, NULL, NULL, NULL };
114 static Widget *player_name[4] = { NULL, NULL, NULL, NULL };
115 static Widget *player_pawn[4] = { NULL, NULL, NULL, NULL };
116 static Widget *player_type[4] = { NULL, NULL, NULL, NULL };
117 static Widget *server = NULL;
118 static Widget *server_chooser = NULL;
119 static Widget *game_name = NULL;
120 static Widget *network_games = NULL;
121 static Widget *network_game[6] = { NULL, NULL, NULL, NULL, NULL, NULL };
122 static Widget *create_game = NULL;
123 static Widget *join_game = NULL;
124 static Widget *start = NULL;
125 static Widget *help = NULL;
126 static Widget *lang = NULL;
127 static Widget *save_last = NULL;
128 static Widget *saved = NULL;
129 
130 /* Options states */
131 static int num_players = 2;
132 static InputSystemMethod player_types[4] = { INPUT_LOCAL, INPUT_LOCAL, INPUT_LOCAL, INPUT_LOCAL };
133 static int network_create_enabled = 0;
134 static int network_join_enabled = 0;
135 LList *network_games_list = NULL;
136 int selected_net_game_id = -1;
137 int selected_net_game_player_slot = -1;
138 static int start_clicked = FALSE;
139 char *player_names[4] = { NULL, NULL, NULL, NULL };
140 
141 /* Return the name of the image for a player type */
get_input_type_img(InputSystemMethod input)142 static const char *get_input_type_img(InputSystemMethod input)
143 {
144 	switch(input)
145 	{
146 	case INPUT_LOCAL: 	return "local.png";
147 	case INPUT_NETWORK:	return "reseau.png";
148 	case INPUT_AI: 		return "computer.png";
149 	default:		assert(0);
150 	}
151 
152 	return "";
153 }
154 
155 static Game *cur_game = NULL;
156 static SDL_mutex *cur_game_mutex = NULL;
157 
options_get_game(void)158 Game *options_get_game(void)
159 {
160 	return cur_game;
161 }
162 
options_game_lock(void)163 void options_game_lock(void)
164 {
165 	SDL_LockMutex(cur_game_mutex);
166 }
167 
options_game_unlock(void)168 void options_game_unlock(void)
169 {
170 	SDL_UnlockMutex(cur_game_mutex);
171 }
172 /**
173  * Get the player number's from a widget
174  *
175  * @param[in]	widget		The widget
176  *
177  * @return a number between 0 and 3 if the widget is a player type or name,
178  * -1 otherwise.
179  */
get_player_num_from_widget(Widget * widget)180 static int get_player_num_from_widget(Widget *widget)
181 {
182 	int i;
183 
184 	for (i = 0; i < 4; i++)
185 		if (widget == player_type[i] || widget == player_name[i])
186 			return i;
187 
188 	return -1;
189 }
190 
191 /**
192  * Copy the (player name's) widget text to the internal player names table
193  * that is used for network games exchanging of names.
194  *
195  * @param[in] 	widget		The player name's widget
196  * @param[in]	data		The (unused) callback data
197  */
player_name_copy(Widget * widget,void * data)198 static void player_name_copy(Widget *widget, void *data)
199 {
200 	int num = get_player_num_from_widget(widget);
201 
202 	if (num < 0)
203 		return;
204 
205     	strncpy(player_names[num], text_widget_get_text(widget), PLAYER_NAME_LEN);
206 }
207 
208 /**
209  * Set the type of a player (network, AI or local), and update GUI parts
210  * accordingly.
211  *
212  * @param[in] 	num		The player number
213  * @param[in]	type		The input type
214  */
player_set_type(int num,InputSystemMethod type)215 static void player_set_type(int num, InputSystemMethod type)
216 {
217 	player_types[num] = type;
218 	widget_set_image(player_type[num], get_input_type_img(player_types[num]));
219 	text_widget_set_editable(player_name[num], type != INPUT_NETWORK);
220 	widget_enable(player_name[num], type != INPUT_NETWORK);
221 	widget_enable(player_type[num], type != INPUT_NETWORK);
222 	if (type != INPUT_NETWORK &&
223 	    !strcmp(text_widget_get_text(player_name[num]), "")) {
224 		text_widget_set_text(player_name[num], NULL);
225 		player_name_copy(player_name[num], NULL);
226 	}
227 }
228 
229 /**
230  * Select a network game
231  *
232  * @param[in] 	widget		The network game's widget
233  * @param[in]	data		The callback data, a Game * structure
234  */
select_net_game(Widget * widget,void * data)235 static void select_net_game(Widget *widget, void *data)
236 {
237 	Game *game = data;
238 	int i;
239 
240 	assert(game != NULL);
241 
242 	if (net_get_info(game) < 0)
243 		return;
244 
245 	text_widget_set_text(game_name, game->name);
246 
247 	selected_net_game_id = game->id;
248 
249 	for (i = 0; i < game->num_players; i++) {
250 		if (i + 1 == game->first_avail_spot) {
251 			player_set_type(i, INPUT_LOCAL);
252 			widget_enable(player_type[i], 0);
253 			selected_net_game_player_slot = i;
254 		} else {
255 			text_widget_set_text(player_name[i],
256 					     game->player_name[i]);
257 			player_set_type(i, INPUT_NETWORK);
258 		}
259 	}
260 }
261 
262 /**
263  * Update all player types according to the internal state (network game
264  * creation or join planned).
265  */
update_player_types(void)266 static void update_player_types(void)
267 {
268 	int i;
269 	if (network_create_enabled) {
270 		player_set_type(0, INPUT_LOCAL);
271 		widget_enable(player_type[0], 0);
272 		for (i = 1; i < num_players; i++)
273 			player_set_type(i, INPUT_NETWORK);
274 	} else if (!network_join_enabled) {
275 		widget_enable(player_type[0], 1);
276 		for (i = 0; i < num_players; i++)
277 			player_set_type(i, INPUT_LOCAL);
278 	} else if (network_join_enabled) {
279 		/* handled by select_net_game */
280 	}
281 }
282 
283 /**
284  * Update the network games list according to the internal state (is joining
285  * selected, number of players, previously selected network game).
286  */
update_games_list(void)287 static void update_games_list(void)
288 {
289 	LList *cur;
290 	int i;
291 
292 	llist_for_each(network_games_list, free_game);
293 	llist_free(network_games_list);
294 	network_games_list = NULL;
295 
296 	if (network_join_enabled) {
297 		network_games_list = net_get_games(num_players);
298 		widget_show(network_games);
299 	} else
300 		widget_hide(network_games);
301 
302 	if (selected_net_game_id > 0 && network_join_enabled) {
303 		network_join_enabled = 0;
304 		selected_net_game_id = -1;
305 		text_widget_set_text(game_name, "");
306 		update_player_types();
307 		network_join_enabled = 1;
308 	}
309 
310 	cur = network_games_list;
311 	for (i = 0; i < 6; i++) {
312 		Game *game;
313 		if (cur) {
314 			game = cur->data;
315 			cur = cur->next;
316 		} else
317 			game = NULL;
318 
319 		if (network_join_enabled)
320 			widget_show(network_game[i]);
321 		else
322 			widget_hide(network_game[i]);
323 
324 		if (network_join_enabled && game != NULL) {
325 			widget_set_clicked_callback(network_game[i],
326 					    select_net_game, game);
327 			text_widget_set_text(network_game[i], game->name);
328 		} else {
329 			widget_set_clicked_callback(network_game[i],
330 					    NULL, NULL);
331 			text_widget_set_text(network_game[i], "");
332 		}
333 	}
334 }
335 
set_server_from_string(const char * string)336 static void set_server_from_string(const char *string)
337 {
338 	if (string && !strcmp(string, get_msg(M_OFFICIAL_SERVER)))
339 		net_set_server(NULL);
340 	else if (string && !strcmp(string, get_msg(M_LOCAL_SERVER)))
341 		net_set_server("127.0.0.1");
342 	else if (string)
343 		net_set_server(string);
344 	else
345 		net_set_server(NULL);
346 }
347 
348 /**
349  * Update the network server to use.
350  *
351  * @param[in]	widget		The server's widget
352  * @param[in]	data		Unused callback data
353  */
set_server(Widget * widget,void * data)354 static void set_server(Widget *widget, void *data)
355 {
356 	const char *text = text_widget_get_text(widget);
357 
358 	set_server_from_string(text);
359 	update_games_list();
360 }
361 
362 /**
363  * Update the number of players.
364  *
365  * @param[in]	widget		The number of players' widget
366  * @param[in]	data		Unused callback data
367  */
num_players_clicked(Widget * widget,void * data)368 static void num_players_clicked(Widget *widget, void *data)
369 {
370 	int i;
371 	if (num_players < 4)
372 		num_players++;
373 	else
374 		num_players = 2;
375 
376 	if (num_players == 2)
377 		widget_set_image(numplayers_icon, "2play.png");
378 	else if (num_players == 3)
379 		widget_set_image(numplayers_icon, "3play.png");
380 	else if (num_players == 4)
381 		widget_set_image(numplayers_icon, "4play.png");
382 
383 	for (i = 0; i < 4; i++) {
384 		if (i < num_players) {
385 			widget_show(player_pawn_box[i]);
386 			widget_show(player_pawn[i]);
387 			widget_show(player_name[i]);
388 			widget_show(player_type[i]);
389 		} else {
390 			widget_hide(player_pawn_box[i]);
391 			widget_hide(player_pawn[i]);
392 			widget_hide(player_name[i]);
393 			widget_hide(player_type[i]);
394 		}
395 	}
396 	update_player_types();
397 	update_games_list();
398 }
399 
400 /**
401  * Update the player input method.
402  *
403  * @param[in]	widget		The player's input method widget
404  * @param[in]	data		Unused callback data
405  */
update_player_method(Widget * widget,void * data)406 static void update_player_method(Widget *widget, void *data)
407 {
408 	int num = get_player_num_from_widget(widget);
409 
410 	if (num < 0)
411 		return;
412 
413 	if (player_types[num] == INPUT_LOCAL)
414 		player_set_type(num, INPUT_AI);
415 	else
416 		player_set_type(num, INPUT_LOCAL);
417 }
418 
419 /**
420  * Update the GUI after clicking the Create Game button.
421  *
422  * @param[in]	widget		The Create Game widget
423  * @param[in]	data		Unused callback data
424  */
do_create_game(Widget * widget,void * data)425 static void do_create_game(Widget *widget, void *data)
426 {
427 	network_create_enabled = !network_create_enabled;
428 	network_join_enabled = 0;
429 	if (network_create_enabled) {
430 		text_widget_set_text(game_name, NULL);
431 		widget_show(game_name);
432 		widget_enable(game_name, 1);
433 		text_widget_set_editable(game_name, 1);
434 		widget_show(server);
435 		widget_show(server_chooser);
436 		widget_enable(server, 1);
437 		text_widget_set_editable(server, 1);
438 	} else {
439 		widget_hide(game_name);
440 		widget_hide(server);
441 		widget_hide(server_chooser);
442 	}
443 
444 	update_player_types();
445 }
446 
447 /**
448  * Update the GUI after clicking the Join Game button.
449  *
450  * @param[in]	widget		The Join Game widget
451  * @param[in]	data		Unused callback data
452  */
do_join_game(Widget * widget,void * data)453 static void do_join_game(Widget *widget, void *data)
454 {
455 	network_join_enabled = !network_join_enabled;
456 	network_create_enabled = 0;
457 	if (network_join_enabled) {
458 		text_widget_set_text(game_name, "");
459 		widget_show(game_name);
460 		widget_enable(game_name, 0);
461 		text_widget_set_editable(game_name, 0);
462 		widget_show(server);
463 		widget_show(server_chooser);
464 		widget_enable(server, 1);
465 		text_widget_set_editable(server, 1);
466 	} else {
467 		widget_hide(game_name);
468 		widget_hide(server);
469 		widget_hide(server_chooser);
470 	}
471 	update_games_list();
472 	update_player_types();
473 }
474 
475 /**
476  * Signal the GUI after clicking the Play! button.
477  *
478  * @param[in]	widget		The Play widget
479  * @param[in]	data		Unused callback data
480  */
do_start(Widget * widget,void * data)481 static void do_start(Widget *widget, void *data)
482 {
483 	start_clicked = 1;
484 }
485 
486 /**
487  * Signal the GUI to save the last played game.
488  *
489  * @param[in]	widget		The Play widget
490  * @param[in]	data		Unused callback data
491  */
do_save_last(Widget * widget,void * data)492 static void do_save_last(Widget *widget, void *data)
493 {
494 	char str[SAVED_LEN];
495 
496 	const char *dir = get_desktop_folder();
497 	char basename_dir[PATH_MAX];
498 	char filename[PATH_MAX];
499 	char path[PATH_MAX];
500 
501 	time_t now = time(NULL);
502 	struct tm *tm;
503 
504 	if (!folder_exists(dir))
505 		dir = get_home_folder();
506 
507 	if (!folder_exists(dir)) {
508 		snprintf(str, SAVED_LEN, "%s %s", get_msg(M_SAVE_FAIL),
509 			dir);
510 		return;
511 	}
512 
513 	tm = localtime(&now);
514 
515 	snprintf(filename, PATH_MAX, "Biloba-%04d-%02d-%02d-%02d%02d.%02d.blb",
516 			tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
517 			tm->tm_hour, tm->tm_min, tm->tm_sec);
518 	filename[PATH_MAX - 1] = '\0';
519 
520 	snprintf(path, PATH_MAX, "%s%s%s", dir, DIR_SEP, filename);
521 
522 	path[PATH_MAX - 1] = '\0';
523 
524 	if (cur_game) {
525 		strncpy(basename_dir, dir, sizeof(basename_dir));
526 
527 		if (replay_dump_game(cur_game, path) == 0)
528 			snprintf(str, SAVED_LEN, "%s: %s%s\n%s", get_msg(M_SAVED_TO),
529 				basename(basename_dir), DIR_SEP, filename);
530 		else
531 			snprintf(str, SAVED_LEN, "%s:\n%s", get_msg(M_SAVE_FAIL),
532 				path);
533 
534 		text_widget_set_text(saved, str);
535 		widget_show(saved);
536 	}
537 }
538 
539 /**
540  * Signal the GUI after clicking the Help button.
541  *
542  * @param[in]	widget		The Help widget
543  * @param[in]	data		Unused callback data
544  */
do_help(Widget * widget,void * data)545 static void do_help(Widget *widget, void *data)
546 {
547 	help_start();
548 }
549 
550 /**
551  * Signal the GUI after clicking the language button.
552  *
553  * @param[in]	widget		The Play widget
554  * @param[in]	data		Unused callback data
555  */
set_lang(Widget * widget,void * data)556 static void set_lang(Widget *widget, void *data)
557 {
558 	if (!strcmp(langpath,"en")) {
559 		langpath="fr";
560 		widget_set_image(lang, "fr.png");
561 	}
562 	else if (!strcmp(langpath,"fr")) {
563 		langpath="es";
564 		widget_set_image(lang, "es.png");
565 	}
566 	else if (!strcmp(langpath,"es")) {
567 		langpath="en";
568 		widget_set_image(lang, "en.png");
569 	}
570 	gui_reload_images();
571 }
572 
hide_saved(Widget * widget,void * data)573 static void hide_saved(Widget *widget, void *data)
574 {
575 	widget_hide(saved);
576 }
577 
server_chooser_get_servers(Widget * widget,char *** strings)578 static int server_chooser_get_servers(Widget *widget, char ***strings)
579 {
580 	char **servers;
581 	char **distant_servers;
582 	int n_distant_servers = 0, i;
583 
584 	n_distant_servers = net_get_servers(&distant_servers);
585 
586 	servers = malloc((2 + n_distant_servers) * sizeof(char *));
587 	servers[0] = strdup(get_msg(M_OFFICIAL_SERVER));
588 	servers[1] = strdup(get_msg(M_LOCAL_SERVER));
589 
590 	for (i = 0; i < n_distant_servers; i++) {
591 		servers[i + 2] = strdup(distant_servers[i]);
592 		free(distant_servers[i]);
593 	}
594 	free(distant_servers);
595 	*strings = servers;
596 
597 	return 2 + n_distant_servers;
598 }
599 
server_chooser_list_cb(Widget * widget,int index,char * string)600 static void server_chooser_list_cb(Widget *widget, int index, char *string)
601 {
602 	set_server_from_string(string);
603 	net_stop_getting_servers();
604 
605 	text_widget_set_text(server, string);
606 	update_games_list();
607 }
608 
609 /**
610  * Build the GUI
611  */
build_gui(void)612 static void build_gui(void)
613 {
614 	int i;
615 
616 	/* First create all necessary widgets */
617 
618 	numplayers = 		widget_create("nplay.png", NUM_PLAYERS_MIN_X, PLAYERS_MIN_Y,
619 					num_players_clicked, NULL);
620 	numplayers_icon = 	widget_create("2play.png", PLAYERS_MIN_X, PLAYERS_MIN_Y,
621 					num_players_clicked, NULL);
622 	title =			widget_create("biloba-title.png", BILOBA_MIN_X, BILOBA_MIN_Y,
623 					NULL, NULL);
624 
625 	for (i = 0; i < 4; i++) {
626 		player_pawn_box[i] =	widget_create("empty_40_40.png", PLAYERPAWN_MIN_X(i+1),
627 					PLAYERPAWN_MIN_Y(i+1), NULL, NULL);
628 		player_name[i] =	widget_create("empty_200_40.png", PLAYERNAME_MIN_X(i+1),
629 					PLAYERNAME_MIN_Y(i+1), NULL, NULL);
630 		player_names[i] = malloc(PLAYER_NAME_LEN + 1);
631 		snprintf(player_names[i], PLAYER_NAME_LEN, "%s%d", get_msg(M_PLAYER), i + 1);
632 		text_widget_init(player_name[i], player_names[i], PLAYER_NAME_LEN, 4, 0,
633 				 player_name_copy, NULL);
634 	}
635 
636 	player_pawn[0] = widget_create("pawn-orange.png", PLAYERPAWN_MIN_X(1)+5, PLAYERPAWN_MIN_Y(1)+5,
637 					NULL, NULL);
638 	player_pawn[1] = widget_create("pawn-blue.png", PLAYERPAWN_MIN_X(2)+5, PLAYERPAWN_MIN_Y(2)+5,
639 					NULL, NULL);
640 	player_pawn[2] = widget_create("pawn-red.png", PLAYERPAWN_MIN_X(3)+5, PLAYERPAWN_MIN_Y(3)+5,
641 					NULL, NULL);
642 	player_pawn[3] = widget_create("pawn-green.png", PLAYERPAWN_MIN_X(4)+5, PLAYERPAWN_MIN_Y(4)+5,
643 					NULL, NULL);
644 
645 	player_type[0] = widget_create("local.png", PLAYERTYPE_MIN_X(1), PLAYERTYPE_MIN_Y(1),
646 					update_player_method, NULL);
647 	player_type[1] = widget_create("local.png", PLAYERTYPE_MIN_X(2), PLAYERTYPE_MIN_Y(2),
648 					update_player_method, NULL);
649 	player_type[2] = widget_create("local.png", PLAYERTYPE_MIN_X(3), PLAYERTYPE_MIN_Y(3),
650 					update_player_method, NULL);
651 	player_type[3] = widget_create("local.png", PLAYERTYPE_MIN_X(4), PLAYERTYPE_MIN_Y(4),
652 					update_player_method, NULL);
653 
654 	server =	 widget_create("server.png", SERVER_MIN_X, SERVER_MIN_Y,
655 					NULL, NULL);
656 	text_widget_init(server, get_msg(M_OFFICIAL_SERVER), SERVER_LEN, 111, 0,
657 			 set_server, NULL);
658 
659 	game_name =	 widget_create("game-name.png", GAMENAME_MIN_X, GAMENAME_MIN_Y,
660 					NULL, NULL);
661 	text_widget_init(game_name, get_msg(M_NEWGAME), GAME_NAME_LEN, 111, 0, NULL, NULL);
662 
663 	network_games =	 widget_create("network-games.png", NETWORK_GAMES_LIST_MIN_X, NETWORK_GAMES_LIST_MIN_Y,
664 					NULL, NULL);
665 	widget_hide(network_games);
666 	widget_hide(server);
667 	widget_hide(game_name);
668 
669 	for (i = 0; i < 6; i++) {
670 		network_game[i] = widget_create("empty_200_40.png", GAMELIST_MIN_X(i), GAMELIST_MIN_Y(i),
671 					NULL, NULL);
672 		widget_hide(network_game[i]);
673 		text_widget_init(network_game[i], "", GAME_NAME_LEN, 0, 0, NULL, NULL);
674 		text_widget_set_editable(network_game[i], FALSE);
675 	}
676 
677 	create_game =	 widget_create("create-game.png", CREATEGAME_MIN_X, CREATEGAME_MIN_Y,
678 					do_create_game, NULL);
679 	join_game =	 widget_create("join-game.png", JOINGAME_MIN_X, JOINGAME_MIN_Y,
680 					do_join_game, NULL);
681 	start =	 	 widget_create("start.png", START_MIN_X, START_MIN_Y,
682 					do_start, NULL);
683 	save_last = 	 widget_create("save_last.png", SAVE_LAST_MIN_X, SAVE_LAST_MIN_Y,
684 					do_save_last, NULL);
685 
686 	help =		 widget_create("help.png", HELP_MIN_X, HELP_MIN_Y,
687 					do_help, NULL);
688 	lang =	 	 widget_create("en.png", LANG_MIN_X, LANG_MIN_Y,
689 					set_lang, NULL);
690 
691 	saved = 	 widget_create("saved.png", SAVED_MIN_X, SAVED_MIN_Y, hide_saved, NULL);
692 	text_widget_init(saved, "", SAVED_LEN, 10, 0, NULL, NULL);
693 	text_widget_set_editable(saved, FALSE);
694 
695 	widget_hide(saved);
696 
697 	/* FIXME: Setting server_chooser is done last just because it's the
698 	 * easiest way to make sure it takes focus over the rest */
699 	server_chooser = widget_create("choose.png", CHOOSE_SERVER_MIN_X, CHOOSE_SERVER_MIN_Y,
700 					NULL, NULL);
701 	list_widget_init(server_chooser, SERVER_MIN_X + (text_widget_get_x_offset(server) - 4),
702 			 SERVER_MIN_Y,
703 			 widget_get_width(server) - (text_widget_get_x_offset(server) - 4),
704 			 server_chooser_get_servers,
705 			 server_chooser_list_cb);
706 	widget_hide(server_chooser);
707 
708 	/* Now set the defaults */
709 	widget_hide(player_pawn[2]); 	 widget_hide(player_pawn[3]);
710 	widget_hide(player_type[2]); 	 widget_hide(player_type[3]);
711 	widget_hide(player_pawn_box[2]); widget_hide(player_pawn_box[3]);
712 	widget_hide(player_name[2]);   	 widget_hide(player_name[3]);
713 }
714 
715 /**
716  * Reset all network-related GUI elements
717  */
reset_net_widgets(void)718 static void reset_net_widgets(void)
719 {
720 	network_join_enabled = FALSE;
721 	network_create_enabled = FALSE;
722 	update_games_list();
723 	update_player_types();
724 	widget_hide(game_name);
725 	widget_hide(server);
726 	widget_hide(server_chooser);
727 }
728 
729 static int use_net = FALSE;
options_using_net(void)730 int options_using_net(void)
731 {
732 	return use_net;
733 }
734 /**
735  * Main GUI loop to get the options
736  *
737  * @return 0 if the game can start, -1 if the caller should quit.
738  */
get_options(const char * replay_file)739 int get_options(const char *replay_file)
740 {
741 	static int initialized = FALSE;
742 	int net_game_number = -1;
743 	int i;
744 
745 	if (!initialized)
746 	{
747 		build_gui();
748 		initialized = TRUE;
749 	}
750 
751 	widget_hide(saved);
752 
753 	if (cur_game && cur_game->move_id > 1)
754 		widget_show(save_last);
755 	else
756 		widget_hide(save_last);
757 
758 	reset_net_widgets();
759 	use_net = FALSE;
760 
761 	if (replay_file) {
762 		struct stat st;
763 		int i;
764 
765 		if (stat(replay_file, &st) != 0 || !S_ISREG(st.st_mode))
766 			return -1;
767 
768 		if (replay_game_setup(replay_file) < 0)
769 			return -1;
770 
771 		set_num_players(replay_get_num_players());
772 		for (i = 0; i < replay_get_num_players(); i++) {
773 			text_widget_set_text(player_name[i],
774 				replay_get_player(i));
775 			player_types[i] = INPUT_REPLAY;
776 		}
777 		return 0;
778 	}
779 
780 choose_again:
781 	start_clicked = 0;
782 	do {
783 		update_gui();
784 		if (gui_wait_event() < 0)
785 			return -1;
786 	} while (!start_clicked);
787 
788 	set_num_players(num_players);
789 
790 	if (network_create_enabled) {
791 		use_net = TRUE;
792 		net_game_number = net_init_game(text_widget_get_text(game_name),
793                                 num_players, player_types, player_names);
794 	} else if (network_join_enabled && selected_net_game_id > 0) {
795 		use_net = TRUE;
796 		net_game_number = selected_net_game_id;
797 		net_join(selected_net_game_id, selected_net_game_player_slot,
798 			 text_widget_get_text(player_name[selected_net_game_player_slot]));
799 	}
800 
801 	if (cur_game_mutex == NULL)
802 		cur_game_mutex = SDL_CreateMutex();
803 
804 	options_game_lock();
805 
806 	free_game(cur_game);
807 	cur_game = init_game();
808 	cur_game->num_players = num_players;
809 
810 	for (i = 0; i < num_players; i++)
811 		cur_game->player_name[i] = strdup(options_get_player_name(i));
812 
813 	options_game_unlock();
814 
815 	if (use_net && (net_game_number < 0 || net_wait_ready(num_players, player_names) < 0))
816 	{
817 		SDL_FillRect(screen, NULL, 0x00000000);
818 		SDL_UpdateRect(screen, 0, 0, 0, 0);
819 		draw_message(get_msg(M_ENOCONN), 200, 284, -1, FALSE);
820 
821 		llist_for_each(network_games_list, free_game);
822 		llist_free(network_games_list);
823 		network_games_list = NULL;
824 
825 		options_game_lock();
826 		free_game(cur_game);
827 		cur_game = NULL;
828 		options_game_unlock();
829 
830 		if (delay_with_event_poll(2000) < 0)
831 			use_net = FALSE;
832 		else
833 			goto choose_again;
834 	}
835 	if (!use_net)
836 		net_close();
837 
838 	llist_for_each(network_games_list, free_game);
839 	llist_free(network_games_list);
840 	network_games_list = NULL;
841 
842 	SDL_FillRect(screen, NULL, 0x00000000);
843 	SDL_UpdateRect(screen, 0, 0, 0, 0);
844 
845 	return 0;
846 }
847 
848 /**
849  * Get a player name
850  *
851  * @param[in]	i		The player number
852  */
options_get_player_name(int i)853 const char *options_get_player_name(int i)
854 {
855 	return text_widget_get_text(player_name[i]);
856 }
857 
858 /**
859  * Get a player type
860  *
861  * @param[in]	i		The player number
862  */
options_get_player_type(int i)863 int options_get_player_type(int i)
864 {
865 	return player_types[i];
866 }
867