Freeciv-3.4
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
73
76
77/* This is the current page. Invalid value at start, to be sure that it won't
78 * be caught through a switch() statement. */
79static enum client_pages current_page = -1;
80
82{
83 struct server_scan *scan;
85};
86
87static struct server_scan_timer_data meta_scan = { NULL, 0 };
88static struct server_scan_timer_data lan_scan = { NULL, 0 };
89
92
94
96
98
99static void connection_state_reset(void);
100
101/**********************************************************************/
105{
106 if (!is_server_running()) {
108
109 /* Saved settings are sent in client/options.c
110 * resend_desired_settable_options() */
111 }
112}
113
114/**********************************************************************/
118{
119 output_window_append(ftc_client, _("Compiling scenario list."));
121}
122
123/**********************************************************************/
130
131/**********************************************************************/
139
140/**********************************************************************/
143static void open_settings(void)
144{
145 option_dialog_popup(_("Set local options"), client_optset);
146}
147
148/**********************************************************************/
151static void main_callback(GtkWidget *w, gpointer data)
152{
153 enum client_pages page = PAGE_MAIN;
154
155 if (client.conn.used) {
157 }
158 if (page != get_client_page()) {
159 set_client_page(page);
160 }
161}
162
163/**********************************************************************/
167 int width, int height, gpointer data)
168{
169 static PangoLayout *layout;
171 static int pwidth, pheight;
172 static bool left = FALSE;
174 struct sprite *intro = (struct sprite *)data;
175
176 cairo_set_source_surface(cr, intro->surface, 0, 0);
177 cairo_paint(cr);
178
179 if (!layout) {
180 char msgbuf[128];
181 const char *rev_ver;
182
184 desc = 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);
327 _("Launches local server, and connects to it for a single-player game."));
328 g_signal_connect(button, "clicked",
330
331 button = gtk_button_new_with_mnemonic(_("Start _Scenario Game"));
333 gtk_grid_attach(GTK_GRID(table), button, 0, 1, 1, 1);
335 _("Loads one of the scenarios for a single-player game. "
336 "Tutorial is one of the scenarios."));
337 g_signal_connect(button, "clicked",
339
340 button = gtk_button_new_with_mnemonic(_("_Load Saved Game"));
342 gtk_grid_attach(GTK_GRID(table), button, 0, 2, 1, 1);
344 _("Continues previously saved single-player game."));
345 g_signal_connect(button, "clicked",
347
348 button = gtk_button_new_with_mnemonic(_("C_onnect to Network Game"));
350 gtk_grid_attach(GTK_GRID(table), button, 1, 0, 1, 1);
352 _("Connects to outside server. "
353 "Sometimes you want to launch a separate server even for local games."));
354 g_signal_connect(button, "clicked",
356
357 button = gtk_button_new_with_mnemonic(_("Client Settings"));
359 gtk_grid_attach(GTK_GRID(table), button, 1, 1, 1, 1);
361 _("Adjusting client-side options."));
362 g_signal_connect(button, "clicked", open_settings, NULL);
363
364 button = icon_label_button_new("application-exit", _("E_xit"));
367 gtk_grid_attach(GTK_GRID(table), button, 1, 2, 1, 1);
369 _("Gives you a break from playing freeciv."));
370 g_signal_connect(button, "clicked",
372
373 return widget;
374}
375
376/****************************************************************************
377 GENERIC SAVE DIALOG
378****************************************************************************/
379typedef void (*save_dialog_action_fn_t) (const char *filename);
380typedef struct fileinfo_list * (*save_dialog_files_fn_t) (void);
381
382struct save_dialog {
388};
389
396
402
403/**********************************************************************/
407{
409 G_TYPE_STRING, /* SD_COL_PRETTY_NAME */
410 G_TYPE_STRING); /* SD_COL_FULL_PATH */
411}
412
413/**********************************************************************/
417 const struct fileinfo_list *files)
418{
420
424 gtk_list_store_set(store, &iter,
426 SD_COL_FULL_PATH, pfile->fullname,
427 -1);
429}
430
431/**********************************************************************/
434static void save_dialog_update(struct save_dialog *pdialog)
435{
436 struct fileinfo_list *files;
437
438 fc_assert_ret(NULL != pdialog);
439
440 /* Update the store. */
441 files = pdialog->files();
444 files);
446}
447
448/**********************************************************************/
452 gint response, gpointer data)
453{
454 if (response == GTK_RESPONSE_OK) {
457
458 if (file != NULL) {
459 gchar *filename = g_file_get_parse_name(file);
460
461 if (NULL != filename) {
462 action(filename);
463 g_free(filename);
464 }
465
466 g_object_unref(file);
467 }
468 }
469
471}
472
473/**********************************************************************/
476static void save_dialog_file_chooser_popup(const char *title,
479{
481
482 /* Create the chooser */
484 _("_Cancel"), GTK_RESPONSE_CANCEL,
486 _("_Save") : _("_Open"),
489
490 g_signal_connect(filechoose, "response",
492
493 /* Display that dialog */
495}
496
497/**********************************************************************/
501 gpointer data)
502{
503 struct save_dialog *pdialog = data;
504
505 switch (response) {
506 case SD_RES_BROWSE:
507 save_dialog_file_chooser_popup(_("Select Location to Save"),
509 pdialog->action);
510 break;
511 case SD_RES_DELETE:
512 {
513 GtkTreeSelection *selection;
514 GtkTreeModel *model;
516 const gchar *full_path;
517
518 selection = gtk_tree_view_get_selection(pdialog->tree_view);
519 if (!gtk_tree_selection_get_selected(selection, &model, &iter)) {
520 return;
521 }
522
523 gtk_tree_model_get(model, &iter, SD_COL_FULL_PATH, &full_path, -1);
524 fc_remove(full_path);
525 save_dialog_update(pdialog);
526 }
527 return;
528 case SD_RES_SAVE:
529 {
530 const char *text = gtk_entry_buffer_get_text(gtk_entry_get_buffer(pdialog->entry));
531 gchar *filename = g_filename_from_utf8(text, -1, NULL, NULL, NULL);
532
533 if (NULL == filename) {
534 return;
535 }
536 pdialog->action(filename);
537 g_free(filename);
538 }
539 break;
540 default:
541 break;
542 }
543
545}
546
547/**********************************************************************/
557
558/**********************************************************************/
565
566/**********************************************************************/
570 gpointer data)
571{
572 struct save_dialog *pdialog = data;
573 GtkTreeModel *model;
575 const gchar *filename;
576
577 if (!gtk_tree_selection_get_selected(selection, &model, &iter)) {
579 return;
580 }
581
583 gtk_tree_model_get(model, &iter, SD_COL_PRETTY_NAME, &filename, -1);
585}
586
587/**********************************************************************/
590static GtkWidget *save_dialog_new(const char *title, const char *savelabel,
591 const char *savefilelabel,
594{
595 GtkWidget *shell, *sbox, *sw, *label, *view, *entry;
596 GtkBox *vbox;
597 GtkListStore *store;
599 GtkTreeSelection *selection;
600 struct save_dialog *pdialog;
601
604
605 /* Save dialog structure. */
606 pdialog = fc_malloc(sizeof(*pdialog));
607 pdialog->action = action;
608 pdialog->files = files;
609
610 /* Shell. */
612 _("_Browse..."), SD_RES_BROWSE,
613 _("_Delete"), SD_RES_DELETE,
614 _("_Cancel"), GTK_RESPONSE_CANCEL,
615 _("_Save"), SD_RES_SAVE,
616 NULL);
617 g_object_set_data_full(G_OBJECT(shell), "save_dialog", pdialog,
622 g_signal_connect(shell, "response",
624 pdialog->shell = GTK_DIALOG(shell);
626
627 /* Tree view. */
628 store = save_dialog_store_new();
632 g_object_unref(store);
634 g_signal_connect(view, "row-activated",
636 pdialog->tree_view = GTK_TREE_VIEW(view);
637
639 gtk_box_append(vbox, sbox);
640
642 "use-underline", TRUE,
643 "mnemonic-widget", view,
644 "label", savelabel,
645 "xalign", 0.0,
646 "yalign", 0.5,
647 NULL);
648 gtk_box_append(GTK_BOX(sbox), label);
649
658
661 g_signal_connect(selection, "changed",
663
666 -1, NULL, rend, "text",
668
669 /* Entry. */
672 g_signal_connect(entry, "activate",
674 pdialog->entry = GTK_ENTRY(entry);
675
681
683 "use-underline", TRUE,
684 "mnemonic-widget", entry,
685 "label", savefilelabel,
686 "xalign", 0.0,
687 "yalign", 0.5,
688 NULL);
689 gtk_box_append(GTK_BOX(sbox), label);
690
692 gtk_box_append(vbox, sbox);
693
694 save_dialog_update(pdialog);
697
698 return shell;
699}
700
701/****************************************************************************
702 NETWORK PAGE
703****************************************************************************/
709
710/**********************************************************************/
714 const struct server_list *list)
715{
718 GtkTreeIter it;
719 GtkListStore *store;
720 const gchar *host, *portstr;
721 int port;
722
723 switch (sstype) {
726 break;
729 break;
730 default:
731 break;
732 }
733
734 if (!sel) {
735 return;
736 }
737
741
742 if (!list) {
743 return;
744 }
745
748 port = atoi(portstr);
749
751 char buf[35];
752
753 if (pserver->humans >= 0) {
754 fc_snprintf(buf, sizeof(buf), "%d", pserver->humans);
755 } else {
756 sz_strlcpy(buf, _("Unknown"));
757 }
758 gtk_list_store_append(store, &it);
759 gtk_list_store_set(store, &it,
760 0, pserver->host,
761 1, pserver->port,
762 2, pserver->version,
763 3, _(pserver->state),
764 4, pserver->nplayers,
765 5, buf,
766 6, pserver->message,
767 -1);
768 if (strcmp(host, pserver->host) == 0 && port == pserver->port) {
770 }
772}
773
774/**********************************************************************/
778{
779 if (meta_scan.scan) {
782 }
783 if (meta_scan.timer != 0) {
785 meta_scan.timer = 0;
786 }
787 if (lan_scan.scan) {
790 }
791 if (lan_scan.timer != 0) {
793 lan_scan.timer = 0;
794 }
795}
796
797/**********************************************************************/
801{
802 struct server_scan_timer_data *scan_data = data;
803 struct server_scan *scan = scan_data->scan;
805
806 if (!scan) {
807 return FALSE;
808 }
809
810 stat = server_scan_poll(scan);
811 if (stat >= SCAN_STATUS_PARTIAL) {
813 struct srv_list *srvrs;
814
816 srvrs = server_scan_get_list(scan);
817 fc_mutex_allocate(&srvrs->mutex);
821 fc_mutex_release(&srvrs->mutex);
822 }
823
825 scan_data->timer = 0;
826 return FALSE;
827 }
828 return TRUE;
829}
830
831/**********************************************************************/
834static void server_scan_error(struct server_scan *scan,
835 const char *message)
836{
838 log_error("%s", message);
839
840 /* Main thread will finalize the scan later (or even concurrently) -
841 * do not do anything here to cause double free or raze condition. */
842}
843
844/**********************************************************************/
857
858/**************************************************************************
859 Network connection state defines.
860**************************************************************************/
867
869
870/**********************************************************************/
874{
876 char *txt;
877
880 free(txt);
881 }
882
883 return TRUE;
884}
885
886/**********************************************************************/
889static void clear_network_statusbar(void)
890{
892 char *txt;
893
895 free(txt);
896 }
897
899}
900
901/**********************************************************************/
904void append_network_statusbar(const char *text, bool force)
905{
907 if (force) {
910 } else {
912 }
913 }
914}
915
916/**********************************************************************/
935
936/**********************************************************************/
940{
941 switch (state) {
942 case LOGIN_TYPE:
944
946 "", -1);
948 "", -1);
949
958 break;
963 "", -1);
964
973
975 break;
980 "", -1);
981
990
992 break;
993 case WAITING_TYPE:
995
1002 break;
1003 }
1004
1005 connection_status = state;
1006}
1007
1008/**********************************************************************/
1011static void connection_state_reset(void)
1012{
1014}
1015
1016/**********************************************************************/
1021 const char *message)
1022{
1024
1025 switch (type) {
1026 case AUTH_NEWUSER_FIRST:
1027 case AUTH_NEWUSER_RETRY:
1029 return;
1030 case AUTH_LOGIN_FIRST:
1031 /* if we magically have a password already present in 'fc_password'
1032 * then, use that and skip the password entry dialog */
1033 if (fc_password[0] != '\0') {
1035
1036 sz_strlcpy(reply.password, fc_password);
1038 return;
1039 } else {
1041 }
1042 return;
1043 case AUTH_LOGIN_RETRY:
1045 return;
1046 }
1047
1048 log_error("Unsupported authentication type %d: %s.", type, message);
1049}
1050
1051/**********************************************************************/
1057{
1058 char errbuf [512];
1060
1061 switch (connection_status) {
1062 case LOGIN_TYPE:
1068
1070 errbuf, sizeof(errbuf)) != -1) {
1071 } else {
1073
1075 }
1076 return;
1077 case NEW_PASSWORD_TYPE:
1078 if (w != network_password) {
1081 sz_strlcpy(reply.password,
1083 if (!fc_strncmp(reply.password, fc_password, MAX_LEN_NAME)) {
1084 fc_password[0] = '\0';
1086
1088 } else {
1089 append_network_statusbar(_("Passwords don't match, enter password."),
1090 TRUE);
1091
1093 }
1094 }
1095 return;
1097 sz_strlcpy(reply.password,
1100
1102 return;
1103 case WAITING_TYPE:
1104 return;
1105 }
1106
1107 log_error("Unsupported connection status: %d", connection_status);
1108}
1109
1110/**********************************************************************/
1116 gpointer data)
1117{
1118 connect_callback(NULL, data);
1119}
1120
1121/**********************************************************************/
1125static void update_server_playerlist(const struct server *pserver)
1126{
1127 GtkListStore *store;
1129 int n, i;
1130
1132 fc_assert_ret(store != NULL);
1133
1134 gtk_list_store_clear(store);
1135 if (!pserver || !pserver->players) {
1136 return;
1137 }
1138
1139 n = pserver->nplayers;
1140 for (i = 0; i < n; i++) {
1141 gtk_list_store_append(store, &iter);
1142 gtk_list_store_set(store, &iter,
1143 0, pserver->players[i].name,
1144 1, pserver->players[i].type,
1145 2, pserver->players[i].host,
1146 3, pserver->players[i].nation,
1147 -1);
1148 }
1149}
1150
1151/**********************************************************************/
1155{
1156 GtkTreeModel *model;
1157 GtkTreeIter it;
1158 const char *host;
1159 int port;
1160 char portstr[32];
1161 const struct server *pserver = NULL;
1162
1163 if (!gtk_tree_selection_get_selected(select, &model, &it)) {
1164 return;
1165 }
1166
1167 if (select == meta_selection) {
1168 GtkTreePath *path;
1169 struct srv_list *srvrs;
1170
1172 path = gtk_tree_model_get_path(model, &it);
1174 /* We are not yet inside mutex protected block */
1175 fc_mutex_allocate(&srvrs->mutex);
1176 }
1177 if (srvrs->servers && path) {
1179
1181 }
1183 /* We are not yet inside mutex protected block */
1184 fc_mutex_release(&srvrs->mutex);
1185 }
1186 gtk_tree_path_free(path);
1187 }
1189
1190 gtk_tree_model_get(model, &it, 0, &host, 1, &port, -1);
1191
1193 fc_snprintf(portstr, sizeof(portstr), "%d", port);
1195}
1196
1197/**********************************************************************/
1212
1213/**********************************************************************/
1217{
1218 GtkWidget *box, *sbox, *bbox, *hbox, *notebook;
1219 GtkWidget *button, *label, *view, *sw, *table;
1220 GtkTreeSelection *selection;
1221 GtkListStore *store;
1223
1229
1230 notebook = gtk_notebook_new();
1231 gtk_box_append(GTK_BOX(box), notebook);
1232
1233 /* LAN pane. */
1235 G_TYPE_INT, /* port */
1236 G_TYPE_STRING, /* version */
1237 G_TYPE_STRING, /* state */
1238 G_TYPE_INT, /* nplayers */
1239 G_TYPE_STRING, /* humans */
1240 G_TYPE_STRING); /* message */
1241
1247
1249 lan_selection = selection;
1251
1256
1257 g_signal_connect(view, "row-activated",
1259 g_signal_connect(selection, "changed",
1261
1262 add_treeview_column(view, _("Server Name"), G_TYPE_STRING, 0);
1263 add_treeview_column(view, _("Port"), G_TYPE_INT, 1);
1264 add_treeview_column(view, _("Version"), G_TYPE_STRING, 2);
1265 add_treeview_column(view, _("Status"), G_TYPE_STRING, 3);
1266 add_treeview_column(view, _("Players"), G_TYPE_INT, 4);
1267 add_treeview_column(view, _("Humans"), G_TYPE_STRING, 5);
1268 add_treeview_column(view, _("Comment"), G_TYPE_STRING, 6);
1269
1270 label = gtk_label_new_with_mnemonic(_("Local _Area Network"));
1271
1281 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), sw, label);
1282
1283
1284 /* Metaserver pane. */
1286 G_TYPE_INT, /* port */
1287 G_TYPE_STRING, /* version */
1288 G_TYPE_STRING, /* state */
1289 G_TYPE_INT, /* nplayers */
1290 G_TYPE_STRING, /* humans */
1291 G_TYPE_STRING); /* message */
1292
1298
1300 meta_selection = selection;
1302
1307
1308 g_signal_connect(view, "row-activated",
1310 g_signal_connect(selection, "changed",
1312
1313 add_treeview_column(view, _("Server Name"), G_TYPE_STRING, 0);
1314 add_treeview_column(view, _("Port"), G_TYPE_INT, 1);
1315 add_treeview_column(view, _("Version"), G_TYPE_STRING, 2);
1316 add_treeview_column(view, _("Status"), G_TYPE_STRING, 3);
1317 add_treeview_column(view, _("Players"), G_TYPE_INT, 4);
1318 add_treeview_column(view, _("Humans"), G_TYPE_STRING, 5);
1319 add_treeview_column(view, _("Comment"), G_TYPE_STRING, 6);
1320
1321 label = gtk_label_new_with_mnemonic(_("Internet _Metaserver"));
1322
1333 gtk_notebook_prepend_page(GTK_NOTEBOOK(notebook), sw, label);
1334 } else {
1335 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), sw, label);
1336 }
1337
1338 /* Bottom part of the page, outside the inner notebook. */
1341
1348
1349 table = gtk_grid_new();
1353
1355 g_signal_connect(network_host, "activate",
1358
1360 "use-underline", TRUE,
1361 "mnemonic-widget", network_host,
1362 "label", _("_Host:"),
1363 "xalign", 0.0,
1364 "yalign", 0.5,
1365 NULL);
1366 gtk_grid_attach(GTK_GRID(table), label, 0, 0, 1, 1);
1367
1369 g_signal_connect(network_port, "activate",
1372
1374 "use-underline", TRUE,
1375 "mnemonic-widget", network_port,
1376 "label", _("_Port:"),
1377 "xalign", 0.0,
1378 "yalign", 0.5,
1379 NULL);
1380 gtk_grid_attach(GTK_GRID(table), label, 0, 1, 1, 1);
1381
1384 g_signal_connect(network_login, "activate",
1387
1389 "use-underline", TRUE,
1390 "mnemonic-widget", network_login,
1391 "label", _("_Login:"),
1392 "xalign", 0.0,
1393 "yalign", 0.5,
1394 NULL);
1395 gtk_widget_set_margin_top(label, 10);
1396 gtk_grid_attach(GTK_GRID(table), label, 0, 3, 1, 1);
1397
1403
1405 "use-underline", TRUE,
1406 "mnemonic-widget", network_password,
1407 "label", _("Pass_word:"),
1408 "xalign", 0.0,
1409 "yalign", 0.5,
1410 NULL);
1411 network_password_label = label;
1412 gtk_grid_attach(GTK_GRID(table), label, 0, 4, 1, 1);
1413
1419
1421 "use-underline", TRUE,
1422 "mnemonic-widget", network_confirm_password,
1423 "label", _("Conf_irm Password:"),
1424 "xalign", 0.0,
1425 "yalign", 0.5,
1426 NULL);
1428 gtk_grid_attach(GTK_GRID(table), label, 0, 5, 1, 1);
1429
1430 /* Server player list. */
1436
1442 add_treeview_column(view, _("Nation"), G_TYPE_STRING, 3);
1443
1450
1458
1459 button = gtk_button_new_from_icon_name("view-refresh");
1460 gtk_box_append(GTK_BOX(bbox), button);
1461 g_signal_connect(button, "clicked",
1463
1464 button = gtk_button_new_with_mnemonic(_("_Cancel"));
1465 gtk_box_append(GTK_BOX(bbox), button);
1466 g_signal_connect(button, "clicked",
1468
1469 button = gtk_button_new_with_mnemonic(_("C_onnect"));
1470 gtk_box_append(GTK_BOX(bbox), button);
1471 g_signal_connect(button, "clicked",
1473
1474 return box;
1475}
1476
1477/****************************************************************************
1478 START PAGE
1479****************************************************************************/
1481
1488
1489
1490/* NB: Must match creation arguments in connection_list_store_new(). */
1507
1508/**********************************************************************/
1512{
1514 G_TYPE_INT, /* CL_COL_PLAYER_NUMBER */
1515 G_TYPE_STRING, /* CL_COL_USER_NAME */
1516 G_TYPE_BOOLEAN, /* CL_COL_READY_STATE */
1517 G_TYPE_STRING, /* CL_COL_PLAYER_NAME */
1518 GDK_TYPE_PIXBUF, /* CL_COL_FLAG */
1519 GDK_TYPE_PIXBUF, /* CL_COL_COLOR */
1520 G_TYPE_STRING, /* CL_COL_NATION */
1521 G_TYPE_STRING, /* CL_COL_TEAM */
1522 G_TYPE_INT, /* CL_COL_CONN_ID */
1523 G_TYPE_INT, /* CL_COL_STYLE */
1524 G_TYPE_INT, /* CL_COL_WEIGHT */
1525 G_TYPE_BOOLEAN); /* CL_COL_COLLAPSED */
1526}
1527
1528/**********************************************************************/
1532static void client_aitoggle_player(void *data)
1533{
1534 struct player *pplayer = player_by_number(FC_PTR_TO_INT(data));
1535
1536 if (NULL != pplayer
1537 && pplayer == client_player()
1538 && !is_human(pplayer)) {
1539 send_chat("/away");
1540 }
1541}
1542
1543/**********************************************************************/
1546static void client_take_player(struct player *pplayer)
1547{
1548 int request_id = send_chat_printf("/take \"%s\"", player_name(pplayer));
1549 void *data = FC_INT_TO_PTR(player_number(pplayer));
1550
1553}
1554
1555/**********************************************************************/
1558static void object_put(GObject *object, struct player *pplayer,
1559 struct connection *pconn)
1560{
1561 /* Note that passing -1 to GINT_TO_POINTER() is buggy with some versions
1562 * of gcc. player_slot_count() is not a valid player number. 0 is not
1563 * a valid connection id (see comment in server/sernet.c:
1564 * makeup_connection_name()). */
1565 g_object_set_data(object, "player_id",
1566 GINT_TO_POINTER(NULL != pplayer
1567 ? player_number(pplayer)
1568 : player_slot_count()));
1569 g_object_set_data(object, "connection_id",
1570 GINT_TO_POINTER(NULL != pconn ? pconn->id : 0));
1571}
1572
1573/**********************************************************************/
1577static bool object_extract(GObject *object, struct player **ppplayer,
1578 struct connection **ppconn)
1579{
1580 bool ret = FALSE;
1581 int id;
1582
1583 if (NULL != ppplayer) {
1584 id = GPOINTER_TO_INT(g_object_get_data(object, "player_id"));
1586 if (NULL != *ppplayer) {
1587 ret = TRUE;
1588 }
1589 }
1590 if (NULL != ppconn) {
1591 id = GPOINTER_TO_INT(g_object_get_data(object, "connection_id"));
1592 *ppconn = conn_by_number(id);
1593 if (NULL != *ppconn) {
1594 ret = TRUE;
1595 }
1596 }
1597
1598 return ret;
1599}
1600
1601/**********************************************************************/
1605{
1606 option_dialog_popup(_("Game Settings"), server_optset);
1607}
1608
1609/**********************************************************************/
1613{
1614 enum ai_level *levels = (enum ai_level *)data;
1615 const char *name;
1616 int i;
1617
1619
1620 if (i != -1) {
1621 enum ai_level level = levels[i];
1622
1623 /* Suppress changes provoked by server rather than local user */
1624 if (server_ai_level() != level) {
1626 send_chat_printf("/%s", name);
1627 }
1628 }
1629}
1630
1631/* HACK: sometimes when creating the ruleset combo the value is set without
1632 * the user's control. In this case we don't want to do a /read. */
1634
1635/**********************************************************************/
1638static void ruleset_selected(const char *name)
1639{
1640 if (name && name[0] != '\0' && !no_ruleset_callback) {
1642 }
1643}
1644
1645/**********************************************************************/
1651{
1652 const char *name = NULL;
1653
1655
1656 if (name != NULL) {
1658 }
1659}
1660
1661/**********************************************************************/
1672
1673/**********************************************************************/
1677{
1678 if (start_aifill_spin) {
1680 /* Suppress callback from this change to avoid a loop. */
1682 /* HACK: this GUI control doesn't have quite the same semantics as the
1683 * server 'aifill' option, in that it claims to represent the minimum
1684 * number of players _including humans_. The GUI control has a minimum
1685 * value of 1, so aifill == 0 will not be represented correctly.
1686 * But there's generally exactly one human player because the control
1687 * only shows up for a locally spawned server, so we more or less
1688 * get away with this. */
1691 }
1692}
1693
1694/**********************************************************************/
1698{
1700}
1701
1702/**********************************************************************/
1706{
1707 if (conn_popover != NULL){
1710
1712 }
1713}
1714
1715/**********************************************************************/
1719 gpointer data)
1720{
1721 struct player *pplayer;
1722 struct team_slot *tslot = g_object_get_data(G_OBJECT(action), "slot");
1723 GMenu *menu = data;
1724
1725 if (object_extract(G_OBJECT(menu), &pplayer, NULL)
1726 && NULL != tslot
1727 && team_slot_index(tslot) != team_number(pplayer->team)) {
1728 send_chat_printf("/team \"%s\" \"%s\"",
1729 player_name(pplayer),
1731 }
1732
1734}
1735
1736/**********************************************************************/
1740 gpointer data)
1741{
1742 struct player *pplayer;
1743 GMenu *menu = data;
1744
1745 if (object_extract(G_OBJECT(menu), &pplayer, NULL)) {
1747 player_number(pplayer), !pplayer->is_ready);
1748 }
1749
1751}
1752
1753/**********************************************************************/
1757 gpointer data)
1758{
1759 struct player *pplayer;
1760 GMenu *menu = data;
1761
1762 if (object_extract(G_OBJECT(menu), &pplayer, NULL)) {
1763 popup_races_dialog(pplayer);
1764 }
1765
1767}
1768
1769/**********************************************************************/
1774 gpointer data)
1775{
1776 struct player *pplayer;
1777 GMenu *menu = data;
1778
1779 if (object_extract(G_OBJECT(menu), &pplayer, NULL)) {
1780 send_chat_printf("/%s \"%s\"",
1781 (char *) g_object_get_data(G_OBJECT(action), "command"),
1782 player_name(pplayer));
1783 }
1784
1786}
1787
1788/**********************************************************************/
1792 gpointer data)
1793{
1794 struct player *pplayer;
1795 GMenu *menu = data;
1796
1797 if (object_extract(G_OBJECT(menu), &pplayer, NULL)) {
1798 client_take_player(pplayer);
1799 }
1800
1802}
1803
1804/**********************************************************************/
1809 GVariant *parameter, gpointer data)
1810{
1811 struct connection *pconn;
1812 GMenu *menu = data;
1813
1814 if (object_extract(G_OBJECT(menu), NULL, &pconn)) {
1816 (char *) g_object_get_data(G_OBJECT(action), "command"),
1817 pconn->username);
1818 }
1819
1821}
1822
1823/**********************************************************************/
1826static void show_conn_popup(struct player *pplayer, struct connection *pconn)
1827{
1829 char buf[4096] = "";
1830
1831 if (pconn) {
1832 cat_snprintf(buf, sizeof(buf), _("Connection name: %s"),
1833 pconn->username);
1834 } else {
1835 cat_snprintf(buf, sizeof(buf), _("Player name: %s"),
1836 player_name(pplayer));
1837 }
1838 cat_snprintf(buf, sizeof(buf), "\n");
1839 if (pconn) {
1840 cat_snprintf(buf, sizeof(buf), _("Host: %s"), pconn->addr);
1841 }
1842 cat_snprintf(buf, sizeof(buf), "\n");
1843
1844 /* Show popup. */
1847 "%s", buf);
1848 gtk_window_set_title(GTK_WINDOW(popup), _("Player/conn info"));
1852}
1853
1854/**********************************************************************/
1858 gpointer data)
1859{
1860 struct player *pplayer;
1861 struct connection *pconn;
1862 GMenu *menu = data;
1863
1864 if (object_extract(G_OBJECT(menu), &pplayer, &pconn)) {
1865 show_conn_popup(pplayer, pconn);
1866 }
1867
1869}
1870
1871/**********************************************************************/
1875static GtkWidget *create_conn_menu(struct player *pplayer,
1876 struct connection *pconn)
1877{
1878 GMenu *menu;
1879 gchar *buf;
1880 GSimpleAction *act;
1881 GActionGroup *group;
1882
1884
1885 menu = g_menu_new();
1886
1887 object_put(G_OBJECT(menu), pplayer, pconn);
1888
1889 buf = g_strdup_printf(_("%s info"),
1890 pconn ? pconn->username : player_name(pplayer));
1891
1892 act = g_simple_action_new("info", NULL);
1894 g_signal_connect(act, "activate", G_CALLBACK(conn_menu_info_chosen), menu);
1895 menu_item_append_unref(menu, g_menu_item_new(buf, "win.info"));
1896
1897 if (NULL != pplayer) {
1898 act = g_simple_action_new("toggle_ready", NULL);
1900 g_signal_connect(act, "activate", G_CALLBACK(conn_menu_ready_chosen), menu);
1902 menu_item_append_unref(menu, g_menu_item_new(_("Toggle player ready"),
1903 "win.toggle_ready"));
1904
1905 act = g_simple_action_new("pick_nation", NULL);
1907 g_signal_connect(act, "activate", G_CALLBACK(conn_menu_nation_chosen), menu);
1910 pplayer));
1911 menu_item_append_unref(menu, g_menu_item_new(_("Pick nation"), "win.pick_nation"));
1912
1913 act = g_simple_action_new("observe", NULL);
1914 g_object_set_data_full(G_OBJECT(act), "command", g_strdup("observe"),
1917 g_signal_connect(act, "activate", G_CALLBACK(conn_menu_player_command), menu);
1918 menu_item_append_unref(menu, g_menu_item_new(_("Observe this player"),
1919 "win.observe"));
1920
1921 act = g_simple_action_new("take_plr", NULL);
1923 g_signal_connect(act, "activate", G_CALLBACK(conn_menu_player_take), menu);
1924 menu_item_append_unref(menu, g_menu_item_new(_("Take this player"),
1925 "win.take_plr"));
1926 }
1927
1929 && pconn->id != client.conn.id) {
1930 act = g_simple_action_new("cut_conn", NULL);
1931 g_object_set_data_full(G_OBJECT(act), "command", g_strdup("cut"),
1935 menu_item_append_unref(menu, g_menu_item_new(_("Cut connection"), "win.cut_conn"));
1936 }
1937
1938 if (ALLOW_CTRL <= client.conn.access_level && NULL != pplayer) {
1939 act = g_simple_action_new("aitoggle", NULL);
1940 g_object_set_data_full(G_OBJECT(act), "command", g_strdup("aitoggle"),
1944 menu_item_append_unref(menu, g_menu_item_new(_("Aitoggle player"), "win.aitoggle"));
1945
1946 if (pplayer != client.conn.playing && game.info.is_new_game) {
1947 act = g_simple_action_new("remove", NULL);
1948 g_object_set_data_full(G_OBJECT(act), "command", g_strdup("remove"),
1952 menu_item_append_unref(menu, g_menu_item_new(_("Remove player"), "win.remove"));
1953 }
1954 }
1955
1957 && pconn->id != client.conn.id) {
1958 enum cmdlevel level;
1959
1960 /* No item for hack access; that would be a serious security hole. */
1962 char actbuf[128];
1963
1964 buf = g_strdup_printf(_("Give %s access"), cmdlevel_name(level));
1965 fc_snprintf(actbuf, sizeof(actbuf), "cmdlevel_%d", level);
1966
1968 g_object_set_data_full(G_OBJECT(act), "command",
1969 g_strdup_printf("cmdlevel %s",
1974 fc_snprintf(actbuf, sizeof(actbuf), "win.cmdlevel_%d", level);
1976 g_free(buf);
1977 }
1978 }
1979
1981 && NULL != pplayer && is_ai(pplayer)) {
1982 enum ai_level level;
1983
1984 for (level = 0; level < AI_LEVEL_COUNT; level++) {
1986 char actbuf[128];
1987
1988 buf = g_strdup_printf(_("Difficulty: %s"), ai_level_translated_name(level));
1989 fc_snprintf(actbuf, sizeof(actbuf), "ailevel_%d", level);
1990
1992 g_object_set_data_full(G_OBJECT(act), "command",
1996 g_signal_connect(act, "activate", G_CALLBACK(conn_menu_player_command), menu);
1997 fc_snprintf(actbuf, sizeof(actbuf), "win.ailevel_%d", level);
1999 g_free(buf);
2000 }
2001 }
2002 }
2003
2004 if (pplayer != NULL /* && game.info.is_new_game */) {
2005 const int count = pplayer->team
2006 ? player_list_size(team_members(pplayer->team)) : 0;
2007 bool need_empty_team = (count != 1);
2008
2009 /* Can't use team_iterate here since it skips empty teams. */
2011 char actbuf[128];
2012 int id;
2013
2014 if (!team_slot_is_used(tslot)) {
2015 if (!need_empty_team) {
2016 continue;
2017 }
2019 }
2020
2022
2023 /* TRANS: e.g., "Put on Team 5" */
2024 buf = g_strdup_printf(_("Put on %s"),
2026 fc_snprintf(actbuf, sizeof(actbuf), "team_%d", id);
2027
2029 g_object_set_data(G_OBJECT(act), "slot", tslot);
2031 g_signal_connect(act, "activate", G_CALLBACK(conn_menu_team_chosen), menu);
2032 fc_snprintf(actbuf, sizeof(actbuf), "win.team_%d", id);
2034 g_free(buf);
2036 }
2037
2042
2043 return conn_popover;
2044}
2045
2046/**********************************************************************/
2050{
2051 if (NULL != connection_list_view) {
2052 GtkTreeSelection *selection =
2054 GtkTreePath *path = data;
2055
2056 gtk_tree_selection_unselect_path(selection, path);
2057 gtk_tree_path_free(path);
2058 }
2059 return FALSE;
2060}
2061
2062/**********************************************************************/
2066 int n_press,
2067 double x, double y, gpointer data)
2068{
2071 GtkTreePath *path = NULL;
2073
2075 x, y,
2076 &path, NULL, NULL, NULL)) {
2077 return FALSE;
2078 }
2079
2080 if (gtk_tree_selection_path_is_selected(selection, path)) {
2081 /* Need to delay to avoid problem with the expander. */
2083 return FALSE; /* Return now, don't free the path. */
2084 }
2085
2086 gtk_tree_path_free(path);
2087
2088 return FALSE;
2089}
2090
2091/**********************************************************************/
2095 int n_press,
2096 double x, double y, gpointer data)
2097{
2100 GtkWidget *parent = data;
2101 GtkTreePath *path = NULL;
2102 GtkWidget *menu;
2103 GtkTreeSelection *selection;
2104 GtkTreeModel *model;
2106 int player_no, conn_id;
2107 struct player *pplayer;
2108 struct connection *pconn;
2109 int bx, by;
2110 GdkRectangle rect = { .x = x, .y = y, .width = 1, .height = 1};
2111
2113
2115 &path, NULL, NULL, NULL)) {
2116 return FALSE;
2117 }
2118
2121
2122 if (!gtk_tree_selection_path_is_selected(selection, path)) {
2123 gtk_tree_selection_select_path(selection, path);
2124 }
2125 gtk_tree_model_get_iter(model, &iter, path);
2126
2127 gtk_tree_model_get(model, &iter, CL_COL_PLAYER_NUMBER, &player_no, -1);
2128 pplayer = player_by_number(player_no);
2129
2130 gtk_tree_model_get(model, &iter, CL_COL_CONN_ID, &conn_id, -1);
2131 pconn = conn_by_number(conn_id);
2132
2133 menu = create_conn_menu(pplayer, pconn);
2134 gtk_widget_set_parent(menu, parent); /* Gtk bug prevents tree view parenting */
2136
2138
2139 gtk_tree_path_free(path);
2140
2141 return TRUE;
2142}
2143
2144/**********************************************************************/
2149 GtkTreePath *path,
2150 gpointer data)
2151{
2153
2154 gtk_tree_store_set(store, iter,
2156}
2157
2158/**********************************************************************/
2163 struct connection **ppconn)
2164{
2165 if (NULL != connection_list_view) {
2167 GtkTreeModel *model;
2168 GtkTreeSelection *selection =
2170
2171 if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
2172 int id;
2173
2174 if (NULL != ppplayer) {
2175 gtk_tree_model_get(model, &iter, CL_COL_PLAYER_NUMBER, &id, -1);
2177 }
2178 if (NULL != ppconn) {
2179 gtk_tree_model_get(model, &iter, CL_COL_CONN_ID, &id, -1);
2180 *ppconn = conn_by_number(id);
2181 }
2182 return TRUE;
2183 }
2184 }
2185
2186 if (NULL != ppplayer) {
2187 *ppplayer = NULL;
2188 }
2189 if (NULL != ppconn) {
2190 *ppconn = NULL;
2191 }
2192 return FALSE;
2193}
2194
2195/**********************************************************************/
2199{
2200 GtkTreeModel *model;
2201 GtkTreeIter parent, child, *iter = NULL;
2202 GtkTreeSelection *selection;
2203 gboolean valid;
2204 const int search_id = pconn->id;
2205 int id;
2206
2207 if (NULL == connection_list_view) {
2208 return;
2209 }
2210
2213
2214 /* Main iteration. */
2215 valid = gtk_tree_model_get_iter_first(model, &parent);
2216 while (valid && NULL == iter) {
2217 gtk_tree_model_get(model, &parent, CL_COL_CONN_ID, &id, -1);
2218 if (search_id == id) {
2219 iter = &parent;
2220 break;
2221 }
2222
2223 /* Node children iteration. */
2224 valid = gtk_tree_model_iter_children(model, &child, &parent);
2225 while (valid && NULL == iter) {
2226 gtk_tree_model_get(model, &child, CL_COL_CONN_ID, &id, -1);
2227 if (search_id == id) {
2228 iter = &child;
2229 break;
2230 }
2231 valid = gtk_tree_model_iter_next(model, &child);
2232 }
2233
2234 valid = gtk_tree_model_iter_next(model, &parent);
2235 }
2236
2237 /* Select iterator. */
2238 if (NULL != iter) {
2240 } else {
2241 log_error("%s(): connection %s not found.",
2243 }
2244}
2245
2246/**********************************************************************/
2250{
2251 if (can_client_control()) {
2254 !client_player()->is_ready);
2255 } else {
2257 }
2258}
2259
2260/**********************************************************************/
2264{
2265 struct player *selected_plr;
2266 bool row_selected = conn_list_selection(&selected_plr, NULL);
2267
2268 if (row_selected && NULL != selected_plr) {
2269 /* "Take <player_name>" */
2271 } else if (can_client_control()) {
2272 /* "Pick Nation" */
2274 } else {
2275 /* "Take a Player" */
2276 send_chat("/take -");
2277 }
2278}
2279
2280/**********************************************************************/
2284{
2285 struct player *selected_plr;
2286 bool row_selected = conn_list_selection(&selected_plr, NULL);
2287
2288 if (row_selected && NULL != selected_plr) {
2289 /* "Observe <player_name>" */
2290 send_chat_printf("/observe \"%s\"", player_name(selected_plr));
2291 } else if (!client_is_global_observer()) {
2292 /* "Observe" */
2293 send_chat("/observe");
2294 } else {
2295 /* "Do not observe" */
2296 send_chat("/detach");
2297 }
2298}
2299
2300/**********************************************************************/
2304{
2305 char buf[2 * MAX_LEN_NAME];
2306 const char *text;
2307 struct player *selected_plr;
2308 bool row_selected = conn_list_selection(&selected_plr, NULL);
2309 bool sensitive;
2310
2311 /*** Ready button. ***/
2312 if (can_client_control()) {
2313 sensitive = client_player()->is_alive;
2314 if (client_player()->is_ready) {
2315 text = _("Not _ready");
2316 } else {
2317 int num_unready = 0;
2318
2319 players_iterate_alive(pplayer) {
2320 if (is_human(pplayer) && !pplayer->is_ready) {
2321 num_unready++;
2322 }
2324
2325 if (num_unready > 1) {
2326 text = _("_Ready");
2327 } else {
2328 /* We are the last unready player so clicking here will
2329 * immediately start the game. */
2330 text = _("_Start");
2331 }
2332 }
2333 } else {
2334 text = _("_Start");
2335 if (can_client_access_hack()) {
2336 sensitive = TRUE;
2338 if (is_human(plr)) {
2339 /* There's human controlled player(s) in game, so it's their
2340 * job to start the game. */
2341 sensitive = FALSE;
2342 break;
2343 }
2345 } else {
2346 sensitive = FALSE;
2347 }
2348 }
2351
2352 /*** Nation button. ***/
2353 if (row_selected && NULL != selected_plr) {
2354 fc_snprintf(buf, sizeof(buf), _("_Take %s"), player_name(selected_plr));
2355 text = buf;
2357 } else if (can_client_control()) {
2358 text = _("Pick _Nation");
2360 } else {
2361 text = _("_Take a Player");
2363 }
2366
2367 /*** Observe button. ***/
2368 if (row_selected && NULL != selected_plr) {
2369 fc_snprintf(buf, sizeof(buf), _("_Observe %s"),
2371 text = buf;
2373 } else if (!client_is_global_observer()) {
2374 text = _("_Observe");
2375 sensitive = TRUE;
2376 } else {
2377 text = _("Do not _observe");
2378 sensitive = TRUE;
2379 }
2382}
2383
2384/**********************************************************************/
2390 GtkTreeIter *start,
2391 const struct player *pplayer)
2392{
2393 const int search_id = player_number(pplayer);
2394 int id;
2395
2396 if (NULL != start) {
2397 *iter = *start;
2398 if (!gtk_tree_model_iter_next(model, iter)) {
2399 return FALSE;
2400 }
2401 } else if (!gtk_tree_model_get_iter_first(model, iter)) {
2402 return FALSE;
2403 }
2404
2405 do {
2407 if (id == search_id) {
2408 return TRUE;
2409 }
2410 } while (gtk_tree_model_iter_next(model, iter));
2411
2412 return FALSE;
2413}
2414
2415/**********************************************************************/
2421 const struct connection *pconn)
2422{
2423 const int search_id = pconn->id;
2424 int id;
2425
2426 if (NULL != start) {
2427 *iter = *start;
2428 if (!gtk_tree_model_iter_next(model, iter)) {
2429 return FALSE;
2430 }
2431 } else if (!gtk_tree_model_iter_children(model, iter, parent)) {
2432 return FALSE;
2433 }
2434
2435 do {
2436 gtk_tree_model_get(model, iter, CL_COL_CONN_ID, &id, -1);
2437 if (id == search_id) {
2438 return TRUE;
2439 }
2440 } while (gtk_tree_model_iter_next(model, iter));
2441
2442 return FALSE;
2443}
2444
2445/**********************************************************************/
2449{
2454 GtkTreeModel *model = GTK_TREE_MODEL(store);
2455 GtkTreePath *path;
2458 GdkPixbuf *flag, *color;
2460 struct player *pselected_player;
2461 struct connection *pselected_conn;
2462 bool is_ready;
2463 const char *nation, *plr_name, *team;
2464 char name[MAX_LEN_NAME + 8];
2466 int conn_id;
2467
2468 /* Refresh the AI skill level control */
2469 if (ai_lvl_combobox) {
2470 enum ai_level new_level = server_ai_level(), level;
2471 int i = 0;
2472
2473 for (level = 0; level < AI_LEVEL_COUNT; level++) {
2475 if (level == new_level) {
2477 break;
2478 }
2479 i++;
2480 }
2481 }
2482 if (level == AI_LEVEL_COUNT) {
2483 /* Probably ai_level_invalid() */
2485 }
2486 }
2487
2488 /* Save the selected connection. */
2490
2491 /* Insert players into the connection list. */
2492 players_iterate(pplayer) {
2493 if (!player_has_flag(pplayer, PLRF_SCENARIO_RESERVED)) {
2494 conn_id = -1;
2496 flag = pplayer->nation ? get_flag(pplayer->nation) : NULL;
2497 color = create_player_icon(pplayer);
2498
2499 conn_list_iterate(pplayer->connections, pconn) {
2500 if (pconn->playing == pplayer && !pconn->observer) {
2501 conn_id = pconn->id;
2502 access_level = pconn->access_level;
2503 break;
2504 }
2506
2507 if (is_ai(pplayer) && !pplayer->was_created
2508 && !pplayer->is_connected) {
2509 /* TRANS: "<Novice AI>" */
2510 fc_snprintf(name, sizeof(name), _("<%s AI>"),
2511 ai_level_translated_name(pplayer->ai_common.skill_level));
2512 } else {
2513 sz_strlcpy(name, pplayer->username);
2514 if (access_level > ALLOW_BASIC) {
2515 sz_strlcat(name, "*");
2516 }
2517 }
2518
2519 is_ready = !is_human(pplayer) ? TRUE : pplayer->is_ready;
2520
2521 if (pplayer->nation == NO_NATION_SELECTED) {
2522 nation = _("Random");
2523 if (pplayer->was_created) {
2524 plr_name = player_name(pplayer);
2525 } else {
2526 plr_name = "";
2527 }
2528 } else {
2529 nation = nation_adjective_for_player(pplayer);
2530 plr_name = player_name(pplayer);
2531 }
2532
2533 team = pplayer->team ? team_name_translation(pplayer->team) : "";
2534
2535 if (model_get_player_iter(model, &parent, pprev_parent, pplayer)) {
2537 } else {
2539 }
2540
2541 gtk_tree_store_set(store, &parent,
2544 CL_COL_READY_STATE, is_ready,
2546 CL_COL_FLAG, flag,
2548 CL_COL_NATION, nation,
2550 CL_COL_CONN_ID, conn_id,
2553 -1);
2554
2555 /* Insert observers of this player as child nodes. */
2556 pprev_child = NULL;
2557 conn_list_iterate(pplayer->connections, pconn) {
2558 if (pconn->id == conn_id) {
2559 continue;
2560 }
2561 if (model_get_conn_iter(model, &child, &parent,
2562 pprev_child, pconn)) {
2563 gtk_tree_store_move_after(store, &child, pprev_child);
2564 } else {
2566 }
2567
2568 gtk_tree_store_set(store, &child,
2570 CL_COL_USER_NAME, pconn->username,
2571 CL_COL_TEAM, _("Observer"),
2572 CL_COL_CONN_ID, pconn->id,
2575 -1);
2576
2577 prev_child = child;
2580
2581 /* Expand node? */
2582 if (NULL != pprev_child) {
2584 if (!collapsed) {
2585 path = gtk_tree_model_get_path(model, &parent);
2587 path, FALSE);
2588 gtk_tree_path_free(path);
2589 }
2590 }
2591
2592 /* Remove trailing rows. */
2593 if (NULL != pprev_child) {
2594 child = prev_child;
2595 if (gtk_tree_model_iter_next(model, &child)) {
2596 while (gtk_tree_store_remove(store, &child)) {
2597 /* Do nothing more. */
2598 }
2599 }
2600 } else if (gtk_tree_model_iter_children(model, &child, &parent)) {
2601 while (gtk_tree_store_remove(store, &child)) {
2602 /* Do nothing more. */
2603 }
2604 }
2605
2608 if (flag) {
2609 g_object_unref(flag);
2610 }
2611 if (color) {
2613 }
2614 }
2616
2617 /* Finally, insert global observers... */
2619 if (NULL != pconn->playing || !pconn->observer) {
2620 continue;
2621 }
2622
2625 } else {
2627 }
2628
2629 gtk_tree_store_set(store, &parent,
2631 CL_COL_USER_NAME, pconn->username,
2632 CL_COL_TEAM, _("Observer"),
2633 CL_COL_CONN_ID, pconn->id,
2636 -1);
2637
2641
2642 /* ...and detached connections. */
2644 if (NULL != pconn->playing || pconn->observer) {
2645 continue;
2646 }
2647
2650 } else {
2652 }
2653
2654 gtk_tree_store_set(store, &parent,
2656 CL_COL_USER_NAME, pconn->username,
2657 CL_COL_TEAM, _("Detached"),
2658 CL_COL_CONN_ID, pconn->id,
2661 -1);
2662
2666
2667 /* Remove trailing rows. */
2668 if (NULL != pprev_parent) {
2670 if (gtk_tree_model_iter_next(model, &parent)) {
2671 while (gtk_tree_store_remove(store, &parent)) {
2672 /* Do nothing more. */
2673 }
2674 }
2675 } else {
2676 gtk_tree_store_clear(store);
2677 }
2678
2679 /* If we were selecting a single connection, let's try to reselect it. */
2682 }
2683 }
2684
2686}
2687
2688/**********************************************************************/
2694 const char *title, int colnum, const char *key)
2695{
2698
2699 if (gtype == G_TYPE_BOOLEAN) {
2702 "active", colnum, NULL);
2703 } else if (gtype == GDK_TYPE_PIXBUF) {
2706 "pixbuf", colnum, NULL);
2707 } else {
2710 "text", colnum,
2711 "style", CL_COL_STYLE,
2712 "weight", CL_COL_WEIGHT,
2713 NULL);
2714 }
2715
2718
2719 if (key != NULL) {
2721 }
2722}
2723
2724/**********************************************************************/
2728{
2729 GtkWidget *box, *sbox, *table, *vgrid;
2730 GtkWidget *view, *sw, *text, *toolkit_view, *button, *spin;
2731 GtkWidget *label;
2732 GtkTreeSelection *selection;
2733 enum ai_level level;
2734 /* There's less than AI_LEVEL_COUNT entries as not all levels have
2735 entries (that's the whole point of this array: index != value),
2736 but this is set safely to the max */
2737 static enum ai_level levels[AI_LEVEL_COUNT];
2738 int i = 0;
2739 int box_row = 0;
2740 int sbox_col = 0;
2741 int grid_row = 0;
2744
2745 box = gtk_grid_new();
2753
2754 sbox = gtk_grid_new();
2756 gtk_grid_attach(GTK_GRID(box), sbox, 0, box_row++, 1, 1);
2757
2758 vgrid = gtk_grid_new();
2769
2770 table = gtk_grid_new();
2775
2781 if (server_optset != NULL) {
2783
2784 if (paifill) {
2787 } /* else it'll be updated later */
2788 }
2789 g_signal_connect_after(spin, "value_changed",
2791
2792 gtk_grid_attach(GTK_GRID(table), spin, 1, 0, 1, 1);
2793
2795 "use-underline", TRUE,
2796 "mnemonic-widget", spin,
2797 /* TRANS: Keep individual lines short */
2798 "label", _("Number of _Players\n(including AI):"),
2799 "xalign", 0.0,
2800 "yalign", 0.5,
2801 NULL);
2802 gtk_grid_attach(GTK_GRID(table), label, 0, 0, 1, 1);
2803
2805
2806 for (level = 0; level < AI_LEVEL_COUNT; level++) {
2809
2811 levels[i] = level;
2812 i++;
2813 }
2814 }
2817 G_CALLBACK(ai_skill_callback), levels);
2818
2820
2822 "use-underline", TRUE,
2823 "mnemonic-widget", ai_lvl_combobox,
2824 "label", _("AI Skill _Level:"),
2825 "xalign", 0.0,
2826 "yalign", 0.5,
2827 NULL);
2828 gtk_grid_attach(GTK_GRID(table), label, 0, 1, 1, 1);
2829
2833
2835
2837 "use-underline", TRUE,
2838 "mnemonic-widget", GTK_COMBO_BOX_TEXT(ruleset_combo),
2839 "label", _("Ruleset:"),
2840 "xalign", 0.0,
2841 "yalign", 0.5,
2842 NULL);
2843 gtk_grid_attach(GTK_GRID(table), label, 0, 2, 1, 1);
2844
2845 button = icon_label_button_new("preferences-system",
2846 _("_More Game Options..."));
2848 gtk_widget_set_margin_end(button, 8);
2849 gtk_widget_set_margin_start(button, 8);
2850 gtk_widget_set_margin_top(button, 8);
2853 g_signal_connect(button, "clicked",
2855 gtk_grid_attach(GTK_GRID(vgrid), button, 0, grid_row++, 1, 1);
2856
2860 gtk_widget_add_css_class(GTK_WIDGET(view), "large-pixbufs");
2864
2867 g_signal_connect(selection, "changed",
2869
2870 add_tree_col(view, G_TYPE_STRING, _("Name"),
2872 add_tree_col(view, G_TYPE_BOOLEAN, _("Ready"),
2874 add_tree_col(view, G_TYPE_STRING, Q_("?player:Leader"),
2877 CL_COL_FLAG, NULL);
2878 add_tree_col(view, GDK_TYPE_PIXBUF, _("Border"),
2880 add_tree_col(view, G_TYPE_STRING, _("Nation"),
2882 add_tree_col(view, G_TYPE_STRING, _("Team"),
2883 CL_COL_TEAM, NULL);
2884
2886 g_signal_connect(controller, "pressed",
2889
2890 g_signal_connect(view, "row-collapsed",
2893 g_signal_connect(view, "row-expanded",
2896
2904
2905 /* This is for a workaround against gtk bug that we can't parent
2906 * popup to the tree view - we have to parent it all the way to sw */
2910 g_signal_connect(controller, "pressed",
2913
2914 gtk_grid_attach(GTK_GRID(sbox), sw, sbox_col++, 0, 1, 1);
2915
2921 gtk_grid_attach(GTK_GRID(box), sw, 0, box_row++, 1, 1);
2922
2926 start_message_area = text;
2927 gtk_widget_set_name(text, "chatline");
2932
2933
2934 /* Vote widgets. */
2935 if (pregame_votebar == NULL) {
2937 }
2939
2941 gtk_grid_attach(GTK_GRID(box), toolkit_view, 0, box_row++, 1, 1);
2942
2943 button = gtk_button_new_with_mnemonic(_("_Cancel"));
2945 g_signal_connect(button, "clicked", G_CALLBACK(main_callback), NULL);
2946
2947 nation_button = icon_label_button_new("document-properties",
2948 _("Pick _Nation"));
2952
2953 observe_button = icon_label_button_new("zoom-in", _("_Observe"));
2957
2958 ready_button = icon_label_button_new("system-run", _("_Ready"));
2960 g_signal_connect(ready_button, "clicked",
2962
2963 return box;
2964}
2965
2966
2967/**********************************************************************/
2970void handle_game_load(bool load_successful, const char *filename)
2971{
2972 if (load_successful) {
2974
2975 if (game.info.is_new_game) {
2976 /* It's pregame. Create a player and connect to it */
2977 send_chat("/take -");
2978 }
2979 }
2980}
2981
2982/**********************************************************************/
2985static void load_filename(const char *filename)
2986{
2987 send_chat_printf("/load %s", filename);
2988}
2989
2990/**********************************************************************/
2993static void load_callback(void)
2994{
2995 GtkTreeIter it;
2996 const gchar *filename;
2997
2999 return;
3000 }
3001
3003 SD_COL_FULL_PATH, &filename, -1);
3004 load_filename(filename);
3005}
3006
3007/**********************************************************************/
3011{
3012 save_dialog_file_chooser_popup(_("Choose Saved Game to Load"),
3015}
3016
3017/**********************************************************************/
3020static void update_load_page(void)
3021{
3022 /* Search for user saved games. */
3024 ".sav", FALSE);
3025
3027 fileinfo_list_destroy(files);
3028}
3029
3030/**********************************************************************/
3034{
3035 GtkWidget *box, *sbox, *bbox;
3036
3037 GtkWidget *button, *label, *view, *sw;
3039 int box_row = 0;
3040 int sbox_row = 0;
3041
3042 box = gtk_grid_new();
3050
3055
3058 -1, NULL, rend, "text", 0, NULL);
3059
3062
3064
3065 g_signal_connect(view, "row-activated",
3067
3068 sbox = gtk_grid_new();
3073 gtk_grid_attach(GTK_GRID(box), sbox, 0, box_row++, 1, 1);
3074
3076 "use-underline", TRUE,
3077 "mnemonic-widget", view,
3078 "label", _("Choose Saved Game to _Load:"),
3079 "xalign", 0.0,
3080 "yalign", 0.5,
3081 NULL);
3082 gtk_grid_attach(GTK_GRID(sbox), label, 0, sbox_row++, 1, 1);
3083
3090 gtk_grid_attach(GTK_GRID(sbox), sw, 0, sbox_row++, 1, 1);
3091
3095 gtk_grid_attach(GTK_GRID(box), bbox, 0, box_row++, 1, 1);
3096
3097 button = gtk_button_new_with_mnemonic(_("_Browse..."));
3098 gtk_box_append(GTK_BOX(bbox), button);
3099 g_signal_connect(button, "clicked",
3101
3102 button = gtk_button_new_with_mnemonic(_("_Cancel"));
3103 gtk_box_append(GTK_BOX(bbox), button);
3104 g_signal_connect(button, "clicked",
3106
3107 button = gtk_button_new_with_mnemonic(_("_OK"));
3108 gtk_box_append(GTK_BOX(bbox), button);
3109 g_signal_connect(button, "clicked",
3111
3112 return box;
3113}
3114
3115/**********************************************************************/
3118static void scenario_list_callback(void)
3119{
3120 GtkTreeIter it;
3121 GtkTextBuffer *buffer;
3122 char *description;
3123 char *authors;
3124 char *filename;
3125 int ver;
3126 char vername[50];
3127
3130 2, &description, -1);
3132 3, &authors, -1);
3134 1, &filename, -1);
3136 4, &ver, -1);
3137 filename = skip_to_basename(filename);
3138 if (ver > 0) {
3139 int maj;
3140 int min;
3141
3142 maj = ver / 1000000;
3143 ver %= 1000000;
3144 min = ver / 10000;
3145 ver %= 10000;
3146 if (ver >= 9000) {
3147 /* Development version, have '+' */
3148 fc_snprintf(vername, sizeof(vername), "%d.%d+", maj, min);
3149 } else {
3150 fc_snprintf(vername, sizeof(vername), "%d.%d", maj, min);
3151 }
3152 } else {
3153 /* TRANS: Old scenario format version */
3154 fc_snprintf(vername, sizeof(vername), _("pre-2.6"));
3155 }
3156 } else {
3157 description = "";
3158 authors = "";
3159 filename = "";
3160 vername[0] = '\0';
3161 }
3162
3164 gtk_text_buffer_set_text(buffer, description, -1);
3166 gtk_text_buffer_set_text(buffer, authors, -1);
3169}
3170
3171/**********************************************************************/
3174static void scenario_callback(void)
3175{
3176 GtkTreeIter it;
3177 char *filename;
3178
3180 return;
3181 }
3182
3183 gtk_tree_model_get(GTK_TREE_MODEL(scenario_store), &it, 1, &filename, -1);
3184 load_filename(filename);
3185}
3186
3187/**********************************************************************/
3191{
3192 save_dialog_file_chooser_popup(_("Choose a Scenario"),
3195}
3196
3197/**********************************************************************/
3200static void update_scenario_page(void)
3201{
3202 struct fileinfo_list *files;
3203
3205
3206 /* search for scenario files. */
3207 files = fileinfolist_infix(get_scenario_dirs(), ".sav", TRUE);
3209 struct section_file *sf;
3210
3211 if ((sf = secfile_load_section(pfile->fullname, "scenario", TRUE))
3212 && secfile_lookup_bool_default(sf, TRUE, "scenario.is_scenario")) {
3213 const char *sname, *sdescription, *sauthors;
3214 int fcver;
3215 int fcdev;
3216 int current_ver = MAJOR_VERSION * 1000000 + MINOR_VERSION * 10000;
3217 int current_dev;
3218
3220 if (PATCH_VERSION >= 90) {
3221 /* Patch level matters on development versions */
3222 current_dev += PATCH_VERSION * 100;
3223 }
3224
3225 fcver = secfile_lookup_int_default(sf, 0, "scenario.game_version");
3226 if (fcver < 30000) {
3227 /* Pre-3.0 versions stored version number without emergency version
3228 * part in the end. To get comparable version number stored,
3229 * multiply by 100. */
3230 fcver *= 100;
3231 }
3232 if (fcver % 10000 >= 9000) {
3233 fcdev = fcver - (fcver % 100); /* Emergency version does not count. */
3234 } else {
3235 fcdev = fcver - (fcver % 10000); /* Patch version does not count. */
3236 }
3237 sname = secfile_lookup_str_default(sf, NULL, "scenario.name");
3239 "scenario.description");
3240 sauthors = secfile_lookup_str_default(sf, NULL, "scenario.authors");
3241 log_debug("scenario file: %s from %s", sname, pfile->fullname);
3242
3243 /* Ignore scenarios for newer freeciv versions than we are. */
3244 if (fcdev <= current_dev) {
3245 bool add_new = TRUE;
3246
3247 if (sname != NULL) {
3248 GtkTreeIter it;
3249 bool valid;
3250
3252 while (valid) {
3253 char *oname;
3254
3256 0, &oname, -1);
3257
3258 if (!strcmp(sname, oname)) {
3259 /* Already listed scenario has the same name as the one we just found */
3260 int existing;
3261
3263 4, &existing, -1);
3264 log_debug("Duplicate %s (%d vs %d)", sname, existing, fcver);
3265
3266 if (existing > fcver) {
3267 /* Already listed one has higher version number */
3268 add_new = FALSE;
3269 } else if (existing < fcver) {
3270 /* New one has higher version number */
3271 add_new = FALSE;
3272
3274 0, sname && strlen(sname) ? Q_(sname) : pfile->name,
3275 1, pfile->fullname,
3276 2, (NULL != sdescription && '\0' != sdescription[0]
3277 ? Q_(sdescription) : ""),
3278 3, (NULL != sauthors && sauthors[0] != '\0'
3279 ? Q_(sauthors) : ""),
3280 4, fcver,
3281 -1);
3282 } else {
3283 /* Same version number -> list both */
3284 }
3285 }
3287 }
3288 }
3289
3290 if (add_new) {
3291 GtkTreeIter it;
3292
3295 0, sname && strlen(sname) ? Q_(sname) : pfile->name,
3296 1, pfile->fullname,
3297 2, (NULL != sdescription && '\0' != sdescription[0]
3298 ? Q_(sdescription) : ""),
3299 3, (NULL != sauthors && sauthors[0] != '\0'
3300 ? Q_(sauthors) : ""),
3301 4, fcver,
3302 -1);
3303 }
3304 }
3305
3306 secfile_destroy(sf);
3307 }
3309
3310 fileinfo_list_destroy(files);
3311}
3312
3313/**********************************************************************/
3317{
3320 GtkWidget *button, *label, *view, *sw, *swa, *text;
3322 int grid_row = 0;
3323 int filenamecol = 0;
3324 int vercol = 0;
3325 int descrow = 0;
3326
3327 vgrid = gtk_grid_new();
3335
3340 G_TYPE_INT);
3345
3348 -1, NULL, rend, "text", 0, NULL);
3349
3354
3356
3357 g_signal_connect(view, "row-activated",
3359
3361 "use-underline", TRUE,
3362 "mnemonic-widget", view,
3363 "label", _("Choose a _Scenario:"),
3364 "xalign", 0.0,
3365 "yalign", 0.5,
3366 NULL);
3367 gtk_grid_attach(GTK_GRID(vgrid), label, 0, grid_row++, 1, 1);
3368
3369 sbox = gtk_grid_new();
3376
3377 hbox = gtk_grid_new();
3380
3386 gtk_grid_attach(GTK_GRID(sbox), sw, 0, 0, 1, 2);
3387
3388 text = gtk_text_view_new();
3394 scenario_description = text;
3395
3401
3402 text = gtk_text_view_new();
3408 scenario_authors = text;
3409
3415
3416 text = gtk_label_new(_("Filename:"));
3421
3428
3429 gtk_grid_attach(GTK_GRID(filenamebox), text, filenamecol++, 0, 1, 1);
3431 filenamecol++, 0, 1, 1);
3432
3433 /* TRANS: Scenario format version */
3434 vertext = gtk_label_new(_("Format:"));
3439
3446
3449 vercol++, 0, 1, 1);
3450
3455 gtk_grid_attach(GTK_GRID(descbox), sw, 0, descrow++, 1, 1);
3458 0, descrow++, 1, 1);
3460 0, descrow++, 1, 1);
3461 gtk_grid_attach(GTK_GRID(sbox), descbox, 1, 0, 1, 2);
3462
3466
3467 button = gtk_button_new_with_mnemonic(_("_Browse..."));
3468 gtk_box_append(GTK_BOX(bbox), button);
3469 g_signal_connect(button, "clicked",
3471
3472 button = gtk_button_new_with_mnemonic(_("_Cancel"));
3473 gtk_box_append(GTK_BOX(bbox), button);
3474 g_signal_connect(button, "clicked",
3476
3477 button = gtk_button_new_with_mnemonic(_("_OK"));
3478 gtk_box_append(GTK_BOX(bbox), button);
3479 g_signal_connect(button, "clicked",
3481
3482 return vgrid;
3483}
3484
3485/**********************************************************************/
3489{
3490 return current_page;
3491}
3492
3493/**********************************************************************/
3497{
3498 /* Don't use current_page directly here because maybe it could be modified
3499 * before we reach the end of this function. */
3501
3502 /* If the page remains the same, don't do anything. */
3503 if (old_page == new_page) {
3504 return;
3505 }
3506
3507 log_debug("Switching client page from %s to %s.",
3508 -1 == old_page ? "(no page)" : client_pages_name(old_page),
3510
3512
3513 switch (old_page) {
3514 case PAGE_SCENARIO:
3515 case PAGE_LOAD:
3516 break;
3517 case PAGE_GAME:
3518 {
3520
3522 if (vmode == NULL) {
3524 }
3525 }
3526 break;
3527 default:
3528 break;
3529 }
3530
3531 switch (new_page) {
3532 case PAGE_MAIN:
3533 case PAGE_START:
3534 if (is_server_running()) {
3537 } else {
3539 }
3543 break;
3544 case PAGE_GAME:
3545 {
3547
3550 if (vmode == NULL) {
3552 }
3555 }
3556 break;
3557 case PAGE_LOAD:
3559 break;
3560 case PAGE_SCENARIO:
3562 break;
3563 case PAGE_NETWORK:
3565 break;
3566 }
3567
3568 /* Hide/show statusbar. */
3569 if (new_page == PAGE_START || new_page == PAGE_GAME) {
3572 } else {
3574 }
3575
3577
3578 /* Update the GUI. */
3579 while (g_main_context_pending(NULL)) {
3581 }
3582
3583 switch (new_page) {
3584 case PAGE_MAIN:
3585 break;
3586 case PAGE_START:
3589 break;
3590 case PAGE_LOAD:
3592 break;
3593 case PAGE_SCENARIO:
3595 break;
3596 case PAGE_GAME:
3600 mapview_thaw();
3601 /* Force a resize "just in case" */
3602 /* this is probably a no-op most of the time */
3604 break;
3605 case PAGE_NETWORK:
3610 break;
3611 }
3612}
3613
3614/****************************************************************************
3615 SAVE GAME DIALOGs
3616****************************************************************************/
3617
3618/**********************************************************************/
3622{
3623 return fileinfolist_infix(get_save_dirs(), ".sav", FALSE);
3624}
3625
3626/**********************************************************************/
3630{
3631 static GtkWidget *shell = NULL;
3632
3633 if (NULL != shell) {
3634 return;
3635 }
3636
3637 shell = save_dialog_new(_("Save Game"), _("Saved _Games:"),
3638 _("Save _Filename:"), send_save_game,
3641 &shell);
3643}
3644
3645/**********************************************************************/
3648static void save_dialog_save_scenario(const char *filename)
3649{
3651}
3652
3653/**********************************************************************/
3657{
3658 return fileinfolist_infix(get_scenario_dirs(), ".sav", FALSE);
3659}
3660
3661/**********************************************************************/
3665{
3666 static GtkWidget *shell = NULL;
3667
3668 if (NULL != shell) {
3669 return;
3670 }
3671
3672 shell = save_dialog_new(_("Save Scenario"), _("Saved Sce_narios:"),
3673 _("Save Sc_enario:"), save_dialog_save_scenario,
3676 &shell);
3678}
3679
3680/**********************************************************************/
3686{
3687 return fileinfolist_infix(get_save_dirs(), ".map", FALSE);
3688}
3689
3690/**********************************************************************/
3694{
3695 static GtkWidget *shell = NULL;
3696
3697 if (NULL != shell) {
3698 return;
3699 }
3700
3701 shell = save_dialog_new(_("Save Map Image"), _("Saved Map _Images:"),
3702 _("Save _Map Images:"), mapimg_client_save,
3705 &shell);
3707}
3708
3709/**********************************************************************/
3712void mapimg_client_save(const char *filename)
3713{
3714 if (!mapimg_client_createmap(filename)) {
3715 char msg[512];
3716
3717 fc_snprintf(msg, sizeof(msg), "(%s)", mapimg_error());
3718 popup_notify_dialog(_("Error"),
3719 _("Error Creating the Map Image!"), msg);
3720 }
3721}
3722
3723/**********************************************************************/
3728void set_rulesets(int num_rulesets, char **rulesets)
3729{
3730 int i;
3731 int def_idx = -1;
3732
3734 for (i = 0; i < num_rulesets; i++) {
3735
3737 if (!strcmp("default", rulesets[i])) {
3738 def_idx = i;
3739 }
3740 }
3741
3743
3744 /* HACK: Server should tell us the current ruleset. */
3746
3748}
#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:1524
bool mapimg_client_createmap(const char *filename)
Definition climisc.c:1471
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:77
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:476
struct connection * conn_by_number(int id)
Definition connection.c:423
#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:36
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:68
#define Q_(String)
Definition fcintl.h:70
#define _(String)
Definition fcintl.h:67
void fc_mutex_allocate(fc_mutex *mutex)
Definition fcthread.c:144
void fc_mutex_release(fc_mutex *mutex)
Definition fcthread.c:152
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: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:178
struct video_mode * resolution_request_get(void)
Definition gui_main.c:2580
void enable_menus(bool enable)
Definition gui_main.c:1021
void refresh_chat_buttons(void)
Definition gui_main.c:2478
void reset_unit_table(void)
Definition gui_main.c:992
GtkWidget * toplevel
Definition gui_main.c:126
void quit_gtk_main(void)
Definition gui_main.c:2306
static struct video_mode vmode
Definition gui_main.c:190
GtkWidget * toplevel_tabs
Definition gui_main.c:128
int screen_height(void)
Definition gui_main.c:2562
#define GUI_GTK_OPTION(optname)
Definition gui_main.h:32
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:984
static GtkListStore * load_store
Definition pages.c:68
static void update_network_page(void)
Definition pages.c:1183
void handle_game_load(bool load_successful, const char *filename)
Definition pages.c:2835
GtkWidget * create_start_page(void)
Definition pages.c:2617
GtkWidget * create_network_page(void)
Definition pages.c:1199
static void client_aitoggle_player(void *data)
Definition pages.c:1503
static GtkWidget * nation_button
Definition pages.c:1454
static void update_server_list(enum server_scan_type sstype, const struct server_list *list)
Definition pages.c:702
static void start_scenario_callback(GtkWidget *w, gpointer data)
Definition pages.c:113
static GtkTreeSelection * scenario_selection
Definition pages.c:72
static void update_start_page_buttons(void)
Definition pages.c:2193
static void save_dialog_response_callback(GtkWidget *w, gint response, gpointer data)
Definition pages.c:487
GtkWidget * create_scenario_page(void)
Definition pages.c:3179
static void show_conn_popup(struct player *pplayer, struct connection *pconn)
Definition pages.c:1761
static GtkWidget * network_confirm_password_label
Definition pages.c:697
void save_mapimg_dialog_popup(void)
Definition pages.c:3545
static void ruleset_selected(const char *name)
Definition pages.c:1609
static void ready_button_callback(GtkWidget *w, gpointer data)
Definition pages.c:2139
static bool conn_list_selection(struct player **ppplayer, struct connection **ppconn)
Definition pages.c:2052
static struct server_scan_timer_data meta_scan
Definition pages.c:85
static void update_network_lists(void)
Definition pages.c:836
static GtkWidget * statusbar
Definition pages.c:88
static GtkListStore * save_dialog_store_new(void)
Definition pages.c:397
void append_network_statusbar(const char *text, bool force)
Definition pages.c:892
static gboolean update_network_statusbar(gpointer data)
Definition pages.c:862
void set_rulesets(int num_rulesets, char **rulesets)
Definition pages.c:3580
void mapimg_client_save(const char *filename)
Definition pages.c:3564
static void conn_menu_player_command(GObject *object, gpointer data)
Definition pages.c:1720
static void load_filename(const char *filename)
Definition pages.c:2850
static GtkWidget * network_login
Definition pages.c:693
static void conn_menu_nation_chosen(GObject *object, gpointer data)
Definition pages.c:1707
static GtkWidget * scenario_description
Definition pages.c:63
void save_game_dialog_popup(void)
Definition pages.c:3481
enum client_pages get_current_client_page(void)
Definition pages.c:3339
static GtkListStore * lan_store
Definition pages.c:68
static enum connection_state connection_status
Definition pages.c:857
save_dialog_columns
Definition pages.c:381
@ SD_COL_NUM
Definition pages.c:385
@ SD_COL_FULL_PATH
Definition pages.c:383
@ SD_COL_PRETTY_NAME
Definition pages.c:382
static struct server_scan_timer_data lan_scan
Definition pages.c:86
static void save_dialog_list_callback(GtkTreeSelection *selection, gpointer data)
Definition pages.c:555
static void connect_network_game_callback(GtkWidget *w, gpointer data)
Definition pages.c:130
static GtkTreeView * connection_list_view
Definition pages.c:1456
connection_state
Definition pages.c:850
@ LOGIN_TYPE
Definition pages.c:851
@ NEW_PASSWORD_TYPE
Definition pages.c:852
@ WAITING_TYPE
Definition pages.c:854
@ ENTER_PASSWORD_TYPE
Definition pages.c:853
static void connect_callback(GtkWidget *w, gpointer data)
Definition pages.c:1041
static void scenario_browse_callback(GtkWidget *w, gpointer data)
Definition pages.c:3053
static GtkListStore * meta_store
Definition pages.c:68
connection_list_columns
Definition pages.c:1462
@ CL_COL_STYLE
Definition pages.c:1472
@ CL_COL_USER_NAME
Definition pages.c:1464
@ CL_COL_READY_STATE
Definition pages.c:1465
@ CL_COL_WEIGHT
Definition pages.c:1473
@ CL_COL_PLAYER_NAME
Definition pages.c:1466
@ CL_COL_NATION
Definition pages.c:1469
@ CL_COL_CONN_ID
Definition pages.c:1471
@ CL_COL_PLAYER_NUMBER
Definition pages.c:1463
@ CL_NUM_COLUMNS
Definition pages.c:1476
@ CL_COL_TEAM
Definition pages.c:1470
@ CL_COL_COLOR
Definition pages.c:1468
@ CL_COL_COLLAPSED
Definition pages.c:1474
@ CL_COL_FLAG
Definition pages.c:1467
static void update_load_page(void)
Definition pages.c:2885
static void save_dialog_update(struct save_dialog *pdialog)
Definition pages.c:425
static GtkWidget * scenario_authors
Definition pages.c:64
static GtkWidget * start_aifill_spin
Definition pages.c:1457
static void ruleset_entry_changed(GtkWidget *w, gpointer data)
Definition pages.c:1621
void(* save_dialog_action_fn_t)(const char *filename)
Definition pages.c:370
static void open_settings(void)
Definition pages.c:139
static void set_connection_state(enum connection_state state)
Definition pages.c:928
static GtkWidget * ruleset_combo
Definition pages.c:91
static void observe_button_callback(GtkWidget *w, gpointer data)
Definition pages.c:2173
static void conn_menu_ready_chosen(GObject *object, gpointer data)
Definition pages.c:1694
static void server_scan_error(struct server_scan *scan, const char *message)
Definition pages.c:823
static void load_callback(void)
Definition pages.c:2858
static void save_dialog_file_chooser_callback(GtkWidget *widget, gint response, gpointer data)
Definition pages.c:442
static void network_list_callback(GtkTreeSelection *select, gpointer data)
Definition pages.c:1137
static GtkListStore * server_playerlist_store
Definition pages.c:70
static void nation_button_callback(GtkWidget *w, gpointer data)
Definition pages.c:2153
void real_set_client_page(enum client_pages new_page)
Definition pages.c:3347
static void conn_menu_connection_command(GObject *object, gpointer data)
Definition pages.c:1747
static void scenario_list_callback(void)
Definition pages.c:2981
static gboolean intro_expose(GtkWidget *w, cairo_t *cr, gpointer *data)
Definition pages.c:162
static void load_browse_callback(GtkWidget *w, gpointer data)
Definition pages.c:2875
static void network_activate_callback(GtkTreeView *view, GtkTreePath *arg1, GtkTreeViewColumn *arg2, gpointer data)
Definition pages.c:1096
static struct fileinfo_list * save_dialog_scenario_list(void)
Definition pages.c:3508
static void connection_state_reset(void)
Definition pages.c:996
void real_conn_list_dialog_update(void *unused)
Definition pages.c:2338
static bool holding_srv_list_mutex
Definition pages.c:93
static GtkTreeStore * connection_list_store
Definition pages.c:1455
static struct fileinfo_list * save_dialog_savegame_list(void)
Definition pages.c:3473
static void start_new_game_callback(GtkWidget *w, gpointer data)
Definition pages.c:100
void destroy_server_scans(void)
Definition pages.c:766
void save_scenario_dialog_popup(void)
Definition pages.c:3516
static GtkTreeSelection * lan_selection
Definition pages.c:73
static void save_dialog_save_scenario(const char *filename)
Definition pages.c:3500
struct fileinfo_list *(* save_dialog_files_fn_t)(void)
Definition pages.c:371
static gboolean check_server_scan(gpointer data)
Definition pages.c:789
static void save_dialog_store_update(GtkListStore *store, const struct fileinfo_list *files)
Definition pages.c:407
static void ai_fill_changed_by_user(GtkWidget *w, gpointer data)
Definition pages.c:1636
static gboolean delayed_unselect_path(gpointer data)
Definition pages.c:1967
static void conn_menu_player_take(GObject *object, gpointer data)
Definition pages.c:1734
static void conn_menu_info_chosen(GObject *object, gpointer data)
Definition pages.c:1792
static bool model_get_player_iter(GtkTreeModel *model, GtkTreeIter *iter, GtkTreeIter *start, const struct player *pplayer)
Definition pages.c:2278
static GtkTreeSelection * load_selection
Definition pages.c:72
static void ai_skill_callback(GtkWidget *w, gpointer data)
Definition pages.c:1583
static enum client_pages current_page
Definition pages.c:77
static GtkWidget * statusbar_frame
Definition pages.c:88
static GtkWidget * network_confirm_password
Definition pages.c:697
static void client_take_player(struct player *pplayer)
Definition pages.c:1517
static void clear_network_statusbar(void)
Definition pages.c:878
static GtkTreeSelection * meta_selection
Definition pages.c:73
static void save_dialog_row_callback(GtkTreeView *tree_view, GtkTreePath *path, GtkTreeViewColumn *column, gpointer data)
Definition pages.c:536
static void connection_list_row_callback(GtkTreeView *tree_view, GtkTreeIter *iter, GtkTreePath *path, gpointer data)
Definition pages.c:2037
save_dialog_response
Definition pages.c:388
@ SD_RES_DELETE
Definition pages.c:390
@ SD_RES_SAVE
Definition pages.c:391
@ SD_RES_BROWSE
Definition pages.c:389
GtkWidget * create_load_page(void)
Definition pages.c:2898
static GtkWidget * ai_lvl_combobox
Definition pages.c:1458
static GtkWidget * network_password_label
Definition pages.c:696
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:576
static GtkWidget * network_host
Definition pages.c:694
static void intro_free(GtkWidget *w, gpointer *data)
Definition pages.c:219
static GtkWidget * network_password
Definition pages.c:696
void handle_authentication_req(enum authentication_type type, const char *message)
Definition pages.c:1005
static GtkTreeStore * connection_list_store_new(void)
Definition pages.c:1482
static bool send_new_aifill_to_server
Definition pages.c:1635
static void save_dialog_file_chooser_popup(const char *title, GtkFileChooserAction action, save_dialog_action_fn_t cb)
Definition pages.c:462
static void add_tree_col(GtkWidget *treeview, GType gtype, const char *title, int colnum, const char *key)
Definition pages.c:2583
static void save_dialog_entry_callback(GtkEntry *entry, gpointer data)
Definition pages.c:547
static void main_callback(GtkWidget *w, gpointer data)
Definition pages.c:147
void update_start_page(void)
Definition pages.c:1669
static void scenario_callback(void)
Definition pages.c:3037
static GtkWidget * start_options_table
Definition pages.c:1453
static bool no_ruleset_callback
Definition pages.c:1604
void ai_fill_changed_by_server(int aifill)
Definition pages.c:1647
static void update_server_playerlist(const struct server *pserver)
Definition pages.c:1108
static GtkWidget * observe_button
Definition pages.c:1454
static GtkWidget * scenario_version
Definition pages.c:66
GtkWidget * create_statusbar(void)
Definition pages.c:907
static void game_options_callback(GtkWidget *w, gpointer data)
Definition pages.c:1575
static GtkListStore * scenario_store
Definition pages.c:68
static bool model_get_conn_iter(GtkTreeModel *model, GtkTreeIter *iter, GtkTreeIter *parent, GtkTreeIter *start, const struct connection *pconn)
Definition pages.c:2309
static GQueue * statusbar_queue
Definition pages.c:89
GtkWidget * start_message_area
Definition pages.c:1451
static void update_scenario_page(void)
Definition pages.c:3063
static GtkWidget * scenario_filename
Definition pages.c:65
static void conn_menu_team_chosen(GObject *object, gpointer data)
Definition pages.c:1677
static GtkWidget * create_conn_menu(struct player *pplayer, struct connection *pconn)
Definition pages.c:1806
static void load_saved_game_callback(GtkWidget *w, gpointer data)
Definition pages.c:122
static bool object_extract(GObject *object, struct player **ppplayer, struct connection **ppconn)
Definition pages.c:1548
static void object_put(GObject *object, struct player *pplayer, struct connection *pconn)
Definition pages.c:1529
static GtkWidget * network_port
Definition pages.c:695
static struct fileinfo_list * save_dialog_mapimg_list(void)
Definition pages.c:3537
GtkWidget * create_main_page(void)
Definition pages.c:229
static void conn_list_select_conn(struct connection *pconn)
Definition pages.c:2088
static GtkWidget * ready_button
Definition pages.c:1454
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:1015
void main_message_area_resize(void *data)
Definition gui_main.c:362
void widget_destroyed(GtkWidget *wdg, void *data)
Definition gui_stuff.c:1158
#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:2094
static void close_conn_menu_popover(void)
Definition pages.c:1705
static gboolean connect_list_left_button(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data)
Definition pages.c:2065
static GtkWidget * conn_popover
Definition pages.c:95
void(* save_dialog_action_fn_t)(const char *filename)
Definition pages.c:605
struct fileinfo_list *(* save_dialog_files_fn_t)(void)
Definition pages.c:606
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
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)
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:1174
#define NO_NATION_SELECTED
Definition nation.h:30
const struct option_set * server_optset
Definition options.c:4369
const struct option_set * client_optset
Definition options.c:1331
int option_int_get(const struct option *poption)
Definition options.c:885
struct option * optset_option_by_name(const struct option_set *poptset, const char *name)
Definition options.c:482
bool option_int_set(struct option *poption, int val)
Definition options.c:929
bool is_settable_ai_level(enum ai_level level)
Definition player.c:1908
struct player * player_by_number(const int player_id)
Definition player.c:837
int player_slot_count(void)
Definition player.c:415
int player_number(const struct player *pplayer)
Definition player.c:826
const char * player_name(const struct player *pplayer)
Definition player.c:885
bool player_has_flag(const struct player *pplayer, enum plr_flag_id flag)
Definition player.c:1979
#define ai_level_cmd(_level_)
Definition player.h:582
#define players_iterate_end
Definition player.h:552
#define players_iterate(_pplayer)
Definition player.h:547
#define is_ai(plr)
Definition player.h:232
#define players_iterate_alive_end
Definition player.h:562
#define is_human(plr)
Definition player.h:231
#define players_iterate_alive(_pplayer)
Definition player.h:557
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:865
void server_scan_finish(struct server_scan *scan)
Definition servers.c:878
struct server_scan * server_scan_begin(enum server_scan_type type, ServerScanErrorFunc error_func)
Definition servers.c:754
enum server_scan_type server_scan_get_type(const struct server_scan *scan)
Definition servers.c:808
enum server_scan_status server_scan_poll(struct server_scan *scan)
Definition servers.c:831
#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:2556
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:377
GtkEntry * entry
Definition pages.c:376
GtkTreeView * tree_view
Definition pages.c:375
GtkDialog * shell
Definition pages.c:374
save_dialog_files_fn_t files
Definition pages.c:378
struct server_scan * scan
Definition pages.c:81
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:925
int cat_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:951
int fc_remove(const char *filename)
Definition support.c:520
#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:409
struct team * team_slot_get_team(const struct team_slot *tslot)
Definition team.c:149
const char * team_slot_name_translation(const struct team_slot *tslot)
Definition team.c:248
int team_number(const struct team *pteam)
Definition team.c:383
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:443
bool team_slot_is_used(const struct team_slot *tslot)
Definition team.c:160
const char * team_slot_rule_name(const struct team_slot *tslot)
Definition team.c:229
#define team_slots_iterate_end
Definition team.h:89
#define team_slots_iterate(_tslot)
Definition team.h:84
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
#define MINOR_VERSION
Definition version_gen.h:7
#define VERSION_STRING
Definition version_gen.h:14
#define MAJOR_VERSION
Definition version_gen.h:6
#define PATCH_VERSION
Definition version_gen.h:8