1 /*
2  *     gtkatlantic - the gtk+ monopd client, enjoy network monopoly games
3  *
4  *
5  *  Copyright © 2002-2015 Sylvain Rochet
6  *
7  *  gtkatlantic is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 2 of the License, or
10  *  (at your option) any later version.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; see the file COPYING. If not, see
19  *  <http://www.gnu.org/licenses/>.
20  */
21 
22 #include "config.h"
23 
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <gtk/gtk.h>
27 #include <string.h>
28 
29 #include "global.h"
30 #include "callback.h"
31 #include "client.h"
32 #include "game.h"
33 #include "interface.h"
34 #include "trade.h"
35 #include "load.h"
36 #include "theme.h"
37 #include "display.h"
38 
39 #include "engine.h"
40 
41 
42 /* **** Show Configuration Panel */
Callback_ShowConfiguration(GtkWidget * menuitem)43 void Callback_ShowConfiguration(GtkWidget* menuitem)  {
44 	(void)menuitem;
45 
46 	interface_create_config_panel();
47 }
48 
49 
50 /* **** Get games from all monopd server */
Callback_ConnectMetaServer(GtkWidget * button)51 void Callback_ConnectMetaServer(GtkWidget* button)  {
52 	(void)button;
53 
54 	if (global->phase < PHASE_GAMECREATE) {
55 		if (global->phase < PHASE_GETGAMES) {
56 			interface_create_getgamespage(false);
57 		}
58 		create_connection_metaserver();
59 	}
60 }
61 
62 
63 /* get games: event "row_select" */
Callback_GetGame_Select(GtkTreeSelection * selection,gpointer data)64 void Callback_GetGame_Select(GtkTreeSelection *selection, gpointer data)  {
65 	GtkTreeModel *model;
66 	gint32 gameid, canbejoined, canbewatched;
67 	(void)data;
68 
69 	GtkWidget *button = g_object_get_data(G_OBJECT(global->MainVerticalBox), "connect_button");
70 
71 	if (!gtk_tree_selection_get_selected(selection, &model, &global->selected_game)) {
72 		if (button) {
73 			gtk_button_set_label(GTK_BUTTON(button), "Select a game");
74 			gtk_widget_set_sensitive(button, FALSE);
75 		}
76 		return;
77 	}
78 
79 	gtk_tree_model_get(model, &global->selected_game, GAMELIST_COLUMN_GAMEID, &gameid, GAMELIST_COLUMN_CANBEJOINED, &canbejoined, GAMELIST_COLUMN_CANBEWATCHED, &canbewatched, -1);
80 
81 	if (button) {
82 		if (gameid < 0) {
83 			gtk_button_set_label(GTK_BUTTON(button), "Create game");
84 			gtk_widget_set_sensitive(button, TRUE);
85 		} else {
86 			if (canbejoined) {
87 				gtk_button_set_label(GTK_BUTTON(button), "Join game");
88 				gtk_widget_set_sensitive(button, TRUE);
89 			} else if (canbewatched) {
90 				gtk_button_set_label(GTK_BUTTON(button), "Watch game");
91 				gtk_widget_set_sensitive(button, TRUE);
92 			} else {
93 				gtk_button_set_label(GTK_BUTTON(button), "This game does not allow spectators");
94 				gtk_widget_set_sensitive(button, FALSE);
95 			}
96 		}
97 	}
98 }
99 
100 
101 /* **** Join/create a game */
Callback_ConnectButton(GtkWidget * button)102 void Callback_ConnectButton(GtkWidget* button)  {
103 	(void)button;
104 	gchar *cmd;
105 	gchar *host, *gametype;
106 	gint32 port, gameid, canbejoined, canbewatched;
107 
108 	gtk_tree_model_get(GTK_TREE_MODEL(global->game_store), &global->selected_game, GAMELIST_COLUMN_HOST, &host, GAMELIST_COLUMN_PORT, &port, GAMELIST_COLUMN_GAMETYPE, &gametype, GAMELIST_COLUMN_GAMEID, &gameid,
109 		   GAMELIST_COLUMN_CANBEJOINED, &canbejoined, GAMELIST_COLUMN_CANBEWATCHED, &canbewatched, -1);
110 
111 	if (! (gameid < 0 || canbejoined || canbewatched)) {
112 		return;
113 	}
114 
115 	/* create a game */
116 	if (gameid < 0)  {
117 		cmd = g_strdup_printf(".n%s\n.gn%s\n", config->nickname, gametype);
118 	}
119 	/* join a game */
120 	else if (canbejoined) {
121 		cmd = g_strdup_printf(".n%s\n.gj%d\n", config->nickname, gameid);
122 	}
123 	/* watch a game */
124 	else {
125 		cmd = g_strdup_printf(".n%s\n.gS%d\n", config->nickname, gameid);
126 	}
127 
128 	client_connect(CONNECT_TYPE_MONOPD_GAME, host, port, cmd);
129 }
130 
131 
132 /* **** Start the game :) */
Callback_StartButton(GtkWidget * button)133 void Callback_StartButton(GtkWidget* button)  {
134 	(void)button;
135 
136 	client_send(global->game_connect, ".gs\n");
137 }
138 
139 
140 /* *** send data to server */
Callback_SendButton(GtkWidget * Button,GtkWidget * entry)141 void Callback_SendButton(GtkWidget* Button, GtkWidget *entry) {
142 	(void)Button;
143 
144 	gchar *tmp, *tmp2;
145 
146 	tmp = g_strdup( gtk_entry_get_text( GTK_ENTRY(entry) ) );
147 	g_strstrip(tmp);
148 
149 	if(tmp[0] != '/')   {
150 
151 		tmp2 = g_strconcat(tmp, "\n", NULL);
152 		g_free(tmp);
153 		tmp = tmp2;
154 		client_send(global->game_connect, tmp);
155 	}
156 	else
157 		parse_specific_send_message(tmp);
158 
159 	g_free(tmp);
160 	gtk_entry_set_text(GTK_ENTRY(entry), "");
161 }
162 
163 
164 /* *** save and apply the config */
CallBack_ok_button_configwindow(GtkWidget * widget)165 void CallBack_ok_button_configwindow(GtkWidget* widget)  {
166 	(void)widget;
167 
168 	gchar *filename, *errormsg;
169 	FILE *file;
170 
171 	if (!global->path_home) {
172 		return;
173 	}
174 	filename = g_strconcat(global->path_home, "/gtkatlantic.conf", NULL);
175 
176 	file = fopen(filename, "wt");
177 	if (!file) {
178 		errormsg = g_strdup_printf("Can't write config file at \"%s\"", filename);
179 		interface_set_infolabel(errormsg, "b00000", false);
180 		g_free(errormsg);
181 		g_free(filename);
182 		return;
183 	}
184 	g_free(filename);
185 
186 	fprintf(file, "player nickname=\"%s\"\n",
187 		gtk_entry_get_text( GTK_ENTRY( g_object_get_data(G_OBJECT(global->ConfigWin), "config_player_nickname") ) )  );
188 	fprintf(file, "metaserver autoconnect=\"%d\" sendclientversion=\"%d\"\n",
189 		gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( g_object_get_data(G_OBJECT(global->ConfigWin), "config_metaserver_autoconnect") ) ),
190 		gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( g_object_get_data(G_OBJECT(global->ConfigWin), "config_metaserver_sendclientversion") ) )  );
191 	fprintf(file, "customserver host=\"%s\" port=\"%d\" autoconnect=\"%d\"\n",
192 		gtk_entry_get_text( GTK_ENTRY( g_object_get_data(G_OBJECT(global->ConfigWin), "config_customserver_host") ) ),
193 		atoi( gtk_entry_get_text( GTK_ENTRY( g_object_get_data(G_OBJECT(global->ConfigWin), "config_customserver_port") ) ) ),
194 		gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( g_object_get_data(G_OBJECT(global->ConfigWin), "config_customserver_autoconnect") ) )  );
195 	fprintf(file, "interface playerlist=\"%s\" token_speed=\"%d\" token_transparency=\"%d\"\n",
196 		gtk_combo_box_text_get_active_text( GTK_COMBO_BOX_TEXT( g_object_get_data(G_OBJECT(global->ConfigWin), "config_gameinterface_playerlistposition") ) ),
197 		(guint32)gtk_adjustment_get_value(GTK_ADJUSTMENT( g_object_get_data(G_OBJECT(global->ConfigWin), "config_gameinterface_tokenanimatespeed") ) ),
198 		gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( g_object_get_data(G_OBJECT(global->ConfigWin), "config_gameinterface_tokentransparency") ) )  );
199 
200 	fclose(file);
201 
202 	read_config_files();
203 
204 	gtk_widget_destroy(global->ConfigWin);
205 }
206 
207 
208 /* *** reallow show config panel */
CallBack_configwindow_destroyed(GtkWidget * widget)209 void CallBack_configwindow_destroyed(GtkWidget* widget)  {
210 	(void)widget;
211 
212 	global->ConfigWin = 0;
213 }
214 
215 
216 /* *** button command pressed */
CallBack_button_command_pressed(GtkWidget * button)217 void CallBack_button_command_pressed(GtkWidget* button) {
218 
219 	gchar *ptr = g_object_get_data(G_OBJECT(button), "command");
220 	client_send(global->game_connect, ptr);
221 }
222 
223 
224 /* *** button command pressed */
Callback_AuctionButton_Absolute(GtkWidget * button,GtkWidget * entry)225 void Callback_AuctionButton_Absolute(GtkWidget* button, GtkWidget* entry)  {
226 	gchar *tosend;
227 	gint32 auction, money;
228 
229 	auction = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(button), "auctionid"));
230 	money = atoi(gtk_entry_get_text(GTK_ENTRY(entry)));
231 	gtk_entry_set_text(GTK_ENTRY(entry), "");
232 
233 	tosend = g_strdup_printf(".ab%d:%d\n", auction, money);
234 	client_send(global->game_connect, tosend);
235 	g_free(tosend);
236 }
237 
238 
239 /* *** button command pressed */
Callback_AuctionButton_Relative(GtkWidget * button)240 void Callback_AuctionButton_Relative(GtkWidget* button)  {
241 	gchar *tosend;
242 	gint32 auction, money;
243 
244 	auction = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(button), "auctionid"));
245 	money = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(currentgame->BoardCenter), "auction_highbid"))
246 		+ GPOINTER_TO_INT(g_object_get_data(G_OBJECT(button), "value_add"));
247 
248 	tosend = g_strdup_printf(".ab%d:%d\n", auction, money);
249 	client_send(global->game_connect, tosend);
250 	g_free(tosend);
251 }
252 
253 
254 /* *** callback clic on estate */
Callback_ClicOnEstate(GtkWidget * widget,GdkEvent * event)255 void Callback_ClicOnEstate(GtkWidget* widget, GdkEvent *event)  {
256 
257 	if (event->type != GDK_BUTTON_PRESS) {
258 		return;
259 	}
260 
261 	GtkWidget *menu = g_object_get_data(G_OBJECT(widget), "menu");
262 #if GTK_CHECK_VERSION(3,22,0)
263 	gtk_menu_popup_at_pointer(GTK_MENU(menu), NULL);
264 #else /* GTK_CHECK_VERSION(3,22,0) */
265 	GdkEventButton *button_event = (GdkEventButton *)event;
266 	gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, button_event->button, button_event->time);
267 #endif /* GTK_CHECK_VERSION(3,22,0) */
268 }
269 
270 
271 /* *** callback clic on estate */
CallBack_PopupMenuEstate(GtkWidget * widget)272 void CallBack_PopupMenuEstate(GtkWidget* widget)  {
273 	guint32 id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(gtk_widget_get_parent(widget)), "estateid"));
274 	gint32 action = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "action"));
275 	gchar *cmd = NULL;
276 
277 	switch (action) {
278 		case ESTATE_ACTION_BUILDHOUSE:
279 			cmd = g_strdup_printf(".hb%d\n", id);
280 			break;
281 		case ESTATE_ACTION_SELLHOUSE:
282 			cmd = g_strdup_printf(".hs%d\n", id);
283 			break;
284 		case ESTATE_ACTION_MORTGAGE:
285 			cmd = g_strdup_printf(".em%d\n", id);
286 			break;
287 		case ESTATE_ACTION_SELL:
288 			cmd = g_strdup_printf(".es%d\n", id);
289 			break;
290 	}
291 
292 	if (cmd) {
293 		client_send(global->game_connect, cmd);
294 		g_free(cmd);
295 	}
296 }
297 
298 
299 /* *** callback enter an estate */
Callback_EnterAnEstate(GtkWidget * widget)300 void Callback_EnterAnEstate(GtkWidget* widget)  {
301 
302 	gint32 id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "estateid"));
303 
304 	eng_obj *pic = currentgame->estate[id].pic;
305 
306 	eng_pic_set_bgcolor(pic, 0x000000);
307 	eng_pic_set_alpha(pic, 170);
308 	update_display();
309 }
310 
311 
312 /* *** callback leave an estate */
Callback_LeaveAnEstate(GtkWidget * widget)313 void Callback_LeaveAnEstate(GtkWidget* widget)  {
314 
315 	gint32 id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "estateid"));
316 
317 	eng_obj *pic = currentgame->estate[id].pic;
318 	eng_pic_unset_alpha(pic);
319 	update_display();
320 }
321 
322 
323 /* *** callback clic on player */
Callback_ClicOnPlayer(GtkWidget * widget,GdkEvent * event)324 void Callback_ClicOnPlayer(GtkWidget* widget, GdkEvent *event)  {
325 
326 	if (event->type != GDK_BUTTON_PRESS) {
327 		return;
328 	}
329 
330 	GtkWidget *menu = g_object_get_data(G_OBJECT(widget), "menu");
331 #if GTK_CHECK_VERSION(3,22,0)
332 	gtk_menu_popup_at_pointer(GTK_MENU(menu), NULL);
333 #else /* GTK_CHECK_VERSION(3,22,0) */
334 	GdkEventButton *button_event = (GdkEventButton *)event;
335 	gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, button_event->button, button_event->time);
336 #endif /* GTK_CHECK_VERSION(3,22,0) */
337 }
338 
339 
340 /* *** callback clic on player */
CallBack_PopupMenuPlayer(GtkWidget * widget)341 void CallBack_PopupMenuPlayer(GtkWidget* widget)  {
342 	player *p = g_object_get_data(G_OBJECT(gtk_widget_get_parent(widget)), "player");
343 	gint32 action = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "action"));
344 	gchar *cmd = NULL;
345 
346 	switch (action) {
347 		case PLAYER_ACTION_TRADE:
348 			cmd = g_strdup_printf(".Tn%d\n", p->playerid);
349 			break;
350 		case PLAYER_ACTION_VERSION:
351 			cmd = g_strdup_printf("!version %s\n", p->name);
352 			break;
353 		case PLAYER_ACTION_DATE:
354 			cmd = g_strdup_printf("!date %s\n", p->name);
355 			break;
356 		case PLAYER_ACTION_PING:
357 			cmd = g_strdup_printf("!ping %s\n", p->name);
358 			break;
359 	}
360 
361 	if (cmd) {
362 		client_send(global->game_connect, cmd);
363 		g_free(cmd);
364 	}
365 }
366 
367 
368 /* *** callback for game option type bool */
Callback_toggle_boolean_gameoption(GtkWidget * widget)369 void Callback_toggle_boolean_gameoption(GtkWidget* widget)  {
370 	gchar *text, *cmd;
371 	gint32 id;
372 
373 	/* commands using the new configupdate protocol */
374 	id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "id"));
375 	if (id > 0) {
376 		text = g_strdup_printf(".gc%d:%d\n", id, gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(widget) )  );
377 		client_send(global->game_connect, text);
378 		g_free(text);
379 		return;
380 	}
381 
382 	/* commands using the old configupdate protocol */
383 	cmd = g_object_get_data(G_OBJECT(widget), "command");
384 	if (cmd) {
385 		text = g_strdup_printf("%s%d\n", cmd, gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(widget) )  );
386 		client_send(global->game_connect, text);
387 		g_free(text);
388 	}
389 }
390 
391 
392 /* *** callback for the entry menu connect to server */
CallBack_menu_connect_to_server(GtkWidget * widget)393 void CallBack_menu_connect_to_server(GtkWidget* widget) {
394 	(void)widget;
395 
396 	if (global->phase < PHASE_GAMECREATE)
397 		interface_create_connectoserver();
398 }
399 
400 
401 /* *** callback for the connect to server menu entry */
CallBack_response_connect_to_server_window(GtkWidget * widget,gint response,GtkWidget * Win)402 void CallBack_response_connect_to_server_window(GtkWidget* widget, gint response, GtkWidget *Win) {
403 	(void)widget;
404 
405 	if (global->phase < PHASE_GAMECREATE && response == GTK_RESPONSE_OK) {
406 		GtkWidget *host = g_object_get_data(G_OBJECT(Win), "host");
407 		GtkWidget *port = g_object_get_data(G_OBJECT(Win), "port");
408 
409 		if (global->phase < PHASE_GETGAMES) {
410 			interface_create_getgamespage(false);
411 		}
412 
413 		create_connection_get_games((gchar*)gtk_entry_get_text(GTK_ENTRY(host)),
414 			atoi(gtk_entry_get_text(GTK_ENTRY(port))));
415 	}
416 
417 	gtk_widget_destroy(Win);
418 }
419 
420 
421 /* *** callback for the entry menu connect to server */
CallBack_menu_public_server_list(GtkWidget * widget)422 void CallBack_menu_public_server_list(GtkWidget* widget) {
423 	(void)widget;
424 
425 	if (global->phase == PHASE_GETGAMES)
426 		interface_create_publicserverlist();
427 }
428 
429 
430 /* *** callback for the entry menu change nickname */
CallBack_menu_change_nickname(GtkWidget * widget)431 void CallBack_menu_change_nickname(GtkWidget* widget)  {
432 	(void)widget;
433 
434 	if(global->phase >= PHASE_GAMECREATE)
435 		interface_create_nicknamewin();
436 }
437 
438 
439 /* *** callback for the ok button of window change nickname */
CallBack_response_changenick_window(GtkWidget * widget,gint response,GtkWidget * Win)440 void CallBack_response_changenick_window(GtkWidget* widget, gint response, GtkWidget *Win) {
441 	(void)widget;
442 
443 	if(response == GTK_RESPONSE_OK)
444 	{
445 		GtkWidget *Entry = g_object_get_data(G_OBJECT(Win), "nickname");
446 		gchar *nickname, *sendstr;
447 
448 		nickname = g_strdup( gtk_entry_get_text(GTK_ENTRY( Entry ) )  );
449 
450 		if (strcmp(player_from_id(global->my_playerid)->name, nickname)) {
451 			sendstr = g_strdup_printf(".n%s\n", nickname);
452 			client_send(global->game_connect, sendstr);
453 			g_free(sendstr);
454 		}
455 
456 		g_free(nickname);
457 	}
458 
459 	gtk_widget_destroy(Win);
460 }
461 
462 
463 /* *** callback for the entry menu reconnect */
CallBack_menu_reconnect(GtkWidget * widget)464 void CallBack_menu_reconnect(GtkWidget* widget)  {
465 	(void)widget;
466 	gchar buf[64];
467 	gchar *filename, *host = NULL, *cmd;
468 	guint32 port;
469 	FILE *file;
470 	size_t len;
471 
472 	if (global->phase > PHASE_GETGAMES) {
473 		return;
474 	}
475 
476 	if (!global->path_home) {
477 		return;
478 	}
479 
480 	/* read cookie file */
481 	filename = g_strconcat(global->path_home, "/cookie", NULL);
482 	file = fopen(filename, "rt");
483 	g_free(filename);
484 
485 	if (!file) {
486 		return;
487 	}
488 
489 	if (fgets(buf, sizeof(buf), file) == NULL) {
490 		goto free_and_return;
491 	}
492 	len = strlen(buf);
493 	if (buf[len-1] != '\n') {
494 		goto free_and_return;
495 	}
496 	buf[len-1] = '\0';
497 	host = g_strdup(buf);
498 
499 	if (fgets(buf, sizeof(buf), file) == NULL) {
500 		goto free_and_return;
501 	}
502 	len = strlen(buf);
503 	if (buf[len-1] != '\n') {
504 		goto free_and_return;
505 	}
506 	buf[len-1] = '\0';
507 	port = atoi(buf);
508 
509 	if (fgets(buf, sizeof(buf), file) == NULL) {
510 		goto free_and_return;
511 	}
512 	len = strlen(buf);
513 	if (buf[len-1] != '\n') {
514 		goto free_and_return;
515 	}
516 	buf[len-1] = '\0';
517 	cmd = g_strdup_printf(".R%s\n", buf);
518 
519 	/* rejoin game */
520 	client_connect(CONNECT_TYPE_MONOPD_GAME, host, port, cmd);
521 
522 free_and_return:
523 	fclose(file);
524 	if (host) g_free(host);
525 }
526 
527 
CallBack_menu_AddPlayer(GtkWidget * widget)528 void CallBack_menu_AddPlayer(GtkWidget *widget) {
529 	player *p = g_object_get_data(G_OBJECT(widget), "player");
530 	if (!p) {
531 		return;
532 	}
533 
534 	gchar *cmd = g_strdup_printf(".gu%d\n", p->playerid);
535 	client_send(global->game_connect, cmd);
536 	g_free(cmd);
537 }
538 
539 
540 /* *** callback for all trades buttons */
CallBack_trade_button(GtkWidget * button)541 void CallBack_trade_button(GtkWidget *button)  {
542 
543 	gchar *sendstr = 0;
544 	gint32 command = GPOINTER_TO_INT(g_object_get_data( G_OBJECT(button), "command" ));
545 	guint32 tradeid = GPOINTER_TO_INT( g_object_get_data( G_OBJECT(button), "tradeid" )  );
546 	guint32	tradeslot = get_trade_slot_with_tradeid(tradeid);
547 
548 	switch(command) {
549 		case TRADE_ACTION_REJECT:
550 			sendstr = g_strdup_printf(".Tr%d\n", tradeid);
551 			client_send(global->game_connect, sendstr);
552 			g_free(sendstr);
553 			break;
554 
555 		case TRADE_ACTION_ACCEPT:
556 			sendstr = g_strdup_printf(".Ta%d:%d\n", tradeid, currentgame->trade[tradeslot].revision);
557 			client_send(global->game_connect, sendstr);
558 			g_free(sendstr);
559 			break;
560 
561 		case TRADE_ACTION_REMOVE:
562 			if(currentgame->trade[tradeslot].select_type == TRADE_TYPE_MONEY)
563 				sendstr = g_strdup_printf(".Tm%d:%d:%d:%d\n", tradeid, currentgame->trade[tradeslot].select_from, currentgame->trade[tradeslot].select_to, 0);
564 
565 			if(currentgame->trade[tradeslot].select_type == TRADE_TYPE_ESTATE)
566 				sendstr = g_strdup_printf(".Te%d:%d:%d\n", tradeid, currentgame->trade[tradeslot].select_aux, currentgame->trade[tradeslot].select_from);
567 
568 			if(currentgame->trade[tradeslot].select_type == TRADE_TYPE_CARD)
569 				sendstr = g_strdup_printf(".Tc%d:%d:%d\n", tradeid, currentgame->trade[tradeslot].select_aux, currentgame->trade[tradeslot].select_from);
570 
571 			if(sendstr)  {
572 				client_send(global->game_connect, sendstr);
573 				g_free(sendstr);
574 			}
575 			break;
576 	}
577 }
578 
579 
580 /* *** callback for all trade component */
CallBack_trade_sub_component(GtkWidget * combo)581 void CallBack_trade_sub_component(GtkWidget *combo)  {
582 
583 	gchar *text;
584 	gint32 tradeslot;
585 
586 	tradeslot = get_trade_slot_with_tradeid( GPOINTER_TO_INT( g_object_get_data( G_OBJECT(combo), "tradeid" )  )  );
587 	if(tradeslot < 0) return;
588 
589 	text = gtk_combo_box_text_get_active_text( GTK_COMBO_BOX_TEXT(combo) );
590 	if( !strcmp(text, "Money")) {
591 		currentgame->trade[tradeslot].current_component = TRADE_TYPE_MONEY;
592 	} else if( !strcmp(text, "Estate")) {
593 		currentgame->trade[tradeslot].current_component = TRADE_TYPE_ESTATE;
594 	} else {
595 		currentgame->trade[tradeslot].current_component = TRADE_TYPE_CARD;
596 	}
597 
598 	trade_rebuild_subcomponent(tradeslot);
599 }
600 
601 
602 /* *** callback for all update component */
CallBack_trade_update_component(GtkWidget * button)603 void CallBack_trade_update_component(GtkWidget *button)  {
604 
605 	gchar *sendstr;
606 	guint32 tradeid, estateid, cardid, tradeslot, money;
607 	player *target, *from, *to;
608 
609 	tradeslot = get_trade_slot_with_tradeid( GPOINTER_TO_INT( g_object_get_data( G_OBJECT(button), "tradeid" )  )  );
610 	tradeid = currentgame->trade[tradeslot].tradeid;
611 
612 	switch(currentgame->trade[tradeslot].current_component)  {
613 
614 		case TRADE_TYPE_ESTATE:
615 
616 			estateid = get_estateid_by_estatename( (gchar*)gtk_combo_box_text_get_active_text( GTK_COMBO_BOX_TEXT(g_object_get_data( G_OBJECT(button), "name_estate" ) ))  );
617 			target = player_from_name((gchar*)gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(g_object_get_data(G_OBJECT(button), "name_target_player"))));
618 
619 			sendstr = g_strdup_printf(".Te%d:%d:%d\n", tradeid, estateid, target->playerid);
620 			client_send(global->game_connect, sendstr);
621 			g_free(sendstr);
622 			break;
623 
624 		case TRADE_TYPE_MONEY:
625 
626 			from = player_from_name((gchar*)gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(g_object_get_data(G_OBJECT(button), "name_from_player"))));
627 			to = player_from_name((gchar*)gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(g_object_get_data(G_OBJECT(button), "name_to_player"))));
628 			money = atoi( gtk_entry_get_text( g_object_get_data( G_OBJECT(button), "amount_money" ) )  );
629 
630 			sendstr = g_strdup_printf(".Tm%d:%d:%d:%d\n", tradeid, from->playerid, to->playerid, money);
631 			client_send(global->game_connect, sendstr);
632 			g_free(sendstr);
633 			break;
634 
635 		case TRADE_TYPE_CARD:
636 
637 			cardid = atoi( gtk_combo_box_text_get_active_text( GTK_COMBO_BOX_TEXT(g_object_get_data( G_OBJECT(button), "name_card" ) ))  );
638 			target = player_from_name((gchar*)gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(g_object_get_data(G_OBJECT(button), "name_target_player"))));
639 			sendstr = g_strdup_printf(".Tc%d:%d:%d\n", tradeid, cardid, target->playerid);
640 			client_send(global->game_connect, sendstr);
641 			g_free(sendstr);
642 			break;
643 	}
644 }
645 
646 
CallBack_get_games_page_destroyed(GtkWidget * widget)647 void CallBack_get_games_page_destroyed(GtkWidget *widget)  {
648 	(void)widget;
649 
650 	g_object_unref(global->server_store);
651 	global->game_store = NULL;
652 	global->server_store = NULL;
653 }
654 
655 
656 /* *** callback for the entry menu leave game */
CallBack_menu_LeaveGame(GtkWidget * widget)657 void CallBack_menu_LeaveGame(GtkWidget* widget)  {
658 	(void)widget;
659 
660 	if (global->phase < PHASE_GAMECREATE) {
661 		return;
662 	}
663 
664 	client_send(global->game_connect, ".gx\n");
665 	game_quit();
666 }
667 
668 
669 /* *** Show estates tree */
CallBack_estates_tree(GtkWidget * widget)670 void CallBack_estates_tree(GtkWidget* widget) {
671 	(void)widget;
672 
673 	if(global->phase != PHASE_GAMEPLAY) return;
674 
675 	interface_create_estates_tree();
676 }
677 
678 
679 
680 
CallBack_EstateTree_SelectRow(GtkTreeSelection * selection,gpointer data)681 void CallBack_EstateTree_SelectRow(GtkTreeSelection *selection, gpointer data)  {
682 	GtkTreeIter iter;
683 	GtkTreeModel *model;
684 	gint32 id = -1;
685 	GtkWidget *parent, *info, *Label;
686 	gchar *Text;
687 
688 	(void)data;
689 
690 	if (!gtk_tree_selection_get_selected(selection, &model, &iter)) {
691 		return;
692 	}
693 
694 	parent = g_object_get_data(G_OBJECT(currentgame->WinEstateTree), "parent_box");
695 	info = g_object_get_data(G_OBJECT(currentgame->WinEstateTree), "info_box");
696 
697 	if(info) gtk_widget_destroy(info);
698 	/* info box */
699 	info = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
700 	g_object_set_data(G_OBJECT(currentgame->WinEstateTree), "info_box", info);
701 	gtk_container_set_border_width(GTK_CONTAINER(info), 10);
702 	gtk_box_pack_start(GTK_BOX(parent), info, TRUE, TRUE, 0);
703 
704 	gtk_tree_model_get(model, &iter, 1, &id, -1);
705 	if(id < 0) {
706 
707 		/* info box */
708 		info = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
709 		g_object_set_data(G_OBJECT(currentgame->WinEstateTree), "info_box", info);
710 		gtk_container_set_border_width(GTK_CONTAINER(info), 10);
711 		gtk_box_pack_start(GTK_BOX(parent), info, TRUE, TRUE, 0);
712 
713 		/* default text */
714 		Label = gtk_label_new("Select an estate...");
715 		gtk_widget_set_halign(Label, GTK_ALIGN_START);
716 		gtk_widget_set_valign(Label, GTK_ALIGN_START);
717 		gtk_box_pack_start(GTK_BOX(info), Label, FALSE, TRUE, 0);
718 
719 		gtk_widget_show_all(info);
720 		return;
721 	}
722 
723 	/* name */
724 	Text = g_strdup_printf("%s", currentgame->estate[id].name);
725 
726 	Label = gtk_label_new(Text);
727 	gtk_widget_set_halign(Label, GTK_ALIGN_START);
728 	gtk_widget_set_valign(Label, GTK_ALIGN_START);
729 	gtk_box_pack_start(GTK_BOX(info), Label, FALSE, TRUE, 0);
730 
731 	g_free(Text);
732 
733 
734 	/* group */
735 	if(currentgame->estate[id].group >= 0)  Text = g_strdup_printf("%s\n", currentgame->group[ currentgame->estate[id].group ].name);
736 	else  Text = g_strdup("\n");
737 
738 	Label = gtk_label_new(Text);
739 	gtk_widget_set_halign(Label, GTK_ALIGN_START);
740 	gtk_widget_set_valign(Label, GTK_ALIGN_START);
741 	gtk_box_pack_start(GTK_BOX(info), Label, FALSE, TRUE, 0);
742 
743 	g_free(Text);
744 
745 	/* state (for sale, owned, mortgaged, unknow?) */
746 	if(currentgame->estate[id].price)  {
747 
748 		if(currentgame->estate[id].owner <= 0)  Text = g_strdup("State: for sale");
749 		else  if(currentgame->estate[id].owner > 0  &&  currentgame->estate[id].mortgaged)  Text = g_strdup("State: mortgaged");
750 		else  if(currentgame->estate[id].owner > 0)  Text = g_strdup("State: owned");
751 		else  Text = g_strdup("State: unknow");
752 
753 		Label = gtk_label_new(Text);
754 		gtk_widget_set_halign(Label, GTK_ALIGN_START);
755 		gtk_widget_set_valign(Label, GTK_ALIGN_START);
756 		gtk_box_pack_start(GTK_BOX(info), Label, FALSE, TRUE, 0);
757 
758 		g_free(Text);
759 	}
760 
761 	/* owner */
762 	if(currentgame->estate[id].price)  {
763 
764 		if(currentgame->estate[id].owner <= 0)  Text = g_strdup("Owner: no");
765 		else  Text = g_strdup_printf("Owner: %s", player_from_id(currentgame->estate[id].owner)->name);
766 
767 		Label = gtk_label_new(Text);
768 		gtk_widget_set_halign(Label, GTK_ALIGN_START);
769 		gtk_widget_set_valign(Label, GTK_ALIGN_START);
770 		gtk_box_pack_start(GTK_BOX(info), Label, FALSE, TRUE, 0);
771 
772 		g_free(Text);
773 	}
774 
775 	/* price */
776 	if(currentgame->estate[id].price)  {
777 
778 		Text = g_strdup_printf("\nPrice: %d", currentgame->estate[id].price);
779 
780 		Label = gtk_label_new(Text);
781 		gtk_widget_set_halign(Label, GTK_ALIGN_START);
782 		gtk_widget_set_valign(Label, GTK_ALIGN_START);
783 		gtk_box_pack_start(GTK_BOX(info), Label, FALSE, TRUE, 0);
784 
785 		g_free(Text);
786 	}
787 
788 	/* money */
789 	if(currentgame->estate[id].money)  {
790 
791 		Text = g_strdup_printf("Money: %d", currentgame->estate[id].money);
792 
793 		Label = gtk_label_new(Text);
794 		gtk_widget_set_halign(Label, GTK_ALIGN_START);
795 		gtk_widget_set_valign(Label, GTK_ALIGN_START);
796 		gtk_box_pack_start(GTK_BOX(info), Label, FALSE, TRUE, 0);
797 
798 		g_free(Text);
799 	}
800 
801 	/* rent */
802 	if(currentgame->estate[id].rent[5])  {
803 
804 		Text = g_strdup_printf("\nRent with no house: %d", currentgame->estate[id].rent[0]);
805 
806 		Label = gtk_label_new(Text);
807 		gtk_widget_set_halign(Label, GTK_ALIGN_START);
808 		gtk_widget_set_valign(Label, GTK_ALIGN_START);
809 		gtk_box_pack_start(GTK_BOX(info), Label, FALSE, TRUE, 0);
810 
811 		g_free(Text);
812 
813 
814 		Text = g_strdup_printf("Rent with 1 house: %d", currentgame->estate[id].rent[1]);
815 
816 		Label = gtk_label_new(Text);
817 		gtk_widget_set_halign(Label, GTK_ALIGN_START);
818 		gtk_widget_set_valign(Label, GTK_ALIGN_START);
819 		gtk_box_pack_start(GTK_BOX(info), Label, FALSE, TRUE, 0);
820 
821 		g_free(Text);
822 
823 
824 		Text = g_strdup_printf("Rent with 2 houses: %d", currentgame->estate[id].rent[2]);
825 
826 		Label = gtk_label_new(Text);
827 		gtk_widget_set_halign(Label, GTK_ALIGN_START);
828 		gtk_widget_set_valign(Label, GTK_ALIGN_START);
829 		gtk_box_pack_start(GTK_BOX(info), Label, FALSE, TRUE, 0);
830 
831 		g_free(Text);
832 
833 
834 		Text = g_strdup_printf("Rent with 3 houses: %d", currentgame->estate[id].rent[3]);
835 
836 		Label = gtk_label_new(Text);
837 		gtk_widget_set_halign(Label, GTK_ALIGN_START);
838 		gtk_widget_set_valign(Label, GTK_ALIGN_START);
839 		gtk_box_pack_start(GTK_BOX(info), Label, FALSE, TRUE, 0);
840 
841 		g_free(Text);
842 
843 
844 		Text = g_strdup_printf("Rent with 4 houses: %d", currentgame->estate[id].rent[4]);
845 
846 		Label = gtk_label_new(Text);
847 		gtk_widget_set_halign(Label, GTK_ALIGN_START);
848 		gtk_widget_set_valign(Label, GTK_ALIGN_START);
849 		gtk_box_pack_start(GTK_BOX(info), Label, FALSE, TRUE, 0);
850 
851 		g_free(Text);
852 
853 
854 		Text = g_strdup_printf("Rent with a hotel: %d", currentgame->estate[id].rent[5]);
855 
856 		Label = gtk_label_new(Text);
857 		gtk_widget_set_halign(Label, GTK_ALIGN_START);
858 		gtk_widget_set_valign(Label, GTK_ALIGN_START);
859 		gtk_box_pack_start(GTK_BOX(info), Label, FALSE, TRUE, 0);
860 
861 		g_free(Text);
862 	}
863 
864 	/* houses prices */
865 	if(currentgame->estate[id].houseprice)  {
866 
867 		Text = g_strdup_printf("\nBuy house price: %d", currentgame->estate[id].houseprice);
868 
869 		Label = gtk_label_new(Text);
870 		gtk_widget_set_halign(Label, GTK_ALIGN_START);
871 		gtk_widget_set_valign(Label, GTK_ALIGN_START);
872 		gtk_box_pack_start(GTK_BOX(info), Label, FALSE, TRUE, 0);
873 
874 		g_free(Text);
875 	}
876 
877 	if(currentgame->estate[id].sellhouseprice)  {
878 
879 		Text = g_strdup_printf("Sell house price: %d", currentgame->estate[id].sellhouseprice);
880 
881 		Label = gtk_label_new(Text);
882 		gtk_widget_set_halign(Label, GTK_ALIGN_START);
883 		gtk_widget_set_valign(Label, GTK_ALIGN_START);
884 		gtk_box_pack_start(GTK_BOX(info), Label, FALSE, TRUE, 0);
885 
886 		g_free(Text);
887 	}
888 
889 	/* number of houses */
890 	if(currentgame->estate[id].houseprice)  {
891 
892 		Text = g_strdup_printf("Number of houses: %d", currentgame->estate[id].houses);
893 
894 		Label = gtk_label_new(Text);
895 		gtk_widget_set_halign(Label, GTK_ALIGN_START);
896 		gtk_widget_set_valign(Label, GTK_ALIGN_START);
897 		gtk_box_pack_start(GTK_BOX(info), Label, FALSE, TRUE, 0);
898 
899 		g_free(Text);
900 	}
901 
902 	/* (un)mortgage value */
903 	if(currentgame->estate[id].mortgageprice)  {
904 
905 		Text = g_strdup_printf("\nMortgage price: %d", currentgame->estate[id].mortgageprice);
906 
907 		Label = gtk_label_new(Text);
908 		gtk_widget_set_halign(Label, GTK_ALIGN_START);
909 		gtk_widget_set_valign(Label, GTK_ALIGN_START);
910 		gtk_box_pack_start(GTK_BOX(info), Label, FALSE, TRUE, 0);
911 
912 		g_free(Text);
913 	}
914 
915 	if(currentgame->estate[id].unmortgageprice)  {
916 
917 		Text = g_strdup_printf("Unmortgage price: %d", currentgame->estate[id].unmortgageprice);
918 
919 		Label = gtk_label_new(Text);
920 		gtk_widget_set_halign(Label, GTK_ALIGN_START);
921 		gtk_widget_set_valign(Label, GTK_ALIGN_START);
922 		gtk_box_pack_start(GTK_BOX(info), Label, FALSE, TRUE, 0);
923 
924 		g_free(Text);
925 	}
926 
927 
928 	gtk_widget_show_all(info);
929 }
930 
931 
CallBack_EstateTree_Destroyed(GtkWidget * widget)932 void CallBack_EstateTree_Destroyed(GtkWidget *widget)  {
933 	(void)widget;
934 
935 	currentgame->WinEstateTree = 0;
936 }
937 
938 
939 /* proposal list: event "row_select" */
Callback_ProposalList_Select(GtkTreeSelection * selection,gpointer data)940 void Callback_ProposalList_Select(GtkTreeSelection *selection, gpointer data) {
941 	GtkTreeIter iter;
942 	GtkTreeModel *model;
943 	gint32 tradeid, tradeslot, typeid, fromid, toid, auxid;
944 	(void)data;
945 
946 	tradeid = GPOINTER_TO_INT( g_object_get_data( G_OBJECT(selection), "tradeid" )  );
947 	tradeslot = get_trade_slot_with_tradeid(tradeid);
948 
949 	if (!gtk_tree_selection_get_selected(selection, &model, &iter)) {
950 		/* Nothing selected */
951 		currentgame->trade[tradeslot].select_type = 0;
952 		currentgame->trade[tradeslot].select_from = 0;
953 		currentgame->trade[tradeslot].select_to = 0;
954 		currentgame->trade[tradeslot].select_aux = 0;
955 		return;
956 	}
957 
958 	gtk_tree_model_get(model, &iter,
959 	  TRADEPROPOSALLIST_COLUMN_TYPE_ID, &typeid,
960 	  TRADEPROPOSALLIST_COLUMN_FROM_ID, &fromid,
961 	  TRADEPROPOSALLIST_COLUMN_TO_ID, &toid,
962 	  TRADEPROPOSALLIST_COLUMN_AUX_ID, &auxid,
963 	  -1);
964 
965 	currentgame->trade[tradeslot].select_type = typeid;
966 	currentgame->trade[tradeslot].select_from = fromid;
967 	currentgame->trade[tradeslot].select_to = toid;
968 	currentgame->trade[tradeslot].select_aux = auxid;
969 }
970 
CallBack_HelpWin_Destroyed(GtkWidget * widget)971 void CallBack_HelpWin_Destroyed(GtkWidget *widget)  {
972 	(void)widget;
973 
974 	global->HelpWin = 0;
975 }
976 
977 
Callback_menu_Themes(GtkWidget * widget)978 void Callback_menu_Themes(GtkWidget *widget)  {
979 	(void)widget;
980 
981 	if(global->ThemeWin)  return;
982 
983 	theme_build_selection_win();
984 	theme_build_database();
985 	theme_fill_selection_list();
986 }
987 
988 
CallBack_ThemeWin_Delete(GtkWidget * widget)989 void CallBack_ThemeWin_Delete(GtkWidget *widget)  {
990 	(void)widget;
991 
992 	theme_preview_free();
993 	gtk_widget_destroy(global->ThemeWin);
994 }
995 
996 
CallBack_ThemeWin_Destroyed(GtkWidget * widget)997 void CallBack_ThemeWin_Destroyed(GtkWidget *widget)  {
998 	(void)widget;
999 
1000 	global->ThemeWin = 0;
1001 }
1002 
1003 
1004 /* theme list: event "row_select" */
Callback_ThemeList_Select(GtkTreeSelection * selection,gpointer data)1005 void Callback_ThemeList_Select(GtkTreeSelection *selection, gpointer data) {
1006 	GtkTreeIter iter;
1007 	GtkTreeModel *model;
1008 	gint32 themeid;
1009 	(void)data;
1010 
1011 	if (!gtk_tree_selection_get_selected(selection, &model, &iter)) {
1012 		return;
1013 	}
1014 
1015 	gtk_tree_model_get(model, &iter,
1016 	  THEMELIST_COLUMN_ID, &themeid,
1017 	  -1);
1018 
1019 	theme_display(themeid);
1020 }
1021 
1022 
1023 /* select/apply a theme */
CallBack_Theme_Apply(GtkWidget * button)1024 void CallBack_Theme_Apply(GtkWidget* button)  {
1025 	(void)button;
1026 
1027 	theme_load( atoi( g_object_get_data(G_OBJECT(global->ThemeWin), "theme_preview_selected") ) );
1028 }
1029