Freeciv-3.3
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 caught through 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;
173 static int pwidth, pheight;
174 static bool left = FALSE;
176 struct sprite *intro = (struct sprite *)data;
177
178 cairo_set_source_surface(cr, intro->surface, 0, 0);
179 cairo_paint(cr);
180
181 if (!layout) {
182 char msgbuf[128];
183 const char *rev_ver;
184
186 desc = pango_font_description_from_string("Sans Bold 10");
189
191
192 if (rev_ver == NULL) {
193 /* TRANS: "version 2.6.0, gui-gtk-3.22 client" */
194 fc_snprintf(msgbuf, sizeof(msgbuf), _("%s%s, %s client"),
196 } else {
197 /* TRANS: "version 2.6.0
198 * commit: [modified] <git commit id>
199 * gui-gtk-3.22 client" */
200 fc_snprintf(msgbuf, sizeof(msgbuf), _("%s%s\ncommit: %s\n%s client"),
202 left = TRUE;
203 }
205
207 }
209
210 cairo_set_source_rgb(cr, 0, 0, 0);
211 cairo_move_to(cr, left ? 4 : allocation.width - pwidth - 3,
212 allocation.height - pheight - 3);
214
215 cairo_set_source_rgb(cr, 1, 1, 1);
216 cairo_move_to(cr, left ? 3 : allocation.width - pwidth - 4,
217 allocation.height - pheight - 4);
219}
220
221/**********************************************************************/
224static void intro_free(GtkWidget *w, gpointer *data)
225{
226 struct sprite *intro = (struct sprite *)data;
227
229}
230
231/**********************************************************************/
235{
236 GtkWidget *widget, *vgrid, *frame, *darea, *button, *table;
238 struct sprite *intro_in, *intro;
239 int width, height;
240 int sh;
241 int space_needed;
242 int grid_row = 0;
243
245
249 widget = vgrid;
250
251 frame = gtk_frame_new(NULL);
253 gtk_widget_set_margin_end(frame, 18);
255 gtk_widget_set_margin_top(frame, 18);
257 gtk_grid_attach(GTK_GRID(vgrid), frame, 0, grid_row++, 1, 1);
258
261 sh = screen_height();
262
263 if (sh <= 0) {
264 /* Assume some minimum height */
265 sh = 600;
266 }
267
268 space_needed = 250;
269#if IS_BETA_VERSION || IS_DEVEL_VERSION
270 /* Alpha or Beta notice takes extra space */
271 space_needed += 50;
272#endif
273
274 if (sh - height < space_needed) {
275 float scale;
276
277 if (sh < (space_needed + 0.2 * height)) {
278 /* Screen is simply too small, use minimum scale */
279 scale = 0.2;
280 } else {
281 scale = (double)(sh - space_needed) / height;
282 }
283 height *= scale;
284 width *= scale;
287 } else {
288 intro = intro_in;
289 }
290 darea = gtk_drawing_area_new();
294 g_signal_connect(widget, "destroy",
296 gtk_frame_set_child(GTK_FRAME(frame), darea);
297
298#if IS_BETA_VERSION || IS_DEVEL_VERSION
299 {
300 GtkWidget *label;
301
303 gtk_widget_set_name(label, "beta_label");
307 gtk_grid_attach(GTK_GRID(vgrid), label, 0, grid_row++, 1, 1);
308 }
309#endif /* IS_BETA_VERSION || IS_DEVEL_VERSION */
310
320
324
325 button = gtk_button_new_with_mnemonic(_("Start _New Game"));
327 gtk_grid_attach(GTK_GRID(table), button, 0, 0, 1, 1);
329 _("Launches local server, and connects to it for a single-player game."));
330 g_signal_connect(button, "clicked",
332
333 button = gtk_button_new_with_mnemonic(_("Start _Scenario Game"));
335 gtk_grid_attach(GTK_GRID(table), button, 0, 1, 1, 1);
337 _("Loads one of the scenarios for a single-player game. "
338 "Tutorial is one of the scenarios."));
339 g_signal_connect(button, "clicked",
341
342 button = gtk_button_new_with_mnemonic(_("_Load Saved Game"));
344 gtk_grid_attach(GTK_GRID(table), button, 0, 2, 1, 1);
346 _("Continues previously saved single-player game."));
347 g_signal_connect(button, "clicked",
349
350 button = gtk_button_new_with_mnemonic(_("C_onnect to Network Game"));
352 gtk_grid_attach(GTK_GRID(table), button, 1, 0, 1, 1);
354 _("Connects to outside server. "
355 "Sometimes you want to launch a separate server even for local games."));
356 g_signal_connect(button, "clicked",
358
359 button = gtk_button_new_with_mnemonic(_("Client Settings"));
361 gtk_grid_attach(GTK_GRID(table), button, 1, 1, 1, 1);
363 _("Adjusting client-side options."));
364 g_signal_connect(button, "clicked", open_settings, NULL);
365
366 button = icon_label_button_new("application-exit", _("E_xit"));
369 gtk_grid_attach(GTK_GRID(table), button, 1, 2, 1, 1);
371 _("Gives you a break from playing freeciv."));
372 g_signal_connect(button, "clicked",
374
375 return widget;
376}
377
378/****************************************************************************
379 GENERIC SAVE DIALOG
380****************************************************************************/
381typedef void (*save_dialog_action_fn_t) (const char *filename);
382typedef struct fileinfo_list * (*save_dialog_files_fn_t) (void);
383
384struct save_dialog {
390};
391
398
404
405/**********************************************************************/
409{
411 G_TYPE_STRING, /* SD_COL_PRETTY_NAME */
412 G_TYPE_STRING); /* SD_COL_FULL_PATH */
413}
414
415/**********************************************************************/
419 const struct fileinfo_list *files)
420{
422
426 gtk_list_store_set(store, &iter,
428 SD_COL_FULL_PATH, pfile->fullname,
429 -1);
431}
432
433/**********************************************************************/
436static void save_dialog_update(struct save_dialog *pdialog)
437{
438 struct fileinfo_list *files;
439
440 fc_assert_ret(NULL != pdialog);
441
442 /* Update the store. */
443 files = pdialog->files();
446 files);
448}
449
450/**********************************************************************/
454 gint response, gpointer data)
455{
456 if (response == GTK_RESPONSE_OK) {
459
460 if (file != NULL) {
461 gchar *filename = g_file_get_parse_name(file);
462
463 if (NULL != filename) {
464 action(filename);
465 g_free(filename);
466 }
467
468 g_object_unref(file);
469 }
470 }
471
473}
474
475/**********************************************************************/
478static void save_dialog_file_chooser_popup(const char *title,
481{
483
484 /* Create the chooser */
486 _("_Cancel"), GTK_RESPONSE_CANCEL,
488 _("_Save") : _("_Open"),
491
492 g_signal_connect(filechoose, "response",
494
495 /* Display that dialog */
497}
498
499/**********************************************************************/
503 gpointer data)
504{
505 struct save_dialog *pdialog = data;
506
507 switch (response) {
508 case SD_RES_BROWSE:
509 save_dialog_file_chooser_popup(_("Select Location to Save"),
511 pdialog->action);
512 break;
513 case SD_RES_DELETE:
514 {
515 GtkTreeSelection *selection;
516 GtkTreeModel *model;
518 const gchar *full_path;
519
520 selection = gtk_tree_view_get_selection(pdialog->tree_view);
521 if (!gtk_tree_selection_get_selected(selection, &model, &iter)) {
522 return;
523 }
524
525 gtk_tree_model_get(model, &iter, SD_COL_FULL_PATH, &full_path, -1);
526 fc_remove(full_path);
527 save_dialog_update(pdialog);
528 }
529 return;
530 case SD_RES_SAVE:
531 {
532 const char *text = gtk_entry_buffer_get_text(gtk_entry_get_buffer(pdialog->entry));
533 gchar *filename = g_filename_from_utf8(text, -1, NULL, NULL, NULL);
534
535 if (NULL == filename) {
536 return;
537 }
538 pdialog->action(filename);
539 g_free(filename);
540 }
541 break;
542 default:
543 break;
544 }
545
547}
548
549/**********************************************************************/
559
560/**********************************************************************/
567
568/**********************************************************************/
572 gpointer data)
573{
574 struct save_dialog *pdialog = data;
575 GtkTreeModel *model;
577 const gchar *filename;
578
579 if (!gtk_tree_selection_get_selected(selection, &model, &iter)) {
581 return;
582 }
583
585 gtk_tree_model_get(model, &iter, SD_COL_PRETTY_NAME, &filename, -1);
587}
588
589/**********************************************************************/
592static GtkWidget *save_dialog_new(const char *title, const char *savelabel,
593 const char *savefilelabel,
596{
597 GtkWidget *shell, *sbox, *sw, *label, *view, *entry;
598 GtkBox *vbox;
599 GtkListStore *store;
601 GtkTreeSelection *selection;
602 struct save_dialog *pdialog;
603
606
607 /* Save dialog structure. */
608 pdialog = fc_malloc(sizeof(*pdialog));
609 pdialog->action = action;
610 pdialog->files = files;
611
612 /* Shell. */
614 _("_Browse..."), SD_RES_BROWSE,
615 _("_Delete"), SD_RES_DELETE,
616 _("_Cancel"), GTK_RESPONSE_CANCEL,
617 _("_Save"), SD_RES_SAVE,
618 NULL);
619 g_object_set_data_full(G_OBJECT(shell), "save_dialog", pdialog,
624 g_signal_connect(shell, "response",
626 pdialog->shell = GTK_DIALOG(shell);
628
629 /* Tree view. */
630 store = save_dialog_store_new();
634 g_object_unref(store);
636 g_signal_connect(view, "row-activated",
638 pdialog->tree_view = GTK_TREE_VIEW(view);
639
641 gtk_box_append(vbox, sbox);
642
644 "use-underline", TRUE,
645 "mnemonic-widget", view,
646 "label", savelabel,
647 "xalign", 0.0,
648 "yalign", 0.5,
649 NULL);
650 gtk_box_append(GTK_BOX(sbox), label);
651
660
663 g_signal_connect(selection, "changed",
665
668 -1, NULL, rend, "text",
670
671 /* Entry. */
674 g_signal_connect(entry, "activate",
676 pdialog->entry = GTK_ENTRY(entry);
677
683
685 "use-underline", TRUE,
686 "mnemonic-widget", entry,
687 "label", savefilelabel,
688 "xalign", 0.0,
689 "yalign", 0.5,
690 NULL);
691 gtk_box_append(GTK_BOX(sbox), label);
692
694 gtk_box_append(vbox, sbox);
695
696 save_dialog_update(pdialog);
699
700 return shell;
701}
702
703/****************************************************************************
704 NETWORK PAGE
705****************************************************************************/
711
712/**********************************************************************/
716 const struct server_list *list)
717{
720 GtkTreeIter it;
721 GtkListStore *store;
722 const gchar *host, *portstr;
723 int port;
724
725 switch (sstype) {
728 break;
731 break;
732 default:
733 break;
734 }
735
736 if (!sel) {
737 return;
738 }
739
743
744 if (!list) {
745 return;
746 }
747
750 port = atoi(portstr);
751
753 char buf[35];
754
755 if (pserver->humans >= 0) {
756 fc_snprintf(buf, sizeof(buf), "%d", pserver->humans);
757 } else {
758 sz_strlcpy(buf, _("Unknown"));
759 }
760 gtk_list_store_append(store, &it);
761 gtk_list_store_set(store, &it,
762 0, pserver->host,
763 1, pserver->port,
764 2, pserver->version,
765 3, _(pserver->state),
766 4, pserver->nplayers,
767 5, buf,
768 6, pserver->message,
769 -1);
770 if (strcmp(host, pserver->host) == 0 && port == pserver->port) {
772 }
774}
775
776/**********************************************************************/
780{
781 if (meta_scan.scan) {
784 }
785 if (meta_scan.timer != 0) {
787 meta_scan.timer = 0;
788 }
789 if (lan_scan.scan) {
792 }
793 if (lan_scan.timer != 0) {
795 lan_scan.timer = 0;
796 }
797}
798
799/**********************************************************************/
803{
804 struct server_scan_timer_data *scan_data = data;
805 struct server_scan *scan = scan_data->scan;
807
808 if (!scan) {
809 return FALSE;
810 }
811
812 stat = server_scan_poll(scan);
813 if (stat >= SCAN_STATUS_PARTIAL) {
815 struct srv_list *srvrs;
816
818 srvrs = server_scan_get_list(scan);
819 fc_mutex_allocate(&srvrs->mutex);
823 fc_mutex_release(&srvrs->mutex);
824 }
825
827 scan_data->timer = 0;
828 return FALSE;
829 }
830 return TRUE;
831}
832
833/**********************************************************************/
836static void server_scan_error(struct server_scan *scan,
837 const char *message)
838{
840 log_error("%s", message);
841
842 /* Main thread will finalize the scan later (or even concurrently) -
843 * do not do anything here to cause double free or raze condition. */
844}
845
846/**********************************************************************/
859
860/**************************************************************************
861 Network connection state defines.
862**************************************************************************/
869
871
872/**********************************************************************/
876{
878 char *txt;
879
882 free(txt);
883 }
884
885 return TRUE;
886}
887
888/**********************************************************************/
891static void clear_network_statusbar(void)
892{
894 char *txt;
895
897 free(txt);
898 }
899
901}
902
903/**********************************************************************/
906void append_network_statusbar(const char *text, bool force)
907{
909 if (force) {
912 } else {
914 }
915 }
916}
917
918/**********************************************************************/
937
938/**********************************************************************/
942{
943 switch (state) {
944 case LOGIN_TYPE:
946
948 "", -1);
950 "", -1);
951
960 break;
965 "", -1);
966
975
977 break;
982 "", -1);
983
992
994 break;
995 case WAITING_TYPE:
997
1004 break;
1005 }
1006
1007 connection_status = state;
1008}
1009
1010/**********************************************************************/
1013static void connection_state_reset(void)
1014{
1016}
1017
1018/**********************************************************************/
1023 const char *message)
1024{
1026
1027 switch (type) {
1028 case AUTH_NEWUSER_FIRST:
1029 case AUTH_NEWUSER_RETRY:
1031 return;
1032 case AUTH_LOGIN_FIRST:
1033 /* if we magically have a password already present in 'fc_password'
1034 * then, use that and skip the password entry dialog */
1035 if (fc_password[0] != '\0') {
1037
1038 sz_strlcpy(reply.password, fc_password);
1040 return;
1041 } else {
1043 }
1044 return;
1045 case AUTH_LOGIN_RETRY:
1047 return;
1048 }
1049
1050 log_error("Unsupported authentication type %d: %s.", type, message);
1051}
1052
1053/**********************************************************************/
1059{
1060 char errbuf [512];
1062
1063 switch (connection_status) {
1064 case LOGIN_TYPE:
1070
1072 errbuf, sizeof(errbuf)) != -1) {
1073 } else {
1075
1077 }
1078 return;
1079 case NEW_PASSWORD_TYPE:
1080 if (w != network_password) {
1083 sz_strlcpy(reply.password,
1085 if (!fc_strncmp(reply.password, fc_password, MAX_LEN_NAME)) {
1086 fc_password[0] = '\0';
1088
1090 } else {
1091 append_network_statusbar(_("Passwords don't match, enter password."),
1092 TRUE);
1093
1095 }
1096 }
1097 return;
1099 sz_strlcpy(reply.password,
1102
1104 return;
1105 case WAITING_TYPE:
1106 return;
1107 }
1108
1109 log_error("Unsupported connection status: %d", connection_status);
1110}
1111
1112/**********************************************************************/
1118 gpointer data)
1119{
1120 connect_callback(NULL, data);
1121}
1122
1123/**********************************************************************/
1127static void update_server_playerlist(const struct server *pserver)
1128{
1129 GtkListStore *store;
1131 int n, i;
1132
1134 fc_assert_ret(store != NULL);
1135
1136 gtk_list_store_clear(store);
1137 if (!pserver || !pserver->players) {
1138 return;
1139 }
1140
1141 n = pserver->nplayers;
1142 for (i = 0; i < n; i++) {
1143 gtk_list_store_append(store, &iter);
1144 gtk_list_store_set(store, &iter,
1145 0, pserver->players[i].name,
1146 1, pserver->players[i].type,
1147 2, pserver->players[i].host,
1148 3, pserver->players[i].nation,
1149 -1);
1150 }
1151}
1152
1153/**********************************************************************/
1157{
1158 GtkTreeModel *model;
1159 GtkTreeIter it;
1160 const char *host;
1161 int port;
1162 char portstr[32];
1163 const struct server *pserver = NULL;
1164
1165 if (!gtk_tree_selection_get_selected(select, &model, &it)) {
1166 return;
1167 }
1168
1169 if (select == meta_selection) {
1170 GtkTreePath *path;
1171 struct srv_list *srvrs;
1172
1174 path = gtk_tree_model_get_path(model, &it);
1176 /* We are not yet inside mutex protected block */
1177 fc_mutex_allocate(&srvrs->mutex);
1178 }
1179 if (srvrs->servers && path) {
1181
1183 }
1185 /* We are not yet inside mutex protected block */
1186 fc_mutex_release(&srvrs->mutex);
1187 }
1188 gtk_tree_path_free(path);
1189 }
1191
1192 gtk_tree_model_get(model, &it, 0, &host, 1, &port, -1);
1193
1195 fc_snprintf(portstr, sizeof(portstr), "%d", port);
1197}
1198
1199/**********************************************************************/
1214
1215/**********************************************************************/
1219{
1220 GtkWidget *box, *sbox, *bbox, *hbox, *notebook;
1221 GtkWidget *button, *label, *view, *sw, *table;
1222 GtkTreeSelection *selection;
1223 GtkListStore *store;
1225
1231
1232 notebook = gtk_notebook_new();
1233 gtk_box_append(GTK_BOX(box), notebook);
1234
1235 /* LAN pane. */
1237 G_TYPE_INT, /* port */
1238 G_TYPE_STRING, /* version */
1239 G_TYPE_STRING, /* state */
1240 G_TYPE_INT, /* nplayers */
1241 G_TYPE_STRING, /* humans */
1242 G_TYPE_STRING); /* message */
1243
1249
1251 lan_selection = selection;
1253
1258
1259 g_signal_connect(view, "row-activated",
1261 g_signal_connect(selection, "changed",
1263
1264 add_treeview_column(view, _("Server Name"), G_TYPE_STRING, 0);
1265 add_treeview_column(view, _("Port"), G_TYPE_INT, 1);
1266 add_treeview_column(view, _("Version"), G_TYPE_STRING, 2);
1267 add_treeview_column(view, _("Status"), G_TYPE_STRING, 3);
1268 add_treeview_column(view, _("Players"), G_TYPE_INT, 4);
1269 add_treeview_column(view, _("Humans"), G_TYPE_STRING, 5);
1270 add_treeview_column(view, _("Comment"), G_TYPE_STRING, 6);
1271
1272 label = gtk_label_new_with_mnemonic(_("Local _Area Network"));
1273
1283 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), sw, label);
1284
1285
1286 /* Metaserver pane. */
1288 G_TYPE_INT, /* port */
1289 G_TYPE_STRING, /* version */
1290 G_TYPE_STRING, /* state */
1291 G_TYPE_INT, /* nplayers */
1292 G_TYPE_STRING, /* humans */
1293 G_TYPE_STRING); /* message */
1294
1300
1302 meta_selection = selection;
1304
1309
1310 g_signal_connect(view, "row-activated",
1312 g_signal_connect(selection, "changed",
1314
1315 add_treeview_column(view, _("Server Name"), G_TYPE_STRING, 0);
1316 add_treeview_column(view, _("Port"), G_TYPE_INT, 1);
1317 add_treeview_column(view, _("Version"), G_TYPE_STRING, 2);
1318 add_treeview_column(view, _("Status"), G_TYPE_STRING, 3);
1319 add_treeview_column(view, _("Players"), G_TYPE_INT, 4);
1320 add_treeview_column(view, _("Humans"), G_TYPE_STRING, 5);
1321 add_treeview_column(view, _("Comment"), G_TYPE_STRING, 6);
1322
1323 label = gtk_label_new_with_mnemonic(_("Internet _Metaserver"));
1324
1335 gtk_notebook_prepend_page(GTK_NOTEBOOK(notebook), sw, label);
1336 } else {
1337 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), sw, label);
1338 }
1339
1340 /* Bottom part of the page, outside the inner notebook. */
1343
1350
1351 table = gtk_grid_new();
1355
1357 g_signal_connect(network_host, "activate",
1360
1362 "use-underline", TRUE,
1363 "mnemonic-widget", network_host,
1364 "label", _("_Host:"),
1365 "xalign", 0.0,
1366 "yalign", 0.5,
1367 NULL);
1368 network_host_label = label;
1369 gtk_grid_attach(GTK_GRID(table), label, 0, 0, 1, 1);
1370
1372 g_signal_connect(network_port, "activate",
1375
1377 "use-underline", TRUE,
1378 "mnemonic-widget", network_port,
1379 "label", _("_Port:"),
1380 "xalign", 0.0,
1381 "yalign", 0.5,
1382 NULL);
1383 network_port_label = label;
1384 gtk_grid_attach(GTK_GRID(table), label, 0, 1, 1, 1);
1385
1388 g_signal_connect(network_login, "activate",
1391
1393 "use-underline", TRUE,
1394 "mnemonic-widget", network_login,
1395 "label", _("_Login:"),
1396 "xalign", 0.0,
1397 "yalign", 0.5,
1398 NULL);
1399 gtk_widget_set_margin_top(label, 10);
1400 network_login_label = label;
1401 gtk_grid_attach(GTK_GRID(table), label, 0, 3, 1, 1);
1402
1408
1410 "use-underline", TRUE,
1411 "mnemonic-widget", network_password,
1412 "label", _("Pass_word:"),
1413 "xalign", 0.0,
1414 "yalign", 0.5,
1415 NULL);
1416 network_password_label = label;
1417 gtk_grid_attach(GTK_GRID(table), label, 0, 4, 1, 1);
1418
1424
1426 "use-underline", TRUE,
1427 "mnemonic-widget", network_confirm_password,
1428 "label", _("Conf_irm Password:"),
1429 "xalign", 0.0,
1430 "yalign", 0.5,
1431 NULL);
1433 gtk_grid_attach(GTK_GRID(table), label, 0, 5, 1, 1);
1434
1435 /* Server player list. */
1441
1447 add_treeview_column(view, _("Nation"), G_TYPE_STRING, 3);
1449
1456
1464
1465 button = gtk_button_new_from_icon_name("view-refresh");
1466 gtk_box_append(GTK_BOX(bbox), button);
1467 g_signal_connect(button, "clicked",
1469
1470 button = gtk_button_new_with_mnemonic(_("_Cancel"));
1471 gtk_box_append(GTK_BOX(bbox), button);
1472 g_signal_connect(button, "clicked",
1474
1475 button = gtk_button_new_with_mnemonic(_("C_onnect"));
1476 gtk_box_append(GTK_BOX(bbox), button);
1477 g_signal_connect(button, "clicked",
1479
1480 return box;
1481}
1482
1483/****************************************************************************
1484 START PAGE
1485****************************************************************************/
1487
1494
1495
1496/* NB: Must match creation arguments in connection_list_store_new(). */
1513
1514/**********************************************************************/
1518{
1520 G_TYPE_INT, /* CL_COL_PLAYER_NUMBER */
1521 G_TYPE_STRING, /* CL_COL_USER_NAME */
1522 G_TYPE_BOOLEAN, /* CL_COL_READY_STATE */
1523 G_TYPE_STRING, /* CL_COL_PLAYER_NAME */
1524 GDK_TYPE_PIXBUF, /* CL_COL_FLAG */
1525 GDK_TYPE_PIXBUF, /* CL_COL_COLOR */
1526 G_TYPE_STRING, /* CL_COL_NATION */
1527 G_TYPE_STRING, /* CL_COL_TEAM */
1528 G_TYPE_INT, /* CL_COL_CONN_ID */
1529 G_TYPE_INT, /* CL_COL_STYLE */
1530 G_TYPE_INT, /* CL_COL_WEIGHT */
1531 G_TYPE_BOOLEAN); /* CL_COL_COLLAPSED */
1532}
1533
1534/**********************************************************************/
1538static void client_aitoggle_player(void *data)
1539{
1540 struct player *pplayer = player_by_number(FC_PTR_TO_INT(data));
1541
1542 if (NULL != pplayer
1543 && pplayer == client_player()
1544 && !is_human(pplayer)) {
1545 send_chat("/away");
1546 }
1547}
1548
1549/**********************************************************************/
1552static void client_take_player(struct player *pplayer)
1553{
1554 int request_id = send_chat_printf("/take \"%s\"", player_name(pplayer));
1555 void *data = FC_INT_TO_PTR(player_number(pplayer));
1556
1559}
1560
1561/**********************************************************************/
1564static void object_put(GObject *object, struct player *pplayer,
1565 struct connection *pconn)
1566{
1567 /* Note that passing -1 to GINT_TO_POINTER() is buggy with some versions
1568 * of gcc. player_slot_count() is not a valid player number. 0 is not
1569 * a valid connection id (see comment in server/sernet.c:
1570 * makeup_connection_name()). */
1571 g_object_set_data(object, "player_id",
1572 GINT_TO_POINTER(NULL != pplayer
1573 ? player_number(pplayer)
1574 : player_slot_count()));
1575 g_object_set_data(object, "connection_id",
1576 GINT_TO_POINTER(NULL != pconn ? pconn->id : 0));
1577}
1578
1579/**********************************************************************/
1583static bool object_extract(GObject *object, struct player **ppplayer,
1584 struct connection **ppconn)
1585{
1586 bool ret = FALSE;
1587 int id;
1588
1589 if (NULL != ppplayer) {
1590 id = GPOINTER_TO_INT(g_object_get_data(object, "player_id"));
1592 if (NULL != *ppplayer) {
1593 ret = TRUE;
1594 }
1595 }
1596 if (NULL != ppconn) {
1597 id = GPOINTER_TO_INT(g_object_get_data(object, "connection_id"));
1598 *ppconn = conn_by_number(id);
1599 if (NULL != *ppconn) {
1600 ret = TRUE;
1601 }
1602 }
1603
1604 return ret;
1605}
1606
1607/**********************************************************************/
1611{
1612 option_dialog_popup(_("Game Settings"), server_optset);
1613}
1614
1615/**********************************************************************/
1619{
1620 enum ai_level *levels = (enum ai_level *)data;
1621 const char *name;
1622 int i;
1623
1625
1626 if (i != -1) {
1627 enum ai_level level = levels[i];
1628
1629 /* Suppress changes provoked by server rather than local user */
1630 if (server_ai_level() != level) {
1632 send_chat_printf("/%s", name);
1633 }
1634 }
1635}
1636
1637/* HACK: sometimes when creating the ruleset combo the value is set without
1638 * the user's control. In this case we don't want to do a /read. */
1640
1641/**********************************************************************/
1644static void ruleset_selected(const char *name)
1645{
1646 if (name && name[0] != '\0' && !no_ruleset_callback) {
1648 }
1649}
1650
1651/**********************************************************************/
1657{
1658 const char *name = NULL;
1659
1661
1662 if (name != NULL) {
1664 }
1665}
1666
1667/**********************************************************************/
1678
1679/**********************************************************************/
1683{
1684 if (start_aifill_spin) {
1686 /* Suppress callback from this change to avoid a loop. */
1688 /* HACK: this GUI control doesn't have quite the same semantics as the
1689 * server 'aifill' option, in that it claims to represent the minimum
1690 * number of players _including humans_. The GUI control has a minimum
1691 * value of 1, so aifill == 0 will not be represented correctly.
1692 * But there's generally exactly one human player because the control
1693 * only shows up for a locally spawned server, so we more or less
1694 * get away with this. */
1697 }
1698}
1699
1700/**********************************************************************/
1704{
1706}
1707
1708/**********************************************************************/
1712{
1713 if (conn_popover != NULL){
1716
1718 }
1719}
1720
1721/**********************************************************************/
1725 gpointer data)
1726{
1727 struct player *pplayer;
1728 struct team_slot *tslot = g_object_get_data(G_OBJECT(action), "slot");
1729 GMenu *menu = data;
1730
1731 if (object_extract(G_OBJECT(menu), &pplayer, NULL)
1732 && NULL != tslot
1733 && team_slot_index(tslot) != team_number(pplayer->team)) {
1734 send_chat_printf("/team \"%s\" \"%s\"",
1735 player_name(pplayer),
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)) {
1753 player_number(pplayer), !pplayer->is_ready);
1754 }
1755
1757}
1758
1759/**********************************************************************/
1763 gpointer data)
1764{
1765 struct player *pplayer;
1766 GMenu *menu = data;
1767
1768 if (object_extract(G_OBJECT(menu), &pplayer, NULL)) {
1769 popup_races_dialog(pplayer);
1770 }
1771
1773}
1774
1775/**********************************************************************/
1780 gpointer data)
1781{
1782 struct player *pplayer;
1783 GMenu *menu = data;
1784
1785 if (object_extract(G_OBJECT(menu), &pplayer, NULL)) {
1786 send_chat_printf("/%s \"%s\"",
1787 (char *) g_object_get_data(G_OBJECT(action), "command"),
1788 player_name(pplayer));
1789 }
1790
1792}
1793
1794/**********************************************************************/
1798 gpointer data)
1799{
1800 struct player *pplayer;
1801 GMenu *menu = data;
1802
1803 if (object_extract(G_OBJECT(menu), &pplayer, NULL)) {
1804 client_take_player(pplayer);
1805 }
1806
1808}
1809
1810/**********************************************************************/
1815 GVariant *parameter, gpointer data)
1816{
1817 struct connection *pconn;
1818 GMenu *menu = data;
1819
1820 if (object_extract(G_OBJECT(menu), NULL, &pconn)) {
1822 (char *) g_object_get_data(G_OBJECT(action), "command"),
1823 pconn->username);
1824 }
1825
1827}
1828
1829/**********************************************************************/
1832static void show_conn_popup(struct player *pplayer, struct connection *pconn)
1833{
1835 char buf[4096] = "";
1836
1837 if (pconn) {
1838 cat_snprintf(buf, sizeof(buf), _("Connection name: %s"),
1839 pconn->username);
1840 } else {
1841 cat_snprintf(buf, sizeof(buf), _("Player name: %s"),
1842 player_name(pplayer));
1843 }
1844 cat_snprintf(buf, sizeof(buf), "\n");
1845 if (pconn) {
1846 cat_snprintf(buf, sizeof(buf), _("Host: %s"), pconn->addr);
1847 }
1848 cat_snprintf(buf, sizeof(buf), "\n");
1849
1850 /* Show popup. */
1853 "%s", buf);
1854 gtk_window_set_title(GTK_WINDOW(popup), _("Player/conn info"));
1858}
1859
1860/**********************************************************************/
1864 gpointer data)
1865{
1866 struct player *pplayer;
1867 struct connection *pconn;
1868 GMenu *menu = data;
1869
1870 if (object_extract(G_OBJECT(menu), &pplayer, &pconn)) {
1871 show_conn_popup(pplayer, pconn);
1872 }
1873
1875}
1876
1877/**********************************************************************/
1881static GtkWidget *create_conn_menu(struct player *pplayer,
1882 struct connection *pconn)
1883{
1884 GMenu *menu;
1885 gchar *buf;
1886 GSimpleAction *act;
1887 GActionGroup *group;
1888
1890
1891 menu = g_menu_new();
1892
1893 object_put(G_OBJECT(menu), pplayer, pconn);
1894
1895 buf = g_strdup_printf(_("%s info"),
1896 pconn ? pconn->username : player_name(pplayer));
1897
1898 act = g_simple_action_new("info", NULL);
1900 g_signal_connect(act, "activate", G_CALLBACK(conn_menu_info_chosen), menu);
1901 menu_item_append_unref(menu, g_menu_item_new(buf, "win.info"));
1902
1903 if (NULL != pplayer) {
1904 act = g_simple_action_new("toggle_ready", NULL);
1906 g_signal_connect(act, "activate", G_CALLBACK(conn_menu_ready_chosen), menu);
1908 menu_item_append_unref(menu, g_menu_item_new(_("Toggle player ready"),
1909 "win.toggle_ready"));
1910
1911 act = g_simple_action_new("pick_nation", NULL);
1913 g_signal_connect(act, "activate", G_CALLBACK(conn_menu_nation_chosen), menu);
1916 pplayer));
1917 menu_item_append_unref(menu, g_menu_item_new(_("Pick nation"), "win.pick_nation"));
1918
1919 act = g_simple_action_new("observe", NULL);
1920 g_object_set_data_full(G_OBJECT(act), "command", g_strdup("observe"),
1923 g_signal_connect(act, "activate", G_CALLBACK(conn_menu_player_command), menu);
1924 menu_item_append_unref(menu, g_menu_item_new(_("Observe this player"),
1925 "win.observe"));
1926
1927 act = g_simple_action_new("take_plr", NULL);
1929 g_signal_connect(act, "activate", G_CALLBACK(conn_menu_player_take), menu);
1930 menu_item_append_unref(menu, g_menu_item_new(_("Take this player"),
1931 "win.take_plr"));
1932 }
1933
1935 && pconn->id != client.conn.id) {
1936 act = g_simple_action_new("cut_conn", NULL);
1937 g_object_set_data_full(G_OBJECT(act), "command", g_strdup("cut"),
1941 menu_item_append_unref(menu, g_menu_item_new(_("Cut connection"), "win.cut_conn"));
1942 }
1943
1944 if (ALLOW_CTRL <= client.conn.access_level && NULL != pplayer) {
1945 act = g_simple_action_new("aitoggle", NULL);
1946 g_object_set_data_full(G_OBJECT(act), "command", g_strdup("aitoggle"),
1950 menu_item_append_unref(menu, g_menu_item_new(_("Aitoggle player"), "win.aitoggle"));
1951
1952 if (pplayer != client.conn.playing && game.info.is_new_game) {
1953 act = g_simple_action_new("remove", NULL);
1954 g_object_set_data_full(G_OBJECT(act), "command", g_strdup("remove"),
1958 menu_item_append_unref(menu, g_menu_item_new(_("Remove player"), "win.remove"));
1959 }
1960 }
1961
1963 && pconn->id != client.conn.id) {
1964 enum cmdlevel level;
1965
1966 /* No item for hack access; that would be a serious security hole. */
1968 char actbuf[128];
1969
1970 buf = g_strdup_printf(_("Give %s access"), cmdlevel_name(level));
1971 fc_snprintf(actbuf, sizeof(actbuf), "cmdlevel_%d", level);
1972
1974 g_object_set_data_full(G_OBJECT(act), "command",
1975 g_strdup_printf("cmdlevel %s",
1980 fc_snprintf(actbuf, sizeof(actbuf), "win.cmdlevel_%d", level);
1982 g_free(buf);
1983 }
1984 }
1985
1987 && NULL != pplayer && is_ai(pplayer)) {
1988 enum ai_level level;
1989
1990 for (level = 0; level < AI_LEVEL_COUNT; level++) {
1992 char actbuf[128];
1993
1994 buf = g_strdup_printf(_("Difficulty: %s"), ai_level_translated_name(level));
1995 fc_snprintf(actbuf, sizeof(actbuf), "ailevel_%d", level);
1996
1998 g_object_set_data_full(G_OBJECT(act), "command",
2002 g_signal_connect(act, "activate", G_CALLBACK(conn_menu_player_command), menu);
2003 fc_snprintf(actbuf, sizeof(actbuf), "win.ailevel_%d", level);
2005 g_free(buf);
2006 }
2007 }
2008 }
2009
2010 if (pplayer != NULL /* && game.info.is_new_game */) {
2011 const int count = pplayer->team
2012 ? player_list_size(team_members(pplayer->team)) : 0;
2013 bool need_empty_team = (count != 1);
2014
2015 /* Can't use team_iterate here since it skips empty teams. */
2017 char actbuf[128];
2018 int id;
2019
2020 if (!team_slot_is_used(tslot)) {
2021 if (!need_empty_team) {
2022 continue;
2023 }
2025 }
2026
2028
2029 /* TRANS: e.g., "Put on Team 5" */
2030 buf = g_strdup_printf(_("Put on %s"),
2032 fc_snprintf(actbuf, sizeof(actbuf), "team_%d", id);
2033
2035 g_object_set_data(G_OBJECT(act), "slot", tslot);
2037 g_signal_connect(act, "activate", G_CALLBACK(conn_menu_team_chosen), menu);
2038 fc_snprintf(actbuf, sizeof(actbuf), "win.team_%d", id);
2040 g_free(buf);
2042 }
2043
2048
2049 return conn_popover;
2050}
2051
2052/**********************************************************************/
2056{
2057 if (NULL != connection_list_view) {
2058 GtkTreeSelection *selection =
2060 GtkTreePath *path = data;
2061
2062 gtk_tree_selection_unselect_path(selection, path);
2063 gtk_tree_path_free(path);
2064 }
2065 return FALSE;
2066}
2067
2068/**********************************************************************/
2072 int n_press,
2073 double x, double y, gpointer data)
2074{
2077 GtkTreePath *path = NULL;
2079
2081 x, y,
2082 &path, NULL, NULL, NULL)) {
2083 return FALSE;
2084 }
2085
2086 if (gtk_tree_selection_path_is_selected(selection, path)) {
2087 /* Need to delay to avoid problem with the expander. */
2089 return FALSE; /* Return now, don't free the path. */
2090 }
2091
2092 gtk_tree_path_free(path);
2093
2094 return FALSE;
2095}
2096
2097/**********************************************************************/
2101 int n_press,
2102 double x, double y, gpointer data)
2103{
2106 GtkWidget *parent = data;
2107 GtkTreePath *path = NULL;
2108 GtkWidget *menu;
2109 GtkTreeSelection *selection;
2110 GtkTreeModel *model;
2112 int player_no, conn_id;
2113 struct player *pplayer;
2114 struct connection *pconn;
2115 int bx, by;
2116 GdkRectangle rect = { .x = x, .y = y, .width = 1, .height = 1};
2117
2119
2121 &path, NULL, NULL, NULL)) {
2122 return FALSE;
2123 }
2124
2127
2128 if (!gtk_tree_selection_path_is_selected(selection, path)) {
2129 gtk_tree_selection_select_path(selection, path);
2130 }
2131 gtk_tree_model_get_iter(model, &iter, path);
2132
2133 gtk_tree_model_get(model, &iter, CL_COL_PLAYER_NUMBER, &player_no, -1);
2134 pplayer = player_by_number(player_no);
2135
2136 gtk_tree_model_get(model, &iter, CL_COL_CONN_ID, &conn_id, -1);
2137 pconn = conn_by_number(conn_id);
2138
2139 menu = create_conn_menu(pplayer, pconn);
2140 gtk_widget_set_parent(menu, parent); /* Gtk bug prevents tree view parenting */
2142
2144
2145 gtk_tree_path_free(path);
2146
2147 return TRUE;
2148}
2149
2150/**********************************************************************/
2155 GtkTreePath *path,
2156 gpointer data)
2157{
2159
2160 gtk_tree_store_set(store, iter,
2162}
2163
2164/**********************************************************************/
2169 struct connection **ppconn)
2170{
2171 if (NULL != connection_list_view) {
2173 GtkTreeModel *model;
2174 GtkTreeSelection *selection =
2176
2177 if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
2178 int id;
2179
2180 if (NULL != ppplayer) {
2181 gtk_tree_model_get(model, &iter, CL_COL_PLAYER_NUMBER, &id, -1);
2183 }
2184 if (NULL != ppconn) {
2185 gtk_tree_model_get(model, &iter, CL_COL_CONN_ID, &id, -1);
2186 *ppconn = conn_by_number(id);
2187 }
2188 return TRUE;
2189 }
2190 }
2191
2192 if (NULL != ppplayer) {
2193 *ppplayer = NULL;
2194 }
2195 if (NULL != ppconn) {
2196 *ppconn = NULL;
2197 }
2198 return FALSE;
2199}
2200
2201/**********************************************************************/
2205{
2206 GtkTreeModel *model;
2207 GtkTreeIter parent, child, *iter = NULL;
2208 GtkTreeSelection *selection;
2209 gboolean valid;
2210 const int search_id = pconn->id;
2211 int id;
2212
2213 if (NULL == connection_list_view) {
2214 return;
2215 }
2216
2219
2220 /* Main iteration. */
2221 valid = gtk_tree_model_get_iter_first(model, &parent);
2222 while (valid && NULL == iter) {
2223 gtk_tree_model_get(model, &parent, CL_COL_CONN_ID, &id, -1);
2224 if (search_id == id) {
2225 iter = &parent;
2226 break;
2227 }
2228
2229 /* Node children iteration. */
2230 valid = gtk_tree_model_iter_children(model, &child, &parent);
2231 while (valid && NULL == iter) {
2232 gtk_tree_model_get(model, &child, CL_COL_CONN_ID, &id, -1);
2233 if (search_id == id) {
2234 iter = &child;
2235 break;
2236 }
2237 valid = gtk_tree_model_iter_next(model, &child);
2238 }
2239
2240 valid = gtk_tree_model_iter_next(model, &parent);
2241 }
2242
2243 /* Select iterator. */
2244 if (NULL != iter) {
2246 } else {
2247 log_error("%s(): connection %s not found.",
2249 }
2250}
2251
2252/**********************************************************************/
2256{
2257 if (can_client_control()) {
2260 !client_player()->is_ready);
2261 } else {
2263 }
2264}
2265
2266/**********************************************************************/
2270{
2271 struct player *selected_plr;
2272 bool row_selected = conn_list_selection(&selected_plr, NULL);
2273
2274 if (row_selected && NULL != selected_plr) {
2275 /* "Take <player_name>" */
2277 } else if (can_client_control()) {
2278 /* "Pick Nation" */
2280 } else {
2281 /* "Take a Player" */
2282 send_chat("/take -");
2283 }
2284}
2285
2286/**********************************************************************/
2290{
2291 struct player *selected_plr;
2292 bool row_selected = conn_list_selection(&selected_plr, NULL);
2293
2294 if (row_selected && NULL != selected_plr) {
2295 /* "Observe <player_name>" */
2296 send_chat_printf("/observe \"%s\"", player_name(selected_plr));
2297 } else if (!client_is_global_observer()) {
2298 /* "Observe" */
2299 send_chat("/observe");
2300 } else {
2301 /* "Do not observe" */
2302 send_chat("/detach");
2303 }
2304}
2305
2306/**********************************************************************/
2310{
2311 char buf[2 * MAX_LEN_NAME];
2312 const char *text;
2313 struct player *selected_plr;
2314 bool row_selected = conn_list_selection(&selected_plr, NULL);
2315 bool sensitive;
2316
2317 /*** Ready button. ***/
2318 if (can_client_control()) {
2319 sensitive = client_player()->is_alive;
2320 if (client_player()->is_ready) {
2321 text = _("Not _ready");
2322 } else {
2323 int num_unready = 0;
2324
2325 players_iterate_alive(pplayer) {
2326 if (is_human(pplayer) && !pplayer->is_ready) {
2327 num_unready++;
2328 }
2330
2331 if (num_unready > 1) {
2332 text = _("_Ready");
2333 } else {
2334 /* We are the last unready player so clicking here will
2335 * immediately start the game. */
2336 text = _("_Start");
2337 }
2338 }
2339 } else {
2340 text = _("_Start");
2341 if (can_client_access_hack()) {
2342 sensitive = TRUE;
2344 if (is_human(plr)) {
2345 /* There's human controlled player(s) in game, so it's their
2346 * job to start the game. */
2347 sensitive = FALSE;
2348 break;
2349 }
2351 } else {
2352 sensitive = FALSE;
2353 }
2354 }
2357
2358 /*** Nation button. ***/
2359 if (row_selected && NULL != selected_plr) {
2360 fc_snprintf(buf, sizeof(buf), _("_Take %s"), player_name(selected_plr));
2361 text = buf;
2363 } else if (can_client_control()) {
2364 text = _("Pick _Nation");
2366 } else {
2367 text = _("_Take a Player");
2369 }
2372
2373 /*** Observe button. ***/
2374 if (row_selected && NULL != selected_plr) {
2375 fc_snprintf(buf, sizeof(buf), _("_Observe %s"),
2377 text = buf;
2379 } else if (!client_is_global_observer()) {
2380 text = _("_Observe");
2381 sensitive = TRUE;
2382 } else {
2383 text = _("Do not _observe");
2384 sensitive = TRUE;
2385 }
2388}
2389
2390/**********************************************************************/
2396 GtkTreeIter *start,
2397 const struct player *pplayer)
2398{
2399 const int search_id = player_number(pplayer);
2400 int id;
2401
2402 if (NULL != start) {
2403 *iter = *start;
2404 if (!gtk_tree_model_iter_next(model, iter)) {
2405 return FALSE;
2406 }
2407 } else if (!gtk_tree_model_get_iter_first(model, iter)) {
2408 return FALSE;
2409 }
2410
2411 do {
2413 if (id == search_id) {
2414 return TRUE;
2415 }
2416 } while (gtk_tree_model_iter_next(model, iter));
2417
2418 return FALSE;
2419}
2420
2421/**********************************************************************/
2427 const struct connection *pconn)
2428{
2429 const int search_id = pconn->id;
2430 int id;
2431
2432 if (NULL != start) {
2433 *iter = *start;
2434 if (!gtk_tree_model_iter_next(model, iter)) {
2435 return FALSE;
2436 }
2437 } else if (!gtk_tree_model_iter_children(model, iter, parent)) {
2438 return FALSE;
2439 }
2440
2441 do {
2442 gtk_tree_model_get(model, iter, CL_COL_CONN_ID, &id, -1);
2443 if (id == search_id) {
2444 return TRUE;
2445 }
2446 } while (gtk_tree_model_iter_next(model, iter));
2447
2448 return FALSE;
2449}
2450
2451/**********************************************************************/
2455{
2460 GtkTreeModel *model = GTK_TREE_MODEL(store);
2461 GtkTreePath *path;
2464 GdkPixbuf *flag, *color;
2466 struct player *pselected_player;
2467 struct connection *pselected_conn;
2468 bool is_ready;
2469 const char *nation, *plr_name, *team;
2470 char name[MAX_LEN_NAME + 8];
2472 int conn_id;
2473
2474 /* Refresh the AI skill level control */
2475 if (ai_lvl_combobox) {
2476 enum ai_level new_level = server_ai_level(), level;
2477 int i = 0;
2478
2479 for (level = 0; level < AI_LEVEL_COUNT; level++) {
2481 if (level == new_level) {
2483 break;
2484 }
2485 i++;
2486 }
2487 }
2488 if (level == AI_LEVEL_COUNT) {
2489 /* Probably ai_level_invalid() */
2491 }
2492 }
2493
2494 /* Save the selected connection. */
2496
2497 /* Insert players into the connection list. */
2498 players_iterate(pplayer) {
2499 if (!player_has_flag(pplayer, PLRF_SCENARIO_RESERVED)) {
2500 conn_id = -1;
2502 flag = pplayer->nation ? get_flag(pplayer->nation) : NULL;
2503 color = create_player_icon(pplayer);
2504
2505 conn_list_iterate(pplayer->connections, pconn) {
2506 if (pconn->playing == pplayer && !pconn->observer) {
2507 conn_id = pconn->id;
2508 access_level = pconn->access_level;
2509 break;
2510 }
2512
2513 if (is_ai(pplayer) && !pplayer->was_created
2514 && !pplayer->is_connected) {
2515 /* TRANS: "<Novice AI>" */
2516 fc_snprintf(name, sizeof(name), _("<%s AI>"),
2517 ai_level_translated_name(pplayer->ai_common.skill_level));
2518 } else {
2519 sz_strlcpy(name, pplayer->username);
2520 if (access_level > ALLOW_BASIC) {
2521 sz_strlcat(name, "*");
2522 }
2523 }
2524
2525 is_ready = !is_human(pplayer) ? TRUE : pplayer->is_ready;
2526
2527 if (pplayer->nation == NO_NATION_SELECTED) {
2528 nation = _("Random");
2529 if (pplayer->was_created) {
2530 plr_name = player_name(pplayer);
2531 } else {
2532 plr_name = "";
2533 }
2534 } else {
2535 nation = nation_adjective_for_player(pplayer);
2536 plr_name = player_name(pplayer);
2537 }
2538
2539 team = pplayer->team ? team_name_translation(pplayer->team) : "";
2540
2541 if (model_get_player_iter(model, &parent, pprev_parent, pplayer)) {
2543 } else {
2545 }
2546
2547 gtk_tree_store_set(store, &parent,
2550 CL_COL_READY_STATE, is_ready,
2552 CL_COL_FLAG, flag,
2554 CL_COL_NATION, nation,
2556 CL_COL_CONN_ID, conn_id,
2559 -1);
2560
2561 /* Insert observers of this player as child nodes. */
2562 pprev_child = NULL;
2563 conn_list_iterate(pplayer->connections, pconn) {
2564 if (pconn->id == conn_id) {
2565 continue;
2566 }
2567 if (model_get_conn_iter(model, &child, &parent,
2568 pprev_child, pconn)) {
2569 gtk_tree_store_move_after(store, &child, pprev_child);
2570 } else {
2572 }
2573
2574 gtk_tree_store_set(store, &child,
2576 CL_COL_USER_NAME, pconn->username,
2577 CL_COL_TEAM, _("Observer"),
2578 CL_COL_CONN_ID, pconn->id,
2581 -1);
2582
2583 prev_child = child;
2586
2587 /* Expand node? */
2588 if (NULL != pprev_child) {
2590 if (!collapsed) {
2591 path = gtk_tree_model_get_path(model, &parent);
2593 path, FALSE);
2594 gtk_tree_path_free(path);
2595 }
2596 }
2597
2598 /* Remove trailing rows. */
2599 if (NULL != pprev_child) {
2600 child = prev_child;
2601 if (gtk_tree_model_iter_next(model, &child)) {
2602 while (gtk_tree_store_remove(store, &child)) {
2603 /* Do nothing more. */
2604 }
2605 }
2606 } else if (gtk_tree_model_iter_children(model, &child, &parent)) {
2607 while (gtk_tree_store_remove(store, &child)) {
2608 /* Do nothing more. */
2609 }
2610 }
2611
2614 if (flag) {
2615 g_object_unref(flag);
2616 }
2617 if (color) {
2619 }
2620 }
2622
2623 /* Finally, insert global observers... */
2625 if (NULL != pconn->playing || !pconn->observer) {
2626 continue;
2627 }
2628
2631 } else {
2633 }
2634
2635 gtk_tree_store_set(store, &parent,
2637 CL_COL_USER_NAME, pconn->username,
2638 CL_COL_TEAM, _("Observer"),
2639 CL_COL_CONN_ID, pconn->id,
2642 -1);
2643
2647
2648 /* ...and detached connections. */
2650 if (NULL != pconn->playing || pconn->observer) {
2651 continue;
2652 }
2653
2656 } else {
2658 }
2659
2660 gtk_tree_store_set(store, &parent,
2662 CL_COL_USER_NAME, pconn->username,
2663 CL_COL_TEAM, _("Detached"),
2664 CL_COL_CONN_ID, pconn->id,
2667 -1);
2668
2672
2673 /* Remove trailing rows. */
2674 if (NULL != pprev_parent) {
2676 if (gtk_tree_model_iter_next(model, &parent)) {
2677 while (gtk_tree_store_remove(store, &parent)) {
2678 /* Do nothing more. */
2679 }
2680 }
2681 } else {
2682 gtk_tree_store_clear(store);
2683 }
2684
2685 /* If we were selecting a single connection, let's try to reselect it. */
2688 }
2689 }
2690
2692}
2693
2694/**********************************************************************/
2700 const char *title, int colnum, const char *key)
2701{
2704
2705 if (gtype == G_TYPE_BOOLEAN) {
2708 "active", colnum, NULL);
2709 } else if (gtype == GDK_TYPE_PIXBUF) {
2712 "pixbuf", colnum, NULL);
2713 } else {
2716 "text", colnum,
2717 "style", CL_COL_STYLE,
2718 "weight", CL_COL_WEIGHT,
2719 NULL);
2720 }
2721
2724
2725 if (key != NULL) {
2727 }
2728}
2729
2730/**********************************************************************/
2734{
2735 GtkWidget *box, *sbox, *table, *vgrid;
2736 GtkWidget *view, *sw, *text, *toolkit_view, *button, *spin;
2737 GtkWidget *label;
2738 GtkTreeSelection *selection;
2739 enum ai_level level;
2740 /* There's less than AI_LEVEL_COUNT entries as not all levels have
2741 entries (that's the whole point of this array: index != value),
2742 but this is set safely to the max */
2743 static enum ai_level levels[AI_LEVEL_COUNT];
2744 int i = 0;
2745 int box_row = 0;
2746 int sbox_col = 0;
2747 int grid_row = 0;
2750
2751 box = gtk_grid_new();
2759
2760 sbox = gtk_grid_new();
2762 gtk_grid_attach(GTK_GRID(box), sbox, 0, box_row++, 1, 1);
2763
2764 vgrid = gtk_grid_new();
2775
2776 table = gtk_grid_new();
2781
2787 if (server_optset != NULL) {
2789
2790 if (paifill) {
2793 } /* else it'll be updated later */
2794 }
2795 g_signal_connect_after(spin, "value_changed",
2797
2798 gtk_grid_attach(GTK_GRID(table), spin, 1, 0, 1, 1);
2799
2801 "use-underline", TRUE,
2802 "mnemonic-widget", spin,
2803 /* TRANS: Keep individual lines short */
2804 "label", _("Number of _Players\n(including AI):"),
2805 "xalign", 0.0,
2806 "yalign", 0.5,
2807 NULL);
2808 gtk_grid_attach(GTK_GRID(table), label, 0, 0, 1, 1);
2809
2811
2812 for (level = 0; level < AI_LEVEL_COUNT; level++) {
2815
2817 levels[i] = level;
2818 i++;
2819 }
2820 }
2823 G_CALLBACK(ai_skill_callback), levels);
2824
2826
2828 "use-underline", TRUE,
2829 "mnemonic-widget", ai_lvl_combobox,
2830 "label", _("AI Skill _Level:"),
2831 "xalign", 0.0,
2832 "yalign", 0.5,
2833 NULL);
2834 gtk_grid_attach(GTK_GRID(table), label, 0, 1, 1, 1);
2835
2839
2841
2843 "use-underline", TRUE,
2844 "mnemonic-widget", GTK_COMBO_BOX_TEXT(ruleset_combo),
2845 "label", _("Ruleset:"),
2846 "xalign", 0.0,
2847 "yalign", 0.5,
2848 NULL);
2849 gtk_grid_attach(GTK_GRID(table), label, 0, 2, 1, 1);
2850
2851 button = icon_label_button_new("preferences-system",
2852 _("_More Game Options..."));
2854 gtk_widget_set_margin_end(button, 8);
2855 gtk_widget_set_margin_start(button, 8);
2856 gtk_widget_set_margin_top(button, 8);
2859 g_signal_connect(button, "clicked",
2861 gtk_grid_attach(GTK_GRID(vgrid), button, 0, grid_row++, 1, 1);
2862
2869
2872 g_signal_connect(selection, "changed",
2874
2875 add_tree_col(view, G_TYPE_STRING, _("Name"),
2877 add_tree_col(view, G_TYPE_BOOLEAN, _("Ready"),
2879 add_tree_col(view, G_TYPE_STRING, Q_("?player:Leader"),
2882 CL_COL_FLAG, NULL);
2883 add_tree_col(view, GDK_TYPE_PIXBUF, _("Border"),
2885 add_tree_col(view, G_TYPE_STRING, _("Nation"),
2887 add_tree_col(view, G_TYPE_STRING, _("Team"),
2888 CL_COL_TEAM, NULL);
2889
2891 g_signal_connect(controller, "pressed",
2894
2895 g_signal_connect(view, "row-collapsed",
2898 g_signal_connect(view, "row-expanded",
2901
2909
2910 /* This is for a workaround against gtk bug that we can't parent
2911 * popup to the tree view - we have to parent it all the way to sw */
2915 g_signal_connect(controller, "pressed",
2918
2919 gtk_grid_attach(GTK_GRID(sbox), sw, sbox_col++, 0, 1, 1);
2920
2926 gtk_grid_attach(GTK_GRID(box), sw, 0, box_row++, 1, 1);
2927
2931 start_message_area = text;
2932 gtk_widget_set_name(text, "chatline");
2937
2938
2939 /* Vote widgets. */
2940 if (pregame_votebar == NULL) {
2942 }
2944
2946 gtk_grid_attach(GTK_GRID(box), toolkit_view, 0, box_row++, 1, 1);
2947
2948 button = gtk_button_new_with_mnemonic(_("_Cancel"));
2950 g_signal_connect(button, "clicked", G_CALLBACK(main_callback), NULL);
2951
2952 nation_button = icon_label_button_new("document-properties",
2953 _("Pick _Nation"));
2957
2958 observe_button = icon_label_button_new("zoom-in", _("_Observe"));
2962
2963 ready_button = icon_label_button_new("system-run", _("_Ready"));
2965 g_signal_connect(ready_button, "clicked",
2967
2968 return box;
2969}
2970
2971
2972/**********************************************************************/
2975void handle_game_load(bool load_successful, const char *filename)
2976{
2977 if (load_successful) {
2979
2980 if (game.info.is_new_game) {
2981 /* It's pregame. Create a player and connect to it */
2982 send_chat("/take -");
2983 }
2984 }
2985}
2986
2987/**********************************************************************/
2990static void load_filename(const char *filename)
2991{
2992 send_chat_printf("/load %s", filename);
2993}
2994
2995/**********************************************************************/
2998static void load_callback(void)
2999{
3000 GtkTreeIter it;
3001 const gchar *filename;
3002
3004 return;
3005 }
3006
3008 SD_COL_FULL_PATH, &filename, -1);
3009 load_filename(filename);
3010}
3011
3012/**********************************************************************/
3016{
3017 save_dialog_file_chooser_popup(_("Choose Saved Game to Load"),
3020}
3021
3022/**********************************************************************/
3025static void update_load_page(void)
3026{
3027 /* Search for user saved games. */
3029 ".sav", FALSE);
3030
3032 fileinfo_list_destroy(files);
3033}
3034
3035/**********************************************************************/
3039{
3040 GtkWidget *box, *sbox, *bbox;
3041
3042 GtkWidget *button, *label, *view, *sw;
3044 int box_row = 0;
3045 int sbox_row = 0;
3046
3047 box = gtk_grid_new();
3055
3060
3063 -1, NULL, rend, "text", 0, NULL);
3064
3067
3069
3070 g_signal_connect(view, "row-activated",
3072
3073 sbox = gtk_grid_new();
3078 gtk_grid_attach(GTK_GRID(box), sbox, 0, box_row++, 1, 1);
3079
3081 "use-underline", TRUE,
3082 "mnemonic-widget", view,
3083 "label", _("Choose Saved Game to _Load:"),
3084 "xalign", 0.0,
3085 "yalign", 0.5,
3086 NULL);
3087 gtk_grid_attach(GTK_GRID(sbox), label, 0, sbox_row++, 1, 1);
3088
3095 gtk_grid_attach(GTK_GRID(sbox), sw, 0, sbox_row++, 1, 1);
3096
3100 gtk_grid_attach(GTK_GRID(box), bbox, 0, box_row++, 1, 1);
3101
3102 button = gtk_button_new_with_mnemonic(_("_Browse..."));
3103 gtk_box_append(GTK_BOX(bbox), button);
3104 g_signal_connect(button, "clicked",
3106
3107 button = gtk_button_new_with_mnemonic(_("_Cancel"));
3108 gtk_box_append(GTK_BOX(bbox), button);
3109 g_signal_connect(button, "clicked",
3111
3112 button = gtk_button_new_with_mnemonic(_("_OK"));
3113 gtk_box_append(GTK_BOX(bbox), button);
3114 g_signal_connect(button, "clicked",
3116
3117 return box;
3118}
3119
3120/**********************************************************************/
3123static void scenario_list_callback(void)
3124{
3125 GtkTreeIter it;
3126 GtkTextBuffer *buffer;
3127 char *description;
3128 char *authors;
3129 char *filename;
3130 int ver;
3131 char vername[50];
3132
3135 2, &description, -1);
3137 3, &authors, -1);
3139 1, &filename, -1);
3141 4, &ver, -1);
3142 filename = skip_to_basename(filename);
3143 if (ver > 0) {
3144 int maj;
3145 int min;
3146
3147 maj = ver / 1000000;
3148 ver %= 1000000;
3149 min = ver / 10000;
3150 ver %= 10000;
3151 if (ver >= 9000) {
3152 /* Development version, have '+' */
3153 fc_snprintf(vername, sizeof(vername), "%d.%d+", maj, min);
3154 } else {
3155 fc_snprintf(vername, sizeof(vername), "%d.%d", maj, min);
3156 }
3157 } else {
3158 /* TRANS: Old scenario format version */
3159 fc_snprintf(vername, sizeof(vername), _("pre-2.6"));
3160 }
3161 } else {
3162 description = "";
3163 authors = "";
3164 filename = "";
3165 vername[0] = '\0';
3166 }
3167
3169 gtk_text_buffer_set_text(buffer, description, -1);
3171 gtk_text_buffer_set_text(buffer, authors, -1);
3174}
3175
3176/**********************************************************************/
3179static void scenario_callback(void)
3180{
3181 GtkTreeIter it;
3182 char *filename;
3183
3185 return;
3186 }
3187
3188 gtk_tree_model_get(GTK_TREE_MODEL(scenario_store), &it, 1, &filename, -1);
3189 load_filename(filename);
3190}
3191
3192/**********************************************************************/
3196{
3197 save_dialog_file_chooser_popup(_("Choose a Scenario"),
3200}
3201
3202/**********************************************************************/
3205static void update_scenario_page(void)
3206{
3207 struct fileinfo_list *files;
3208
3210
3211 /* search for scenario files. */
3212 files = fileinfolist_infix(get_scenario_dirs(), ".sav", TRUE);
3214 struct section_file *sf;
3215
3216 if ((sf = secfile_load_section(pfile->fullname, "scenario", TRUE))
3217 && secfile_lookup_bool_default(sf, TRUE, "scenario.is_scenario")) {
3218 const char *sname, *sdescription, *sauthors;
3219 int fcver;
3220 int fcdev;
3221 int current_ver = MAJOR_VERSION * 1000000 + MINOR_VERSION * 10000;
3222 int current_dev;
3223
3225 if (PATCH_VERSION >= 90) {
3226 /* Patch level matters on development versions */
3227 current_dev += PATCH_VERSION * 100;
3228 }
3229
3230 fcver = secfile_lookup_int_default(sf, 0, "scenario.game_version");
3231 if (fcver < 30000) {
3232 /* Pre-3.0 versions stored version number without emergency version
3233 * part in the end. To get comparable version number stored,
3234 * multiply by 100. */
3235 fcver *= 100;
3236 }
3237 if (fcver % 10000 >= 9000) {
3238 fcdev = fcver - (fcver % 100); /* Emergency version does not count. */
3239 } else {
3240 fcdev = fcver - (fcver % 10000); /* Patch version does not count. */
3241 }
3242 sname = secfile_lookup_str_default(sf, NULL, "scenario.name");
3244 "scenario.description");
3245 sauthors = secfile_lookup_str_default(sf, NULL, "scenario.authors");
3246 log_debug("scenario file: %s from %s", sname, pfile->fullname);
3247
3248 /* Ignore scenarios for newer freeciv versions than we are. */
3249 if (fcdev <= current_dev) {
3250 bool add_new = TRUE;
3251
3252 if (sname != NULL) {
3253 GtkTreeIter it;
3254 bool valid;
3255
3257 while (valid) {
3258 char *oname;
3259
3261 0, &oname, -1);
3262
3263 if (!strcmp(sname, oname)) {
3264 /* Already listed scenario has the same name as the one we just found */
3265 int existing;
3266
3268 4, &existing, -1);
3269 log_debug("Duplicate %s (%d vs %d)", sname, existing, fcver);
3270
3271 if (existing > fcver) {
3272 /* Already listed one has higher version number */
3273 add_new = FALSE;
3274 } else if (existing < fcver) {
3275 /* New one has higher version number */
3276 add_new = FALSE;
3277
3279 0, sname && strlen(sname) ? Q_(sname) : pfile->name,
3280 1, pfile->fullname,
3281 2, (NULL != sdescription && '\0' != sdescription[0]
3282 ? Q_(sdescription) : ""),
3283 3, (NULL != sauthors && sauthors[0] != '\0'
3284 ? Q_(sauthors) : ""),
3285 4, fcver,
3286 -1);
3287 } else {
3288 /* Same version number -> list both */
3289 }
3290 }
3292 }
3293 }
3294
3295 if (add_new) {
3296 GtkTreeIter it;
3297
3300 0, sname && strlen(sname) ? Q_(sname) : pfile->name,
3301 1, pfile->fullname,
3302 2, (NULL != sdescription && '\0' != sdescription[0]
3303 ? Q_(sdescription) : ""),
3304 3, (NULL != sauthors && sauthors[0] != '\0'
3305 ? Q_(sauthors) : ""),
3306 4, fcver,
3307 -1);
3308 }
3309 }
3310
3311 secfile_destroy(sf);
3312 }
3314
3315 fileinfo_list_destroy(files);
3316}
3317
3318/**********************************************************************/
3322{
3325 GtkWidget *button, *label, *view, *sw, *swa, *text;
3327 int grid_row = 0;
3328 int filenamecol = 0;
3329 int vercol = 0;
3330 int descrow = 0;
3331
3332 vgrid = gtk_grid_new();
3340
3345 G_TYPE_INT);
3350
3353 -1, NULL, rend, "text", 0, NULL);
3354
3359
3361
3362 g_signal_connect(view, "row-activated",
3364
3366 "use-underline", TRUE,
3367 "mnemonic-widget", view,
3368 "label", _("Choose a _Scenario:"),
3369 "xalign", 0.0,
3370 "yalign", 0.5,
3371 NULL);
3372 gtk_grid_attach(GTK_GRID(vgrid), label, 0, grid_row++, 1, 1);
3373
3374 sbox = gtk_grid_new();
3381
3382 hbox = gtk_grid_new();
3385
3391 gtk_grid_attach(GTK_GRID(sbox), sw, 0, 0, 1, 2);
3392
3393 text = gtk_text_view_new();
3399 scenario_description = text;
3400
3406
3407 text = gtk_text_view_new();
3413 scenario_authors = text;
3414
3420
3421 text = gtk_label_new(_("Filename:"));
3426
3433
3434 gtk_grid_attach(GTK_GRID(filenamebox), text, filenamecol++, 0, 1, 1);
3436 filenamecol++, 0, 1, 1);
3437
3438 /* TRANS: Scenario format version */
3439 vertext = gtk_label_new(_("Format:"));
3444
3451
3454 vercol++, 0, 1, 1);
3455
3460 gtk_grid_attach(GTK_GRID(descbox), sw, 0, descrow++, 1, 1);
3463 0, descrow++, 1, 1);
3465 0, descrow++, 1, 1);
3466 gtk_grid_attach(GTK_GRID(sbox), descbox, 1, 0, 1, 2);
3467
3471
3472 button = gtk_button_new_with_mnemonic(_("_Browse..."));
3473 gtk_box_append(GTK_BOX(bbox), button);
3474 g_signal_connect(button, "clicked",
3476
3477 button = gtk_button_new_with_mnemonic(_("_Cancel"));
3478 gtk_box_append(GTK_BOX(bbox), button);
3479 g_signal_connect(button, "clicked",
3481
3482 button = gtk_button_new_with_mnemonic(_("_OK"));
3483 gtk_box_append(GTK_BOX(bbox), button);
3484 g_signal_connect(button, "clicked",
3486
3487 return vgrid;
3488}
3489
3490/**********************************************************************/
3494{
3495 return current_page;
3496}
3497
3498/**********************************************************************/
3502{
3503 /* Don't use current_page directly here because maybe it could be modified
3504 * before we reach the end of this function. */
3506
3507 /* If the page remains the same, don't do anything. */
3508 if (old_page == new_page) {
3509 return;
3510 }
3511
3512 log_debug("Switching client page from %s to %s.",
3513 -1 == old_page ? "(no page)" : client_pages_name(old_page),
3515
3517
3518 switch (old_page) {
3519 case PAGE_SCENARIO:
3520 case PAGE_LOAD:
3521 break;
3522 case PAGE_GAME:
3523 {
3525
3527 if (vmode == NULL) {
3529 }
3530 }
3531 break;
3532 default:
3533 break;
3534 }
3535
3536 switch (new_page) {
3537 case PAGE_MAIN:
3538 case PAGE_START:
3539 if (is_server_running()) {
3542 } else {
3544 }
3548 break;
3549 case PAGE_GAME:
3550 {
3552
3555 if (vmode == NULL) {
3557 }
3560 }
3561 break;
3562 case PAGE_LOAD:
3564 break;
3565 case PAGE_SCENARIO:
3567 break;
3568 case PAGE_NETWORK:
3570 break;
3571 }
3572
3573 /* Hide/show statusbar. */
3574 if (new_page == PAGE_START || new_page == PAGE_GAME) {
3577 } else {
3579 }
3580
3582
3583 /* Update the GUI. */
3584 while (g_main_context_pending(NULL)) {
3586 }
3587
3588 switch (new_page) {
3589 case PAGE_MAIN:
3590 break;
3591 case PAGE_START:
3594 break;
3595 case PAGE_LOAD:
3597 break;
3598 case PAGE_SCENARIO:
3600 break;
3601 case PAGE_GAME:
3605 mapview_thaw();
3608 break;
3609 case PAGE_NETWORK:
3614 break;
3615 }
3616}
3617
3618/****************************************************************************
3619 SAVE GAME DIALOGs
3620****************************************************************************/
3621
3622/**********************************************************************/
3626{
3627 return fileinfolist_infix(get_save_dirs(), ".sav", FALSE);
3628}
3629
3630/**********************************************************************/
3634{
3635 static GtkWidget *shell = NULL;
3636
3637 if (NULL != shell) {
3638 return;
3639 }
3640
3641 shell = save_dialog_new(_("Save Game"), _("Saved _Games:"),
3642 _("Save _Filename:"), send_save_game,
3645 &shell);
3647}
3648
3649/**********************************************************************/
3652static void save_dialog_save_scenario(const char *filename)
3653{
3655}
3656
3657/**********************************************************************/
3661{
3662 return fileinfolist_infix(get_scenario_dirs(), ".sav", FALSE);
3663}
3664
3665/**********************************************************************/
3669{
3670 static GtkWidget *shell = NULL;
3671
3672 if (NULL != shell) {
3673 return;
3674 }
3675
3676 shell = save_dialog_new(_("Save Scenario"), _("Saved Sce_narios:"),
3677 _("Save Sc_enario:"), save_dialog_save_scenario,
3680 &shell);
3682}
3683
3684/**********************************************************************/
3690{
3691 return fileinfolist_infix(get_save_dirs(), ".map", FALSE);
3692}
3693
3694/**********************************************************************/
3698{
3699 static GtkWidget *shell = NULL;
3700
3701 if (NULL != shell) {
3702 return;
3703 }
3704
3705 shell = save_dialog_new(_("Save Map Image"), _("Saved Map _Images:"),
3706 _("Save _Map Images:"), mapimg_client_save,
3709 &shell);
3711}
3712
3713/**********************************************************************/
3716void mapimg_client_save(const char *filename)
3717{
3718 if (!mapimg_client_createmap(filename)) {
3719 char msg[512];
3720
3721 fc_snprintf(msg, sizeof(msg), "(%s)", mapimg_error());
3722 popup_notify_dialog(_("Error"),
3723 _("Error Creating the Map Image!"), msg);
3724 }
3725}
3726
3727/**********************************************************************/
3732void set_rulesets(int num_rulesets, char **rulesets)
3733{
3734 int i;
3735 int def_idx = -1;
3736
3738 for (i = 0; i < num_rulesets; i++) {
3739
3741 if (!strcmp("default", rulesets[i])) {
3742 def_idx = i;
3743 }
3744 }
3745
3747
3748 /* HACK: Server should tell us the current ruleset. */
3750
3752}
#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:1519
bool mapimg_client_createmap(const char *filename)
Definition climisc.c:1466
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:76
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:61
static PangoLayout * layout
Definition canvas.c:325
void inputline_toolkit_view_append_button(GtkWidget *toolkit_view, GtkWidget *button)
Definition chatline.c:1293
GtkWidget * inputline_toolkit_view_new(void)
Definition chatline.c:1271
void inputline_grab_focus(void)
Definition chatline.c:80
void chatline_scroll_to_bottom(bool delayed)
Definition chatline.c:1007
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:106
GtkTextBuffer * message_buffer
Definition gui_main.c:179
struct video_mode * resolution_request_get(void)
Definition gui_main.c:2612
void enable_menus(bool enable)
Definition gui_main.c:1053
void refresh_chat_buttons(void)
Definition gui_main.c:2510
void add_idle_callback(void(callback)(void *), void *data)
Definition gui_main.c:2406
void reset_unit_table(void)
Definition gui_main.c:1024
GtkWidget * toplevel
Definition gui_main.c:126
void quit_gtk_main(void)
Definition gui_main.c:2338
static struct video_mode vmode
Definition gui_main.c:192
GtkWidget * toplevel_tabs
Definition gui_main.c:128
int screen_height(void)
Definition gui_main.c:2594
#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:1185
void handle_game_load(bool load_successful, const char *filename)
Definition pages.c:2841
GtkWidget * create_start_page(void)
Definition pages.c:2623
GtkWidget * create_network_page(void)
Definition pages.c:1201
static void client_aitoggle_player(void *data)
Definition pages.c:1509
static GtkWidget * nation_button
Definition pages.c:1460
static void update_server_list(enum server_scan_type sstype, const struct server_list *list)
Definition pages.c:704
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:2199
static void save_dialog_response_callback(GtkWidget *w, gint response, gpointer data)
Definition pages.c:489
GtkWidget * create_scenario_page(void)
Definition pages.c:3185
static void show_conn_popup(struct player *pplayer, struct connection *pconn)
Definition pages.c:1767
static GtkWidget * network_confirm_password_label
Definition pages.c:699
void save_mapimg_dialog_popup(void)
Definition pages.c:3551
static void ruleset_selected(const char *name)
Definition pages.c:1615
static void ready_button_callback(GtkWidget *w, gpointer data)
Definition pages.c:2145
static bool conn_list_selection(struct player **ppplayer, struct connection **ppconn)
Definition pages.c:2058
static struct server_scan_timer_data meta_scan
Definition pages.c:86
static void update_network_lists(void)
Definition pages.c:838
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:399
void append_network_statusbar(const char *text, bool force)
Definition pages.c:894
static gboolean update_network_statusbar(gpointer data)
Definition pages.c:864
void set_rulesets(int num_rulesets, char **rulesets)
Definition pages.c:3586
void mapimg_client_save(const char *filename)
Definition pages.c:3570
static void conn_menu_player_command(GObject *object, gpointer data)
Definition pages.c:1726
static void load_filename(const char *filename)
Definition pages.c:2856
static void conn_menu_nation_chosen(GObject *object, gpointer data)
Definition pages.c:1713
static GtkWidget * scenario_description
Definition pages.c:63
void save_game_dialog_popup(void)
Definition pages.c:3487
enum client_pages get_current_client_page(void)
Definition pages.c:3345
static GtkListStore * lan_store
Definition pages.c:68
static enum connection_state connection_status
Definition pages.c:859
save_dialog_columns
Definition pages.c:383
@ SD_COL_NUM
Definition pages.c:387
@ SD_COL_FULL_PATH
Definition pages.c:385
@ SD_COL_PRETTY_NAME
Definition pages.c:384
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:557
static void connect_network_game_callback(GtkWidget *w, gpointer data)
Definition pages.c:132
static GtkTreeView * connection_list_view
Definition pages.c:1462
static GtkWidget * network_login
Definition pages.c:695
static GtkWidget * network_login_label
Definition pages.c:695
connection_state
Definition pages.c:852
@ LOGIN_TYPE
Definition pages.c:853
@ NEW_PASSWORD_TYPE
Definition pages.c:854
@ WAITING_TYPE
Definition pages.c:856
@ ENTER_PASSWORD_TYPE
Definition pages.c:855
static void connect_callback(GtkWidget *w, gpointer data)
Definition pages.c:1043
static void scenario_browse_callback(GtkWidget *w, gpointer data)
Definition pages.c:3059
static GtkListStore * meta_store
Definition pages.c:68
connection_list_columns
Definition pages.c:1468
@ CL_COL_STYLE
Definition pages.c:1478
@ CL_COL_USER_NAME
Definition pages.c:1470
@ CL_COL_READY_STATE
Definition pages.c:1471
@ CL_COL_WEIGHT
Definition pages.c:1479
@ CL_COL_PLAYER_NAME
Definition pages.c:1472
@ CL_COL_NATION
Definition pages.c:1475
@ CL_COL_CONN_ID
Definition pages.c:1477
@ CL_COL_PLAYER_NUMBER
Definition pages.c:1469
@ CL_NUM_COLUMNS
Definition pages.c:1482
@ CL_COL_TEAM
Definition pages.c:1476
@ CL_COL_COLOR
Definition pages.c:1474
@ CL_COL_COLLAPSED
Definition pages.c:1480
@ CL_COL_FLAG
Definition pages.c:1473
static void update_load_page(void)
Definition pages.c:2891
static void save_dialog_update(struct save_dialog *pdialog)
Definition pages.c:427
static GtkWidget * scenario_authors
Definition pages.c:64
static GtkWidget * start_aifill_spin
Definition pages.c:1463
static void ruleset_entry_changed(GtkWidget *w, gpointer data)
Definition pages.c:1627
void(* save_dialog_action_fn_t)(const char *filename)
Definition pages.c:372
static void open_settings(void)
Definition pages.c:141
static void set_connection_state(enum connection_state state)
Definition pages.c:930
static GtkWidget * ruleset_combo
Definition pages.c:93
static void observe_button_callback(GtkWidget *w, gpointer data)
Definition pages.c:2179
static void conn_menu_ready_chosen(GObject *object, gpointer data)
Definition pages.c:1700
static void server_scan_error(struct server_scan *scan, const char *message)
Definition pages.c:825
static void load_callback(void)
Definition pages.c:2864
static void save_dialog_file_chooser_callback(GtkWidget *widget, gint response, gpointer data)
Definition pages.c:444
static void network_list_callback(GtkTreeSelection *select, gpointer data)
Definition pages.c:1139
static GtkListStore * server_playerlist_store
Definition pages.c:70
static void nation_button_callback(GtkWidget *w, gpointer data)
Definition pages.c:2159
void real_set_client_page(enum client_pages new_page)
Definition pages.c:3353
static void conn_menu_connection_command(GObject *object, gpointer data)
Definition pages.c:1753
static void scenario_list_callback(void)
Definition pages.c:2987
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:2881
static void network_activate_callback(GtkTreeView *view, GtkTreePath *arg1, GtkTreeViewColumn *arg2, gpointer data)
Definition pages.c:1098
static struct fileinfo_list * save_dialog_scenario_list(void)
Definition pages.c:3514
static void connection_state_reset(void)
Definition pages.c:998
void real_conn_list_dialog_update(void *unused)
Definition pages.c:2344
static bool holding_srv_list_mutex
Definition pages.c:95
static GtkTreeStore * connection_list_store
Definition pages.c:1461
static struct fileinfo_list * save_dialog_savegame_list(void)
Definition pages.c:3479
static void start_new_game_callback(GtkWidget *w, gpointer data)
Definition pages.c:102
void destroy_server_scans(void)
Definition pages.c:768
void save_scenario_dialog_popup(void)
Definition pages.c:3522
static GtkTreeSelection * lan_selection
Definition pages.c:74
static void save_dialog_save_scenario(const char *filename)
Definition pages.c:3506
struct fileinfo_list *(* save_dialog_files_fn_t)(void)
Definition pages.c:373
static gboolean check_server_scan(gpointer data)
Definition pages.c:791
static void save_dialog_store_update(GtkListStore *store, const struct fileinfo_list *files)
Definition pages.c:409
static void ai_fill_changed_by_user(GtkWidget *w, gpointer data)
Definition pages.c:1642
static gboolean delayed_unselect_path(gpointer data)
Definition pages.c:1973
static void conn_menu_player_take(GObject *object, gpointer data)
Definition pages.c:1740
static void conn_menu_info_chosen(GObject *object, gpointer data)
Definition pages.c:1798
static bool model_get_player_iter(GtkTreeModel *model, GtkTreeIter *iter, GtkTreeIter *start, const struct player *pplayer)
Definition pages.c:2284
static GtkTreeSelection * load_selection
Definition pages.c:73
static void ai_skill_callback(GtkWidget *w, gpointer data)
Definition pages.c:1589
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:699
static void client_take_player(struct player *pplayer)
Definition pages.c:1523
static void clear_network_statusbar(void)
Definition pages.c:880
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:538
static void connection_list_row_callback(GtkTreeView *tree_view, GtkTreeIter *iter, GtkTreePath *path, gpointer data)
Definition pages.c:2043
save_dialog_response
Definition pages.c:390
@ SD_RES_DELETE
Definition pages.c:392
@ SD_RES_SAVE
Definition pages.c:393
@ SD_RES_BROWSE
Definition pages.c:391
GtkWidget * create_load_page(void)
Definition pages.c:2904
static GtkWidget * ai_lvl_combobox
Definition pages.c:1464
static GtkWidget * network_password_label
Definition pages.c:698
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:578
static void intro_free(GtkWidget *w, gpointer *data)
Definition pages.c:221
static GtkWidget * network_password
Definition pages.c:698
static GtkWidget * network_host
Definition pages.c:696
void handle_authentication_req(enum authentication_type type, const char *message)
Definition pages.c:1007
static GtkTreeStore * connection_list_store_new(void)
Definition pages.c:1488
static bool send_new_aifill_to_server
Definition pages.c:1641
static void save_dialog_file_chooser_popup(const char *title, GtkFileChooserAction action, save_dialog_action_fn_t cb)
Definition pages.c:464
static GtkWidget * network_port
Definition pages.c:697
static void add_tree_col(GtkWidget *treeview, GType gtype, const char *title, int colnum, const char *key)
Definition pages.c:2589
static void save_dialog_entry_callback(GtkEntry *entry, gpointer data)
Definition pages.c:549
static void main_callback(GtkWidget *w, gpointer data)
Definition pages.c:149
void update_start_page(void)
Definition pages.c:1675
static void scenario_callback(void)
Definition pages.c:3043
static GtkWidget * start_options_table
Definition pages.c:1459
static bool no_ruleset_callback
Definition pages.c:1610
void ai_fill_changed_by_server(int aifill)
Definition pages.c:1653
static void update_server_playerlist(const struct server *pserver)
Definition pages.c:1110
static GtkWidget * observe_button
Definition pages.c:1460
static GtkWidget * scenario_version
Definition pages.c:66
GtkWidget * create_statusbar(void)
Definition pages.c:909
static void game_options_callback(GtkWidget *w, gpointer data)
Definition pages.c:1581
static GtkListStore * scenario_store
Definition pages.c:68
static GtkWidget * network_host_label
Definition pages.c:696
static bool model_get_conn_iter(GtkTreeModel *model, GtkTreeIter *iter, GtkTreeIter *parent, GtkTreeIter *start, const struct connection *pconn)
Definition pages.c:2315
static GQueue * statusbar_queue
Definition pages.c:90
GtkWidget * start_message_area
Definition pages.c:1457
static GtkWidget * network_port_label
Definition pages.c:697
static void update_scenario_page(void)
Definition pages.c:3069
static GtkWidget * scenario_filename
Definition pages.c:65
static void conn_menu_team_chosen(GObject *object, gpointer data)
Definition pages.c:1683
static GtkWidget * create_conn_menu(struct player *pplayer, struct connection *pconn)
Definition pages.c:1812
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:1554
static void object_put(GObject *object, struct player *pplayer, struct connection *pconn)
Definition pages.c:1535
static struct fileinfo_list * save_dialog_mapimg_list(void)
Definition pages.c:3543
GtkWidget * create_main_page(void)
Definition pages.c:231
static void conn_list_select_conn(struct connection *pconn)
Definition pages.c:2094
static GtkWidget * ready_button
Definition pages.c:1460
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:1043
void animation_idle_cb(void *data)
Definition gui_main.c:2429
void main_message_area_resize(void *data)
Definition gui_main.c:360
void widget_destroyed(GtkWidget *wdg, void *data)
Definition gui_stuff.c:1155
#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:2100
static void close_conn_menu_popover(void)
Definition pages.c:1711
static gboolean connect_list_left_button(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data)
Definition pages.c:2071
static GtkWidget * conn_popover
Definition pages.c:97
void(* save_dialog_action_fn_t)(const char *filename)
Definition pages.c:607
struct fileinfo_list *(* save_dialog_files_fn_t)(void)
Definition pages.c:608
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:192
#define fc_assert_ret_val(condition, val)
Definition log.h:195
#define log_debug(message,...)
Definition log.h:116
#define log_error(message,...)
Definition log.h:104
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:4278
const struct option_set * client_optset
Definition options.c:1316
int option_int_get(const struct option *poption)
Definition options.c:870
struct option * optset_option_by_name(const struct option_set *poptset, const char *name)
Definition options.c:467
bool option_int_set(struct option *poption, int val)
Definition options.c:914
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)
bool is_settable_ai_level(enum ai_level level)
Definition player.c:1925
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:1996
#define ai_level_cmd(_level_)
Definition player.h:572
#define players_iterate_end
Definition player.h:542
#define players_iterate(_pplayer)
Definition player.h:537
#define is_ai(plr)
Definition player.h:232
#define players_iterate_alive_end
Definition player.h:552
#define is_human(plr)
Definition player.h:231
#define players_iterate_alive(_pplayer)
Definition player.h:547
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:971
const struct strvec * get_save_dirs(void)
Definition shared.c:934
char * skip_to_basename(char *filepath)
Definition shared.c:1753
struct fileinfo_list * fileinfolist_infix(const struct strvec *dirs, const char *infix, bool nodups)
Definition shared.c:1204
#define fileinfo_list_iterate(list, pnode)
Definition shared.h:182
#define FC_PTR_TO_INT(p)
Definition shared.h:95
#define fileinfo_list_iterate_end
Definition shared.h:184
#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:2506
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:261
bool is_ready
Definition player.h:262
save_dialog_action_fn_t action
Definition pages.c:379
GtkEntry * entry
Definition pages.c:378
GtkTreeView * tree_view
Definition pages.c:377
GtkDialog * shell
Definition pages.c:376
save_dialog_files_fn_t files
Definition pages.c:380
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:960
int cat_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:986
int fc_remove(const char *filename)
Definition support.c:555
#define sz_strlcpy(dest, src)
Definition support.h:195
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
#define sz_strlcat(dest, src)
Definition support.h:196
#define fc_strncmp(_s1_, _s2_, _len_)
Definition support.h:160
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:973
void client_start_server_and_set_page(enum client_pages page)
void set_client_page(enum client_pages page)
void update_queue_connect_processing_finished(int request_id, uq_callback_t callback, void *data)
enum client_pages get_client_page(void)
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