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 "chat.h"
34#include "dataio.h"
35#include "game.h"
36#include "mapimg.h"
37#include "version.h"
38
39/* client */
40#include "client_main.h"
41#include "climisc.h"
42#include "clinet.h"
43#include "connectdlg_common.h"
44#include "packhand.h"
45#include "servers.h"
46#include "update_queue.h"
47
48/* client/gui-gtk-4.0 */
49#include "chatline.h"
50#include "connectdlg.h"
51#include "dialogs.h"
52#include "graphics.h"
53#include "gui_main.h"
54#include "gui_stuff.h"
55#include "mapview.h"
56#include "menu.h"
57#include "optiondlg.h"
58#include "plrdlg.h" /* get_flag() */
59#include "repodlgs.h"
60#include "voteinfo_bar.h"
61
62#include "pages.h"
63
64
69
71
74
77
78/* This is the current page. Invalid value at start, to be sure that it won't
79 * be catch throught a switch() statement. */
80static enum client_pages current_page = -1;
81
83{
84 struct server_scan *scan;
86};
87
88static struct server_scan_timer_data meta_scan = { NULL, 0 };
89static struct server_scan_timer_data lan_scan = { NULL, 0 };
90
94
96
98
100
101static void connection_state_reset(void);
102
103/**********************************************************************/
107{
108 if (!is_server_running()) {
110
111 /* Saved settings are sent in client/options.c
112 * resend_desired_settable_options() */
113 }
114}
115
116/**********************************************************************/
120{
121 output_window_append(ftc_client, _("Compiling scenario list."));
123}
124
125/**********************************************************************/
132
133/**********************************************************************/
141
142/**********************************************************************/
145static void open_settings(void)
146{
147 option_dialog_popup(_("Set local options"), client_optset);
148}
149
150/**********************************************************************/
153static void main_callback(GtkWidget *w, gpointer data)
154{
155 enum client_pages page = PAGE_MAIN;
156
157 if (client.conn.used) {
159 }
160 if (page != get_client_page()) {
161 set_client_page(page);
162 }
163}
164
165/**********************************************************************/
169 int width, int height, gpointer data)
170{
171 static PangoLayout *layout;
172 static int pwidth, pheight;
173 static bool left = FALSE;
175 struct sprite *intro = (struct sprite *)data;
176
177 cairo_set_source_surface(cr, intro->surface, 0, 0);
178 cairo_paint(cr);
179
180 if (!layout) {
181 char msgbuf[128];
182 const char *rev_ver;
183
186 pango_font_description_from_string("Sans Bold 10"));
187
189
190 if (rev_ver == NULL) {
191 /* TRANS: "version 2.6.0, gui-gtk-3.22 client" */
192 fc_snprintf(msgbuf, sizeof(msgbuf), _("%s%s, %s client"),
194 } else {
195 /* TRANS: "version 2.6.0
196 * commit: [modified] <git commit id>
197 * gui-gtk-3.22 client" */
198 fc_snprintf(msgbuf, sizeof(msgbuf), _("%s%s\ncommit: %s\n%s client"),
200 left = TRUE;
201 }
203
205 }
207
208 cairo_set_source_rgb(cr, 0, 0, 0);
209 cairo_move_to(cr, left ? 4 : allocation.width - pwidth - 3,
210 allocation.height - pheight - 3);
212
213 cairo_set_source_rgb(cr, 1, 1, 1);
214 cairo_move_to(cr, left ? 3 : allocation.width - pwidth - 4,
215 allocation.height - pheight - 4);
217}
218
219/**********************************************************************/
222static void intro_free(GtkWidget *w, gpointer *data)
223{
224 struct sprite *intro = (struct sprite *)data;
225
227}
228
229/**********************************************************************/
233{
234 GtkWidget *widget, *vgrid, *frame, *darea, *button, *table;
236 struct sprite *intro_in, *intro;
237 int width, height;
238 int sh;
239 int space_needed;
240 int grid_row = 0;
241
243
247 widget = vgrid;
248
249 frame = gtk_frame_new(NULL);
251 gtk_widget_set_margin_end(frame, 18);
253 gtk_widget_set_margin_top(frame, 18);
255 gtk_grid_attach(GTK_GRID(vgrid), frame, 0, grid_row++, 1, 1);
256
259 sh = screen_height();
260
261 if (sh <= 0) {
262 /* Assume some minimum height */
263 sh = 600;
264 }
265
266 space_needed = 250;
267#if IS_BETA_VERSION || IS_DEVEL_VERSION
268 /* Alpha or Beta notice takes extra space */
269 space_needed += 50;
270#endif
271
272 if (sh - height < space_needed) {
273 float scale;
274
275 if (sh < (space_needed + 0.2 * height)) {
276 /* Screen is simply too small, use minimum scale */
277 scale = 0.2;
278 } else {
279 scale = (double)(sh - space_needed) / height;
280 }
281 height *= scale;
282 width *= scale;
285 } else {
286 intro = intro_in;
287 }
288 darea = gtk_drawing_area_new();
292 g_signal_connect(widget, "destroy",
294 gtk_frame_set_child(GTK_FRAME(frame), darea);
295
296#if IS_BETA_VERSION || IS_DEVEL_VERSION
297 {
298 GtkWidget *label;
299
301 gtk_widget_set_name(label, "beta_label");
305 gtk_grid_attach(GTK_GRID(vgrid), label, 0, grid_row++, 1, 1);
306 }
307#endif /* IS_BETA_VERSION || IS_DEVEL_VERSION */
308
318
322
323 button = gtk_button_new_with_mnemonic(_("Start _New Game"));
325 gtk_grid_attach(GTK_GRID(table), button, 0, 0, 1, 1);
326 g_signal_connect(button, "clicked",
328
329 button = gtk_button_new_with_mnemonic(_("Start _Scenario Game"));
331 gtk_grid_attach(GTK_GRID(table), button, 0, 1, 1, 1);
332 g_signal_connect(button, "clicked",
334
335 button = gtk_button_new_with_mnemonic(_("_Load Saved Game"));
337 gtk_grid_attach(GTK_GRID(table), button, 0, 2, 1, 1);
338 g_signal_connect(button, "clicked",
340
341 button = gtk_button_new_with_mnemonic(_("C_onnect to Network Game"));
343 gtk_grid_attach(GTK_GRID(table), button, 1, 0, 1, 1);
344 g_signal_connect(button, "clicked",
346
347 button = gtk_button_new_with_mnemonic(_("Client Settings"));
349 gtk_grid_attach(GTK_GRID(table), button, 1, 1, 1, 1);
350 g_signal_connect(button, "clicked", open_settings, NULL);
351
352 button = icon_label_button_new("application-exit", _("E_xit"));
355 gtk_grid_attach(GTK_GRID(table), button, 1, 2, 1, 1);
356 g_signal_connect(button, "clicked",
358
359 return widget;
360}
361
362/****************************************************************************
363 GENERIC SAVE DIALOG
364****************************************************************************/
365typedef void (*save_dialog_action_fn_t) (const char *filename);
366typedef struct fileinfo_list * (*save_dialog_files_fn_t) (void);
367
368struct save_dialog {
374};
375
382
388
389/**********************************************************************/
393{
395 G_TYPE_STRING, /* SD_COL_PRETTY_NAME */
396 G_TYPE_STRING); /* SD_COL_FULL_PATH */
397}
398
399/**********************************************************************/
403 const struct fileinfo_list *files)
404{
406
410 gtk_list_store_set(store, &iter,
412 SD_COL_FULL_PATH, pfile->fullname,
413 -1);
415}
416
417/**********************************************************************/
420static void save_dialog_update(struct save_dialog *pdialog)
421{
422 struct fileinfo_list *files;
423
424 fc_assert_ret(NULL != pdialog);
425
426 /* Update the store. */
427 files = pdialog->files();
430 files);
432}
433
434/**********************************************************************/
438 gint response, gpointer data)
439{
440 if (response == GTK_RESPONSE_OK) {
443
444 if (file != NULL) {
445 gchar *filename = g_file_get_parse_name(file);
446
447 if (NULL != filename) {
448 action(filename);
449 g_free(filename);
450 }
451
452 g_object_unref(file);
453 }
454 }
455
457}
458
459/**********************************************************************/
462static void save_dialog_file_chooser_popup(const char *title,
465{
467
468 /* Create the chooser */
470 _("_Cancel"), GTK_RESPONSE_CANCEL,
472 _("_Save") : _("_Open"),
475
476 g_signal_connect(filechoose, "response",
478
479 /* Display that dialog */
481}
482
483/**********************************************************************/
487 gpointer data)
488{
489 struct save_dialog *pdialog = data;
490
491 switch (response) {
492 case SD_RES_BROWSE:
493 save_dialog_file_chooser_popup(_("Select Location to Save"),
495 pdialog->action);
496 break;
497 case SD_RES_DELETE:
498 {
499 GtkTreeSelection *selection;
500 GtkTreeModel *model;
502 const gchar *full_path;
503
504 selection = gtk_tree_view_get_selection(pdialog->tree_view);
505 if (!gtk_tree_selection_get_selected(selection, &model, &iter)) {
506 return;
507 }
508
511 save_dialog_update(pdialog);
512 }
513 return;
514 case SD_RES_SAVE:
515 {
516 const char *text = gtk_entry_buffer_get_text(gtk_entry_get_buffer(pdialog->entry));
517 gchar *filename = g_filename_from_utf8(text, -1, NULL, NULL, NULL);
518
519 if (NULL == filename) {
520 return;
521 }
522 pdialog->action(filename);
523 g_free(filename);
524 }
525 break;
526 default:
527 break;
528 }
529
531}
532
533/**********************************************************************/
543
544/**********************************************************************/
551
552/**********************************************************************/
556 gpointer data)
557{
558 struct save_dialog *pdialog = data;
559 GtkTreeModel *model;
561 const gchar *filename;
562
563 if (!gtk_tree_selection_get_selected(selection, &model, &iter)) {
565 return;
566 }
567
569 gtk_tree_model_get(model, &iter, SD_COL_PRETTY_NAME, &filename, -1);
571}
572
573/**********************************************************************/
576static GtkWidget *save_dialog_new(const char *title, const char *savelabel,
577 const char *savefilelabel,
580{
581 GtkWidget *shell, *sbox, *sw, *label, *view, *entry;
582 GtkBox *vbox;
583 GtkListStore *store;
585 GtkTreeSelection *selection;
586 struct save_dialog *pdialog;
587
590
591 /* Save dialog structure. */
592 pdialog = fc_malloc(sizeof(*pdialog));
593 pdialog->action = action;
594 pdialog->files = files;
595
596 /* Shell. */
598 _("_Browse..."), SD_RES_BROWSE,
599 _("_Delete"), SD_RES_DELETE,
600 _("_Cancel"), GTK_RESPONSE_CANCEL,
601 _("_Save"), SD_RES_SAVE,
602 NULL);
603 g_object_set_data_full(G_OBJECT(shell), "save_dialog", pdialog,
608 g_signal_connect(shell, "response",
610 pdialog->shell = GTK_DIALOG(shell);
612
613 /* Tree view. */
614 store = save_dialog_store_new();
618 g_object_unref(store);
620 g_signal_connect(view, "row-activated",
622 pdialog->tree_view = GTK_TREE_VIEW(view);
623
625 gtk_box_append(vbox, sbox);
626
628 "use-underline", TRUE,
629 "mnemonic-widget", view,
630 "label", savelabel,
631 "xalign", 0.0,
632 "yalign", 0.5,
633 NULL);
634 gtk_box_append(GTK_BOX(sbox), label);
635
644
647 g_signal_connect(selection, "changed",
649
652 -1, NULL, rend, "text",
654
655 /* Entry. */
658 g_signal_connect(entry, "activate",
660 pdialog->entry = GTK_ENTRY(entry);
661
667
669 "use-underline", TRUE,
670 "mnemonic-widget", entry,
671 "label", savefilelabel,
672 "xalign", 0.0,
673 "yalign", 0.5,
674 NULL);
675 gtk_box_append(GTK_BOX(sbox), label);
676
678 gtk_box_append(vbox, sbox);
679
680 save_dialog_update(pdialog);
683
684 return shell;
685}
686
687/****************************************************************************
688 NETWORK PAGE
689****************************************************************************/
695
696/**********************************************************************/
700 const struct server_list *list)
701{
704 GtkTreeIter it;
705 GtkListStore *store;
706 const gchar *host, *portstr;
707 int port;
708
709 switch (sstype) {
712 break;
715 break;
716 default:
717 break;
718 }
719
720 if (!sel) {
721 return;
722 }
723
727
728 if (!list) {
729 return;
730 }
731
734 port = atoi(portstr);
735
737 char buf[35];
738
739 if (pserver->humans >= 0) {
740 fc_snprintf(buf, sizeof(buf), "%d", pserver->humans);
741 } else {
742 sz_strlcpy(buf, _("Unknown"));
743 }
744 gtk_list_store_append(store, &it);
745 gtk_list_store_set(store, &it,
746 0, pserver->host,
747 1, pserver->port,
748 2, pserver->version,
749 3, _(pserver->state),
750 4, pserver->nplayers,
751 5, buf,
752 6, pserver->message,
753 -1);
754 if (strcmp(host, pserver->host) == 0 && port == pserver->port) {
756 }
758}
759
760/**********************************************************************/
764{
765 if (meta_scan.scan) {
768 }
769 if (meta_scan.timer != 0) {
771 meta_scan.timer = 0;
772 }
773 if (lan_scan.scan) {
776 }
777 if (lan_scan.timer != 0) {
779 lan_scan.timer = 0;
780 }
781}
782
783/**********************************************************************/
787{
788 struct server_scan_timer_data *scan_data = data;
789 struct server_scan *scan = scan_data->scan;
791
792 if (!scan) {
793 return FALSE;
794 }
795
796 stat = server_scan_poll(scan);
797 if (stat >= SCAN_STATUS_PARTIAL) {
799 struct srv_list *srvrs;
800
802 srvrs = server_scan_get_list(scan);
803 fc_mutex_allocate(&srvrs->mutex);
807 fc_mutex_release(&srvrs->mutex);
808 }
809
811 scan_data->timer = 0;
812 return FALSE;
813 }
814 return TRUE;
815}
816
817/**********************************************************************/
820static void server_scan_error(struct server_scan *scan,
821 const char *message)
822{
824 log_error("%s", message);
825
826 /* Main thread will finalize the scan later (or even concurrently) -
827 * do not do anything here to cause double free or raze condition. */
828}
829
830/**********************************************************************/
843
844/**************************************************************************
845 Network connection state defines.
846**************************************************************************/
853
855
856/**********************************************************************/
860{
862 char *txt;
863
866 free(txt);
867 }
868
869 return TRUE;
870}
871
872/**********************************************************************/
875static void clear_network_statusbar(void)
876{
878 char *txt;
879
881 free(txt);
882 }
884}
885
886/**********************************************************************/
889void append_network_statusbar(const char *text, bool force)
890{
892 if (force) {
895 } else {
897 }
898 }
899}
900
901/**********************************************************************/
920
921/**********************************************************************/
925{
926 switch (state) {
927 case LOGIN_TYPE:
929
931 "", -1);
933 "", -1);
934
943 break;
948 "", -1);
949
958
960 break;
965 "", -1);
966
975
977 break;
978 case WAITING_TYPE:
980
987 break;
988 }
989
990 connection_status = state;
991}
992
993/**********************************************************************/
1000
1001/**********************************************************************/
1006 const char *message)
1007{
1009
1010 switch (type) {
1011 case AUTH_NEWUSER_FIRST:
1012 case AUTH_NEWUSER_RETRY:
1014 return;
1015 case AUTH_LOGIN_FIRST:
1016 /* if we magically have a password already present in 'fc_password'
1017 * then, use that and skip the password entry dialog */
1018 if (fc_password[0] != '\0') {
1020
1021 sz_strlcpy(reply.password, fc_password);
1023 return;
1024 } else {
1026 }
1027 return;
1028 case AUTH_LOGIN_RETRY:
1030 return;
1031 }
1032
1033 log_error("Unsupported authentication type %d: %s.", type, message);
1034}
1035
1036/**********************************************************************/
1042{
1043 char errbuf [512];
1045
1046 switch (connection_status) {
1047 case LOGIN_TYPE:
1053
1055 errbuf, sizeof(errbuf)) != -1) {
1056 } else {
1058
1060 }
1061 return;
1062 case NEW_PASSWORD_TYPE:
1063 if (w != network_password) {
1066 sz_strlcpy(reply.password,
1068 if (!fc_strncmp(reply.password, fc_password, MAX_LEN_NAME)) {
1069 fc_password[0] = '\0';
1071
1073 } else {
1074 append_network_statusbar(_("Passwords don't match, enter password."),
1075 TRUE);
1076
1078 }
1079 }
1080 return;
1082 sz_strlcpy(reply.password,
1085
1087 return;
1088 case WAITING_TYPE:
1089 return;
1090 }
1091
1092 log_error("Unsupported connection status: %d", connection_status);
1093}
1094
1095/**********************************************************************/
1101 gpointer data)
1102{
1103 connect_callback(NULL, data);
1104}
1105
1106/**********************************************************************/
1110static void update_server_playerlist(const struct server *pserver)
1111{
1112 GtkListStore *store;
1114 int n, i;
1115
1117 fc_assert_ret(store != NULL);
1118
1119 gtk_list_store_clear(store);
1120 if (!pserver || !pserver->players) {
1121 return;
1122 }
1123
1124 n = pserver->nplayers;
1125 for (i = 0; i < n; i++) {
1126 gtk_list_store_append(store, &iter);
1127 gtk_list_store_set(store, &iter,
1128 0, pserver->players[i].name,
1129 1, pserver->players[i].type,
1130 2, pserver->players[i].host,
1131 3, pserver->players[i].nation,
1132 -1);
1133 }
1134}
1135
1136/**********************************************************************/
1140{
1141 GtkTreeModel *model;
1142 GtkTreeIter it;
1143 const char *host;
1144 int port;
1145 char portstr[32];
1146 const struct server *pserver = NULL;
1147
1148 if (!gtk_tree_selection_get_selected(select, &model, &it)) {
1149 return;
1150 }
1151
1152 if (select == meta_selection) {
1153 GtkTreePath *path;
1154 struct srv_list *srvrs;
1155
1157 path = gtk_tree_model_get_path(model, &it);
1159 /* We are not yet inside mutex protected block */
1160 fc_mutex_allocate(&srvrs->mutex);
1161 }
1162 if (srvrs->servers && path) {
1164
1166 }
1168 /* We are not yet inside mutex protected block */
1169 fc_mutex_release(&srvrs->mutex);
1170 }
1171 gtk_tree_path_free(path);
1172 }
1174
1175 gtk_tree_model_get(model, &it, 0, &host, 1, &port, -1);
1176
1178 fc_snprintf(portstr, sizeof(portstr), "%d", port);
1180}
1181
1182/**********************************************************************/
1197
1198/**********************************************************************/
1202{
1203 GtkWidget *box, *sbox, *bbox, *hbox, *notebook;
1204 GtkWidget *button, *label, *view, *sw, *table;
1205 GtkTreeSelection *selection;
1206 GtkListStore *store;
1208
1214
1215 notebook = gtk_notebook_new();
1216 gtk_box_append(GTK_BOX(box), notebook);
1217
1218 /* LAN pane. */
1220 G_TYPE_INT, /* port */
1221 G_TYPE_STRING, /* version */
1222 G_TYPE_STRING, /* state */
1223 G_TYPE_INT, /* nplayers */
1224 G_TYPE_STRING, /* humans */
1225 G_TYPE_STRING); /* message */
1226
1232
1234 lan_selection = selection;
1236
1241
1242 g_signal_connect(view, "row-activated",
1244 g_signal_connect(selection, "changed",
1246
1247 add_treeview_column(view, _("Server Name"), G_TYPE_STRING, 0);
1248 add_treeview_column(view, _("Port"), G_TYPE_INT, 1);
1249 add_treeview_column(view, _("Version"), G_TYPE_STRING, 2);
1250 add_treeview_column(view, _("Status"), G_TYPE_STRING, 3);
1251 add_treeview_column(view, _("Players"), G_TYPE_INT, 4);
1252 add_treeview_column(view, _("Humans"), G_TYPE_STRING, 5);
1253 add_treeview_column(view, _("Comment"), G_TYPE_STRING, 6);
1254
1255 label = gtk_label_new_with_mnemonic(_("Local _Area Network"));
1256
1266 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), sw, label);
1267
1268
1269 /* Metaserver pane. */
1271 G_TYPE_INT, /* port */
1272 G_TYPE_STRING, /* version */
1273 G_TYPE_STRING, /* state */
1274 G_TYPE_INT, /* nplayers */
1275 G_TYPE_STRING, /* humans */
1276 G_TYPE_STRING); /* message */
1277
1283
1285 meta_selection = selection;
1287
1292
1293 g_signal_connect(view, "row-activated",
1295 g_signal_connect(selection, "changed",
1297
1298 add_treeview_column(view, _("Server Name"), G_TYPE_STRING, 0);
1299 add_treeview_column(view, _("Port"), G_TYPE_INT, 1);
1300 add_treeview_column(view, _("Version"), G_TYPE_STRING, 2);
1301 add_treeview_column(view, _("Status"), G_TYPE_STRING, 3);
1302 add_treeview_column(view, _("Players"), G_TYPE_INT, 4);
1303 add_treeview_column(view, _("Humans"), G_TYPE_STRING, 5);
1304 add_treeview_column(view, _("Comment"), G_TYPE_STRING, 6);
1305
1306 label = gtk_label_new_with_mnemonic(_("Internet _Metaserver"));
1307
1318 gtk_notebook_prepend_page(GTK_NOTEBOOK(notebook), sw, label);
1319 } else {
1320 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), sw, label);
1321 }
1322
1323 /* Bottom part of the page, outside the inner notebook. */
1326
1333
1334 table = gtk_grid_new();
1338
1340 g_signal_connect(network_host, "activate",
1343
1345 "use-underline", TRUE,
1346 "mnemonic-widget", network_host,
1347 "label", _("_Host:"),
1348 "xalign", 0.0,
1349 "yalign", 0.5,
1350 NULL);
1351 network_host_label = label;
1352 gtk_grid_attach(GTK_GRID(table), label, 0, 0, 1, 1);
1353
1355 g_signal_connect(network_port, "activate",
1358
1360 "use-underline", TRUE,
1361 "mnemonic-widget", network_port,
1362 "label", _("_Port:"),
1363 "xalign", 0.0,
1364 "yalign", 0.5,
1365 NULL);
1366 network_port_label = label;
1367 gtk_grid_attach(GTK_GRID(table), label, 0, 1, 1, 1);
1368
1371 g_signal_connect(network_login, "activate",
1374
1376 "use-underline", TRUE,
1377 "mnemonic-widget", network_login,
1378 "label", _("_Login:"),
1379 "xalign", 0.0,
1380 "yalign", 0.5,
1381 NULL);
1382 gtk_widget_set_margin_top(label, 10);
1383 network_login_label = label;
1384 gtk_grid_attach(GTK_GRID(table), label, 0, 3, 1, 1);
1385
1391
1393 "use-underline", TRUE,
1394 "mnemonic-widget", network_password,
1395 "label", _("Pass_word:"),
1396 "xalign", 0.0,
1397 "yalign", 0.5,
1398 NULL);
1399 network_password_label = label;
1400 gtk_grid_attach(GTK_GRID(table), label, 0, 4, 1, 1);
1401
1407
1409 "use-underline", TRUE,
1410 "mnemonic-widget", network_confirm_password,
1411 "label", _("Conf_irm Password:"),
1412 "xalign", 0.0,
1413 "yalign", 0.5,
1414 NULL);
1416 gtk_grid_attach(GTK_GRID(table), label, 0, 5, 1, 1);
1417
1418 /* Server player list. */
1424
1430 add_treeview_column(view, _("Nation"), G_TYPE_STRING, 3);
1432
1439
1447
1448 button = gtk_button_new_from_icon_name("view-refresh");
1449 gtk_box_append(GTK_BOX(bbox), button);
1450 g_signal_connect(button, "clicked",
1452
1453 button = gtk_button_new_with_mnemonic(_("_Cancel"));
1454 gtk_box_append(GTK_BOX(bbox), button);
1455 g_signal_connect(button, "clicked",
1457
1458 button = gtk_button_new_with_mnemonic(_("C_onnect"));
1459 gtk_box_append(GTK_BOX(bbox), button);
1460 g_signal_connect(button, "clicked",
1462
1463 return box;
1464}
1465
1466/****************************************************************************
1467 START PAGE
1468****************************************************************************/
1470
1477
1478
1479/* NB: Must match creation arguments in connection_list_store_new(). */
1496
1497/**********************************************************************/
1501{
1503 G_TYPE_INT, /* CL_COL_PLAYER_NUMBER */
1504 G_TYPE_STRING, /* CL_COL_USER_NAME */
1505 G_TYPE_BOOLEAN, /* CL_COL_READY_STATE */
1506 G_TYPE_STRING, /* CL_COL_PLAYER_NAME */
1507 GDK_TYPE_PIXBUF, /* CL_COL_FLAG */
1508 GDK_TYPE_PIXBUF, /* CL_COL_COLOR */
1509 G_TYPE_STRING, /* CL_COL_NATION */
1510 G_TYPE_STRING, /* CL_COL_TEAM */
1511 G_TYPE_INT, /* CL_COL_CONN_ID */
1512 G_TYPE_INT, /* CL_COL_STYLE */
1513 G_TYPE_INT, /* CL_COL_WEIGHT */
1514 G_TYPE_BOOLEAN); /* CL_COL_COLLAPSED */
1515}
1516
1517/**********************************************************************/
1521static void client_aitoggle_player(void *data)
1522{
1523 struct player *pplayer = player_by_number(FC_PTR_TO_INT(data));
1524
1525 if (NULL != pplayer
1526 && pplayer == client_player()
1527 && !is_human(pplayer)) {
1528 send_chat("/away");
1529 }
1530}
1531
1532/**********************************************************************/
1535static void client_take_player(struct player *pplayer)
1536{
1537 int request_id = send_chat_printf("/take \"%s\"", player_name(pplayer));
1538 void *data = FC_INT_TO_PTR(player_number(pplayer));
1539
1542}
1543
1544/**********************************************************************/
1547static void object_put(GObject *object, struct player *pplayer,
1548 struct connection *pconn)
1549{
1550 /* Note that passing -1 to GINT_TO_POINTER() is buggy with some versions
1551 * of gcc. player_slot_count() is not a valid player number. 0 is not
1552 * a valid connection id (see comment in server/sernet.c:
1553 * makeup_connection_name()). */
1554 g_object_set_data(object, "player_id",
1555 GINT_TO_POINTER(NULL != pplayer
1556 ? player_number(pplayer)
1557 : player_slot_count()));
1558 g_object_set_data(object, "connection_id",
1559 GINT_TO_POINTER(NULL != pconn ? pconn->id : 0));
1560}
1561
1562/**********************************************************************/
1566static bool object_extract(GObject *object, struct player **ppplayer,
1567 struct connection **ppconn)
1568{
1569 bool ret = FALSE;
1570 int id;
1571
1572 if (NULL != ppplayer) {
1573 id = GPOINTER_TO_INT(g_object_get_data(object, "player_id"));
1575 if (NULL != *ppplayer) {
1576 ret = TRUE;
1577 }
1578 }
1579 if (NULL != ppconn) {
1580 id = GPOINTER_TO_INT(g_object_get_data(object, "connection_id"));
1581 *ppconn = conn_by_number(id);
1582 if (NULL != *ppconn) {
1583 ret = TRUE;
1584 }
1585 }
1586
1587 return ret;
1588}
1589
1590/**********************************************************************/
1594{
1595 option_dialog_popup(_("Game Settings"), server_optset);
1596}
1597
1598/**********************************************************************/
1602{
1603 enum ai_level *levels = (enum ai_level *)data;
1604 const char *name;
1605 int i;
1606
1608
1609 if (i != -1) {
1610 enum ai_level level = levels[i];
1611
1612 /* Suppress changes provoked by server rather than local user */
1613 if (server_ai_level() != level) {
1615 send_chat_printf("/%s", name);
1616 }
1617 }
1618}
1619
1620/* HACK: sometimes when creating the ruleset combo the value is set without
1621 * the user's control. In this case we don't want to do a /read. */
1623
1624/**********************************************************************/
1627static void ruleset_selected(const char *name)
1628{
1629 if (name && name[0] != '\0' && !no_ruleset_callback) {
1631 }
1632}
1633
1634/**********************************************************************/
1640{
1641 const char *name = NULL;
1642
1644
1645 if (name != NULL) {
1647 }
1648}
1649
1650/**********************************************************************/
1661
1662/**********************************************************************/
1666{
1667 if (start_aifill_spin) {
1668 bool old = send_new_aifill_to_server;
1669 /* Suppress callback from this change to avoid a loop. */
1671 /* HACK: this GUI control doesn't have quite the same semantics as the
1672 * server 'aifill' option, in that it claims to represent the minimum
1673 * number of players _including humans_. The GUI control has a minimum
1674 * value of 1, so aifill == 0 will not be represented correctly.
1675 * But there's generally exactly one human player because the control
1676 * only shows up for a locally spawned server, so we more or less
1677 * get away with this. */
1680 }
1681}
1682
1683/**********************************************************************/
1687{
1689}
1690
1691/**********************************************************************/
1695{
1696 if (conn_popover != NULL){
1699
1701 }
1702}
1703
1704/**********************************************************************/
1708 gpointer data)
1709{
1710 struct player *pplayer;
1711 struct team_slot *tslot = g_object_get_data(G_OBJECT(action), "slot");
1712 GMenu *menu = data;
1713
1714 if (object_extract(G_OBJECT(menu), &pplayer, NULL)
1715 && NULL != tslot
1716 && team_slot_index(tslot) != team_number(pplayer->team)) {
1717 send_chat_printf("/team \"%s\" \"%s\"",
1718 player_name(pplayer),
1720 }
1721
1723}
1724
1725/**********************************************************************/
1729 gpointer data)
1730{
1731 struct player *pplayer;
1732 GMenu *menu = data;
1733
1734 if (object_extract(G_OBJECT(menu), &pplayer, NULL)) {
1736 player_number(pplayer), !pplayer->is_ready);
1737 }
1738
1740}
1741
1742/**********************************************************************/
1746 gpointer data)
1747{
1748 struct player *pplayer;
1749 GMenu *menu = data;
1750
1751 if (object_extract(G_OBJECT(menu), &pplayer, NULL)) {
1752 popup_races_dialog(pplayer);
1753 }
1754
1756}
1757
1758/**********************************************************************/
1763 gpointer data)
1764{
1765 struct player *pplayer;
1766 GMenu *menu = data;
1767
1768 if (object_extract(G_OBJECT(menu), &pplayer, NULL)) {
1769 send_chat_printf("/%s \"%s\"",
1770 (char *) g_object_get_data(G_OBJECT(action), "command"),
1771 player_name(pplayer));
1772 }
1773
1775}
1776
1777/**********************************************************************/
1781 gpointer data)
1782{
1783 struct player *pplayer;
1784 GMenu *menu = data;
1785
1786 if (object_extract(G_OBJECT(menu), &pplayer, NULL)) {
1787 client_take_player(pplayer);
1788 }
1789
1791}
1792
1793/**********************************************************************/
1798 GVariant *parameter, gpointer data)
1799{
1800 struct connection *pconn;
1801 GMenu *menu = data;
1802
1803 if (object_extract(G_OBJECT(menu), NULL, &pconn)) {
1805 (char *) g_object_get_data(G_OBJECT(action), "command"),
1806 pconn->username);
1807 }
1808
1810}
1811
1812/**********************************************************************/
1815static void show_conn_popup(struct player *pplayer, struct connection *pconn)
1816{
1818 char buf[4096] = "";
1819
1820 if (pconn) {
1821 cat_snprintf(buf, sizeof(buf), _("Connection name: %s"),
1822 pconn->username);
1823 } else {
1824 cat_snprintf(buf, sizeof(buf), _("Player name: %s"),
1825 player_name(pplayer));
1826 }
1827 cat_snprintf(buf, sizeof(buf), "\n");
1828 if (pconn) {
1829 cat_snprintf(buf, sizeof(buf), _("Host: %s"), pconn->addr);
1830 }
1831 cat_snprintf(buf, sizeof(buf), "\n");
1832
1833 /* Show popup. */
1836 "%s", buf);
1837 gtk_window_set_title(GTK_WINDOW(popup), _("Player/conn info"));
1841}
1842
1843/**********************************************************************/
1847 gpointer data)
1848{
1849 struct player *pplayer;
1850 struct connection *pconn;
1851 GMenu *menu = data;
1852
1853 if (object_extract(G_OBJECT(menu), &pplayer, &pconn)) {
1854 show_conn_popup(pplayer, pconn);
1855 }
1856
1858}
1859
1860/**********************************************************************/
1864static GtkWidget *create_conn_menu(struct player *pplayer,
1865 struct connection *pconn)
1866{
1867 GMenu *menu;
1868 gchar *buf;
1869 GSimpleAction *act;
1870 GActionGroup *group;
1871
1873
1874 menu = g_menu_new();
1875
1876 object_put(G_OBJECT(menu), pplayer, pconn);
1877
1878 buf = g_strdup_printf(_("%s info"),
1879 pconn ? pconn->username : player_name(pplayer));
1880
1881 act = g_simple_action_new("info", NULL);
1883 g_signal_connect(act, "activate", G_CALLBACK(conn_menu_info_chosen), menu);
1884 menu_item_append_unref(menu, g_menu_item_new(buf, "win.info"));
1885
1886 if (NULL != pplayer) {
1887 act = g_simple_action_new("toggle_ready", NULL);
1889 g_signal_connect(act, "activate", G_CALLBACK(conn_menu_ready_chosen), menu);
1891 menu_item_append_unref(menu, g_menu_item_new(_("Toggle player ready"),
1892 "win.toggle_ready"));
1893
1894 act = g_simple_action_new("pick_nation", NULL);
1896 g_signal_connect(act, "activate", G_CALLBACK(conn_menu_nation_chosen), menu);
1899 pplayer));
1900 menu_item_append_unref(menu, g_menu_item_new(_("Pick nation"), "win.pick_nation"));
1901
1902 act = g_simple_action_new("observe", NULL);
1903 g_object_set_data_full(G_OBJECT(act), "command", g_strdup("observe"),
1906 g_signal_connect(act, "activate", G_CALLBACK(conn_menu_player_command), menu);
1907 menu_item_append_unref(menu, g_menu_item_new(_("Observe this player"),
1908 "win.observe"));
1909
1910 act = g_simple_action_new("take_plr", NULL);
1912 g_signal_connect(act, "activate", G_CALLBACK(conn_menu_player_take), menu);
1913 menu_item_append_unref(menu, g_menu_item_new(_("Take this player"),
1914 "win.take_plr"));
1915 }
1916
1918 && pconn->id != client.conn.id) {
1919 act = g_simple_action_new("cut_conn", NULL);
1920 g_object_set_data_full(G_OBJECT(act), "command", g_strdup("cut"),
1924 menu_item_append_unref(menu, g_menu_item_new(_("Cut connection"), "win.cut_conn"));
1925 }
1926
1927 if (ALLOW_CTRL <= client.conn.access_level && NULL != pplayer) {
1928 act = g_simple_action_new("aitoggle", NULL);
1929 g_object_set_data_full(G_OBJECT(act), "command", g_strdup("aitoggle"),
1933 menu_item_append_unref(menu, g_menu_item_new(_("Aitoggle player"), "win.aitoggle"));
1934
1935 if (pplayer != client.conn.playing && game.info.is_new_game) {
1936 act = g_simple_action_new("remove", NULL);
1937 g_object_set_data_full(G_OBJECT(act), "command", g_strdup("remove"),
1941 menu_item_append_unref(menu, g_menu_item_new(_("Remove player"), "win.remove"));
1942 }
1943 }
1944
1946 && pconn->id != client.conn.id) {
1947 enum cmdlevel level;
1948
1949 /* No item for hack access; that would be a serious security hole. */
1951 char actbuf[128];
1952
1953 buf = g_strdup_printf(_("Give %s access"), cmdlevel_name(level));
1954 fc_snprintf(actbuf, sizeof(actbuf), "cmdlevel_%d", level);
1955
1957 g_object_set_data_full(G_OBJECT(act), "command",
1958 g_strdup_printf("cmdlevel %s",
1963 fc_snprintf(actbuf, sizeof(actbuf), "win.cmdlevel_%d", level);
1965 g_free(buf);
1966 }
1967 }
1968
1970 && NULL != pplayer && is_ai(pplayer)) {
1971 enum ai_level level;
1972
1973 for (level = 0; level < AI_LEVEL_COUNT; level++) {
1975 char actbuf[128];
1976
1977 buf = g_strdup_printf(_("Difficulty: %s"), ai_level_translated_name(level));
1978 fc_snprintf(actbuf, sizeof(actbuf), "ailevel_%d", level);
1979
1981 g_object_set_data_full(G_OBJECT(act), "command",
1985 g_signal_connect(act, "activate", G_CALLBACK(conn_menu_player_command), menu);
1986 fc_snprintf(actbuf, sizeof(actbuf), "win.ailevel_%d", level);
1988 g_free(buf);
1989 }
1990 }
1991 }
1992
1993 if (pplayer != NULL /* && game.info.is_new_game */) {
1994 const int count = pplayer->team
1995 ? player_list_size(team_members(pplayer->team)) : 0;
1996 bool need_empty_team = (count != 1);
1997
1998 /* Can't use team_iterate here since it skips empty teams. */
2000 char actbuf[128];
2001 int id;
2002
2003 if (!team_slot_is_used(tslot)) {
2004 if (!need_empty_team) {
2005 continue;
2006 }
2008 }
2009
2011
2012 /* TRANS: e.g., "Put on Team 5" */
2013 buf = g_strdup_printf(_("Put on %s"),
2015 fc_snprintf(actbuf, sizeof(actbuf), "team_%d", id);
2016
2018 g_object_set_data(G_OBJECT(act), "slot", tslot);
2020 g_signal_connect(act, "activate", G_CALLBACK(conn_menu_team_chosen), menu);
2021 fc_snprintf(actbuf, sizeof(actbuf), "win.team_%d", id);
2023 g_free(buf);
2025 }
2026
2031
2032 return conn_popover;
2033}
2034
2035/**********************************************************************/
2039{
2040 if (NULL != connection_list_view) {
2041 GtkTreeSelection *selection =
2043 GtkTreePath *path = data;
2044
2045 gtk_tree_selection_unselect_path(selection, path);
2046 gtk_tree_path_free(path);
2047 }
2048 return FALSE;
2049}
2050
2051/**********************************************************************/
2055 int n_press,
2056 double x, double y, gpointer data)
2057{
2060 GtkTreePath *path = NULL;
2062
2064 x, y,
2065 &path, NULL, NULL, NULL)) {
2066 return FALSE;
2067 }
2068
2069 if (gtk_tree_selection_path_is_selected(selection, path)) {
2070 /* Need to delay to avoid problem with the expander. */
2072 return FALSE; /* Return now, don't free the path. */
2073 }
2074
2075 gtk_tree_path_free(path);
2076
2077 return FALSE;
2078}
2079
2080/**********************************************************************/
2084 int n_press,
2085 double x, double y, gpointer data)
2086{
2089 GtkWidget *parent = data;
2090 GtkTreePath *path = NULL;
2091 GtkWidget *menu;
2092 GtkTreeSelection *selection;
2093 GtkTreeModel *model;
2095 int player_no, conn_id;
2096 struct player *pplayer;
2097 struct connection *pconn;
2098 int bx, by;
2099 GdkRectangle rect = { .x = x, .y = y, .width = 1, .height = 1};
2100
2102
2104 &path, NULL, NULL, NULL)) {
2105 return FALSE;
2106 }
2107
2110
2111 if (!gtk_tree_selection_path_is_selected(selection, path)) {
2112 gtk_tree_selection_select_path(selection, path);
2113 }
2114 gtk_tree_model_get_iter(model, &iter, path);
2115
2116 gtk_tree_model_get(model, &iter, CL_COL_PLAYER_NUMBER, &player_no, -1);
2117 pplayer = player_by_number(player_no);
2118
2119 gtk_tree_model_get(model, &iter, CL_COL_CONN_ID, &conn_id, -1);
2120 pconn = conn_by_number(conn_id);
2121
2122 menu = create_conn_menu(pplayer, pconn);
2123 gtk_widget_set_parent(menu, parent); /* Gtk bug prevents tree view parenting */
2125
2127
2128 gtk_tree_path_free(path);
2129
2130 return TRUE;
2131}
2132
2133/**********************************************************************/
2138 GtkTreePath *path,
2139 gpointer data)
2140{
2142
2143 gtk_tree_store_set(store, iter,
2145}
2146
2147/**********************************************************************/
2152 struct connection **ppconn)
2153{
2154 if (NULL != connection_list_view) {
2156 GtkTreeModel *model;
2157 GtkTreeSelection *selection =
2159
2160 if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
2161 int id;
2162
2163 if (NULL != ppplayer) {
2164 gtk_tree_model_get(model, &iter, CL_COL_PLAYER_NUMBER, &id, -1);
2166 }
2167 if (NULL != ppconn) {
2168 gtk_tree_model_get(model, &iter, CL_COL_CONN_ID, &id, -1);
2169 *ppconn = conn_by_number(id);
2170 }
2171 return TRUE;
2172 }
2173 }
2174
2175 if (NULL != ppplayer) {
2176 *ppplayer = NULL;
2177 }
2178 if (NULL != ppconn) {
2179 *ppconn = NULL;
2180 }
2181 return FALSE;
2182}
2183
2184/**********************************************************************/
2188{
2189 GtkTreeModel *model;
2190 GtkTreeIter parent, child, *iter = NULL;
2191 GtkTreeSelection *selection;
2192 gboolean valid;
2193 const int search_id = pconn->id;
2194 int id;
2195
2196 if (NULL == connection_list_view) {
2197 return;
2198 }
2199
2202
2203 /* Main iteration. */
2204 valid = gtk_tree_model_get_iter_first(model, &parent);
2205 while (valid && NULL == iter) {
2206 gtk_tree_model_get(model, &parent, CL_COL_CONN_ID, &id, -1);
2207 if (search_id == id) {
2208 iter = &parent;
2209 break;
2210 }
2211
2212 /* Node children iteration. */
2213 valid = gtk_tree_model_iter_children(model, &child, &parent);
2214 while (valid && NULL == iter) {
2215 gtk_tree_model_get(model, &child, CL_COL_CONN_ID, &id, -1);
2216 if (search_id == id) {
2217 iter = &child;
2218 break;
2219 }
2220 valid = gtk_tree_model_iter_next(model, &child);
2221 }
2222
2223 valid = gtk_tree_model_iter_next(model, &parent);
2224 }
2225
2226 /* Select iterator. */
2227 if (NULL != iter) {
2229 } else {
2230 log_error("%s(): connection %s not found.",
2232 }
2233}
2234
2235/**********************************************************************/
2239{
2240 if (can_client_control()) {
2243 !client_player()->is_ready);
2244 } else {
2246 }
2247}
2248
2249/**********************************************************************/
2253{
2254 struct player *selected_plr;
2255 bool row_selected = conn_list_selection(&selected_plr, NULL);
2256
2257 if (row_selected && NULL != selected_plr) {
2258 /* "Take <player_name>" */
2260 } else if (can_client_control()) {
2261 /* "Pick Nation" */
2263 } else {
2264 /* "Take a Player" */
2265 send_chat("/take -");
2266 }
2267}
2268
2269/**********************************************************************/
2273{
2274 struct player *selected_plr;
2275 bool row_selected = conn_list_selection(&selected_plr, NULL);
2276
2277 if (row_selected && NULL != selected_plr) {
2278 /* "Observe <player_name>" */
2279 send_chat_printf("/observe \"%s\"", player_name(selected_plr));
2280 } else if (!client_is_global_observer()) {
2281 /* "Observe" */
2282 send_chat("/observe");
2283 } else {
2284 /* "Do not observe" */
2285 send_chat("/detach");
2286 }
2287}
2288
2289/**********************************************************************/
2293{
2294 char buf[2 * MAX_LEN_NAME];
2295 const char *text;
2296 struct player *selected_plr;
2297 bool row_selected = conn_list_selection(&selected_plr, NULL);
2298 bool sensitive;
2299
2300 /*** Ready button. ***/
2301 if (can_client_control()) {
2302 sensitive = client_player()->is_alive;
2303 if (client_player()->is_ready) {
2304 text = _("Not _ready");
2305 } else {
2306 int num_unready = 0;
2307
2308 players_iterate_alive(pplayer) {
2309 if (is_human(pplayer) && !pplayer->is_ready) {
2310 num_unready++;
2311 }
2313
2314 if (num_unready > 1) {
2315 text = _("_Ready");
2316 } else {
2317 /* We are the last unready player so clicking here will
2318 * immediately start the game. */
2319 text = _("_Start");
2320 }
2321 }
2322 } else {
2323 text = _("_Start");
2324 if (can_client_access_hack()) {
2325 sensitive = TRUE;
2327 if (is_human(plr)) {
2328 /* There's human controlled player(s) in game, so it's their
2329 * job to start the game. */
2330 sensitive = FALSE;
2331 break;
2332 }
2334 } else {
2335 sensitive = FALSE;
2336 }
2337 }
2340
2341 /*** Nation button. ***/
2342 if (row_selected && NULL != selected_plr) {
2343 fc_snprintf(buf, sizeof(buf), _("_Take %s"), player_name(selected_plr));
2344 text = buf;
2346 } else if (can_client_control()) {
2347 text = _("Pick _Nation");
2349 } else {
2350 text = _("_Take a Player");
2352 }
2355
2356 /*** Observe button. ***/
2357 if (row_selected && NULL != selected_plr) {
2358 fc_snprintf(buf, sizeof(buf), _("_Observe %s"),
2360 text = buf;
2362 } else if (!client_is_global_observer()) {
2363 text = _("_Observe");
2364 sensitive = TRUE;
2365 } else {
2366 text = _("Do not _observe");
2367 sensitive = TRUE;
2368 }
2371}
2372
2373/**********************************************************************/
2379 GtkTreeIter *start,
2380 const struct player *pplayer)
2381{
2382 const int search_id = player_number(pplayer);
2383 int id;
2384
2385 if (NULL != start) {
2386 *iter = *start;
2387 if (!gtk_tree_model_iter_next(model, iter)) {
2388 return FALSE;
2389 }
2390 } else if (!gtk_tree_model_get_iter_first(model, iter)) {
2391 return FALSE;
2392 }
2393
2394 do {
2396 if (id == search_id) {
2397 return TRUE;
2398 }
2399 } while (gtk_tree_model_iter_next(model, iter));
2400
2401 return FALSE;
2402}
2403
2404/**********************************************************************/
2410 const struct connection *pconn)
2411{
2412 const int search_id = pconn->id;
2413 int id;
2414
2415 if (NULL != start) {
2416 *iter = *start;
2417 if (!gtk_tree_model_iter_next(model, iter)) {
2418 return FALSE;
2419 }
2420 } else if (!gtk_tree_model_iter_children(model, iter, parent)) {
2421 return FALSE;
2422 }
2423
2424 do {
2425 gtk_tree_model_get(model, iter, CL_COL_CONN_ID, &id, -1);
2426 if (id == search_id) {
2427 return TRUE;
2428 }
2429 } while (gtk_tree_model_iter_next(model, iter));
2430
2431 return FALSE;
2432}
2433
2434/**********************************************************************/
2438{
2443 GtkTreeModel *model = GTK_TREE_MODEL(store);
2444 GtkTreePath *path;
2447 GdkPixbuf *flag, *color;
2449 struct player *pselected_player;
2450 struct connection *pselected_conn;
2451 bool is_ready;
2452 const char *nation, *plr_name, *team;
2453 char name[MAX_LEN_NAME + 8];
2455 int conn_id;
2456
2457 /* Refresh the AI skill level control */
2458 if (ai_lvl_combobox) {
2459 enum ai_level new_level = server_ai_level(), level;
2460 int i = 0;
2461
2462 for (level = 0; level < AI_LEVEL_COUNT; level++) {
2464 if (level == new_level) {
2466 break;
2467 }
2468 i++;
2469 }
2470 }
2471 if (level == AI_LEVEL_COUNT) {
2472 /* Probably ai_level_invalid() */
2474 }
2475 }
2476
2477 /* Save the selected connection. */
2479
2480 /* Insert players into the connection list. */
2481 players_iterate(pplayer) {
2482 if (!player_has_flag(pplayer, PLRF_SCENARIO_RESERVED)) {
2483 conn_id = -1;
2485 flag = pplayer->nation ? get_flag(pplayer->nation) : NULL;
2486 color = create_player_icon(pplayer);
2487
2488 conn_list_iterate(pplayer->connections, pconn) {
2489 if (pconn->playing == pplayer && !pconn->observer) {
2490 conn_id = pconn->id;
2491 access_level = pconn->access_level;
2492 break;
2493 }
2495
2496 if (is_ai(pplayer) && !pplayer->was_created
2497 && !pplayer->is_connected) {
2498 /* TRANS: "<Novice AI>" */
2499 fc_snprintf(name, sizeof(name), _("<%s AI>"),
2500 ai_level_translated_name(pplayer->ai_common.skill_level));
2501 } else {
2502 sz_strlcpy(name, pplayer->username);
2503 if (access_level > ALLOW_BASIC) {
2504 sz_strlcat(name, "*");
2505 }
2506 }
2507
2508 is_ready = !is_human(pplayer) ? TRUE : pplayer->is_ready;
2509
2510 if (pplayer->nation == NO_NATION_SELECTED) {
2511 nation = _("Random");
2512 if (pplayer->was_created) {
2513 plr_name = player_name(pplayer);
2514 } else {
2515 plr_name = "";
2516 }
2517 } else {
2518 nation = nation_adjective_for_player(pplayer);
2519 plr_name = player_name(pplayer);
2520 }
2521
2522 team = pplayer->team ? team_name_translation(pplayer->team) : "";
2523
2524 if (model_get_player_iter(model, &parent, pprev_parent, pplayer)) {
2526 } else {
2528 }
2529
2530 gtk_tree_store_set(store, &parent,
2533 CL_COL_READY_STATE, is_ready,
2535 CL_COL_FLAG, flag,
2537 CL_COL_NATION, nation,
2539 CL_COL_CONN_ID, conn_id,
2542 -1);
2543
2544 /* Insert observers of this player as child nodes. */
2545 pprev_child = NULL;
2546 conn_list_iterate(pplayer->connections, pconn) {
2547 if (pconn->id == conn_id) {
2548 continue;
2549 }
2550 if (model_get_conn_iter(model, &child, &parent,
2551 pprev_child, pconn)) {
2552 gtk_tree_store_move_after(store, &child, pprev_child);
2553 } else {
2555 }
2556
2557 gtk_tree_store_set(store, &child,
2559 CL_COL_USER_NAME, pconn->username,
2560 CL_COL_TEAM, _("Observer"),
2561 CL_COL_CONN_ID, pconn->id,
2564 -1);
2565
2566 prev_child = child;
2569
2570 /* Expand node? */
2571 if (NULL != pprev_child) {
2573 if (!collapsed) {
2574 path = gtk_tree_model_get_path(model, &parent);
2576 path, FALSE);
2577 gtk_tree_path_free(path);
2578 }
2579 }
2580
2581 /* Remove trailing rows. */
2582 if (NULL != pprev_child) {
2583 child = prev_child;
2584 if (gtk_tree_model_iter_next(model, &child)) {
2585 while (gtk_tree_store_remove(store, &child)) {
2586 /* Do nothing more. */
2587 }
2588 }
2589 } else if (gtk_tree_model_iter_children(model, &child, &parent)) {
2590 while (gtk_tree_store_remove(store, &child)) {
2591 /* Do nothing more. */
2592 }
2593 }
2594
2597 if (flag) {
2598 g_object_unref(flag);
2599 }
2600 if (color) {
2602 }
2603 }
2605
2606 /* Finally, insert global observers... */
2608 if (NULL != pconn->playing || !pconn->observer) {
2609 continue;
2610 }
2611
2614 } else {
2616 }
2617
2618 gtk_tree_store_set(store, &parent,
2620 CL_COL_USER_NAME, pconn->username,
2621 CL_COL_TEAM, _("Observer"),
2622 CL_COL_CONN_ID, pconn->id,
2625 -1);
2626
2630
2631 /* ...and detached connections. */
2633 if (NULL != pconn->playing || pconn->observer) {
2634 continue;
2635 }
2636
2639 } else {
2641 }
2642
2643 gtk_tree_store_set(store, &parent,
2645 CL_COL_USER_NAME, pconn->username,
2646 CL_COL_TEAM, _("Detached"),
2647 CL_COL_CONN_ID, pconn->id,
2650 -1);
2651
2655
2656 /* Remove trailing rows. */
2657 if (NULL != pprev_parent) {
2659 if (gtk_tree_model_iter_next(model, &parent)) {
2660 while (gtk_tree_store_remove(store, &parent)) {
2661 /* Do nothing more. */
2662 }
2663 }
2664 } else {
2665 gtk_tree_store_clear(store);
2666 }
2667
2668 /* If we were selecting a single connection, let's try to reselect it. */
2671 }
2672 }
2673
2675}
2676
2677/**********************************************************************/
2683 const char *title, int colnum, const char *key)
2684{
2687
2688 if (gtype == G_TYPE_BOOLEAN) {
2691 "active", colnum, NULL);
2692 } else if (gtype == GDK_TYPE_PIXBUF) {
2695 "pixbuf", colnum, NULL);
2696 } else {
2699 "text", colnum,
2700 "style", CL_COL_STYLE,
2701 "weight", CL_COL_WEIGHT,
2702 NULL);
2703 }
2704
2707
2708 if (key != NULL) {
2710 }
2711}
2712
2713/**********************************************************************/
2717{
2718 GtkWidget *box, *sbox, *table, *vgrid;
2719 GtkWidget *view, *sw, *text, *toolkit_view, *button, *spin;
2720 GtkWidget *label;
2721 GtkTreeSelection *selection;
2722 enum ai_level level;
2723 /* There's less than AI_LEVEL_COUNT entries as not all levels have
2724 entries (that's the whole point of this array: index != value),
2725 but this is set safely to the max */
2726 static enum ai_level levels[AI_LEVEL_COUNT];
2727 int i = 0;
2728 int box_row = 0;
2729 int sbox_col = 0;
2730 int grid_row = 0;
2733
2734 box = gtk_grid_new();
2742
2743 sbox = gtk_grid_new();
2745 gtk_grid_attach(GTK_GRID(box), sbox, 0, box_row++, 1, 1);
2746
2747 vgrid = gtk_grid_new();
2758
2759 table = gtk_grid_new();
2764
2770 if (server_optset != NULL) {
2772 if (paifill) {
2775 } /* else it'll be updated later */
2776 }
2777 g_signal_connect_after(spin, "value_changed",
2779
2780 gtk_grid_attach(GTK_GRID(table), spin, 1, 0, 1, 1);
2781
2783 "use-underline", TRUE,
2784 "mnemonic-widget", spin,
2785 /* TRANS: Keep individual lines short */
2786 "label", _("Number of _Players\n(including AI):"),
2787 "xalign", 0.0,
2788 "yalign", 0.5,
2789 NULL);
2790 gtk_grid_attach(GTK_GRID(table), label, 0, 0, 1, 1);
2791
2793
2794 for (level = 0; level < AI_LEVEL_COUNT; level++) {
2797
2799 levels[i] = level;
2800 i++;
2801 }
2802 }
2805 G_CALLBACK(ai_skill_callback), levels);
2806
2808
2810 "use-underline", TRUE,
2811 "mnemonic-widget", ai_lvl_combobox,
2812 "label", _("AI Skill _Level:"),
2813 "xalign", 0.0,
2814 "yalign", 0.5,
2815 NULL);
2816 gtk_grid_attach(GTK_GRID(table), label, 0, 1, 1, 1);
2817
2821
2823
2825 "use-underline", TRUE,
2826 "mnemonic-widget", GTK_COMBO_BOX_TEXT(ruleset_combo),
2827 "label", _("Ruleset:"),
2828 "xalign", 0.0,
2829 "yalign", 0.5,
2830 NULL);
2831 gtk_grid_attach(GTK_GRID(table), label, 0, 2, 1, 1);
2832
2833 button = icon_label_button_new("preferences-system",
2834 _("_More Game Options..."));
2836 gtk_widget_set_margin_end(button, 8);
2837 gtk_widget_set_margin_start(button, 8);
2838 gtk_widget_set_margin_top(button, 8);
2841 g_signal_connect(button, "clicked",
2843 gtk_grid_attach(GTK_GRID(vgrid), button, 0, grid_row++, 1, 1);
2844
2851
2854 g_signal_connect(selection, "changed",
2856
2857 add_tree_col(view, G_TYPE_STRING, _("Name"),
2859 add_tree_col(view, G_TYPE_BOOLEAN, _("Ready"),
2861 add_tree_col(view, G_TYPE_STRING, Q_("?player:Leader"),
2864 CL_COL_FLAG, NULL);
2865 add_tree_col(view, GDK_TYPE_PIXBUF, _("Border"),
2867 add_tree_col(view, G_TYPE_STRING, _("Nation"),
2869 add_tree_col(view, G_TYPE_STRING, _("Team"),
2870 CL_COL_TEAM, NULL);
2871
2873 g_signal_connect(controller, "pressed",
2876
2877 g_signal_connect(view, "row-collapsed",
2880 g_signal_connect(view, "row-expanded",
2883
2891
2892 /* This is for a workaround against gtk bug that we can't parent
2893 * popup to the tree view - we have to parent it all the way to sw */
2897 g_signal_connect(controller, "pressed",
2900
2901 gtk_grid_attach(GTK_GRID(sbox), sw, sbox_col++, 0, 1, 1);
2902
2908 gtk_grid_attach(GTK_GRID(box), sw, 0, box_row++, 1, 1);
2909
2913 start_message_area = text;
2914 gtk_widget_set_name(text, "chatline");
2919
2920
2921 /* Vote widgets. */
2922 if (pregame_votebar == NULL) {
2924 }
2926
2928 gtk_grid_attach(GTK_GRID(box), toolkit_view, 0, box_row++, 1, 1);
2929
2930 button = gtk_button_new_with_mnemonic(_("_Cancel"));
2932 g_signal_connect(button, "clicked", G_CALLBACK(main_callback), NULL);
2933
2934 nation_button = icon_label_button_new("document-properties",
2935 _("Pick _Nation"));
2939
2940 observe_button = icon_label_button_new("zoom-in", _("_Observe"));
2944
2945 ready_button = icon_label_button_new("system-run", _("_Ready"));
2947 g_signal_connect(ready_button, "clicked",
2949
2950 return box;
2951}
2952
2953
2954/**********************************************************************/
2957void handle_game_load(bool load_successful, const char *filename)
2958{
2959 if (load_successful) {
2961
2962 if (game.info.is_new_game) {
2963 /* It's pregame. Create a player and connect to it */
2964 send_chat("/take -");
2965 }
2966 }
2967}
2968
2969/**********************************************************************/
2972static void load_filename(const char *filename)
2973{
2974 send_chat_printf("/load %s", filename);
2975}
2976
2977/**********************************************************************/
2980static void load_callback(void)
2981{
2982 GtkTreeIter it;
2983 const gchar *filename;
2984
2986 return;
2987 }
2988
2990 SD_COL_FULL_PATH, &filename, -1);
2991 load_filename(filename);
2992}
2993
2994/**********************************************************************/
2998{
2999 save_dialog_file_chooser_popup(_("Choose Saved Game to Load"),
3002}
3003
3004/**********************************************************************/
3007static void update_load_page(void)
3008{
3009 /* Search for user saved games. */
3011 ".sav", FALSE);
3012
3014 fileinfo_list_destroy(files);
3015}
3016
3017/**********************************************************************/
3021{
3022 GtkWidget *box, *sbox, *bbox;
3023
3024 GtkWidget *button, *label, *view, *sw;
3026 int box_row = 0;
3027 int sbox_row = 0;
3028
3029 box = gtk_grid_new();
3037
3042
3045 -1, NULL, rend, "text", 0, NULL);
3046
3049
3051
3052 g_signal_connect(view, "row-activated",
3054
3055 sbox = gtk_grid_new();
3060 gtk_grid_attach(GTK_GRID(box), sbox, 0, box_row++, 1, 1);
3061
3063 "use-underline", TRUE,
3064 "mnemonic-widget", view,
3065 "label", _("Choose Saved Game to _Load:"),
3066 "xalign", 0.0,
3067 "yalign", 0.5,
3068 NULL);
3069 gtk_grid_attach(GTK_GRID(sbox), label, 0, sbox_row++, 1, 1);
3070
3077 gtk_grid_attach(GTK_GRID(sbox), sw, 0, sbox_row++, 1, 1);
3078
3082 gtk_grid_attach(GTK_GRID(box), bbox, 0, box_row++, 1, 1);
3083
3084 button = gtk_button_new_with_mnemonic(_("_Browse..."));
3085 gtk_box_append(GTK_BOX(bbox), button);
3086 g_signal_connect(button, "clicked",
3088
3089 button = gtk_button_new_with_mnemonic(_("_Cancel"));
3090 gtk_box_append(GTK_BOX(bbox), button);
3091 g_signal_connect(button, "clicked",
3093
3094 button = gtk_button_new_with_mnemonic(_("_OK"));
3095 gtk_box_append(GTK_BOX(bbox), button);
3096 g_signal_connect(button, "clicked",
3098
3099 return box;
3100}
3101
3102/**********************************************************************/
3105static void scenario_list_callback(void)
3106{
3107 GtkTreeIter it;
3108 GtkTextBuffer *buffer;
3109 char *description;
3110 char *authors;
3111 char *filename;
3112 int ver;
3113 char vername[50];
3114
3117 2, &description, -1);
3119 3, &authors, -1);
3121 1, &filename, -1);
3123 4, &ver, -1);
3124 filename = skip_to_basename(filename);
3125 if (ver > 0) {
3126 int maj;
3127 int min;
3128
3129 maj = ver / 1000000;
3130 ver %= 1000000;
3131 min = ver / 10000;
3132 ver %= 10000;
3133 if (ver >= 9000) {
3134 /* Development version, have '+' */
3135 fc_snprintf(vername, sizeof(vername), "%d.%d+", maj, min);
3136 } else {
3137 fc_snprintf(vername, sizeof(vername), "%d.%d", maj, min);
3138 }
3139 } else {
3140 /* TRANS: Old scenario format version */
3141 fc_snprintf(vername, sizeof(vername), _("pre-2.6"));
3142 }
3143 } else {
3144 description = "";
3145 authors = "";
3146 filename = "";
3147 vername[0] = '\0';
3148 }
3149
3151 gtk_text_buffer_set_text(buffer, description, -1);
3153 gtk_text_buffer_set_text(buffer, authors, -1);
3156}
3157
3158/**********************************************************************/
3161static void scenario_callback(void)
3162{
3163 GtkTreeIter it;
3164 char *filename;
3165
3167 return;
3168 }
3169
3170 gtk_tree_model_get(GTK_TREE_MODEL(scenario_store), &it, 1, &filename, -1);
3171 load_filename(filename);
3172}
3173
3174/**********************************************************************/
3178{
3179 save_dialog_file_chooser_popup(_("Choose a Scenario"),
3182}
3183
3184/**********************************************************************/
3187static void update_scenario_page(void)
3188{
3189 struct fileinfo_list *files;
3190
3192
3193 /* search for scenario files. */
3194 files = fileinfolist_infix(get_scenario_dirs(), ".sav", TRUE);
3196 struct section_file *sf;
3197
3198 if ((sf = secfile_load_section(pfile->fullname, "scenario", TRUE))
3199 && secfile_lookup_bool_default(sf, TRUE, "scenario.is_scenario")) {
3200 const char *sname, *sdescription, *sauthors;
3201 int fcver;
3202 int fcdev;
3203 int current_ver = MAJOR_VERSION * 1000000 + MINOR_VERSION * 10000;
3204 int current_dev;
3205
3207 if (PATCH_VERSION >= 90) {
3208 /* Patch level matters on development versions */
3209 current_dev += PATCH_VERSION * 100;
3210 }
3211
3212 fcver = secfile_lookup_int_default(sf, 0, "scenario.game_version");
3213 if (fcver < 30000) {
3214 /* Pre-3.0 versions stored version number without emergency version
3215 * part in the end. To get comparable version number stored,
3216 * multiply by 100. */
3217 fcver *= 100;
3218 }
3219 if (fcver % 10000 >= 9000) {
3220 fcdev = fcver - (fcver % 100); /* Emergency version does not count. */
3221 } else {
3222 fcdev = fcver - (fcver % 10000); /* Patch version does not count. */
3223 }
3224 sname = secfile_lookup_str_default(sf, NULL, "scenario.name");
3226 "scenario.description");
3227 sauthors = secfile_lookup_str_default(sf, NULL, "scenario.authors");
3228 log_debug("scenario file: %s from %s", sname, pfile->fullname);
3229
3230 /* Ignore scenarios for newer freeciv versions than we are. */
3231 if (fcdev <= current_dev) {
3232 bool add_new = TRUE;
3233
3234 if (sname != NULL) {
3235 GtkTreeIter it;
3236 bool valid;
3237
3239 while (valid) {
3240 char *oname;
3241
3243 0, &oname, -1);
3244
3245 if (!strcmp(sname, oname)) {
3246 /* Already listed scenario has the same name as the one we just found */
3247 int existing;
3248
3250 4, &existing, -1);
3251 log_debug("Duplicate %s (%d vs %d)", sname, existing, fcver);
3252
3253 if (existing > fcver) {
3254 /* Already listed one has higher version number */
3255 add_new = FALSE;
3256 } else if (existing < fcver) {
3257 /* New one has higher version number */
3258 add_new = FALSE;
3259
3261 0, sname && strlen(sname) ? Q_(sname) : pfile->name,
3262 1, pfile->fullname,
3263 2, (NULL != sdescription && '\0' != sdescription[0]
3264 ? Q_(sdescription) : ""),
3265 3, (NULL != sauthors && sauthors[0] != '\0'
3266 ? Q_(sauthors) : ""),
3267 4, fcver,
3268 -1);
3269 } else {
3270 /* Same version number -> list both */
3271 }
3272 }
3274 }
3275 }
3276
3277 if (add_new) {
3278 GtkTreeIter it;
3279
3282 0, sname && strlen(sname) ? Q_(sname) : pfile->name,
3283 1, pfile->fullname,
3284 2, (NULL != sdescription && '\0' != sdescription[0]
3285 ? Q_(sdescription) : ""),
3286 3, (NULL != sauthors && sauthors[0] != '\0'
3287 ? Q_(sauthors) : ""),
3288 4, fcver,
3289 -1);
3290 }
3291 }
3292
3293 secfile_destroy(sf);
3294 }
3296
3297 fileinfo_list_destroy(files);
3298}
3299
3300/**********************************************************************/
3304{
3307 GtkWidget *button, *label, *view, *sw, *swa, *text;
3309 int grid_row = 0;
3310 int filenamecol = 0;
3311 int vercol = 0;
3312 int descrow = 0;
3313
3314 vgrid = gtk_grid_new();
3322
3327 G_TYPE_INT);
3332
3335 -1, NULL, rend, "text", 0, NULL);
3336
3341
3343
3344 g_signal_connect(view, "row-activated",
3346
3348 "use-underline", TRUE,
3349 "mnemonic-widget", view,
3350 "label", _("Choose a _Scenario:"),
3351 "xalign", 0.0,
3352 "yalign", 0.5,
3353 NULL);
3354 gtk_grid_attach(GTK_GRID(vgrid), label, 0, grid_row++, 1, 1);
3355
3356 sbox = gtk_grid_new();
3363
3364 hbox = gtk_grid_new();
3367
3373 gtk_grid_attach(GTK_GRID(sbox), sw, 0, 0, 1, 2);
3374
3375 text = gtk_text_view_new();
3381 scenario_description = text;
3382
3388
3389 text = gtk_text_view_new();
3395 scenario_authors = text;
3396
3402
3403 text = gtk_label_new(_("Filename:"));
3408
3415
3416 gtk_grid_attach(GTK_GRID(filenamebox), text, filenamecol++, 0, 1, 1);
3418 filenamecol++, 0, 1, 1);
3419
3420 /* TRANS: Scenario format version */
3421 vertext = gtk_label_new(_("Format:"));
3426
3433
3436 vercol++, 0, 1, 1);
3437
3442 gtk_grid_attach(GTK_GRID(descbox), sw, 0, descrow++, 1, 1);
3445 0, descrow++, 1, 1);
3447 0, descrow++, 1, 1);
3448 gtk_grid_attach(GTK_GRID(sbox), descbox, 1, 0, 1, 2);
3449
3453
3454 button = gtk_button_new_with_mnemonic(_("_Browse..."));
3455 gtk_box_append(GTK_BOX(bbox), button);
3456 g_signal_connect(button, "clicked",
3458
3459 button = gtk_button_new_with_mnemonic(_("_Cancel"));
3460 gtk_box_append(GTK_BOX(bbox), button);
3461 g_signal_connect(button, "clicked",
3463
3464 button = gtk_button_new_with_mnemonic(_("_OK"));
3465 gtk_box_append(GTK_BOX(bbox), button);
3466 g_signal_connect(button, "clicked",
3468
3469 return vgrid;
3470}
3471
3472/**********************************************************************/
3476{
3477 return current_page;
3478}
3479
3480/**********************************************************************/
3484{
3485 /* Don't use current_page directly here because maybe it could be modified
3486 * before we reach the end of this function. */
3488
3489 /* If the page remains the same, don't do anything. */
3490 if (old_page == new_page) {
3491 return;
3492 }
3493
3494 log_debug("Switching client page from %s to %s.",
3495 -1 == old_page ? "(no page)" : client_pages_name(old_page),
3497
3499
3500 switch (old_page) {
3501 case PAGE_SCENARIO:
3502 case PAGE_LOAD:
3503 break;
3504 case PAGE_GAME:
3505 {
3507
3509 if (vmode == NULL) {
3511 }
3512 }
3513 break;
3514 default:
3515 break;
3516 }
3517
3518 switch (new_page) {
3519 case PAGE_MAIN:
3520 case PAGE_START:
3521 if (is_server_running()) {
3524 } else {
3526 }
3530 break;
3531 case PAGE_GAME:
3532 {
3534
3537 if (vmode == NULL) {
3539 }
3542 }
3543 break;
3544 case PAGE_LOAD:
3546 break;
3547 case PAGE_SCENARIO:
3549 break;
3550 case PAGE_NETWORK:
3552 break;
3553 }
3554
3555 /* Hide/show statusbar. */
3556 if (new_page == PAGE_START || new_page == PAGE_GAME) {
3559 } else {
3561 }
3562
3564
3565 /* Update the GUI. */
3566 while (g_main_context_pending(NULL)) {
3568 }
3569
3570 switch (new_page) {
3571 case PAGE_MAIN:
3572 break;
3573 case PAGE_START:
3576 break;
3577 case PAGE_LOAD:
3579 break;
3580 case PAGE_SCENARIO:
3582 break;
3583 case PAGE_GAME:
3587 mapview_thaw();
3590 break;
3591 case PAGE_NETWORK:
3596 break;
3597 }
3598}
3599
3600/****************************************************************************
3601 SAVE GAME DIALOGs
3602****************************************************************************/
3603
3604/**********************************************************************/
3608{
3609 return fileinfolist_infix(get_save_dirs(), ".sav", FALSE);
3610}
3611
3612/**********************************************************************/
3616{
3617 static GtkWidget *shell = NULL;
3618
3619 if (NULL != shell) {
3620 return;
3621 }
3622
3623 shell = save_dialog_new(_("Save Game"), _("Saved _Games:"),
3624 _("Save _Filename:"), send_save_game,
3627 &shell);
3629}
3630
3631/**********************************************************************/
3634static void save_dialog_save_scenario(const char *filename)
3635{
3637}
3638
3639/**********************************************************************/
3643{
3644 return fileinfolist_infix(get_scenario_dirs(), ".sav", FALSE);
3645}
3646
3647/**********************************************************************/
3651{
3652 static GtkWidget *shell = NULL;
3653
3654 if (NULL != shell) {
3655 return;
3656 }
3657
3658 shell = save_dialog_new(_("Save Scenario"), _("Saved Sce_narios:"),
3659 _("Save Sc_enario:"), save_dialog_save_scenario,
3662 &shell);
3664}
3665
3666/**********************************************************************/
3672{
3673 return fileinfolist_infix(get_save_dirs(), ".map", FALSE);
3674}
3675
3676/**********************************************************************/
3680{
3681 static GtkWidget *shell = NULL;
3682
3683 if (NULL != shell) {
3684 return;
3685 }
3686
3687 shell = save_dialog_new(_("Save Map Image"), _("Saved Map _Images:"),
3688 _("Save _Map Images:"), mapimg_client_save,
3691 &shell);
3693}
3694
3695/**********************************************************************/
3698void mapimg_client_save(const char *filename)
3699{
3700 if (!mapimg_client_createmap(filename)) {
3701 char msg[512];
3702
3703 fc_snprintf(msg, sizeof(msg), "(%s)", mapimg_error());
3704 popup_notify_dialog(_("Error"),
3705 _("Error Creating the Map Image!"), msg);
3706 }
3707}
3708
3709/**********************************************************************/
3714void set_rulesets(int num_rulesets, char **rulesets)
3715{
3716 int i;
3717 int def_idx = -1;
3718
3720 for (i = 0; i < num_rulesets; i++) {
3721
3723 if (!strcmp("default", rulesets[i])) {
3724 def_idx = i;
3725 }
3726 }
3727
3729
3730 /* HACK: server should tell us the current ruleset. */
3732
3734}
#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
#define SERVER_COMMAND_PREFIX_STR
Definition chat.h:29
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
#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 add_idle_callback(void(callback)(void *), void *data)
Definition gui_main.c:2427
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 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
gboolean terminate_signal_processing(GtkEventControllerFocus *controller, gpointer data)
Definition gui_main.c:1050
void animation_idle_cb(void *data)
Definition gui_main.c:2436
void main_message_area_resize(void *data)
Definition gui_main.c:368
void widget_destroyed(GtkWidget *wdg, void *data)
Definition gui_stuff.c:1154
#define menu_item_append_unref(menu, item)
Definition gui_stuff.h:149
static gboolean connect_list_right_button(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data)
Definition pages.c:2083
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 void close_conn_menu_popover(void)
Definition pages.c:1694
static gboolean connect_list_left_button(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data)
Definition pages.c:2054
static GtkWidget * conn_popover
Definition pages.c:97
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 y
Definition sprite_g.h:31
struct sprite int int int int struct sprite int int float scale
Definition sprite_g.h:33
struct sprite int x
Definition sprite_g.h:31
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
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
struct team * team_slot_get_team(const struct team_slot *tslot)
Definition team.c:150
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