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