Freeciv-3.2
Loading...
Searching...
No Matches
pages.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18#include <stdio.h>
19#include <time.h>
20
21#include <sys/stat.h>
22
23#include <gtk/gtk.h>
24
25/* utility */
26#include "fcintl.h"
27#include "log.h"
28#include "mem.h"
29#include "shared.h"
30#include "support.h"
31
32/* common */
33#include "dataio.h"
34#include "game.h"
35#include "mapimg.h"
36#include "version.h"
37
38/* client */
39#include "client_main.h"
40#include "climisc.h"
41#include "clinet.h"
42#include "connectdlg_common.h"
43#include "packhand.h"
44#include "servers.h"
45#include "update_queue.h"
46
47/* client/gui-gtk-3.22 */
48#include "chatline.h"
49#include "connectdlg.h"
50#include "dialogs.h"
51#include "graphics.h"
52#include "gui_main.h"
53#include "gui_stuff.h"
54#include "mapview.h"
55#include "optiondlg.h"
56#include "plrdlg.h" /* get_flag() */
57#include "repodlgs.h"
58#include "voteinfo_bar.h"
59
60#include "pages.h"
61
62
67
69
72
75
76/* This is the current page. Invalid value at start, to be sure that it won't
77 * be catch throught a switch() statement. */
78static enum client_pages current_page = -1;
79
85
86static struct server_scan_timer_data meta_scan = { NULL, 0 };
87static struct server_scan_timer_data lan_scan = { NULL, 0 };
88
92
94
96
97static void connection_state_reset(void);
98
99/**********************************************************************/
103{
104 if (!is_server_running()) {
106
107 /* Saved settings are sent in client/options.c
108 * resend_desired_settable_options() */
109 }
110}
111
112/**********************************************************************/
116{
117 output_window_append(ftc_client, _("Compiling scenario list."));
119}
120
121/**********************************************************************/
128
129/**********************************************************************/
137
138/**********************************************************************/
141static void open_settings(void)
142{
143 option_dialog_popup(_("Set local options"), client_optset);
144}
145
146/**********************************************************************/
149static void main_callback(GtkWidget *w, gpointer data)
150{
151 enum client_pages page = PAGE_MAIN;
152
153 if (client.conn.used) {
155 }
156 if (page != get_client_page()) {
157 set_client_page(page);
158 }
159}
160
161/**********************************************************************/
165{
166 static PangoLayout *layout;
167 static int width, height;
168 static bool left = FALSE;
170 struct sprite *intro = (struct sprite *)data;
171
172 cairo_set_source_surface(cr, intro->surface, 0, 0);
173 cairo_paint(cr);
174
175 if (!layout) {
176 char msgbuf[128];
177 const char *rev_ver;
178
181 pango_font_description_from_string("Sans Bold 10"));
182
184
185 if (rev_ver == NULL) {
186 /* TRANS: "version 2.6.0, gui-gtk-3.22 client" */
187 fc_snprintf(msgbuf, sizeof(msgbuf), _("%s%s, %s client"),
189 } else {
190 /* TRANS: "version 2.6.0
191 * commit: [modified] <git commit id>
192 * gui-gtk-3.22 client" */
193 fc_snprintf(msgbuf, sizeof(msgbuf), _("%s%s\ncommit: %s\n%s client"),
195 left = TRUE;
196 }
198
200 }
202
203 cairo_set_source_rgb(cr, 0, 0, 0);
204 cairo_move_to(cr, left ? 4 : allocation.width - width - 3,
205 allocation.height - height - 3);
207
208 cairo_set_source_rgb(cr, 1, 1, 1);
209 cairo_move_to(cr, left ? 3 : allocation.width - width - 4,
210 allocation.height - height - 4);
212
213 return TRUE;
214}
215
216/**********************************************************************/
219static void intro_free(GtkWidget *w, gpointer *data)
220{
221 struct sprite *intro = (struct sprite *)data;
222
224}
225
226/**********************************************************************/
230{
231 GtkWidget *widget, *vbox, *frame, *darea, *button, *table;
233 struct sprite *intro_in, *intro;
234 int width, height;
235 int sh;
236 int space_needed;
237
239
240 vbox = gtk_grid_new();
243 widget = vbox;
244
245 frame = gtk_frame_new(NULL);
246 g_object_set(frame, "margin", 18, NULL);
249 gtk_container_add(GTK_CONTAINER(vbox), frame);
250
253 sh = screen_height();
254
255 if (sh <= 0) {
256 /* Assume some minimum height */
257 sh = 600;
258 }
259
260 space_needed = 250;
261#if IS_BETA_VERSION || IS_DEVEL_VERSION
262 /* Alpha or Beta notice takes extra space */
263 space_needed += 50;
264#endif
265
266 if (sh - height < space_needed) {
267 float scale;
268
269 if (sh < (space_needed + 0.2 * height)) {
270 /* Screen is simply too small, use minimum scale */
271 scale = 0.2;
272 } else {
273 scale = (double)(sh - space_needed) / height;
274 }
275 height *= scale;
276 width *= scale;
279 } else {
280 intro = intro_in;
281 }
282 darea = gtk_drawing_area_new();
284 g_signal_connect(darea, "draw",
286 g_signal_connect(widget, "destroy",
288 gtk_container_add(GTK_CONTAINER(frame), darea);
289
290#if IS_BETA_VERSION || IS_DEVEL_VERSION
291 {
292 GtkWidget *label;
293
295 gtk_widget_set_name(label, "beta_label");
299 gtk_container_add(GTK_CONTAINER(vbox), label);
300 }
301#endif /* IS_BETA_VERSION || IS_DEVEL_VERSION */
302
304 g_object_set(table, "margin", 12, NULL);
309
313
314 button = gtk_button_new_with_mnemonic(_("Start _New Game"));
316 gtk_grid_attach(GTK_GRID(table), button, 0, 0, 1, 1);
317 g_signal_connect(button, "clicked",
319
320 button = gtk_button_new_with_mnemonic(_("Start _Scenario Game"));
322 gtk_grid_attach(GTK_GRID(table), button, 0, 1, 1, 1);
323 g_signal_connect(button, "clicked",
325
326 button = gtk_button_new_with_mnemonic(_("_Load Saved Game"));
328 gtk_grid_attach(GTK_GRID(table), button, 0, 2, 1, 1);
329 g_signal_connect(button, "clicked",
331
332 button = gtk_button_new_with_mnemonic(_("C_onnect to Network Game"));
334 gtk_grid_attach(GTK_GRID(table), button, 1, 0, 1, 1);
335 g_signal_connect(button, "clicked",
337
338 button = gtk_button_new_with_mnemonic(_("Client Settings"));
340 gtk_grid_attach(GTK_GRID(table), button, 1, 1, 1, 1);
341 g_signal_connect(button, "clicked", open_settings, NULL);
342
343 button = icon_label_button_new("application-exit", _("E_xit"));
346 gtk_grid_attach(GTK_GRID(table), button, 1, 2, 1, 1);
347 g_signal_connect(button, "clicked",
349
350 return widget;
351}
352
353/****************************************************************************
354 GENERIC SAVE DIALOG
355****************************************************************************/
356typedef void (*save_dialog_action_fn_t) (const char *filename);
357typedef struct fileinfo_list * (*save_dialog_files_fn_t) (void);
358
366
373
379
380/**********************************************************************/
384{
386 G_TYPE_STRING, /* SD_COL_PRETTY_NAME */
387 G_TYPE_STRING); /* SD_COL_FULL_PATH */
388}
389
390/**********************************************************************/
394 const struct fileinfo_list *files)
395{
397
401 gtk_list_store_set(store, &iter,
403 SD_COL_FULL_PATH, pfile->fullname,
404 -1);
406}
407
408/**********************************************************************/
411static void save_dialog_update(struct save_dialog *pdialog)
412{
413 struct fileinfo_list *files;
414
415 fc_assert_ret(NULL != pdialog);
416
417 /* Update the store. */
418 files = pdialog->files();
421 files);
423}
424
425/**********************************************************************/
429 gint response, gpointer data)
430{
431 if (response == GTK_RESPONSE_OK) {
435 -1, NULL, NULL, NULL);
436
437 if (NULL != filename) {
438 action(filename);
439 g_free(filename);
440 }
441 }
443}
444
445/**********************************************************************/
469
470/**********************************************************************/
474 gpointer data)
475{
476 struct save_dialog *pdialog = data;
477
478 switch (response) {
479 case SD_RES_BROWSE:
480 save_dialog_file_chooser_popup(_("Select Location to Save"),
482 pdialog->action);
483 break;
484 case SD_RES_DELETE:
485 {
486 GtkTreeSelection *selection;
487 GtkTreeModel *model;
489 const gchar *full_path;
490
491 selection = gtk_tree_view_get_selection(pdialog->tree_view);
492 if (!gtk_tree_selection_get_selected(selection, &model, &iter)) {
493 return;
494 }
495
498 save_dialog_update(pdialog);
499 }
500 return;
501 case SD_RES_SAVE:
502 {
503 const char *text = gtk_entry_get_text(pdialog->entry);
504 gchar *filename = g_filename_from_utf8(text, -1, NULL, NULL, NULL);
505
506 if (NULL == filename) {
507 return;
508 }
509 pdialog->action(filename);
510 g_free(filename);
511 }
512 break;
513 default:
514 break;
515 }
517}
518
519/**********************************************************************/
529
530/**********************************************************************/
537
538/**********************************************************************/
542 gpointer data)
543{
544 struct save_dialog *pdialog = data;
545 GtkTreeModel *model;
547 const gchar *filename;
548
549 if (!gtk_tree_selection_get_selected(selection, &model, &iter)) {
551 return;
552 }
553
555 gtk_tree_model_get(model, &iter, SD_COL_PRETTY_NAME, &filename, -1);
556 gtk_entry_set_text(pdialog->entry, filename);
557}
558
559/**********************************************************************/
562static GtkWidget *save_dialog_new(const char *title, const char *savelabel,
563 const char *savefilelabel,
566{
567 GtkWidget *shell, *sbox, *sw, *label, *view, *entry;
568 GtkContainer *vbox;
569 GtkListStore *store;
571 GtkTreeSelection *selection;
572 struct save_dialog *pdialog;
573
576
577 /* Save dialog structure. */
578 pdialog = fc_malloc(sizeof(*pdialog));
579 pdialog->action = action;
580 pdialog->files = files;
581
582 /* Shell. */
584 _("_Browse..."), SD_RES_BROWSE,
585 _("_Delete"), SD_RES_DELETE,
586 _("_Cancel"), GTK_RESPONSE_CANCEL,
587 _("_Save"), SD_RES_SAVE,
588 NULL);
589 g_object_set_data_full(G_OBJECT(shell), "save_dialog", pdialog,
594 g_signal_connect(shell, "response",
596 pdialog->shell = GTK_DIALOG(shell);
598
599 /* Tree view. */
600 store = save_dialog_store_new();
604 g_object_unref(store);
606 g_signal_connect(view, "row-activated",
608 pdialog->tree_view = GTK_TREE_VIEW(view);
609
610 sbox = gtk_grid_new();
614 gtk_container_add(vbox, sbox);
615
617 "use-underline", TRUE,
618 "mnemonic-widget", view,
619 "label", savelabel,
620 "xalign", 0.0,
621 "yalign", 0.5,
622 NULL);
624
634
637 g_signal_connect(selection, "changed",
639
642 -1, NULL, rend, "text",
644
645 /* Entry. */
648 g_signal_connect(entry, "activate",
650 pdialog->entry = GTK_ENTRY(entry);
651
652 sbox = gtk_grid_new();
653 g_object_set(sbox, "margin", 12, NULL);
657
659 "use-underline", TRUE,
660 "mnemonic-widget", entry,
661 "label", savefilelabel,
662 "xalign", 0.0,
663 "yalign", 0.5,
664 NULL);
666
668 gtk_container_add(vbox, sbox);
669
670 save_dialog_update(pdialog);
673 return shell;
674}
675
676/****************************************************************************
677 NETWORK PAGE
678****************************************************************************/
684
685/**********************************************************************/
689 const struct server_list *list)
690{
693 GtkTreeIter it;
694 GtkListStore *store;
695 const gchar *host, *portstr;
696 int port;
697
698 switch (sstype) {
701 break;
704 break;
705 default:
706 break;
707 }
708
709 if (!sel) {
710 return;
711 }
712
716
717 if (!list) {
718 return;
719 }
720
723 port = atoi(portstr);
724
726 char buf[35];
727
728 if (pserver->humans >= 0) {
729 fc_snprintf(buf, sizeof(buf), "%d", pserver->humans);
730 } else {
731 sz_strlcpy(buf, _("Unknown"));
732 }
733 gtk_list_store_append(store, &it);
734 gtk_list_store_set(store, &it,
735 0, pserver->host,
736 1, pserver->port,
737 2, pserver->version,
738 3, _(pserver->state),
739 4, pserver->nplayers,
740 5, buf,
741 6, pserver->message,
742 -1);
743 if (strcmp(host, pserver->host) == 0 && port == pserver->port) {
745 }
747}
748
749/**********************************************************************/
753{
754 if (meta_scan.scan) {
757 }
758 if (meta_scan.timer != 0) {
760 meta_scan.timer = 0;
761 }
762 if (lan_scan.scan) {
765 }
766 if (lan_scan.timer != 0) {
768 lan_scan.timer = 0;
769 }
770}
771
772/**********************************************************************/
776{
777 struct server_scan_timer_data *scan_data = data;
778 struct server_scan *scan = scan_data->scan;
780
781 if (!scan) {
782 return FALSE;
783 }
784
785 stat = server_scan_poll(scan);
786 if (stat >= SCAN_STATUS_PARTIAL) {
788 struct srv_list *srvrs;
789
791 srvrs = server_scan_get_list(scan);
792 fc_mutex_allocate(&srvrs->mutex);
796 fc_mutex_release(&srvrs->mutex);
797 }
798
800 scan_data->timer = 0;
801 return FALSE;
802 }
803 return TRUE;
804}
805
806/**********************************************************************/
809static void server_scan_error(struct server_scan *scan,
810 const char *message)
811{
813 log_error("%s", message);
814
815 /* Main thread will finalize the scan later (or even concurrently) -
816 * do not do anything here to cause double free or raze condition. */
817}
818
819/**********************************************************************/
832
833/**************************************************************************
834 Network connection state defines.
835**************************************************************************/
842
844
845/**********************************************************************/
849{
851 char *txt;
852
855 free(txt);
856 }
857
858 return TRUE;
859}
860
861/**********************************************************************/
864static void clear_network_statusbar(void)
865{
867 char *txt;
868
870 free(txt);
871 }
873}
874
875/**********************************************************************/
878void append_network_statusbar(const char *text, bool force)
879{
881 if (force) {
884 } else {
886 }
887 }
888}
889
890/**********************************************************************/
910
911/**********************************************************************/
915{
916 switch (state) {
917 case LOGIN_TYPE:
919
922
931 break;
936
945
947 break;
952
961
963 break;
964 case WAITING_TYPE:
966
973 break;
974 }
975
976 connection_status = state;
977}
978
979/**********************************************************************/
986
987/**********************************************************************/
992 const char *message)
993{
995
996 switch (type) {
1000 return;
1001 case AUTH_LOGIN_FIRST:
1002 /* if we magically have a password already present in 'fc_password'
1003 * then, use that and skip the password entry dialog */
1004 if (fc_password[0] != '\0') {
1006
1007 sz_strlcpy(reply.password, fc_password);
1009 return;
1010 } else {
1012 }
1013 return;
1014 case AUTH_LOGIN_RETRY:
1016 return;
1017 }
1018
1019 log_error("Unsupported authentication type %d: %s.", type, message);
1020}
1021
1022/**********************************************************************/
1028{
1029 char errbuf [512];
1031
1032 switch (connection_status) {
1033 case LOGIN_TYPE:
1037
1039 errbuf, sizeof(errbuf)) != -1) {
1040 } else {
1042
1044 }
1045 return;
1046 case NEW_PASSWORD_TYPE:
1047 if (w != network_password) {
1050 sz_strlcpy(reply.password,
1052 if (!fc_strncmp(reply.password, fc_password, MAX_LEN_NAME)) {
1053 fc_password[0] = '\0';
1055
1057 } else {
1058 append_network_statusbar(_("Passwords don't match, enter password."),
1059 TRUE);
1060
1062 }
1063 }
1064 return;
1066 sz_strlcpy(reply.password,
1069
1071 return;
1072 case WAITING_TYPE:
1073 return;
1074 }
1075
1076 log_error("Unsupported connection status: %d", connection_status);
1077}
1078
1079/**********************************************************************/
1085 gpointer data)
1086{
1087 connect_callback(NULL, data);
1088}
1089
1090/**********************************************************************/
1094static void update_server_playerlist(const struct server *pserver)
1095{
1096 GtkListStore *store;
1098 int n, i;
1099
1101 fc_assert_ret(store != NULL);
1102
1103 gtk_list_store_clear(store);
1104 if (!pserver || !pserver->players) {
1105 return;
1106 }
1107
1108 n = pserver->nplayers;
1109 for (i = 0; i < n; i++) {
1110 gtk_list_store_append(store, &iter);
1111 gtk_list_store_set(store, &iter,
1112 0, pserver->players[i].name,
1113 1, pserver->players[i].type,
1114 2, pserver->players[i].host,
1115 3, pserver->players[i].nation,
1116 -1);
1117 }
1118}
1119
1120/**********************************************************************/
1124{
1125 GtkTreeModel *model;
1126 GtkTreeIter it;
1127 const char *host;
1128 int port;
1129 char portstr[32];
1130 const struct server *pserver = NULL;
1131
1132 if (!gtk_tree_selection_get_selected(select, &model, &it)) {
1133 return;
1134 }
1135
1136 if (select == meta_selection) {
1137 GtkTreePath *path;
1138 struct srv_list *srvrs;
1139
1141 path = gtk_tree_model_get_path(model, &it);
1143 /* We are not yet inside mutex protected block */
1144 fc_mutex_allocate(&srvrs->mutex);
1145 }
1146 if (srvrs->servers && path) {
1148
1150 }
1152 /* We are not yet inside mutex protected block */
1153 fc_mutex_release(&srvrs->mutex);
1154 }
1155 gtk_tree_path_free(path);
1156 }
1158
1159 gtk_tree_model_get(model, &it, 0, &host, 1, &port, -1);
1160
1162 fc_snprintf(portstr, sizeof(portstr), "%d", port);
1164}
1165
1166/**********************************************************************/
1181
1182/**********************************************************************/
1186{
1187 GtkWidget *box, *sbox, *bbox, *hbox, *notebook;
1188 GtkWidget *button, *label, *view, *sw, *table;
1189 GtkTreeSelection *selection;
1190 GtkListStore *store;
1191
1192 box = gtk_grid_new();
1196
1197 notebook = gtk_notebook_new();
1198 gtk_container_add(GTK_CONTAINER(box), notebook);
1199
1200 /* LAN pane. */
1202 G_TYPE_INT, /* port */
1203 G_TYPE_STRING, /* version */
1204 G_TYPE_STRING, /* state */
1205 G_TYPE_INT, /* nplayers */
1206 G_TYPE_STRING, /* humans */
1207 G_TYPE_STRING); /* message */
1208
1214
1216 lan_selection = selection;
1218 g_signal_connect(view, "focus",
1220 g_signal_connect(view, "row-activated",
1222 g_signal_connect(selection, "changed",
1224
1225 add_treeview_column(view, _("Server Name"), G_TYPE_STRING, 0);
1226 add_treeview_column(view, _("Port"), G_TYPE_INT, 1);
1227 add_treeview_column(view, _("Version"), G_TYPE_STRING, 2);
1228 add_treeview_column(view, _("Status"), G_TYPE_STRING, 3);
1229 add_treeview_column(view, _("Players"), G_TYPE_INT, 4);
1230 add_treeview_column(view, _("Humans"), G_TYPE_STRING, 5);
1231 add_treeview_column(view, _("Comment"), G_TYPE_STRING, 6);
1232
1233 label = gtk_label_new_with_mnemonic(_("Local _Area Network"));
1234
1242 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), sw, label);
1243
1244
1245 /* Metaserver pane. */
1247 G_TYPE_INT, /* port */
1248 G_TYPE_STRING, /* version */
1249 G_TYPE_STRING, /* state */
1250 G_TYPE_INT, /* nplayers */
1251 G_TYPE_STRING, /* humans */
1252 G_TYPE_STRING); /* message */
1253
1259
1261 meta_selection = selection;
1263 g_signal_connect(view, "focus",
1265 g_signal_connect(view, "row-activated",
1267 g_signal_connect(selection, "changed",
1269
1270 add_treeview_column(view, _("Server Name"), G_TYPE_STRING, 0);
1271 add_treeview_column(view, _("Port"), G_TYPE_INT, 1);
1272 add_treeview_column(view, _("Version"), G_TYPE_STRING, 2);
1273 add_treeview_column(view, _("Status"), G_TYPE_STRING, 3);
1274 add_treeview_column(view, _("Players"), G_TYPE_INT, 4);
1275 add_treeview_column(view, _("Humans"), G_TYPE_STRING, 5);
1276 add_treeview_column(view, _("Comment"), G_TYPE_STRING, 6);
1277
1278 label = gtk_label_new_with_mnemonic(_("Internet _Metaserver"));
1279
1288 gtk_notebook_prepend_page(GTK_NOTEBOOK(notebook), sw, label);
1289 } else {
1290 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), sw, label);
1291 }
1292
1293 /* Bottom part of the page, outside the inner notebook. */
1294 sbox = gtk_grid_new();
1298
1299 hbox = gtk_grid_new();
1301 g_object_set(hbox, "margin", 8, NULL);
1303
1304 table = gtk_grid_new();
1308
1310 g_signal_connect(network_host, "activate",
1313
1315 "use-underline", TRUE,
1316 "mnemonic-widget", network_host,
1317 "label", _("_Host:"),
1318 "xalign", 0.0,
1319 "yalign", 0.5,
1320 NULL);
1321 network_host_label = label;
1322 gtk_grid_attach(GTK_GRID(table), label, 0, 0, 1, 1);
1323
1325 g_signal_connect(network_port, "activate",
1328
1330 "use-underline", TRUE,
1331 "mnemonic-widget", network_port,
1332 "label", _("_Port:"),
1333 "xalign", 0.0,
1334 "yalign", 0.5,
1335 NULL);
1336 network_port_label = label;
1337 gtk_grid_attach(GTK_GRID(table), label, 0, 1, 1, 1);
1338
1341 g_signal_connect(network_login, "activate",
1344
1346 "use-underline", TRUE,
1347 "mnemonic-widget", network_login,
1348 "label", _("_Login:"),
1349 "xalign", 0.0,
1350 "yalign", 0.5,
1351 NULL);
1352 gtk_widget_set_margin_top(label, 10);
1353 network_login_label = label;
1354 gtk_grid_attach(GTK_GRID(table), label, 0, 3, 1, 1);
1355
1361
1363 "use-underline", TRUE,
1364 "mnemonic-widget", network_password,
1365 "label", _("Pass_word:"),
1366 "xalign", 0.0,
1367 "yalign", 0.5,
1368 NULL);
1369 network_password_label = label;
1370 gtk_grid_attach(GTK_GRID(table), label, 0, 4, 1, 1);
1371
1377
1379 "use-underline", TRUE,
1380 "mnemonic-widget", network_confirm_password,
1381 "label", _("Conf_irm Password:"),
1382 "xalign", 0.0,
1383 "yalign", 0.5,
1384 NULL);
1386 gtk_grid_attach(GTK_GRID(table), label, 0, 5, 1, 1);
1387
1388 /* Server player list. */
1394
1400 add_treeview_column(view, _("Nation"), G_TYPE_STRING, 3);
1402
1410
1411
1413 g_object_set(bbox, "margin", 2, NULL);
1417
1418 button = gtk_button_new_from_icon_name("view-refresh", GTK_ICON_SIZE_BUTTON);
1421 g_signal_connect(button, "clicked",
1423
1424 button = gtk_button_new_with_mnemonic(_("_Cancel"));
1426 g_signal_connect(button, "clicked",
1428
1429 button = gtk_button_new_with_mnemonic(_("C_onnect"));
1431 g_signal_connect(button, "clicked",
1433
1434 return box;
1435}
1436
1437
1438/****************************************************************************
1439 START PAGE
1440****************************************************************************/
1442
1449
1450
1451/* NB: Must match creation arguments in connection_list_store_new(). */
1468
1469/**********************************************************************/
1473{
1475 G_TYPE_INT, /* CL_COL_PLAYER_NUMBER */
1476 G_TYPE_STRING, /* CL_COL_USER_NAME */
1477 G_TYPE_BOOLEAN, /* CL_COL_READY_STATE */
1478 G_TYPE_STRING, /* CL_COL_PLAYER_NAME */
1479 GDK_TYPE_PIXBUF, /* CL_COL_FLAG */
1480 GDK_TYPE_PIXBUF, /* CL_COL_COLOR */
1481 G_TYPE_STRING, /* CL_COL_NATION */
1482 G_TYPE_STRING, /* CL_COL_TEAM */
1483 G_TYPE_INT, /* CL_COL_CONN_ID */
1484 G_TYPE_INT, /* CL_COL_STYLE */
1485 G_TYPE_INT, /* CL_COL_WEIGHT */
1486 G_TYPE_BOOLEAN); /* CL_COL_COLLAPSED */
1487}
1488
1489/**********************************************************************/
1493static void client_aitoggle_player(void *data)
1494{
1495 struct player *pplayer = player_by_number(FC_PTR_TO_INT(data));
1496
1497 if (NULL != pplayer
1498 && pplayer == client_player()
1499 && !is_human(pplayer)) {
1500 send_chat("/away");
1501 }
1502}
1503
1504/**********************************************************************/
1507static void client_take_player(struct player *pplayer)
1508{
1509 int request_id = send_chat_printf("/take \"%s\"", player_name(pplayer));
1510 void *data = FC_INT_TO_PTR(player_number(pplayer));
1511
1514}
1515
1516/**********************************************************************/
1519static void object_put(GObject *object, struct player *pplayer,
1520 struct connection *pconn)
1521{
1522 /* Note that passing -1 to GINT_TO_POINTER() is buggy with some versions
1523 * of gcc. player_slot_count() is not a valid player number. 0 is not
1524 * a valid connection id (see comment in server/sernet.c:
1525 * makeup_connection_name()). */
1526 g_object_set_data(object, "player_id",
1527 GINT_TO_POINTER(NULL != pplayer
1528 ? player_number(pplayer)
1529 : player_slot_count()));
1530 g_object_set_data(object, "connection_id",
1531 GINT_TO_POINTER(NULL != pconn ? pconn->id : 0));
1532}
1533
1534/**********************************************************************/
1538static bool object_extract(GObject *object, struct player **ppplayer,
1539 struct connection **ppconn)
1540{
1541 bool ret = FALSE;
1542 int id;
1543
1544 if (NULL != ppplayer) {
1545 id = GPOINTER_TO_INT(g_object_get_data(object, "player_id"));
1547 if (NULL != *ppplayer) {
1548 ret = TRUE;
1549 }
1550 }
1551 if (NULL != ppconn) {
1552 id = GPOINTER_TO_INT(g_object_get_data(object, "connection_id"));
1553 *ppconn = conn_by_number(id);
1554 if (NULL != *ppconn) {
1555 ret = TRUE;
1556 }
1557 }
1558
1559 return ret;
1560}
1561
1562/**********************************************************************/
1566{
1567 option_dialog_popup(_("Game Settings"), server_optset);
1568}
1569
1570/**********************************************************************/
1574{
1575 enum ai_level *levels = (enum ai_level *)data;
1576 const char *name;
1577 int i;
1578
1580
1581 if (i != -1) {
1582 enum ai_level level = levels[i];
1583
1584 /* Suppress changes provoked by server rather than local user */
1585 if (server_ai_level() != level) {
1587 send_chat_printf("/%s", name);
1588 }
1589 }
1590}
1591
1592/* HACK: sometimes when creating the ruleset combo the value is set without
1593 * the user's control. In this case we don't want to do a /read. */
1595
1596/**********************************************************************/
1599static void ruleset_selected(const char *name)
1600{
1601 if (name && name[0] != '\0' && !no_ruleset_callback) {
1603 }
1604}
1605
1606/**********************************************************************/
1612{
1613 const char *name = NULL;
1614
1616
1617 if (name != NULL) {
1619 }
1620}
1621
1622/**********************************************************************/
1633
1634/**********************************************************************/
1638{
1639 if (start_aifill_spin) {
1640 bool old = send_new_aifill_to_server;
1641
1642 /* Suppress callback from this change to avoid a loop. */
1644 /* HACK: this GUI control doesn't have quite the same semantics as the
1645 * server 'aifill' option, in that it claims to represent the minimum
1646 * number of players _including humans_. The GUI control has a minimum
1647 * value of 1, so aifill == 0 will not be represented correctly.
1648 * But there's generally exactly one human player because the control
1649 * only shows up for a locally spawned server, so we more or less
1650 * get away with this. */
1653 }
1654}
1655
1656/**********************************************************************/
1660{
1662}
1663
1664/**********************************************************************/
1667static void conn_menu_team_chosen(GObject *object, gpointer data)
1668{
1669 struct player *pplayer;
1670 struct team_slot *tslot = data;
1671
1672 if (object_extract(object, &pplayer, NULL)
1673 && NULL != tslot
1674 && team_slot_index(tslot) != team_number(pplayer->team)) {
1675 send_chat_printf("/team \"%s\" \"%s\"",
1676 player_name(pplayer),
1678 }
1679}
1680
1681/**********************************************************************/
1684static void conn_menu_ready_chosen(GObject *object, gpointer data)
1685{
1686 struct player *pplayer;
1687
1688 if (object_extract(object, &pplayer, NULL)) {
1690 player_number(pplayer), !pplayer->is_ready);
1691 }
1692}
1693
1694/**********************************************************************/
1697static void conn_menu_nation_chosen(GObject *object, gpointer data)
1698{
1699 struct player *pplayer;
1700
1701 if (object_extract(object, &pplayer, NULL)) {
1702 popup_races_dialog(pplayer);
1703 }
1704}
1705
1706/**********************************************************************/
1711{
1712 struct player *pplayer;
1713
1714 if (object_extract(object, &pplayer, NULL)) {
1715 send_chat_printf("/%s \"%s\"",
1716 (char *) g_object_get_data(G_OBJECT(data), "command"),
1717 player_name(pplayer));
1718 }
1719}
1720
1721/**********************************************************************/
1724static void conn_menu_player_take(GObject *object, gpointer data)
1725{
1726 struct player *pplayer;
1727
1728 if (object_extract(object, &pplayer, NULL)) {
1729 client_take_player(pplayer);
1730 }
1731}
1732
1733/**********************************************************************/
1738{
1739 struct connection *pconn;
1740
1741 if (object_extract(object, NULL, &pconn)) {
1742 send_chat_printf("/%s \"%s\"",
1743 (char *) g_object_get_data(G_OBJECT(data), "command"),
1744 pconn->username);
1745 }
1746}
1747
1748/**********************************************************************/
1751static void show_conn_popup(struct player *pplayer, struct connection *pconn)
1752{
1754 char buf[4096] = "";
1755
1756 if (pconn) {
1757 cat_snprintf(buf, sizeof(buf), _("Connection name: %s"),
1758 pconn->username);
1759 } else {
1760 cat_snprintf(buf, sizeof(buf), _("Player name: %s"),
1761 player_name(pplayer));
1762 }
1763 cat_snprintf(buf, sizeof(buf), "\n");
1764 if (pconn) {
1765 cat_snprintf(buf, sizeof(buf), _("Host: %s"), pconn->addr);
1766 }
1767 cat_snprintf(buf, sizeof(buf), "\n");
1768
1769 /* Show popup. */
1772 "%s", buf);
1773 gtk_window_set_title(GTK_WINDOW(popup), _("Player/conn info"));
1777}
1778
1779/**********************************************************************/
1782static void conn_menu_info_chosen(GObject *object, gpointer data)
1783{
1784 struct player *pplayer;
1785 struct connection *pconn;
1786
1787 if (object_extract(object, &pplayer, &pconn)) {
1788 show_conn_popup(pplayer, pconn);
1789 }
1790}
1791
1792/**********************************************************************/
1796static GtkWidget *create_conn_menu(struct player *pplayer,
1797 struct connection *pconn)
1798{
1799 GtkWidget *menu;
1800 GtkWidget *item;
1801 gchar *buf;
1802
1803 menu = gtk_menu_new();
1804 object_put(G_OBJECT(menu), pplayer, pconn);
1805
1806 buf = g_strdup_printf(_("%s info"),
1807 pconn ? pconn->username : player_name(pplayer));
1809 g_free(buf);
1811 g_signal_connect_swapped(item, "activate",
1813
1814 if (NULL != pplayer) {
1815 item = gtk_menu_item_new_with_label(_("Toggle player ready"));
1818 g_signal_connect_swapped(item, "activate",
1820
1821 item = gtk_menu_item_new_with_label(_("Pick nation"));
1824 pplayer));
1826 g_signal_connect_swapped(item, "activate",
1828
1829 item = gtk_menu_item_new_with_label(_("Observe this player"));
1831 g_object_set_data_full(G_OBJECT(item), "command", g_strdup("observe"),
1833 g_signal_connect_swapped(item, "activate",
1835
1836 item = gtk_menu_item_new_with_label(_("Take this player"));
1838 g_signal_connect_swapped(item, "activate",
1840 }
1841
1843 && (pconn->id != client.conn.id || NULL != pplayer)) {
1846
1847 if (pconn->id != client.conn.id) {
1848 item = gtk_menu_item_new_with_label(_("Cut connection"));
1850 g_object_set_data_full(G_OBJECT(item), "command", g_strdup("cut"),
1852 g_signal_connect_swapped(item, "activate",
1854 menu);
1855 }
1856 }
1857
1858 if (ALLOW_CTRL <= client.conn.access_level && NULL != pplayer) {
1859 item = gtk_menu_item_new_with_label(_("Aitoggle player"));
1861 g_object_set_data_full(G_OBJECT(item), "command", g_strdup("aitoggle"),
1863 g_signal_connect_swapped(item, "activate",
1865
1866 if (pplayer != client.conn.playing && game.info.is_new_game) {
1867 item = gtk_menu_item_new_with_label(_("Remove player"));
1869 g_object_set_data_full(G_OBJECT(item), "command", g_strdup("remove"),
1871 g_signal_connect_swapped(item, "activate",
1873 }
1874 }
1875
1877 && pconn->id != client.conn.id) {
1878 enum cmdlevel level;
1879
1880 /* No item for hack access; that would be a serious security hole. */
1882 /* TRANS: Give access level to a connection. */
1883 buf = g_strdup_printf(_("Give %s access"),
1886 g_free(buf);
1889 g_strdup_printf("cmdlevel %s",
1892 g_signal_connect_swapped(item, "activate",
1894 menu);
1895 }
1896 }
1897
1899 && NULL != pplayer && is_ai(pplayer)) {
1900 enum ai_level level;
1901
1904
1905 for (level = 0; level < AI_LEVEL_COUNT; level++) {
1908 const char *level_cmd = ai_level_cmd(level);
1909
1914 g_signal_connect_swapped(item, "activate",
1916 }
1917 }
1918 }
1919
1920 if (pplayer && game.info.is_new_game) {
1921 const int count = pplayer->team
1922 ? player_list_size(team_members(pplayer->team)) : 0;
1923 bool need_empty_team = (count != 1);
1924
1927
1928 /* Can't use team_iterate here since it skips empty teams. */
1930 if (!team_slot_is_used(tslot)) {
1931 if (!need_empty_team) {
1932 continue;
1933 }
1935 }
1936
1937 /* TRANS: e.g., "Put on Team 5" */
1938 buf = g_strdup_printf(_("Put on %s"),
1941 g_free(buf);
1943 object_put(G_OBJECT(item), pplayer, NULL);
1945 tslot);
1947 }
1948
1949 gtk_widget_show_all(menu);
1950
1951 return menu;
1952}
1953
1954/**********************************************************************/
1958{
1959 if (NULL != connection_list_view) {
1960 GtkTreeSelection *selection =
1962 GtkTreePath *path = data;
1963
1964 gtk_tree_selection_unselect_path(selection, path);
1965 gtk_tree_path_free(path);
1966 }
1967 return FALSE;
1968}
1969
1970/**********************************************************************/
1975 gpointer data)
1976{
1978 GtkTreePath *path = NULL;
1980 gboolean ret = FALSE;
1981
1982 if ((1 != event->button && 3 != event->button)
1983 || GDK_BUTTON_PRESS != event->type
1985 event->x, event->y,
1986 &path, NULL, NULL, NULL)) {
1987 return FALSE;
1988 }
1989
1990 if (1 == event->button) {
1991 if (gtk_tree_selection_path_is_selected(selection, path)) {
1992 /* Need to delay to avoid problem with the expander. */
1994 return FALSE; /* Return now, don't free the path. */
1995 }
1996 } else if (3 == event->button) {
1999 GtkWidget *menu;
2000 int player_no, conn_id;
2001 struct player *pplayer;
2002 struct connection *pconn;
2003
2004 if (!gtk_tree_selection_path_is_selected(selection, path)) {
2005 gtk_tree_selection_select_path(selection, path);
2006 }
2007 gtk_tree_model_get_iter(model, &iter, path);
2008
2009 gtk_tree_model_get(model, &iter, CL_COL_PLAYER_NUMBER, &player_no, -1);
2010 pplayer = player_by_number(player_no);
2011
2012 gtk_tree_model_get(model, &iter, CL_COL_CONN_ID, &conn_id, -1);
2013 pconn = conn_by_number(conn_id);
2014
2015 menu = create_conn_menu(pplayer, pconn);
2017 ret = TRUE;
2018 }
2019
2020 gtk_tree_path_free(path);
2021 return ret;
2022}
2023
2024/**********************************************************************/
2029 GtkTreePath *path,
2030 gpointer data)
2031{
2033
2034 gtk_tree_store_set(store, iter,
2036}
2037
2038/**********************************************************************/
2043 struct connection **ppconn)
2044{
2045 if (NULL != connection_list_view) {
2047 GtkTreeModel *model;
2048 GtkTreeSelection *selection =
2050
2051 if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
2052 int id;
2053
2054 if (NULL != ppplayer) {
2055 gtk_tree_model_get(model, &iter, CL_COL_PLAYER_NUMBER, &id, -1);
2057 }
2058 if (NULL != ppconn) {
2059 gtk_tree_model_get(model, &iter, CL_COL_CONN_ID, &id, -1);
2060 *ppconn = conn_by_number(id);
2061 }
2062 return TRUE;
2063 }
2064 }
2065
2066 if (NULL != ppplayer) {
2067 *ppplayer = NULL;
2068 }
2069 if (NULL != ppconn) {
2070 *ppconn = NULL;
2071 }
2072 return FALSE;
2073}
2074
2075/**********************************************************************/
2079{
2080 GtkTreeModel *model;
2081 GtkTreeIter parent, child, *iter = NULL;
2082 GtkTreeSelection *selection;
2083 gboolean valid;
2084 const int search_id = pconn->id;
2085 int id;
2086
2087 if (NULL == connection_list_view) {
2088 return;
2089 }
2090
2093
2094 /* Main iteration. */
2095 valid = gtk_tree_model_get_iter_first(model, &parent);
2096 while (valid && NULL == iter) {
2097 gtk_tree_model_get(model, &parent, CL_COL_CONN_ID, &id, -1);
2098 if (search_id == id) {
2099 iter = &parent;
2100 break;
2101 }
2102
2103 /* Node children iteration. */
2104 valid = gtk_tree_model_iter_children(model, &child, &parent);
2105 while (valid && NULL == iter) {
2106 gtk_tree_model_get(model, &child, CL_COL_CONN_ID, &id, -1);
2107 if (search_id == id) {
2108 iter = &child;
2109 break;
2110 }
2111 valid = gtk_tree_model_iter_next(model, &child);
2112 }
2113
2114 valid = gtk_tree_model_iter_next(model, &parent);
2115 }
2116
2117 /* Select iterator. */
2118 if (NULL != iter) {
2120 } else {
2121 log_error("%s(): connection %s not found.",
2123 }
2124}
2125
2126/**********************************************************************/
2130{
2131 if (can_client_control()) {
2134 !client_player()->is_ready);
2135 } else {
2137 }
2138}
2139
2140/**********************************************************************/
2144{
2145 struct player *selected_plr;
2146 bool row_selected = conn_list_selection(&selected_plr, NULL);
2147
2148 if (row_selected && NULL != selected_plr) {
2149 /* "Take <player_name>" */
2151 } else if (can_client_control()) {
2152 /* "Pick Nation" */
2154 } else {
2155 /* "Take a Player" */
2156 send_chat("/take -");
2157 }
2158}
2159
2160/**********************************************************************/
2164{
2165 struct player *selected_plr;
2166 bool row_selected = conn_list_selection(&selected_plr, NULL);
2167
2168 if (row_selected && NULL != selected_plr) {
2169 /* "Observe <player_name>" */
2170 send_chat_printf("/observe \"%s\"", player_name(selected_plr));
2171 } else if (!client_is_global_observer()) {
2172 /* "Observe" */
2173 send_chat("/observe");
2174 } else {
2175 /* "Do not observe" */
2176 send_chat("/detach");
2177 }
2178}
2179
2180/**********************************************************************/
2184{
2185 char buf[2 * MAX_LEN_NAME];
2186 const char *text;
2187 struct player *selected_plr;
2188 bool row_selected = conn_list_selection(&selected_plr, NULL);
2189 bool sensitive;
2190
2191 /*** Ready button. ***/
2192 if (can_client_control()) {
2193 sensitive = client_player()->is_alive;
2194 if (client_player()->is_ready) {
2195 text = _("Not _ready");
2196 } else {
2197 int num_unready = 0;
2198
2199 players_iterate_alive(pplayer) {
2200 if (is_human(pplayer) && !pplayer->is_ready) {
2201 num_unready++;
2202 }
2204
2205 if (num_unready > 1) {
2206 text = _("_Ready");
2207 } else {
2208 /* We are the last unready player so clicking here will
2209 * immediately start the game. */
2210 text = _("_Start");
2211 }
2212 }
2213 } else {
2214 text = _("_Start");
2215 if (can_client_access_hack()) {
2216 sensitive = TRUE;
2218 if (is_human(plr)) {
2219 /* There's human controlled player(s) in game, so it's their
2220 * job to start the game. */
2221 sensitive = FALSE;
2222 break;
2223 }
2225 } else {
2226 sensitive = FALSE;
2227 }
2228 }
2231
2232 /*** Nation button. ***/
2233 if (row_selected && NULL != selected_plr) {
2234 fc_snprintf(buf, sizeof(buf), _("_Take %s"), player_name(selected_plr));
2235 text = buf;
2237 } else if (can_client_control()) {
2238 text = _("Pick _Nation");
2240 } else {
2241 text = _("_Take a Player");
2243 }
2246
2247 /*** Observe button. ***/
2248 if (row_selected && NULL != selected_plr) {
2249 fc_snprintf(buf, sizeof(buf), _("_Observe %s"),
2251 text = buf;
2253 } else if (!client_is_global_observer()) {
2254 text = _("_Observe");
2255 sensitive = TRUE;
2256 } else {
2257 text = _("Do not _observe");
2258 sensitive = TRUE;
2259 }
2262}
2263
2264/**********************************************************************/
2270 GtkTreeIter *start,
2271 const struct player *pplayer)
2272{
2273 const int search_id = player_number(pplayer);
2274 int id;
2275
2276 if (NULL != start) {
2277 *iter = *start;
2278 if (!gtk_tree_model_iter_next(model, iter)) {
2279 return FALSE;
2280 }
2281 } else if (!gtk_tree_model_get_iter_first(model, iter)) {
2282 return FALSE;
2283 }
2284
2285 do {
2287 if (id == search_id) {
2288 return TRUE;
2289 }
2290 } while (gtk_tree_model_iter_next(model, iter));
2291
2292 return FALSE;
2293}
2294
2295/**********************************************************************/
2301 const struct connection *pconn)
2302{
2303 const int search_id = pconn->id;
2304 int id;
2305
2306 if (NULL != start) {
2307 *iter = *start;
2308 if (!gtk_tree_model_iter_next(model, iter)) {
2309 return FALSE;
2310 }
2311 } else if (!gtk_tree_model_iter_children(model, iter, parent)) {
2312 return FALSE;
2313 }
2314
2315 do {
2316 gtk_tree_model_get(model, iter, CL_COL_CONN_ID, &id, -1);
2317 if (id == search_id) {
2318 return TRUE;
2319 }
2320 } while (gtk_tree_model_iter_next(model, iter));
2321
2322 return FALSE;
2323}
2324
2325/**********************************************************************/
2329{
2334 GtkTreeModel *model = GTK_TREE_MODEL(store);
2335 GtkTreePath *path;
2338 GdkPixbuf *flag, *color;
2340 struct player *pselected_player;
2341 struct connection *pselected_conn;
2342 bool is_ready;
2343 const char *nation, *plr_name, *team;
2344 char name[MAX_LEN_NAME + 8];
2346 int conn_id;
2347
2348 /* Refresh the AI skill level control */
2349 if (ai_lvl_combobox) {
2350 enum ai_level new_level = server_ai_level(), level;
2351 int i = 0;
2352
2353 for (level = 0; level < AI_LEVEL_COUNT; level++) {
2355 if (level == new_level) {
2357 break;
2358 }
2359 i++;
2360 }
2361 }
2362 if (level == AI_LEVEL_COUNT) {
2363 /* Probably ai_level_invalid() */
2365 }
2366 }
2367
2368 /* Save the selected connection. */
2370
2371 /* Insert players into the connection list. */
2372 players_iterate(pplayer) {
2373 if (!player_has_flag(pplayer, PLRF_SCENARIO_RESERVED)) {
2374 conn_id = -1;
2376 flag = pplayer->nation ? get_flag(pplayer->nation) : NULL;
2377 color = create_player_icon(pplayer);
2378
2379 conn_list_iterate(pplayer->connections, pconn) {
2380 if (pconn->playing == pplayer && !pconn->observer) {
2381 conn_id = pconn->id;
2382 access_level = pconn->access_level;
2383 break;
2384 }
2386
2387 if (is_ai(pplayer) && !pplayer->was_created
2388 && !pplayer->is_connected) {
2389 /* TRANS: "<Novice AI>" */
2390 fc_snprintf(name, sizeof(name), _("<%s AI>"),
2391 ai_level_translated_name(pplayer->ai_common.skill_level));
2392 } else {
2393 sz_strlcpy(name, pplayer->username);
2394 if (access_level > ALLOW_BASIC) {
2395 sz_strlcat(name, "*");
2396 }
2397 }
2398
2399 is_ready = !is_human(pplayer) ? TRUE : pplayer->is_ready;
2400
2401 if (pplayer->nation == NO_NATION_SELECTED) {
2402 nation = _("Random");
2403 if (pplayer->was_created) {
2404 plr_name = player_name(pplayer);
2405 } else {
2406 plr_name = "";
2407 }
2408 } else {
2409 nation = nation_adjective_for_player(pplayer);
2410 plr_name = player_name(pplayer);
2411 }
2412
2413 team = pplayer->team ? team_name_translation(pplayer->team) : "";
2414
2415 if (model_get_player_iter(model, &parent, pprev_parent, pplayer)) {
2417 } else {
2419 }
2420
2421 gtk_tree_store_set(store, &parent,
2424 CL_COL_READY_STATE, is_ready,
2426 CL_COL_FLAG, flag,
2428 CL_COL_NATION, nation,
2430 CL_COL_CONN_ID, conn_id,
2433 -1);
2434
2435 /* Insert observers of this player as child nodes. */
2436 pprev_child = NULL;
2437 conn_list_iterate(pplayer->connections, pconn) {
2438 if (pconn->id == conn_id) {
2439 continue;
2440 }
2441 if (model_get_conn_iter(model, &child, &parent,
2442 pprev_child, pconn)) {
2443 gtk_tree_store_move_after(store, &child, pprev_child);
2444 } else {
2446 }
2447
2448 gtk_tree_store_set(store, &child,
2450 CL_COL_USER_NAME, pconn->username,
2451 CL_COL_TEAM, _("Observer"),
2452 CL_COL_CONN_ID, pconn->id,
2455 -1);
2456
2457 prev_child = child;
2460
2461 /* Expand node? */
2462 if (NULL != pprev_child) {
2464 if (!collapsed) {
2465 path = gtk_tree_model_get_path(model, &parent);
2467 path, FALSE);
2468 gtk_tree_path_free(path);
2469 }
2470 }
2471
2472 /* Remove trailing rows. */
2473 if (NULL != pprev_child) {
2474 child = prev_child;
2475 if (gtk_tree_model_iter_next(model, &child)) {
2476 while (gtk_tree_store_remove(store, &child)) {
2477 /* Do nothing more. */
2478 }
2479 }
2480 } else if (gtk_tree_model_iter_children(model, &child, &parent)) {
2481 while (gtk_tree_store_remove(store, &child)) {
2482 /* Do nothing more. */
2483 }
2484 }
2485
2488 if (flag) {
2489 g_object_unref(flag);
2490 }
2491 if (color) {
2493 }
2494 }
2496
2497 /* Finally, insert global observers... */
2499 if (NULL != pconn->playing || !pconn->observer) {
2500 continue;
2501 }
2502
2505 } else {
2507 }
2508
2509 gtk_tree_store_set(store, &parent,
2511 CL_COL_USER_NAME, pconn->username,
2512 CL_COL_TEAM, _("Observer"),
2513 CL_COL_CONN_ID, pconn->id,
2516 -1);
2517
2521
2522 /* ...and detached connections. */
2524 if (NULL != pconn->playing || pconn->observer) {
2525 continue;
2526 }
2527
2530 } else {
2532 }
2533
2534 gtk_tree_store_set(store, &parent,
2536 CL_COL_USER_NAME, pconn->username,
2537 CL_COL_TEAM, _("Detached"),
2538 CL_COL_CONN_ID, pconn->id,
2541 -1);
2542
2546
2547 /* Remove trailing rows. */
2548 if (NULL != pprev_parent) {
2550 if (gtk_tree_model_iter_next(model, &parent)) {
2551 while (gtk_tree_store_remove(store, &parent)) {
2552 /* Do nothing more. */
2553 }
2554 }
2555 } else {
2556 gtk_tree_store_clear(store);
2557 }
2558
2559 /* If we were selecting a single connection, let's try to reselect it. */
2562 }
2563 }
2564
2566}
2567
2568/**********************************************************************/
2574 const char *title, int colnum, const char *key)
2575{
2578
2579 if (gtype == G_TYPE_BOOLEAN) {
2582 "active", colnum, NULL);
2583 } else if (gtype == GDK_TYPE_PIXBUF) {
2586 "pixbuf", colnum, NULL);
2587 } else {
2590 "text", colnum,
2591 "style", CL_COL_STYLE,
2592 "weight", CL_COL_WEIGHT,
2593 NULL);
2594 }
2595
2598
2599 if (key != NULL) {
2601 }
2602}
2603
2604/**********************************************************************/
2608{
2609 GtkWidget *box, *sbox, *table, *vbox;
2610 GtkWidget *view, *sw, *text, *toolkit_view, *button, *spin;
2611 GtkWidget *label;
2612 GtkTreeSelection *selection;
2613 enum ai_level level;
2614 /* There's less than AI_LEVEL_COUNT entries as not all levels have
2615 entries (that's the whole point of this array: index != value),
2616 but this is set safely to the max */
2617 static enum ai_level levels[AI_LEVEL_COUNT];
2618 int i = 0;
2619
2620 box = gtk_grid_new();
2625
2626 sbox = gtk_grid_new();
2629
2630 vbox = gtk_grid_new();
2631 g_object_set(vbox, "margin", 12, NULL);
2638
2639 table = gtk_grid_new();
2644
2650 if (server_optset != NULL) {
2652 if (paifill) {
2655 } /* else it'll be updated later */
2656 }
2657 g_signal_connect_after(spin, "value_changed",
2659
2660 gtk_grid_attach(GTK_GRID(table), spin, 1, 0, 1, 1);
2661
2663 "use-underline", TRUE,
2664 "mnemonic-widget", spin,
2665 /* TRANS: Keep individual lines short */
2666 "label", _("Number of _Players\n(including AI):"),
2667 "xalign", 0.0,
2668 "yalign", 0.5,
2669 NULL);
2670 gtk_grid_attach(GTK_GRID(table), label, 0, 0, 1, 1);
2671
2673
2674 for (level = 0; level < AI_LEVEL_COUNT; level++) {
2677
2679 levels[i] = level;
2680 i++;
2681 }
2682 }
2685 G_CALLBACK(ai_skill_callback), levels);
2686
2688
2690 "use-underline", TRUE,
2691 "mnemonic-widget", ai_lvl_combobox,
2692 "label", _("AI Skill _Level:"),
2693 "xalign", 0.0,
2694 "yalign", 0.5,
2695 NULL);
2696 gtk_grid_attach(GTK_GRID(table), label, 0, 1, 1, 1);
2697
2701
2703
2705 "use-underline", TRUE,
2706 "mnemonic-widget", GTK_COMBO_BOX_TEXT(ruleset_combo),
2707 "label", _("Ruleset:"),
2708 "xalign", 0.0,
2709 "yalign", 0.5,
2710 NULL);
2711 gtk_grid_attach(GTK_GRID(table), label, 0, 2, 1, 1);
2712
2713 button = icon_label_button_new("preferences-system",
2714 _("_More Game Options..."));
2715 g_object_set(button, "margin", 8, NULL);
2718 g_signal_connect(button, "clicked",
2720 gtk_container_add(GTK_CONTAINER(vbox), button);
2721
2728
2731 g_signal_connect(selection, "changed",
2733
2734 add_tree_col(view, G_TYPE_STRING, _("Name"),
2736 add_tree_col(view, G_TYPE_BOOLEAN, _("Ready"),
2738 add_tree_col(view, G_TYPE_STRING, Q_("?player:Leader"),
2741 CL_COL_FLAG, NULL);
2742 add_tree_col(view, GDK_TYPE_PIXBUF, _("Border"),
2744 add_tree_col(view, G_TYPE_STRING, _("Nation"),
2746 add_tree_col(view, G_TYPE_STRING, _("Team"),
2747 CL_COL_TEAM, NULL);
2748
2749 g_signal_connect(view, "button-press-event",
2751 g_signal_connect(view, "row-collapsed",
2754 g_signal_connect(view, "row-expanded",
2757
2767
2768
2776
2780 start_message_area = text;
2781 gtk_widget_set_name(text, "chatline");
2786
2787
2788 /* Vote widgets. */
2789 if (pregame_votebar == NULL) {
2791 }
2793
2794
2797
2798 button = gtk_button_new_with_mnemonic(_("_Cancel"));
2800 g_signal_connect(button, "clicked", G_CALLBACK(main_callback), NULL);
2801
2802 nation_button = icon_label_button_new("document-properties",
2803 _("Pick _Nation"));
2807
2808 observe_button = icon_label_button_new("zoom-in", _("_Observe"));
2812
2813 ready_button = icon_label_button_new("system-run", _("_Ready"));
2815 g_signal_connect(ready_button, "clicked",
2817
2818 return box;
2819}
2820
2821
2822/**********************************************************************/
2825void handle_game_load(bool load_successful, const char *filename)
2826{
2827 if (load_successful) {
2829
2830 if (game.info.is_new_game) {
2831 /* It's pregame. Create a player and connect to it */
2832 send_chat("/take -");
2833 }
2834 }
2835}
2836
2837/**********************************************************************/
2840static void load_filename(const char *filename)
2841{
2842 send_chat_printf("/load %s", filename);
2843}
2844
2845/**********************************************************************/
2848static void load_callback(void)
2849{
2850 GtkTreeIter it;
2851 const gchar *filename;
2852
2854 return;
2855 }
2856
2858 SD_COL_FULL_PATH, &filename, -1);
2859 load_filename(filename);
2860}
2861
2862/**********************************************************************/
2866{
2867 save_dialog_file_chooser_popup(_("Choose Saved Game to Load"),
2870}
2871
2872/**********************************************************************/
2875static void update_load_page(void)
2876{
2877 /* Search for user saved games. */
2879 ".sav", FALSE);
2880
2882 fileinfo_list_destroy(files);
2883}
2884
2885/**********************************************************************/
2889{
2890 GtkWidget *box, *sbox, *bbox;
2891
2892 GtkWidget *button, *label, *view, *sw;
2894
2895 box = gtk_grid_new();
2900
2905
2908 -1, NULL, rend, "text", 0, NULL);
2909
2912
2914
2915 g_signal_connect(view, "row-activated",
2917
2918 sbox = gtk_grid_new();
2924
2926 "use-underline", TRUE,
2927 "mnemonic-widget", view,
2928 "label", _("Choose Saved Game to _Load:"),
2929 "xalign", 0.0,
2930 "yalign", 0.5,
2931 NULL);
2933
2942
2948
2949 button = gtk_button_new_with_mnemonic(_("_Browse..."));
2952 g_signal_connect(button, "clicked",
2954
2955 button = gtk_button_new_with_mnemonic(_("_Cancel"));
2957 g_signal_connect(button, "clicked",
2959
2960 button = gtk_button_new_with_mnemonic(_("_OK"));
2962 g_signal_connect(button, "clicked",
2964
2965 return box;
2966}
2967
2968/**********************************************************************/
2971static void scenario_list_callback(void)
2972{
2973 GtkTreeIter it;
2974 GtkTextBuffer *buffer;
2975 char *description;
2976 char *authors;
2977 char *filename;
2978 int ver;
2979 char vername[50];
2980
2983 2, &description, -1);
2985 3, &authors, -1);
2987 1, &filename, -1);
2989 4, &ver, -1);
2990 filename = skip_to_basename(filename);
2991 if (ver > 0) {
2992 int maj;
2993 int min;
2994
2995 maj = ver / 1000000;
2996 ver %= 1000000;
2997 min = ver / 10000;
2998 ver %= 10000;
2999 if (ver >= 9000) {
3000 /* Development version, have '+' */
3001 fc_snprintf(vername, sizeof(vername), "%d.%d+", maj, min);
3002 } else {
3003 fc_snprintf(vername, sizeof(vername), "%d.%d", maj, min);
3004 }
3005 } else {
3006 /* TRANS: Old scenario format version */
3007 fc_snprintf(vername, sizeof(vername), _("pre-2.6"));
3008 }
3009 } else {
3010 description = "";
3011 authors = "";
3012 filename = "";
3013 vername[0] = '\0';
3014 }
3015
3017 gtk_text_buffer_set_text(buffer, description, -1);
3019 gtk_text_buffer_set_text(buffer, authors, -1);
3022}
3023
3024/**********************************************************************/
3027static void scenario_callback(void)
3028{
3029 GtkTreeIter it;
3030 char *filename;
3031
3033 return;
3034 }
3035
3036 gtk_tree_model_get(GTK_TREE_MODEL(scenario_store), &it, 1, &filename, -1);
3037 load_filename(filename);
3038}
3039
3040/**********************************************************************/
3044{
3045 save_dialog_file_chooser_popup(_("Choose a Scenario"),
3048}
3049
3050/**********************************************************************/
3053static void update_scenario_page(void)
3054{
3055 struct fileinfo_list *files;
3056
3058
3059 /* search for scenario files. */
3060 files = fileinfolist_infix(get_scenario_dirs(), ".sav", TRUE);
3062 struct section_file *sf;
3063
3064 if ((sf = secfile_load_section(pfile->fullname, "scenario", TRUE))
3065 && secfile_lookup_bool_default(sf, TRUE, "scenario.is_scenario")) {
3066 const char *sname, *sdescription, *sauthors;
3067 int fcver;
3068 int fcdev;
3069 int current_ver = MAJOR_VERSION * 1000000 + MINOR_VERSION * 10000;
3070 int current_dev;
3071
3073 if (PATCH_VERSION >= 90) {
3074 /* Patch level matters on development versions */
3075 current_dev += PATCH_VERSION * 100;
3076 }
3077
3078 fcver = secfile_lookup_int_default(sf, 0, "scenario.game_version");
3079 if (fcver < 30000) {
3080 /* Pre-3.0 versions stored version number without emergency version
3081 * part in the end. To get comparable version number stored,
3082 * multiply by 100. */
3083 fcver *= 100;
3084 }
3085 if (fcver % 10000 >= 9000) {
3086 fcdev = fcver - (fcver % 100); /* Emergency version does not count. */
3087 } else {
3088 fcdev = fcver - (fcver % 10000); /* Patch version does not count. */
3089 }
3090 sname = secfile_lookup_str_default(sf, NULL, "scenario.name");
3092 "scenario.description");
3093 sauthors = secfile_lookup_str_default(sf, NULL, "scenario.authors");
3094 log_debug("scenario file: %s from %s", sname, pfile->fullname);
3095
3096 /* Ignore scenarios for newer freeciv versions than we are. */
3097 if (fcdev <= current_dev) {
3098 bool add_new = TRUE;
3099
3100 if (sname != NULL) {
3101 GtkTreeIter it;
3102 bool valid;
3103
3105 while (valid) {
3106 char *oname;
3107
3109 0, &oname, -1);
3110
3111 if (!strcmp(sname, oname)) {
3112 /* Already listed scenario has the same name as the one we just found */
3113 int existing;
3114
3116 4, &existing, -1);
3117 log_debug("Duplicate %s (%d vs %d)", sname, existing, fcver);
3118
3119 if (existing > fcver) {
3120 /* Already listed one has higher version number */
3121 add_new = FALSE;
3122 } else if (existing < fcver) {
3123 /* New one has higher version number */
3124 add_new = FALSE;
3125
3127 0, sname && strlen(sname) ? Q_(sname) : pfile->name,
3128 1, pfile->fullname,
3129 2, (NULL != sdescription && '\0' != sdescription[0]
3130 ? Q_(sdescription) : ""),
3131 3, (NULL != sauthors && sauthors[0] != '\0'
3132 ? Q_(sauthors) : ""),
3133 4, fcver,
3134 -1);
3135 } else {
3136 /* Same version number -> list both */
3137 }
3138 }
3140 }
3141 }
3142
3143 if (add_new) {
3144 GtkTreeIter it;
3145
3148 0, sname && strlen(sname) ? Q_(sname) : pfile->name,
3149 1, pfile->fullname,
3150 2, (NULL != sdescription && '\0' != sdescription[0]
3151 ? Q_(sdescription) : ""),
3152 3, (NULL != sauthors && sauthors[0] != '\0'
3153 ? Q_(sauthors) : ""),
3154 4, fcver,
3155 -1);
3156 }
3157 }
3158
3159 secfile_destroy(sf);
3160 }
3162
3163 fileinfo_list_destroy(files);
3164}
3165
3166/**********************************************************************/
3170{
3171 GtkWidget *vbox, *hbox, *sbox, *bbox, *filenamebox, *descbox;
3173 GtkWidget *button, *label, *view, *sw, *swa, *text;
3175
3176 vbox = gtk_grid_new();
3181
3186 G_TYPE_INT);
3191
3194 -1, NULL, rend, "text", 0, NULL);
3195
3200
3202
3203 g_signal_connect(view, "row-activated",
3205
3207 "use-underline", TRUE,
3208 "mnemonic-widget", view,
3209 "label", _("Choose a _Scenario:"),
3210 "xalign", 0.0,
3211 "yalign", 0.5,
3212 NULL);
3213 gtk_container_add(GTK_CONTAINER(vbox), label);
3214
3215 sbox = gtk_grid_new();
3222
3223 hbox = gtk_grid_new();
3226
3233 gtk_grid_attach(GTK_GRID(sbox), sw, 0, 0, 1, 2);
3234
3235 text = gtk_text_view_new();
3241 scenario_description = text;
3242
3249
3250 text = gtk_text_view_new();
3256 scenario_authors = text;
3257
3264
3265 text = gtk_label_new(_("Filename:"));
3270
3273 g_object_set(filenamebox, "margin", 5, NULL);
3274
3277
3278 /* TRANS: Scenario format version */
3279 vertext = gtk_label_new(_("Format:"));
3284
3287 g_object_set(versionbox, "margin", 5, NULL);
3288
3291
3300 gtk_grid_attach(GTK_GRID(sbox), descbox, 1, 0, 1, 2);
3301
3306
3307 button = gtk_button_new_with_mnemonic(_("_Browse..."));
3310 g_signal_connect(button, "clicked",
3312
3313 button = gtk_button_new_with_mnemonic(_("_Cancel"));
3315 g_signal_connect(button, "clicked",
3317
3318 button = gtk_button_new_with_mnemonic(_("_OK"));
3320 g_signal_connect(button, "clicked",
3322
3323 return vbox;
3324}
3325
3326/**********************************************************************/
3330{
3331 return current_page;
3332}
3333
3334/**********************************************************************/
3338{
3339 /* Don't use current_page directly here because maybe it could be modified
3340 * before we reach the end of this function. */
3342
3343 /* If the page remains the same, don't do anything. */
3344 if (old_page == new_page) {
3345 return;
3346 }
3347
3348 log_debug("Switching client page from %s to %s.",
3349 -1 == old_page ? "(no page)" : client_pages_name(old_page),
3351
3353
3354 switch (old_page) {
3355 case PAGE_SCENARIO:
3356 case PAGE_LOAD:
3357 break;
3358 case PAGE_GAME:
3359 {
3361
3363 if (vmode == NULL) {
3365 }
3366 }
3367 break;
3368 default:
3369 break;
3370 }
3371
3372 switch (new_page) {
3373 case PAGE_MAIN:
3374 case PAGE_START:
3375 if (is_server_running()) {
3376 if (game.info.is_new_game) {
3378 } else {
3380 }
3382 } else {
3384 }
3388 break;
3389 case PAGE_GAME:
3390 {
3392
3395 if (vmode == NULL) {
3397 }
3400 }
3401 break;
3402 case PAGE_LOAD:
3404 break;
3405 case PAGE_SCENARIO:
3407 break;
3408 case PAGE_NETWORK:
3410 break;
3411 }
3412
3413 /* hide/show statusbar. */
3414 if (new_page == PAGE_START || new_page == PAGE_GAME) {
3417 } else {
3419 }
3420
3422
3423 /* Update the GUI. */
3424 while (gtk_events_pending()) {
3426 }
3427
3428 switch (new_page) {
3429 case PAGE_MAIN:
3430 break;
3431 case PAGE_START:
3434 break;
3435 case PAGE_LOAD:
3437 break;
3438 case PAGE_SCENARIO:
3440 break;
3441 case PAGE_GAME:
3445 mapview_thaw();
3446 break;
3447 case PAGE_NETWORK:
3452 break;
3453 }
3454}
3455
3456/****************************************************************************
3457 SAVE GAME DIALOGs
3458****************************************************************************/
3459
3460/**********************************************************************/
3464{
3465 return fileinfolist_infix(get_save_dirs(), ".sav", FALSE);
3466}
3467
3468/**********************************************************************/
3472{
3473 static GtkWidget *shell = NULL;
3474
3475 if (NULL != shell) {
3476 return;
3477 }
3478
3479 shell = save_dialog_new(_("Save Game"), _("Saved _Games:"),
3480 _("Save _Filename:"), send_save_game,
3483 &shell);
3485}
3486
3487/**********************************************************************/
3490static void save_dialog_save_scenario(const char *filename)
3491{
3493}
3494
3495/**********************************************************************/
3499{
3500 return fileinfolist_infix(get_scenario_dirs(), ".sav", FALSE);
3501}
3502
3503/**********************************************************************/
3507{
3508 static GtkWidget *shell = NULL;
3509
3510 if (NULL != shell) {
3511 return;
3512 }
3513
3514 shell = save_dialog_new(_("Save Scenario"), _("Saved Sce_narios:"),
3515 _("Save Sc_enario:"), save_dialog_save_scenario,
3518 &shell);
3520}
3521
3522/**********************************************************************/
3528{
3529 return fileinfolist_infix(get_save_dirs(), ".map", FALSE);
3530}
3531
3532/**********************************************************************/
3536{
3537 static GtkWidget *shell = NULL;
3538
3539 if (NULL != shell) {
3540 return;
3541 }
3542
3543 shell = save_dialog_new(_("Save Map Image"), _("Saved Map _Images:"),
3544 _("Save _Map Images:"), mapimg_client_save,
3547 &shell);
3549}
3550
3551/**********************************************************************/
3554void mapimg_client_save(const char *filename)
3555{
3556 if (!mapimg_client_createmap(filename)) {
3557 char msg[512];
3558
3559 fc_snprintf(msg, sizeof(msg), "(%s)", mapimg_error());
3560 popup_notify_dialog(_("Error"),
3561 _("Error Creating the Map Image!"), msg);
3562 }
3563}
3564
3565/**********************************************************************/
3570void set_rulesets(int num_rulesets, char **rulesets)
3571{
3572 int i;
3573 int def_idx = -1;
3574
3576 for (i = 0; i < num_rulesets; i++) {
3577
3579 if (!strcmp("default", rulesets[i])) {
3580 def_idx = i;
3581 }
3582 }
3583
3585
3586 /* HACK: server should tell us the current ruleset. */
3588
3590}
#define n
Definition astring.c:77
struct canvas int int struct sprite int int int int height
Definition canvas_g.h:44
struct canvas int int struct sprite int int int width
Definition canvas_g.h:44
int send_chat_printf(const char *format,...)
int send_chat(const char *message)
void output_window_append(const struct ft_color color, const char *featured_text)
bool can_client_control(void)
bool client_is_global_observer(void)
bool client_is_observer(void)
char user_name[512]
char server_host[512]
struct civclient client
enum client_states client_state(void)
char fc_password[MAX_LEN_PASSWORD]
int server_port
#define client_player()
@ C_S_PREPARING
Definition client_main.h:46
enum ai_level server_ai_level(void)
Definition climisc.c:1507
bool mapimg_client_createmap(const char *filename)
Definition climisc.c:1454
void center_on_something(void)
Definition climisc.c:430
static struct fc_sockaddr_list * list
Definition clinet.c:102
int connect_to_server(const char *username, const char *hostname, int port, char *errbuf, int errbufsize)
Definition clinet.c:249
void disconnect_from_server(bool leaving_sound)
Definition clinet.c:306
char * incite_cost
Definition comments.c:74
authentication_type
Definition conn_types.h:41
@ AUTH_NEWUSER_RETRY
Definition conn_types.h:45
@ AUTH_NEWUSER_FIRST
Definition conn_types.h:43
@ AUTH_LOGIN_RETRY
Definition conn_types.h:44
@ AUTH_LOGIN_FIRST
Definition conn_types.h:42
void send_save_game(const char *filename)
void set_ruleset(const char *ruleset)
bool is_server_running(void)
bool client_start_server(void)
bool can_client_access_hack(void)
const char * conn_description(const struct connection *pconn)
Definition connection.c:474
struct connection * conn_by_number(int id)
Definition connection.c:421
#define conn_list_iterate(connlist, pconn)
Definition connection.h:108
#define conn_list_iterate_end
Definition connection.h:110
popup_notify_dialog
Definition dialogs_g.h:37
int int id
Definition editgui_g.h:28
enum event_type event
Definition events.c:81
#define MAX_NUM_PLAYERS
Definition fc_types.h:36
#define MAX_LEN_NAME
Definition fc_types.h:66
#define Q_(String)
Definition fcintl.h:70
#define _(String)
Definition fcintl.h:67
void fc_mutex_allocate(fc_mutex *mutex)
void fc_mutex_release(fc_mutex *mutex)
const struct ft_color ftc_client
struct civ_game game
Definition game.c:62
static PangoLayout * layout
Definition canvas.c:325
void inputline_toolkit_view_append_button(GtkWidget *toolkit_view, GtkWidget *button)
Definition chatline.c:1292
GtkWidget * inputline_toolkit_view_new(void)
Definition chatline.c:1270
void inputline_grab_focus(void)
Definition chatline.c:79
void chatline_scroll_to_bottom(bool delayed)
Definition chatline.c:1006
void popup_races_dialog(struct player *pplayer)
Definition dialogs.c:1215
static struct tile * pos
Definition finddlg.c:53
const char * client_string
Definition gui_main.c:105
GtkTextBuffer * message_buffer
Definition gui_main.c:178
struct video_mode * resolution_request_get(void)
Definition gui_main.c:2633
void enable_menus(bool enable)
Definition gui_main.c:1074
void refresh_chat_buttons(void)
Definition gui_main.c:2531
void reset_unit_table(void)
Definition gui_main.c:1045
GtkWidget * toplevel
Definition gui_main.c:125
void quit_gtk_main(void)
Definition gui_main.c:2359
static struct video_mode vmode
Definition gui_main.c:191
GtkWidget * toplevel_tabs
Definition gui_main.c:127
int screen_height(void)
Definition gui_main.c:2615
#define GUI_GTK_OPTION(optname)
Definition gui_main.h:25
void gtk_tree_view_focus(GtkTreeView *view)
Definition gui_stuff.c:236
void gtk_stockbutton_set_label(GtkWidget *button, const gchar *label_text)
Definition gui_stuff.c:96
GtkWidget * icon_label_button_new(const gchar *icon_name, const gchar *label_text)
Definition gui_stuff.c:76
GtkTreeViewColumn * add_treeview_column(GtkWidget *view, const char *title, GType gtype, int model_index)
Definition gui_stuff.c:1123
void setup_dialog(GtkWidget *shell, GtkWidget *parent)
Definition gui_stuff.c:287
void mapview_freeze(void)
Definition mapview.c:373
void overview_size_changed(void)
Definition mapview.c:326
void mapview_thaw(void)
Definition mapview.c:381
static struct gui_dialog * shell
Definition messagedlg.c:39
void option_dialog_popup(const char *name, const struct option_set *poptset)
Definition optiondlg.c:972
static GtkListStore * load_store
Definition pages.c:68
static void update_network_page(void)
Definition pages.c:1169
void handle_game_load(bool load_successful, const char *filename)
Definition pages.c:2825
GtkWidget * create_start_page(void)
Definition pages.c:2607
GtkWidget * create_network_page(void)
Definition pages.c:1185
static void client_aitoggle_player(void *data)
Definition pages.c:1493
static GtkWidget * nation_button
Definition pages.c:1444
static void update_server_list(enum server_scan_type sstype, const struct server_list *list)
Definition pages.c:688
static void start_scenario_callback(GtkWidget *w, gpointer data)
Definition pages.c:115
static GtkTreeSelection * scenario_selection
Definition pages.c:73
static void update_start_page_buttons(void)
Definition pages.c:2183
static void save_dialog_response_callback(GtkWidget *w, gint response, gpointer data)
Definition pages.c:473
GtkWidget * create_scenario_page(void)
Definition pages.c:3169
static void show_conn_popup(struct player *pplayer, struct connection *pconn)
Definition pages.c:1751
static GtkWidget * network_confirm_password_label
Definition pages.c:683
void save_mapimg_dialog_popup(void)
Definition pages.c:3535
static void ruleset_selected(const char *name)
Definition pages.c:1599
static void ready_button_callback(GtkWidget *w, gpointer data)
Definition pages.c:2129
static bool conn_list_selection(struct player **ppplayer, struct connection **ppconn)
Definition pages.c:2042
static struct server_scan_timer_data meta_scan
Definition pages.c:86
static void update_network_lists(void)
Definition pages.c:822
static GtkWidget * statusbar
Definition pages.c:89
static GtkWidget * server_playerlist_view
Definition pages.c:71
static GtkListStore * save_dialog_store_new(void)
Definition pages.c:383
void append_network_statusbar(const char *text, bool force)
Definition pages.c:878
static gboolean update_network_statusbar(gpointer data)
Definition pages.c:848
void set_rulesets(int num_rulesets, char **rulesets)
Definition pages.c:3570
void mapimg_client_save(const char *filename)
Definition pages.c:3554
static void conn_menu_player_command(GObject *object, gpointer data)
Definition pages.c:1710
static void load_filename(const char *filename)
Definition pages.c:2840
static void conn_menu_nation_chosen(GObject *object, gpointer data)
Definition pages.c:1697
static GtkWidget * scenario_description
Definition pages.c:63
void save_game_dialog_popup(void)
Definition pages.c:3471
enum client_pages get_current_client_page(void)
Definition pages.c:3329
static GtkListStore * lan_store
Definition pages.c:68
static enum connection_state connection_status
Definition pages.c:843
save_dialog_columns
Definition pages.c:367
@ SD_COL_NUM
Definition pages.c:371
@ SD_COL_FULL_PATH
Definition pages.c:369
@ SD_COL_PRETTY_NAME
Definition pages.c:368
static struct server_scan_timer_data lan_scan
Definition pages.c:87
static void save_dialog_list_callback(GtkTreeSelection *selection, gpointer data)
Definition pages.c:541
static void connect_network_game_callback(GtkWidget *w, gpointer data)
Definition pages.c:132
static GtkTreeView * connection_list_view
Definition pages.c:1446
static GtkWidget * network_login
Definition pages.c:679
static GtkWidget * network_login_label
Definition pages.c:679
connection_state
Definition pages.c:836
@ LOGIN_TYPE
Definition pages.c:837
@ NEW_PASSWORD_TYPE
Definition pages.c:838
@ WAITING_TYPE
Definition pages.c:840
@ ENTER_PASSWORD_TYPE
Definition pages.c:839
static void connect_callback(GtkWidget *w, gpointer data)
Definition pages.c:1027
static void scenario_browse_callback(GtkWidget *w, gpointer data)
Definition pages.c:3043
static GtkListStore * meta_store
Definition pages.c:68
connection_list_columns
Definition pages.c:1452
@ CL_COL_STYLE
Definition pages.c:1462
@ CL_COL_USER_NAME
Definition pages.c:1454
@ CL_COL_READY_STATE
Definition pages.c:1455
@ CL_COL_WEIGHT
Definition pages.c:1463
@ CL_COL_PLAYER_NAME
Definition pages.c:1456
@ CL_COL_NATION
Definition pages.c:1459
@ CL_COL_CONN_ID
Definition pages.c:1461
@ CL_COL_PLAYER_NUMBER
Definition pages.c:1453
@ CL_NUM_COLUMNS
Definition pages.c:1466
@ CL_COL_TEAM
Definition pages.c:1460
@ CL_COL_COLOR
Definition pages.c:1458
@ CL_COL_COLLAPSED
Definition pages.c:1464
@ CL_COL_FLAG
Definition pages.c:1457
static void update_load_page(void)
Definition pages.c:2875
static void save_dialog_update(struct save_dialog *pdialog)
Definition pages.c:411
static GtkWidget * scenario_authors
Definition pages.c:64
static GtkWidget * start_aifill_spin
Definition pages.c:1447
static void ruleset_entry_changed(GtkWidget *w, gpointer data)
Definition pages.c:1611
void(* save_dialog_action_fn_t)(const char *filename)
Definition pages.c:356
static void open_settings(void)
Definition pages.c:141
static void set_connection_state(enum connection_state state)
Definition pages.c:914
static GtkWidget * ruleset_combo
Definition pages.c:93
static void observe_button_callback(GtkWidget *w, gpointer data)
Definition pages.c:2163
static void conn_menu_ready_chosen(GObject *object, gpointer data)
Definition pages.c:1684
static void server_scan_error(struct server_scan *scan, const char *message)
Definition pages.c:809
static void load_callback(void)
Definition pages.c:2848
static void save_dialog_file_chooser_callback(GtkWidget *widget, gint response, gpointer data)
Definition pages.c:428
static void network_list_callback(GtkTreeSelection *select, gpointer data)
Definition pages.c:1123
static GtkListStore * server_playerlist_store
Definition pages.c:70
static void nation_button_callback(GtkWidget *w, gpointer data)
Definition pages.c:2143
void real_set_client_page(enum client_pages new_page)
Definition pages.c:3337
static void conn_menu_connection_command(GObject *object, gpointer data)
Definition pages.c:1737
static void scenario_list_callback(void)
Definition pages.c:2971
static gboolean intro_expose(GtkWidget *w, cairo_t *cr, gpointer *data)
Definition pages.c:164
static void load_browse_callback(GtkWidget *w, gpointer data)
Definition pages.c:2865
static void network_activate_callback(GtkTreeView *view, GtkTreePath *arg1, GtkTreeViewColumn *arg2, gpointer data)
Definition pages.c:1082
static struct fileinfo_list * save_dialog_scenario_list(void)
Definition pages.c:3498
static void connection_state_reset(void)
Definition pages.c:982
void real_conn_list_dialog_update(void *unused)
Definition pages.c:2328
static gboolean connection_list_event(GtkWidget *widget, GdkEventButton *event, gpointer data)
Definition pages.c:1973
static bool holding_srv_list_mutex
Definition pages.c:95
static GtkTreeStore * connection_list_store
Definition pages.c:1445
static struct fileinfo_list * save_dialog_savegame_list(void)
Definition pages.c:3463
static void start_new_game_callback(GtkWidget *w, gpointer data)
Definition pages.c:102
void destroy_server_scans(void)
Definition pages.c:752
void save_scenario_dialog_popup(void)
Definition pages.c:3506
static GtkTreeSelection * lan_selection
Definition pages.c:74
static void save_dialog_save_scenario(const char *filename)
Definition pages.c:3490
struct fileinfo_list *(* save_dialog_files_fn_t)(void)
Definition pages.c:357
static gboolean check_server_scan(gpointer data)
Definition pages.c:775
static void save_dialog_store_update(GtkListStore *store, const struct fileinfo_list *files)
Definition pages.c:393
static void ai_fill_changed_by_user(GtkWidget *w, gpointer data)
Definition pages.c:1626
static gboolean delayed_unselect_path(gpointer data)
Definition pages.c:1957
static void conn_menu_player_take(GObject *object, gpointer data)
Definition pages.c:1724
static void conn_menu_info_chosen(GObject *object, gpointer data)
Definition pages.c:1782
static bool model_get_player_iter(GtkTreeModel *model, GtkTreeIter *iter, GtkTreeIter *start, const struct player *pplayer)
Definition pages.c:2268
static GtkTreeSelection * load_selection
Definition pages.c:73
static void ai_skill_callback(GtkWidget *w, gpointer data)
Definition pages.c:1573
static enum client_pages current_page
Definition pages.c:78
static GtkWidget * statusbar_frame
Definition pages.c:89
static GtkWidget * network_confirm_password
Definition pages.c:683
static void client_take_player(struct player *pplayer)
Definition pages.c:1507
static void clear_network_statusbar(void)
Definition pages.c:864
static GtkTreeSelection * meta_selection
Definition pages.c:74
static void save_dialog_row_callback(GtkTreeView *tree_view, GtkTreePath *path, GtkTreeViewColumn *column, gpointer data)
Definition pages.c:522
static void connection_list_row_callback(GtkTreeView *tree_view, GtkTreeIter *iter, GtkTreePath *path, gpointer data)
Definition pages.c:2027
save_dialog_response
Definition pages.c:374
@ SD_RES_DELETE
Definition pages.c:376
@ SD_RES_SAVE
Definition pages.c:377
@ SD_RES_BROWSE
Definition pages.c:375
GtkWidget * create_load_page(void)
Definition pages.c:2888
static GtkWidget * ai_lvl_combobox
Definition pages.c:1448
static GtkWidget * network_password_label
Definition pages.c:682
static GtkWidget * save_dialog_new(const char *title, const char *savelabel, const char *savefilelabel, save_dialog_action_fn_t action, save_dialog_files_fn_t files)
Definition pages.c:562
static void intro_free(GtkWidget *w, gpointer *data)
Definition pages.c:219
static GtkWidget * network_password
Definition pages.c:682
static GtkWidget * network_host
Definition pages.c:680
void handle_authentication_req(enum authentication_type type, const char *message)
Definition pages.c:991
static GtkTreeStore * connection_list_store_new(void)
Definition pages.c:1472
static bool send_new_aifill_to_server
Definition pages.c:1625
static void save_dialog_file_chooser_popup(const char *title, GtkFileChooserAction action, save_dialog_action_fn_t cb)
Definition pages.c:448
static GtkWidget * network_port
Definition pages.c:681
static void add_tree_col(GtkWidget *treeview, GType gtype, const char *title, int colnum, const char *key)
Definition pages.c:2573
static void save_dialog_entry_callback(GtkEntry *entry, gpointer data)
Definition pages.c:533
static void main_callback(GtkWidget *w, gpointer data)
Definition pages.c:149
void update_start_page(void)
Definition pages.c:1659
static void scenario_callback(void)
Definition pages.c:3027
static GtkWidget * start_options_table
Definition pages.c:1443
static bool no_ruleset_callback
Definition pages.c:1594
void ai_fill_changed_by_server(int aifill)
Definition pages.c:1637
static void update_server_playerlist(const struct server *pserver)
Definition pages.c:1094
static GtkWidget * observe_button
Definition pages.c:1444
static GtkWidget * scenario_version
Definition pages.c:66
GtkWidget * create_statusbar(void)
Definition pages.c:893
static void game_options_callback(GtkWidget *w, gpointer data)
Definition pages.c:1565
static GtkListStore * scenario_store
Definition pages.c:68
static GtkWidget * network_host_label
Definition pages.c:680
static bool model_get_conn_iter(GtkTreeModel *model, GtkTreeIter *iter, GtkTreeIter *parent, GtkTreeIter *start, const struct connection *pconn)
Definition pages.c:2299
static GQueue * statusbar_queue
Definition pages.c:90
GtkWidget * start_message_area
Definition pages.c:1441
static GtkWidget * network_port_label
Definition pages.c:681
static void update_scenario_page(void)
Definition pages.c:3053
static GtkWidget * scenario_filename
Definition pages.c:65
static void conn_menu_team_chosen(GObject *object, gpointer data)
Definition pages.c:1667
static GtkWidget * create_conn_menu(struct player *pplayer, struct connection *pconn)
Definition pages.c:1796
static void load_saved_game_callback(GtkWidget *w, gpointer data)
Definition pages.c:124
static guint statusbar_timer
Definition pages.c:91
static bool object_extract(GObject *object, struct player **ppplayer, struct connection **ppconn)
Definition pages.c:1538
static void object_put(GObject *object, struct player *pplayer, struct connection *pconn)
Definition pages.c:1519
static struct fileinfo_list * save_dialog_mapimg_list(void)
Definition pages.c:3527
GtkWidget * create_main_page(void)
Definition pages.c:229
static void conn_list_select_conn(struct connection *pconn)
Definition pages.c:2078
static GtkWidget * ready_button
Definition pages.c:1444
GdkPixbuf * create_player_icon(const struct player *plr)
Definition plrdlg.c:117
GdkPixbuf * get_flag(const struct nation_type *nation)
Definition plrdlg.c:607
const char * title
Definition repodlgs.c:1314
GType type
Definition repodlgs.c:1313
void free_sprite(struct sprite *s)
Definition sprite.c:278
struct sprite * sprite_scale(struct sprite *src, int new_w, int new_h)
Definition sprite.c:291
struct sprite * load_gfxfile(const char *filename, bool svgflag)
Definition sprite.c:170
void voteinfo_gui_update(void)
GtkWidget * voteinfo_bar_new(bool split_bar)
GtkWidget * pregame_votebar
void(* save_dialog_action_fn_t)(const char *filename)
Definition pages.c:365
struct fileinfo_list *(* save_dialog_files_fn_t)(void)
Definition pages.c:366
static struct server_list * server_list
Definition connectdlg.c:61
static enum client_pages old_page
Definition pages.c:46
void conn_list_dialog_update(void)
const char * name
Definition inputfile.c:127
#define fc_assert_ret(condition)
Definition log.h:191
#define fc_assert_ret_val(condition, val)
Definition log.h:194
#define log_debug(message,...)
Definition log.h:115
#define log_error(message,...)
Definition log.h:103
const char * mapimg_error(void)
Definition mapimg.c:759
#define fc_strdup(str)
Definition mem.h:43
#define fc_malloc(sz)
Definition mem.h:34
const char * nation_adjective_for_player(const struct player *pplayer)
Definition nation.c:169
bool can_conn_edit_players_nation(const struct connection *pconn, const struct player *pplayer)
Definition nation.c:1187
#define NO_NATION_SELECTED
Definition nation.h:30
const struct option_set * server_optset
Definition options.c:4019
const struct option_set * client_optset
Definition options.c:1279
int option_int_get(const struct option *poption)
Definition options.c:833
struct option * optset_option_by_name(const struct option_set *poptset, const char *name)
Definition options.c:430
bool option_int_set(struct option *poption, int val)
Definition options.c:877
int send_packet_authentication_reply(struct connection *pc, const struct packet_authentication_reply *packet)
int dsend_packet_save_scenario(struct connection *pc, const char *name)
int dsend_packet_player_ready(struct connection *pc, int player_no, bool is_ready)
void client_start_server_and_set_page(enum client_pages page)
void set_client_page(enum client_pages page)
enum client_pages get_client_page(void)
bool is_settable_ai_level(enum ai_level level)
Definition player.c:1919
struct player * player_by_number(const int player_id)
Definition player.c:849
int player_slot_count(void)
Definition player.c:418
int player_number(const struct player *pplayer)
Definition player.c:837
const char * player_name(const struct player *pplayer)
Definition player.c:895
bool player_has_flag(const struct player *pplayer, enum plr_flag_id flag)
Definition player.c:1990
#define ai_level_cmd(_level_)
Definition player.h:567
#define players_iterate_end
Definition player.h:537
#define players_iterate(_pplayer)
Definition player.h:532
#define is_ai(plr)
Definition player.h:230
#define players_iterate_alive_end
Definition player.h:547
#define is_human(plr)
Definition player.h:229
#define players_iterate_alive(_pplayer)
Definition player.h:542
void secfile_destroy(struct section_file *secfile)
struct section_file * secfile_load_section(const char *filename, const char *section, bool allow_duplicates)
bool secfile_lookup_bool_default(const struct section_file *secfile, bool def, const char *path,...)
int secfile_lookup_int_default(const struct section_file *secfile, int def, const char *path,...)
const char * secfile_lookup_str_default(const struct section_file *secfile, const char *def, const char *path,...)
struct srv_list * server_scan_get_list(struct server_scan *scan)
Definition servers.c:866
void server_scan_finish(struct server_scan *scan)
Definition servers.c:879
struct server_scan * server_scan_begin(enum server_scan_type type, ServerScanErrorFunc error_func)
Definition servers.c:755
enum server_scan_type server_scan_get_type(const struct server_scan *scan)
Definition servers.c:809
enum server_scan_status server_scan_poll(struct server_scan *scan)
Definition servers.c:832
#define server_list_iterate_end
Definition servers.h:57
server_scan_status
Definition servers.h:79
@ SCAN_STATUS_PARTIAL
Definition servers.h:82
@ SCAN_STATUS_ERROR
Definition servers.h:80
@ SCAN_STATUS_DONE
Definition servers.h:83
#define server_list_iterate(serverlist, pserver)
Definition servers.h:55
server_scan_type
Definition servers.h:67
@ SERVER_SCAN_LOCAL
Definition servers.h:68
@ SERVER_SCAN_GLOBAL
Definition servers.h:69
struct setting_list * level[OLEVELS_NUM]
Definition settings.c:190
const struct strvec * get_scenario_dirs(void)
Definition shared.c:978
const struct strvec * get_save_dirs(void)
Definition shared.c:941
char * skip_to_basename(char *filepath)
Definition shared.c:1757
struct fileinfo_list * fileinfolist_infix(const struct strvec *dirs, const char *infix, bool nodups)
Definition shared.c:1211
#define fileinfo_list_iterate(list, pnode)
Definition shared.h:176
#define FC_PTR_TO_INT(p)
Definition shared.h:95
#define fileinfo_list_iterate_end
Definition shared.h:178
#define FC_INT_TO_PTR(i)
Definition shared.h:94
size_t size
Definition specvec.h:72
struct sprite int int int int struct sprite int int float scale
Definition sprite_g.h:33
struct sprite int int int int struct sprite int int float bool smooth get_sprite_dimensions
Definition sprite_g.h:36
const char * aifill(int amount)
Definition srv_main.c:2464
struct conn_list * est_connections
Definition game.h:97
struct packet_game_info info
Definition game.h:89
struct connection conn
Definition client_main.h:96
Definition colors.h:21
struct player * playing
Definition connection.h:151
enum cmdlevel access_level
Definition connection.h:177
Definition climisc.h:80
struct team * team
Definition player.h:259
bool is_ready
Definition player.h:260
save_dialog_action_fn_t action
Definition pages.c:363
GtkEntry * entry
Definition pages.c:362
GtkTreeView * tree_view
Definition pages.c:361
GtkDialog * shell
Definition pages.c:360
save_dialog_files_fn_t files
Definition pages.c:364
struct server_scan * scan
Definition pages.c:82
fc_mutex mutex
Definition servers.h:64
struct server_list * servers
Definition servers.h:63
Definition team.c:40
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:974
int cat_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:1000
int fc_remove(const char *filename)
Definition support.c:557
#define sz_strlcpy(dest, src)
Definition support.h:189
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
#define sz_strlcat(dest, src)
Definition support.h:190
#define fc_strncmp(_s1_, _s2_, _len_)
Definition support.h:154
const char * team_name_translation(const struct team *pteam)
Definition team.c:420
const char * team_slot_name_translation(const struct team_slot *tslot)
Definition team.c:253
int team_number(const struct team *pteam)
Definition team.c:391
int team_slot_index(const struct team_slot *tslot)
Definition team.c:138
const struct player_list * team_members(const struct team *pteam)
Definition team.c:456
bool team_slot_is_used(const struct team_slot *tslot)
Definition team.c:162
const char * team_slot_rule_name(const struct team_slot *tslot)
Definition team.c:233
#define team_slots_iterate_end
Definition team.h:77
#define team_slots_iterate(_tslot)
Definition team.h:72
const char * tileset_main_intro_filename(const struct tileset *t)
Definition tilespec.c:947
void update_queue_connect_processing_finished(int request_id, uq_callback_t callback, void *data)
const char * fc_git_revision(void)
Definition version.c:75
const char * unstable_message(void)
Definition version.c:160
const char * word_version(void)
Definition version.c:62