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-5.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#define FC_TYPE_HOST_ROW (fc_host_row_get_type())
104
106
119
124
126
136
137
138#define FC_TYPE_PLR_ROW (fc_plr_row_get_type())
139
141
151
156
158
165
166
167#define FC_TYPE_SCEN_ROW (fc_scen_row_get_type())
168
170
181
186
188
189
190#define FC_TYPE_SAVE_ROW (fc_save_row_get_type())
191
193
201
206
208
209/**********************************************************************/
212static void
216
217/**********************************************************************/
220static void
224
225/**********************************************************************/
228#if 0
229static FcHostRow *fc_host_row_new(void)
230{
231 FcHostRow *result;
232
233 result = g_object_new(FC_TYPE_HOST_ROW, nullptr);
234
235 return result;
236}
237#endif
238
239/**********************************************************************/
242static void
246
247/**********************************************************************/
250static void
254
255/**********************************************************************/
258#if 0
259static FcPlrRow *fc_plr_row_new(void)
260{
261 FcPlrRow *result;
262
263 result = g_object_new(FC_TYPE_PLR_ROW, nullptr);
264
265 return result;
266}
267#endif
268
269/**********************************************************************/
272static void
276
277/**********************************************************************/
280static void
284
285/**********************************************************************/
288#if 0
289static FcScenRow *fc_scen_row_new(void)
290{
291 FcScenRow *result;
292
293 result = g_object_new(FC_TYPE_SCEN_ROW, nullptr);
294
295 return result;
296}
297#endif
298
299/**********************************************************************/
302static void
306
307/**********************************************************************/
310static void
314
315/**********************************************************************/
318#if 0
319static FcSaveRow *fc_save_row_new(void)
320{
321 FcSaveRow *result;
322
323 result = g_object_new(FC_TYPE_SAVE_ROW, nullptr);
324
325 return result;
326}
327#endif
328
329/**********************************************************************/
333{
334 if (!is_server_running()) {
336
337 /* Saved settings are sent in client/options.c
338 * resend_desired_settable_options() */
339 }
340}
341
342/**********************************************************************/
346{
347 output_window_append(ftc_client, _("Compiling scenario list."));
349}
350
351/**********************************************************************/
358
359/**********************************************************************/
367
368/**********************************************************************/
371static void open_settings(void)
372{
373 option_dialog_popup(_("Set local options"), client_optset);
374}
375
376/**********************************************************************/
379static void main_callback(GtkWidget *w, gpointer data)
380{
381 enum client_pages page = PAGE_MAIN;
382
383 if (client.conn.used) {
385 }
386 if (page != get_client_page()) {
387 set_client_page(page);
388 }
389}
390
391/**********************************************************************/
395 int width, int height, gpointer data)
396{
397 static PangoLayout *layout;
399 static int pwidth, pheight;
400 static bool left = FALSE;
402 struct sprite *intro = (struct sprite *)data;
403
404 cairo_set_source_surface(cr, intro->surface, 0, 0);
405 cairo_paint(cr);
406
407 if (!layout) {
408 char msgbuf[128];
409 const char *rev_ver;
410
412 desc = pango_font_description_from_string("Sans Bold 10");
415
417
418 if (rev_ver == NULL) {
419 /* TRANS: "version 2.6.0, gui-gtk-3.22 client" */
420 fc_snprintf(msgbuf, sizeof(msgbuf), _("%s%s, %s client"),
422 } else {
423 /* TRANS: "version 2.6.0
424 * commit: [modified] <git commit id>
425 * gui-gtk-3.22 client" */
426 fc_snprintf(msgbuf, sizeof(msgbuf), _("%s%s\ncommit: %s\n%s client"),
428 left = TRUE;
429 }
431
433 }
435
436 cairo_set_source_rgb(cr, 0, 0, 0);
437 cairo_move_to(cr, left ? 4 : allocation.width - pwidth - 3,
438 allocation.height - pheight - 3);
440
441 cairo_set_source_rgb(cr, 1, 1, 1);
442 cairo_move_to(cr, left ? 3 : allocation.width - pwidth - 4,
443 allocation.height - pheight - 4);
445}
446
447/**********************************************************************/
450static void intro_free(GtkWidget *w, gpointer *data)
451{
452 struct sprite *intro = (struct sprite *)data;
453
455}
456
457/**********************************************************************/
461{
462 GtkWidget *widget, *vgrid, *frame, *darea, *button, *table;
464 struct sprite *intro_in, *intro;
465 int width, height;
466 int sh;
467 int space_needed;
468 int grid_row = 0;
469
471
475 widget = vgrid;
476
477 frame = gtk_frame_new(NULL);
479 gtk_widget_set_margin_end(frame, 18);
481 gtk_widget_set_margin_top(frame, 18);
483 gtk_grid_attach(GTK_GRID(vgrid), frame, 0, grid_row++, 1, 1);
484
487 sh = screen_height();
488
489 if (sh <= 0) {
490 /* Assume some minimum height */
491 sh = 600;
492 }
493
494 space_needed = 250;
495#if IS_BETA_VERSION || IS_DEVEL_VERSION
496 /* Alpha or Beta notice takes extra space */
497 space_needed += 50;
498#endif
499
500 if (sh - height < space_needed) {
501 float scale;
502
503 if (sh < (space_needed + 0.2 * height)) {
504 /* Screen is simply too small, use minimum scale */
505 scale = 0.2;
506 } else {
507 scale = (double)(sh - space_needed) / height;
508 }
509 height *= scale;
510 width *= scale;
513 } else {
514 intro = intro_in;
515 }
516 darea = gtk_drawing_area_new();
520 g_signal_connect(widget, "destroy",
522 gtk_frame_set_child(GTK_FRAME(frame), darea);
523
524#if IS_BETA_VERSION || IS_DEVEL_VERSION
525 {
526 GtkWidget *label;
527
529 gtk_widget_set_name(label, "beta_label");
533 gtk_grid_attach(GTK_GRID(vgrid), label, 0, grid_row++, 1, 1);
534 }
535#endif /* IS_BETA_VERSION || IS_DEVEL_VERSION */
536
546
550
551 button = gtk_button_new_with_mnemonic(_("Start _New Game"));
553 gtk_grid_attach(GTK_GRID(table), button, 0, 0, 1, 1);
555 _("Launches local server, and connects to it for a single-player game."));
556 g_signal_connect(button, "clicked",
558
559 button = gtk_button_new_with_mnemonic(_("Start _Scenario Game"));
561 gtk_grid_attach(GTK_GRID(table), button, 0, 1, 1, 1);
563 _("Loads one of the scenarios for a single-player game. "
564 "Tutorial is one of the scenarios."));
565 g_signal_connect(button, "clicked",
567
568 button = gtk_button_new_with_mnemonic(_("_Load Saved Game"));
570 gtk_grid_attach(GTK_GRID(table), button, 0, 2, 1, 1);
572 _("Continues previously saved single-player game."));
573 g_signal_connect(button, "clicked",
575
576 button = gtk_button_new_with_mnemonic(_("C_onnect to Network Game"));
578 gtk_grid_attach(GTK_GRID(table), button, 1, 0, 1, 1);
580 _("Connects to outside server. "
581 "Sometimes you want to launch a separate server even for local games."));
582 g_signal_connect(button, "clicked",
584
585 button = gtk_button_new_with_mnemonic(_("Client Settings"));
587 gtk_grid_attach(GTK_GRID(table), button, 1, 1, 1, 1);
589 _("Adjusting client-side options."));
590 g_signal_connect(button, "clicked", open_settings, NULL);
591
592 button = icon_label_button_new("application-exit", _("E_xit"));
595 gtk_grid_attach(GTK_GRID(table), button, 1, 2, 1, 1);
597 _("Gives you a break from playing freeciv."));
598 g_signal_connect(button, "clicked",
600
601 return widget;
602}
603
604/****************************************************************************
605 GENERIC SAVE DIALOG
606****************************************************************************/
607typedef void (*save_dialog_action_fn_t) (const char *filename);
608typedef struct fileinfo_list * (*save_dialog_files_fn_t) (void);
609
610struct save_dialog {
616};
617
624
630
631/**********************************************************************/
635{
637 G_TYPE_STRING, /* SD_COL_PRETTY_NAME */
638 G_TYPE_STRING); /* SD_COL_FULL_PATH */
639}
640
641/**********************************************************************/
645 const struct fileinfo_list *files)
646{
648
652 gtk_list_store_set(store, &iter,
654 SD_COL_FULL_PATH, pfile->fullname,
655 -1);
657}
658
659/**********************************************************************/
662static void save_dialog_update(struct save_dialog *pdialog)
663{
664 struct fileinfo_list *files;
665
666 fc_assert_ret(NULL != pdialog);
667
668 /* Update the store. */
669 files = pdialog->files();
672 files);
674}
675
676/**********************************************************************/
680 gint response, gpointer data)
681{
682 if (response == GTK_RESPONSE_OK) {
685
686 if (file != NULL) {
687 gchar *filename = g_file_get_parse_name(file);
688
689 if (NULL != filename) {
690 action(filename);
691 g_free(filename);
692 }
693
694 g_object_unref(file);
695 }
696 }
697
699}
700
701/**********************************************************************/
704static void save_dialog_file_chooser_popup(const char *title,
707{
709
710 /* Create the chooser */
712 _("_Cancel"), GTK_RESPONSE_CANCEL,
714 _("_Save") : _("_Open"),
717
718 g_signal_connect(filechoose, "response",
720
721 /* Display that dialog */
723}
724
725/**********************************************************************/
729 gpointer data)
730{
731 struct save_dialog *pdialog = data;
732
733 switch (response) {
734 case SD_RES_BROWSE:
735 save_dialog_file_chooser_popup(_("Select Location to Save"),
737 pdialog->action);
738 break;
739 case SD_RES_DELETE:
740 {
741 GtkTreeSelection *selection;
742 GtkTreeModel *model;
744 const gchar *full_path;
745
746 selection = gtk_tree_view_get_selection(pdialog->tree_view);
747 if (!gtk_tree_selection_get_selected(selection, &model, &iter)) {
748 return;
749 }
750
751 gtk_tree_model_get(model, &iter, SD_COL_FULL_PATH, &full_path, -1);
752 fc_remove(full_path);
753 save_dialog_update(pdialog);
754 }
755 return;
756 case SD_RES_SAVE:
757 {
758 const char *text = gtk_entry_buffer_get_text(gtk_entry_get_buffer(pdialog->entry));
759 gchar *filename = g_filename_from_utf8(text, -1, NULL, NULL, NULL);
760
761 if (NULL == filename) {
762 return;
763 }
764 pdialog->action(filename);
765 g_free(filename);
766 }
767 break;
768 default:
769 break;
770 }
771
773}
774
775/**********************************************************************/
785
786/**********************************************************************/
793
794/**********************************************************************/
798 gpointer data)
799{
800 struct save_dialog *pdialog = data;
801 GtkTreeModel *model;
803 const gchar *filename;
804
805 if (!gtk_tree_selection_get_selected(selection, &model, &iter)) {
807 return;
808 }
809
811 gtk_tree_model_get(model, &iter, SD_COL_PRETTY_NAME, &filename, -1);
813}
814
815/**********************************************************************/
829
830/**********************************************************************/
839
840/**********************************************************************/
843static GtkWidget *save_dialog_new(const char *title, const char *savelabel,
844 const char *savefilelabel,
847{
848 GtkWidget *shell, *sbox, *sw, *label, *view, *entry;
849 GtkBox *vbox;
850 GtkListStore *store;
853 GtkTreeSelection *selection;
854 struct save_dialog *pdialog;
855
858
859 /* Save dialog structure. */
860 pdialog = fc_malloc(sizeof(*pdialog));
861 pdialog->action = action;
862 pdialog->files = files;
863
864 /* Shell. */
866 _("_Browse..."), SD_RES_BROWSE,
867 _("_Delete"), SD_RES_DELETE,
868 _("_Cancel"), GTK_RESPONSE_CANCEL,
869 _("_Save"), SD_RES_SAVE,
870 NULL);
871 g_object_set_data_full(G_OBJECT(shell), "save_dialog", pdialog,
876 g_signal_connect(shell, "response",
878 pdialog->shell = GTK_DIALOG(shell);
880
881 /* Tree view. */
882 store = save_dialog_store_new();
883
886 nullptr);
888 nullptr);
889
893 g_object_unref(store);
895 g_signal_connect(view, "row-activated",
897 pdialog->tree_view = GTK_TREE_VIEW(view);
898
900 gtk_box_append(vbox, sbox);
901
903 "use-underline", TRUE,
904 "mnemonic-widget", view,
905 "label", savelabel,
906 "xalign", 0.0,
907 "yalign", 0.5,
908 NULL);
909 gtk_box_append(GTK_BOX(sbox), label);
910
919
922 g_signal_connect(selection, "changed",
924
927 -1, NULL, rend, "text",
929
930 /* Entry. */
933 g_signal_connect(entry, "activate",
935 pdialog->entry = GTK_ENTRY(entry);
936
942
944 "use-underline", TRUE,
945 "mnemonic-widget", entry,
946 "label", savefilelabel,
947 "xalign", 0.0,
948 "yalign", 0.5,
949 NULL);
950 gtk_box_append(GTK_BOX(sbox), label);
951
953 gtk_box_append(vbox, sbox);
954
955 save_dialog_update(pdialog);
958
959 return shell;
960}
961
962/****************************************************************************
963 NETWORK PAGE
964****************************************************************************/
970
971/**********************************************************************/
975 const struct server_list *list)
976{
979 GtkTreeIter it;
980 GtkListStore *store;
981 const gchar *host, *portstr;
982 int port;
983
984 switch (sstype) {
987 break;
990 break;
991 default:
992 break;
993 }
994
995 if (!sel) {
996 return;
997 }
998
1001 gtk_list_store_clear(store);
1002
1003 if (!list) {
1004 return;
1005 }
1006
1009 port = atoi(portstr);
1010
1012 char buf[35];
1013
1014 if (pserver->humans >= 0) {
1015 fc_snprintf(buf, sizeof(buf), "%d", pserver->humans);
1016 } else {
1017 sz_strlcpy(buf, _("Unknown"));
1018 }
1019 gtk_list_store_append(store, &it);
1020 gtk_list_store_set(store, &it,
1021 0, pserver->host,
1022 1, pserver->port,
1023 2, pserver->version,
1024 3, _(pserver->state),
1025 4, pserver->nplayers,
1026 5, buf,
1027 6, pserver->message,
1028 -1);
1029 if (strcmp(host, pserver->host) == 0 && port == pserver->port) {
1031 }
1033}
1034
1035/**********************************************************************/
1039{
1040 if (meta_scan.scan) {
1043 }
1044 if (meta_scan.timer != 0) {
1046 meta_scan.timer = 0;
1047 }
1048 if (lan_scan.scan) {
1050 lan_scan.scan = NULL;
1051 }
1052 if (lan_scan.timer != 0) {
1054 lan_scan.timer = 0;
1055 }
1056}
1057
1058/**********************************************************************/
1062{
1063 struct server_scan_timer_data *scan_data = data;
1064 struct server_scan *scan = scan_data->scan;
1066
1067 if (!scan) {
1068 return FALSE;
1069 }
1070
1071 stat = server_scan_poll(scan);
1072 if (stat >= SCAN_STATUS_PARTIAL) {
1074 struct srv_list *srvrs;
1075
1076 type = server_scan_get_type(scan);
1077 srvrs = server_scan_get_list(scan);
1078 fc_mutex_allocate(&srvrs->mutex);
1082 fc_mutex_release(&srvrs->mutex);
1083 }
1084
1086 scan_data->timer = 0;
1087 return FALSE;
1088 }
1089 return TRUE;
1090}
1091
1092/**********************************************************************/
1095static void server_scan_error(struct server_scan *scan,
1096 const char *message)
1097{
1099 log_error("%s", message);
1100
1101 /* Main thread will finalize the scan later (or even concurrently) -
1102 * do not do anything here to cause double free or raze condition. */
1103}
1104
1105/**********************************************************************/
1118
1119/**************************************************************************
1120 Network connection state defines.
1121**************************************************************************/
1128
1130
1131/**********************************************************************/
1135{
1137 char *txt;
1138
1141 free(txt);
1142 }
1143
1144 return TRUE;
1145}
1146
1147/**********************************************************************/
1151{
1153 char *txt;
1154
1156 free(txt);
1157 }
1158
1160}
1161
1162/**********************************************************************/
1165void append_network_statusbar(const char *text, bool force)
1166{
1168 if (force) {
1171 } else {
1173 }
1174 }
1175}
1176
1177/**********************************************************************/
1196
1197/**********************************************************************/
1201{
1202 switch (state) {
1203 case LOGIN_TYPE:
1205
1207 "", -1);
1209 "", -1);
1210
1219 break;
1220 case NEW_PASSWORD_TYPE:
1224 "", -1);
1225
1234
1236 break;
1241 "", -1);
1242
1251
1253 break;
1254 case WAITING_TYPE:
1256
1263 break;
1264 }
1265
1266 connection_status = state;
1267}
1268
1269/**********************************************************************/
1272static void connection_state_reset(void)
1273{
1275}
1276
1277/**********************************************************************/
1282 const char *message)
1283{
1285
1286 switch (type) {
1287 case AUTH_NEWUSER_FIRST:
1288 case AUTH_NEWUSER_RETRY:
1290 return;
1291 case AUTH_LOGIN_FIRST:
1292 /* if we magically have a password already present in 'fc_password'
1293 * then, use that and skip the password entry dialog */
1294 if (fc_password[0] != '\0') {
1296
1297 sz_strlcpy(reply.password, fc_password);
1299 return;
1300 } else {
1302 }
1303 return;
1304 case AUTH_LOGIN_RETRY:
1306 return;
1307 }
1308
1309 log_error("Unsupported authentication type %d: %s.", type, message);
1310}
1311
1312/**********************************************************************/
1318{
1319 char errbuf [512];
1321
1322 switch (connection_status) {
1323 case LOGIN_TYPE:
1329
1331 errbuf, sizeof(errbuf)) != -1) {
1332 } else {
1334
1336 }
1337 return;
1338 case NEW_PASSWORD_TYPE:
1339 if (w != network_password) {
1342 sz_strlcpy(reply.password,
1344 if (!fc_strncmp(reply.password, fc_password, MAX_LEN_NAME)) {
1345 fc_password[0] = '\0';
1347
1349 } else {
1350 append_network_statusbar(_("Passwords don't match, enter password."),
1351 TRUE);
1352
1354 }
1355 }
1356 return;
1358 sz_strlcpy(reply.password,
1361
1363 return;
1364 case WAITING_TYPE:
1365 return;
1366 }
1367
1368 log_error("Unsupported connection status: %d", connection_status);
1369}
1370
1371/**********************************************************************/
1377 gpointer data)
1378{
1379 connect_callback(NULL, data);
1380}
1381
1382/**********************************************************************/
1386static void update_server_playerlist(const struct server *pserver)
1387{
1388 GtkListStore *store;
1390 int n, i;
1391
1393 fc_assert_ret(store != NULL);
1394
1395 gtk_list_store_clear(store);
1396 if (!pserver || !pserver->players) {
1397 return;
1398 }
1399
1400 n = pserver->nplayers;
1401 for (i = 0; i < n; i++) {
1402 gtk_list_store_append(store, &iter);
1403 gtk_list_store_set(store, &iter,
1404 0, pserver->players[i].name,
1405 1, pserver->players[i].type,
1406 2, pserver->players[i].host,
1407 3, pserver->players[i].nation,
1408 -1);
1409 }
1410}
1411
1412/**********************************************************************/
1416{
1417 GtkTreeModel *model;
1418 GtkTreeIter it;
1419 const char *host;
1420 int port;
1421 char portstr[32];
1422 const struct server *pserver = NULL;
1423
1424 if (!gtk_tree_selection_get_selected(select, &model, &it)) {
1425 return;
1426 }
1427
1428 if (select == meta_selection) {
1429 GtkTreePath *path;
1430 struct srv_list *srvrs;
1431
1433 path = gtk_tree_model_get_path(model, &it);
1435 /* We are not yet inside mutex protected block */
1436 fc_mutex_allocate(&srvrs->mutex);
1437 }
1438 if (srvrs->servers && path) {
1440
1442 }
1444 /* We are not yet inside mutex protected block */
1445 fc_mutex_release(&srvrs->mutex);
1446 }
1447 gtk_tree_path_free(path);
1448 }
1450
1451 gtk_tree_model_get(model, &it, 0, &host, 1, &port, -1);
1452
1454 fc_snprintf(portstr, sizeof(portstr), "%d", port);
1456}
1457
1458/**********************************************************************/
1473
1474/**********************************************************************/
1479 gpointer user_data)
1480{
1481 FcHostRow *row;
1483 char buf[512];
1484
1486
1487 switch (GPOINTER_TO_INT(user_data)) {
1488 case host_row_host:
1489 gtk_label_set_text(GTK_LABEL(child), row->host);
1490 break;
1491 case host_row_port:
1492 fc_snprintf(buf, sizeof(buf), "%d", row->port);
1494 break;
1495 case host_row_version:
1496 gtk_label_set_text(GTK_LABEL(child), row->version);
1497 break;
1498 case host_row_state:
1499 gtk_label_set_text(GTK_LABEL(child), row->state);
1500 break;
1501 case host_row_nplayers:
1502 fc_snprintf(buf, sizeof(buf), "%d", row->nplayers);
1504 break;
1505 case host_row_humans:
1506 gtk_label_set_text(GTK_LABEL(child), row->humans);
1507 break;
1508 case host_row_message:
1509 gtk_label_set_text(GTK_LABEL(child), row->message);
1510 break;
1511 }
1512}
1513
1514/**********************************************************************/
1523
1524/**********************************************************************/
1529 gpointer user_data)
1530{
1531 FcPlrRow *row;
1533
1535
1536 switch (GPOINTER_TO_INT(user_data)) {
1537 case plr_row_name:
1538 gtk_label_set_text(GTK_LABEL(child), row->name);
1539 break;
1540 case plr_row_type:
1541 gtk_label_set_text(GTK_LABEL(child), row->type);
1542 break;
1543 case plr_row_host:
1544 gtk_label_set_text(GTK_LABEL(child), row->host);
1545 break;
1546 case plr_row_nation:
1547 gtk_label_set_text(GTK_LABEL(child), row->nation);
1548 break;
1549 }
1550}
1551
1552/**********************************************************************/
1561
1562/**********************************************************************/
1566{
1567 GtkWidget *box, *sbox, *bbox, *hbox, *notebook;
1568 GtkWidget *button, *label, *view, *sw, *table;
1569 GtkTreeSelection *selection;
1570 GtkListStore *store;
1573
1579
1580 notebook = gtk_notebook_new();
1581 gtk_box_append(GTK_BOX(box), notebook);
1582
1583 /* LAN pane. */
1585 G_TYPE_INT, /* port */
1586 G_TYPE_STRING, /* version */
1587 G_TYPE_STRING, /* state */
1588 G_TYPE_INT, /* nplayers */
1589 G_TYPE_STRING, /* humans */
1590 G_TYPE_STRING); /* message */
1591
1596 nullptr);
1597
1603
1605 lan_selection = selection;
1607
1612
1613 g_signal_connect(view, "row-activated",
1615 g_signal_connect(selection, "changed",
1617
1618 add_treeview_column(view, _("Server Name"), G_TYPE_STRING, 0);
1619 add_treeview_column(view, _("Port"), G_TYPE_INT, 1);
1620 add_treeview_column(view, _("Version"), G_TYPE_STRING, 2);
1621 add_treeview_column(view, _("Status"), G_TYPE_STRING, 3);
1622 add_treeview_column(view, _("Players"), G_TYPE_INT, 4);
1623 add_treeview_column(view, _("Humans"), G_TYPE_STRING, 5);
1624 add_treeview_column(view, _("Comment"), G_TYPE_STRING, 6);
1625
1626 label = gtk_label_new_with_mnemonic(_("Local _Area Network"));
1627
1637 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), sw, label);
1638
1639
1640 /* Metaserver pane. */
1642 G_TYPE_INT, /* port */
1643 G_TYPE_STRING, /* version */
1644 G_TYPE_STRING, /* state */
1645 G_TYPE_INT, /* nplayers */
1646 G_TYPE_STRING, /* humans */
1647 G_TYPE_STRING); /* message */
1648
1654
1656 meta_selection = selection;
1658
1663
1664 g_signal_connect(view, "row-activated",
1666 g_signal_connect(selection, "changed",
1668
1669 add_treeview_column(view, _("Server Name"), G_TYPE_STRING, 0);
1670 add_treeview_column(view, _("Port"), G_TYPE_INT, 1);
1671 add_treeview_column(view, _("Version"), G_TYPE_STRING, 2);
1672 add_treeview_column(view, _("Status"), G_TYPE_STRING, 3);
1673 add_treeview_column(view, _("Players"), G_TYPE_INT, 4);
1674 add_treeview_column(view, _("Humans"), G_TYPE_STRING, 5);
1675 add_treeview_column(view, _("Comment"), G_TYPE_STRING, 6);
1676
1677 label = gtk_label_new_with_mnemonic(_("Internet _Metaserver"));
1678
1689 gtk_notebook_prepend_page(GTK_NOTEBOOK(notebook), sw, label);
1690 } else {
1691 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), sw, label);
1692 }
1693
1694 /* Bottom part of the page, outside the inner notebook. */
1697
1704
1705 table = gtk_grid_new();
1709
1711 g_signal_connect(network_host, "activate",
1714
1716 "use-underline", TRUE,
1717 "mnemonic-widget", network_host,
1718 "label", _("_Host:"),
1719 "xalign", 0.0,
1720 "yalign", 0.5,
1721 NULL);
1722 network_host_label = label;
1723 gtk_grid_attach(GTK_GRID(table), label, 0, 0, 1, 1);
1724
1726 g_signal_connect(network_port, "activate",
1729
1731 "use-underline", TRUE,
1732 "mnemonic-widget", network_port,
1733 "label", _("_Port:"),
1734 "xalign", 0.0,
1735 "yalign", 0.5,
1736 NULL);
1737 network_port_label = label;
1738 gtk_grid_attach(GTK_GRID(table), label, 0, 1, 1, 1);
1739
1742 g_signal_connect(network_login, "activate",
1745
1747 "use-underline", TRUE,
1748 "mnemonic-widget", network_login,
1749 "label", _("_Login:"),
1750 "xalign", 0.0,
1751 "yalign", 0.5,
1752 NULL);
1753 gtk_widget_set_margin_top(label, 10);
1754 network_login_label = label;
1755 gtk_grid_attach(GTK_GRID(table), label, 0, 3, 1, 1);
1756
1762
1764 "use-underline", TRUE,
1765 "mnemonic-widget", network_password,
1766 "label", _("Pass_word:"),
1767 "xalign", 0.0,
1768 "yalign", 0.5,
1769 NULL);
1770 network_password_label = label;
1771 gtk_grid_attach(GTK_GRID(table), label, 0, 4, 1, 1);
1772
1778
1780 "use-underline", TRUE,
1781 "mnemonic-widget", network_confirm_password,
1782 "label", _("Conf_irm Password:"),
1783 "xalign", 0.0,
1784 "yalign", 0.5,
1785 NULL);
1787 gtk_grid_attach(GTK_GRID(table), label, 0, 5, 1, 1);
1788
1789 /* Server player list. */
1795
1800 nullptr);
1801
1807 add_treeview_column(view, _("Nation"), G_TYPE_STRING, 3);
1809
1816
1824
1825 button = gtk_button_new_from_icon_name("view-refresh");
1826 gtk_box_append(GTK_BOX(bbox), button);
1827 g_signal_connect(button, "clicked",
1829
1830 button = gtk_button_new_with_mnemonic(_("_Cancel"));
1831 gtk_box_append(GTK_BOX(bbox), button);
1832 g_signal_connect(button, "clicked",
1834
1835 button = gtk_button_new_with_mnemonic(_("C_onnect"));
1836 gtk_box_append(GTK_BOX(bbox), button);
1837 g_signal_connect(button, "clicked",
1839
1840 return box;
1841}
1842
1843/****************************************************************************
1844 START PAGE
1845****************************************************************************/
1847
1854
1855
1856/* NB: Must match creation arguments in connection_list_store_new(). */
1873
1874/**********************************************************************/
1878{
1880 G_TYPE_INT, /* CL_COL_PLAYER_NUMBER */
1881 G_TYPE_STRING, /* CL_COL_USER_NAME */
1882 G_TYPE_BOOLEAN, /* CL_COL_READY_STATE */
1883 G_TYPE_STRING, /* CL_COL_PLAYER_NAME */
1884 GDK_TYPE_PIXBUF, /* CL_COL_FLAG */
1885 GDK_TYPE_PIXBUF, /* CL_COL_COLOR */
1886 G_TYPE_STRING, /* CL_COL_NATION */
1887 G_TYPE_STRING, /* CL_COL_TEAM */
1888 G_TYPE_INT, /* CL_COL_CONN_ID */
1889 G_TYPE_INT, /* CL_COL_STYLE */
1890 G_TYPE_INT, /* CL_COL_WEIGHT */
1891 G_TYPE_BOOLEAN); /* CL_COL_COLLAPSED */
1892}
1893
1894/**********************************************************************/
1898static void client_aitoggle_player(void *data)
1899{
1900 struct player *pplayer = player_by_number(FC_PTR_TO_INT(data));
1901
1902 if (NULL != pplayer
1903 && pplayer == client_player()
1904 && !is_human(pplayer)) {
1905 send_chat("/away");
1906 }
1907}
1908
1909/**********************************************************************/
1912static void client_take_player(struct player *pplayer)
1913{
1914 int request_id = send_chat_printf("/take \"%s\"", player_name(pplayer));
1915 void *data = FC_INT_TO_PTR(player_number(pplayer));
1916
1919}
1920
1921/**********************************************************************/
1924static void object_put(GObject *object, struct player *pplayer,
1925 struct connection *pconn)
1926{
1927 /* Note that passing -1 to GINT_TO_POINTER() is buggy with some versions
1928 * of gcc. player_slot_count() is not a valid player number. 0 is not
1929 * a valid connection id (see comment in server/sernet.c:
1930 * makeup_connection_name()). */
1931 g_object_set_data(object, "player_id",
1932 GINT_TO_POINTER(NULL != pplayer
1933 ? player_number(pplayer)
1934 : player_slot_count()));
1935 g_object_set_data(object, "connection_id",
1936 GINT_TO_POINTER(NULL != pconn ? pconn->id : 0));
1937}
1938
1939/**********************************************************************/
1943static bool object_extract(GObject *object, struct player **ppplayer,
1944 struct connection **ppconn)
1945{
1946 bool ret = FALSE;
1947 int id;
1948
1949 if (NULL != ppplayer) {
1950 id = GPOINTER_TO_INT(g_object_get_data(object, "player_id"));
1952 if (NULL != *ppplayer) {
1953 ret = TRUE;
1954 }
1955 }
1956 if (NULL != ppconn) {
1957 id = GPOINTER_TO_INT(g_object_get_data(object, "connection_id"));
1958 *ppconn = conn_by_number(id);
1959 if (NULL != *ppconn) {
1960 ret = TRUE;
1961 }
1962 }
1963
1964 return ret;
1965}
1966
1967/**********************************************************************/
1971{
1972 option_dialog_popup(_("Game Settings"), server_optset);
1973}
1974
1975/**********************************************************************/
1979{
1980 enum ai_level *levels = (enum ai_level *)data;
1981 const char *name;
1982 int i;
1983
1985
1986 if (i != -1) {
1987 enum ai_level level = levels[i];
1988
1989 /* Suppress changes provoked by server rather than local user */
1990 if (server_ai_level() != level) {
1992 send_chat_printf("/%s", name);
1993 }
1994 }
1995}
1996
1997/* HACK: sometimes when creating the ruleset combo the value is set without
1998 * the user's control. In this case we don't want to do a /read. */
2000
2001/**********************************************************************/
2004static void ruleset_selected(const char *name)
2005{
2006 if (name && name[0] != '\0' && !no_ruleset_callback) {
2008 }
2009}
2010
2011/**********************************************************************/
2017{
2018 const char *name = NULL;
2019
2021
2022 if (name != NULL) {
2024 }
2025}
2026
2027/**********************************************************************/
2038
2039/**********************************************************************/
2043{
2044 if (start_aifill_spin) {
2046 /* Suppress callback from this change to avoid a loop. */
2048 /* HACK: this GUI control doesn't have quite the same semantics as the
2049 * server 'aifill' option, in that it claims to represent the minimum
2050 * number of players _including humans_. The GUI control has a minimum
2051 * value of 1, so aifill == 0 will not be represented correctly.
2052 * But there's generally exactly one human player because the control
2053 * only shows up for a locally spawned server, so we more or less
2054 * get away with this. */
2057 }
2058}
2059
2060/**********************************************************************/
2064{
2066}
2067
2068/**********************************************************************/
2072{
2073 if (conn_popover != NULL){
2076
2078 }
2079}
2080
2081/**********************************************************************/
2085 gpointer data)
2086{
2087 struct player *pplayer;
2088 struct team_slot *tslot = g_object_get_data(G_OBJECT(action), "slot");
2089 GMenu *menu = data;
2090
2091 if (object_extract(G_OBJECT(menu), &pplayer, NULL)
2092 && NULL != tslot
2093 && team_slot_index(tslot) != team_number(pplayer->team)) {
2094 send_chat_printf("/team \"%s\" \"%s\"",
2095 player_name(pplayer),
2097 }
2098
2100}
2101
2102/**********************************************************************/
2106 gpointer data)
2107{
2108 struct player *pplayer;
2109 GMenu *menu = data;
2110
2111 if (object_extract(G_OBJECT(menu), &pplayer, NULL)) {
2113 player_number(pplayer), !pplayer->is_ready);
2114 }
2115
2117}
2118
2119/**********************************************************************/
2123 gpointer data)
2124{
2125 struct player *pplayer;
2126 GMenu *menu = data;
2127
2128 if (object_extract(G_OBJECT(menu), &pplayer, NULL)) {
2129 popup_races_dialog(pplayer);
2130 }
2131
2133}
2134
2135/**********************************************************************/
2140 gpointer data)
2141{
2142 struct player *pplayer;
2143 GMenu *menu = data;
2144
2145 if (object_extract(G_OBJECT(menu), &pplayer, NULL)) {
2146 send_chat_printf("/%s \"%s\"",
2147 (char *) g_object_get_data(G_OBJECT(action), "command"),
2148 player_name(pplayer));
2149 }
2150
2152}
2153
2154/**********************************************************************/
2158 gpointer data)
2159{
2160 struct player *pplayer;
2161 GMenu *menu = data;
2162
2163 if (object_extract(G_OBJECT(menu), &pplayer, NULL)) {
2164 client_take_player(pplayer);
2165 }
2166
2168}
2169
2170/**********************************************************************/
2175 GVariant *parameter, gpointer data)
2176{
2177 struct connection *pconn;
2178 GMenu *menu = data;
2179
2180 if (object_extract(G_OBJECT(menu), NULL, &pconn)) {
2182 (char *) g_object_get_data(G_OBJECT(action), "command"),
2183 pconn->username);
2184 }
2185
2187}
2188
2189/**********************************************************************/
2192static void show_conn_popup(struct player *pplayer, struct connection *pconn)
2193{
2195 char buf[4096] = "";
2196
2197 if (pconn) {
2198 cat_snprintf(buf, sizeof(buf), _("Connection name: %s"),
2199 pconn->username);
2200 } else {
2201 cat_snprintf(buf, sizeof(buf), _("Player name: %s"),
2202 player_name(pplayer));
2203 }
2204 cat_snprintf(buf, sizeof(buf), "\n");
2205 if (pconn) {
2206 cat_snprintf(buf, sizeof(buf), _("Host: %s"), pconn->addr);
2207 }
2208 cat_snprintf(buf, sizeof(buf), "\n");
2209
2210 /* Show popup. */
2213 "%s", buf);
2214 gtk_window_set_title(GTK_WINDOW(popup), _("Player/conn info"));
2218}
2219
2220/**********************************************************************/
2224 gpointer data)
2225{
2226 struct player *pplayer;
2227 struct connection *pconn;
2228 GMenu *menu = data;
2229
2230 if (object_extract(G_OBJECT(menu), &pplayer, &pconn)) {
2231 show_conn_popup(pplayer, pconn);
2232 }
2233
2235}
2236
2237/**********************************************************************/
2241static GtkWidget *create_conn_menu(struct player *pplayer,
2242 struct connection *pconn)
2243{
2244 GMenu *menu;
2245 gchar *buf;
2246 GSimpleAction *act;
2247 GActionGroup *group;
2248
2250
2251 menu = g_menu_new();
2252
2253 object_put(G_OBJECT(menu), pplayer, pconn);
2254
2255 buf = g_strdup_printf(_("%s info"),
2256 pconn ? pconn->username : player_name(pplayer));
2257
2258 act = g_simple_action_new("info", NULL);
2260 g_signal_connect(act, "activate", G_CALLBACK(conn_menu_info_chosen), menu);
2261 menu_item_append_unref(menu, g_menu_item_new(buf, "win.info"));
2262
2263 if (NULL != pplayer) {
2264 act = g_simple_action_new("toggle_ready", NULL);
2266 g_signal_connect(act, "activate", G_CALLBACK(conn_menu_ready_chosen), menu);
2268 menu_item_append_unref(menu, g_menu_item_new(_("Toggle player ready"),
2269 "win.toggle_ready"));
2270
2271 act = g_simple_action_new("pick_nation", NULL);
2273 g_signal_connect(act, "activate", G_CALLBACK(conn_menu_nation_chosen), menu);
2276 pplayer));
2277 menu_item_append_unref(menu, g_menu_item_new(_("Pick nation"), "win.pick_nation"));
2278
2279 act = g_simple_action_new("observe", NULL);
2280 g_object_set_data_full(G_OBJECT(act), "command", g_strdup("observe"),
2283 g_signal_connect(act, "activate", G_CALLBACK(conn_menu_player_command), menu);
2284 menu_item_append_unref(menu, g_menu_item_new(_("Observe this player"),
2285 "win.observe"));
2286
2287 act = g_simple_action_new("take_plr", NULL);
2289 g_signal_connect(act, "activate", G_CALLBACK(conn_menu_player_take), menu);
2290 menu_item_append_unref(menu, g_menu_item_new(_("Take this player"),
2291 "win.take_plr"));
2292 }
2293
2295 && pconn->id != client.conn.id) {
2296 act = g_simple_action_new("cut_conn", NULL);
2297 g_object_set_data_full(G_OBJECT(act), "command", g_strdup("cut"),
2301 menu_item_append_unref(menu, g_menu_item_new(_("Cut connection"), "win.cut_conn"));
2302 }
2303
2304 if (ALLOW_CTRL <= client.conn.access_level && NULL != pplayer) {
2305 act = g_simple_action_new("aitoggle", NULL);
2306 g_object_set_data_full(G_OBJECT(act), "command", g_strdup("aitoggle"),
2310 menu_item_append_unref(menu, g_menu_item_new(_("Aitoggle player"), "win.aitoggle"));
2311
2312 if (pplayer != client.conn.playing && game.info.is_new_game) {
2313 act = g_simple_action_new("remove", NULL);
2314 g_object_set_data_full(G_OBJECT(act), "command", g_strdup("remove"),
2318 menu_item_append_unref(menu, g_menu_item_new(_("Remove player"), "win.remove"));
2319 }
2320 }
2321
2323 && pconn->id != client.conn.id) {
2324 enum cmdlevel level;
2325
2326 /* No item for hack access; that would be a serious security hole. */
2328 char actbuf[128];
2329
2330 buf = g_strdup_printf(_("Give %s access"), cmdlevel_name(level));
2331 fc_snprintf(actbuf, sizeof(actbuf), "cmdlevel_%d", level);
2332
2334 g_object_set_data_full(G_OBJECT(act), "command",
2335 g_strdup_printf("cmdlevel %s",
2340 fc_snprintf(actbuf, sizeof(actbuf), "win.cmdlevel_%d", level);
2342 g_free(buf);
2343 }
2344 }
2345
2347 && NULL != pplayer && is_ai(pplayer)) {
2348 enum ai_level level;
2349
2350 for (level = 0; level < AI_LEVEL_COUNT; level++) {
2352 char actbuf[128];
2353
2354 buf = g_strdup_printf(_("Difficulty: %s"), ai_level_translated_name(level));
2355 fc_snprintf(actbuf, sizeof(actbuf), "ailevel_%d", level);
2356
2358 g_object_set_data_full(G_OBJECT(act), "command",
2362 g_signal_connect(act, "activate", G_CALLBACK(conn_menu_player_command), menu);
2363 fc_snprintf(actbuf, sizeof(actbuf), "win.ailevel_%d", level);
2365 g_free(buf);
2366 }
2367 }
2368 }
2369
2370 if (pplayer != NULL /* && game.info.is_new_game */) {
2371 const int count = pplayer->team
2372 ? player_list_size(team_members(pplayer->team)) : 0;
2373 bool need_empty_team = (count != 1);
2374
2375 /* Can't use team_iterate here since it skips empty teams. */
2377 char actbuf[128];
2378 int id;
2379
2380 if (!team_slot_is_used(tslot)) {
2381 if (!need_empty_team) {
2382 continue;
2383 }
2385 }
2386
2388
2389 /* TRANS: e.g., "Put on Team 5" */
2390 buf = g_strdup_printf(_("Put on %s"),
2392 fc_snprintf(actbuf, sizeof(actbuf), "team_%d", id);
2393
2395 g_object_set_data(G_OBJECT(act), "slot", tslot);
2397 g_signal_connect(act, "activate", G_CALLBACK(conn_menu_team_chosen), menu);
2398 fc_snprintf(actbuf, sizeof(actbuf), "win.team_%d", id);
2400 g_free(buf);
2402 }
2403
2408
2409 return conn_popover;
2410}
2411
2412/**********************************************************************/
2416{
2417 if (NULL != connection_list_view) {
2418 GtkTreeSelection *selection =
2420 GtkTreePath *path = data;
2421
2422 gtk_tree_selection_unselect_path(selection, path);
2423 gtk_tree_path_free(path);
2424 }
2425 return FALSE;
2426}
2427
2428/**********************************************************************/
2432 int n_press,
2433 double x, double y, gpointer data)
2434{
2437 GtkTreePath *path = NULL;
2439
2441 x, y,
2442 &path, NULL, NULL, NULL)) {
2443 return FALSE;
2444 }
2445
2446 if (gtk_tree_selection_path_is_selected(selection, path)) {
2447 /* Need to delay to avoid problem with the expander. */
2449 return FALSE; /* Return now, don't free the path. */
2450 }
2451
2452 gtk_tree_path_free(path);
2453
2454 return FALSE;
2455}
2456
2457/**********************************************************************/
2461 int n_press,
2462 double x, double y, gpointer data)
2463{
2466 GtkWidget *parent = data;
2467 GtkTreePath *path = NULL;
2468 GtkWidget *menu;
2469 GtkTreeSelection *selection;
2470 GtkTreeModel *model;
2472 int player_no, conn_id;
2473 struct player *pplayer;
2474 struct connection *pconn;
2475 int bx, by;
2476 GdkRectangle rect = { .x = x, .y = y, .width = 1, .height = 1};
2477
2479
2481 &path, NULL, NULL, NULL)) {
2482 return FALSE;
2483 }
2484
2487
2488 if (!gtk_tree_selection_path_is_selected(selection, path)) {
2489 gtk_tree_selection_select_path(selection, path);
2490 }
2491 gtk_tree_model_get_iter(model, &iter, path);
2492
2493 gtk_tree_model_get(model, &iter, CL_COL_PLAYER_NUMBER, &player_no, -1);
2494 pplayer = player_by_number(player_no);
2495
2496 gtk_tree_model_get(model, &iter, CL_COL_CONN_ID, &conn_id, -1);
2497 pconn = conn_by_number(conn_id);
2498
2499 menu = create_conn_menu(pplayer, pconn);
2500 gtk_widget_set_parent(menu, parent); /* Gtk bug prevents tree view parenting */
2502
2504
2505 gtk_tree_path_free(path);
2506
2507 return TRUE;
2508}
2509
2510/**********************************************************************/
2515 GtkTreePath *path,
2516 gpointer data)
2517{
2519
2520 gtk_tree_store_set(store, iter,
2522}
2523
2524/**********************************************************************/
2529 struct connection **ppconn)
2530{
2531 if (NULL != connection_list_view) {
2533 GtkTreeModel *model;
2534 GtkTreeSelection *selection =
2536
2537 if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
2538 int id;
2539
2540 if (NULL != ppplayer) {
2541 gtk_tree_model_get(model, &iter, CL_COL_PLAYER_NUMBER, &id, -1);
2543 }
2544 if (NULL != ppconn) {
2545 gtk_tree_model_get(model, &iter, CL_COL_CONN_ID, &id, -1);
2546 *ppconn = conn_by_number(id);
2547 }
2548 return TRUE;
2549 }
2550 }
2551
2552 if (NULL != ppplayer) {
2553 *ppplayer = NULL;
2554 }
2555 if (NULL != ppconn) {
2556 *ppconn = NULL;
2557 }
2558 return FALSE;
2559}
2560
2561/**********************************************************************/
2565{
2566 GtkTreeModel *model;
2567 GtkTreeIter parent, child, *iter = NULL;
2568 GtkTreeSelection *selection;
2569 gboolean valid;
2570 const int search_id = pconn->id;
2571 int id;
2572
2573 if (NULL == connection_list_view) {
2574 return;
2575 }
2576
2579
2580 /* Main iteration. */
2581 valid = gtk_tree_model_get_iter_first(model, &parent);
2582 while (valid && NULL == iter) {
2583 gtk_tree_model_get(model, &parent, CL_COL_CONN_ID, &id, -1);
2584 if (search_id == id) {
2585 iter = &parent;
2586 break;
2587 }
2588
2589 /* Node children iteration. */
2590 valid = gtk_tree_model_iter_children(model, &child, &parent);
2591 while (valid && NULL == iter) {
2592 gtk_tree_model_get(model, &child, CL_COL_CONN_ID, &id, -1);
2593 if (search_id == id) {
2594 iter = &child;
2595 break;
2596 }
2597 valid = gtk_tree_model_iter_next(model, &child);
2598 }
2599
2600 valid = gtk_tree_model_iter_next(model, &parent);
2601 }
2602
2603 /* Select iterator. */
2604 if (NULL != iter) {
2606 } else {
2607 log_error("%s(): connection %s not found.",
2609 }
2610}
2611
2612/**********************************************************************/
2616{
2617 if (can_client_control()) {
2620 !client_player()->is_ready);
2621 } else {
2623 }
2624}
2625
2626/**********************************************************************/
2630{
2631 struct player *selected_plr;
2632 bool row_selected = conn_list_selection(&selected_plr, NULL);
2633
2634 if (row_selected && NULL != selected_plr) {
2635 /* "Take <player_name>" */
2637 } else if (can_client_control()) {
2638 /* "Pick Nation" */
2640 } else {
2641 /* "Take a Player" */
2642 send_chat("/take -");
2643 }
2644}
2645
2646/**********************************************************************/
2650{
2651 struct player *selected_plr;
2652 bool row_selected = conn_list_selection(&selected_plr, NULL);
2653
2654 if (row_selected && NULL != selected_plr) {
2655 /* "Observe <player_name>" */
2656 send_chat_printf("/observe \"%s\"", player_name(selected_plr));
2657 } else if (!client_is_global_observer()) {
2658 /* "Observe" */
2659 send_chat("/observe");
2660 } else {
2661 /* "Do not observe" */
2662 send_chat("/detach");
2663 }
2664}
2665
2666/**********************************************************************/
2670{
2671 char buf[2 * MAX_LEN_NAME];
2672 const char *text;
2673 struct player *selected_plr;
2674 bool row_selected = conn_list_selection(&selected_plr, NULL);
2675 bool sensitive;
2676
2677 /*** Ready button. ***/
2678 if (can_client_control()) {
2679 sensitive = client_player()->is_alive;
2680 if (client_player()->is_ready) {
2681 text = _("Not _ready");
2682 } else {
2683 int num_unready = 0;
2684
2685 players_iterate_alive(pplayer) {
2686 if (is_human(pplayer) && !pplayer->is_ready) {
2687 num_unready++;
2688 }
2690
2691 if (num_unready > 1) {
2692 text = _("_Ready");
2693 } else {
2694 /* We are the last unready player so clicking here will
2695 * immediately start the game. */
2696 text = _("_Start");
2697 }
2698 }
2699 } else {
2700 text = _("_Start");
2701 if (can_client_access_hack()) {
2702 sensitive = TRUE;
2704 if (is_human(plr)) {
2705 /* There's human controlled player(s) in game, so it's their
2706 * job to start the game. */
2707 sensitive = FALSE;
2708 break;
2709 }
2711 } else {
2712 sensitive = FALSE;
2713 }
2714 }
2717
2718 /*** Nation button. ***/
2719 if (row_selected && NULL != selected_plr) {
2720 fc_snprintf(buf, sizeof(buf), _("_Take %s"), player_name(selected_plr));
2721 text = buf;
2723 } else if (can_client_control()) {
2724 text = _("Pick _Nation");
2726 } else {
2727 text = _("_Take a Player");
2729 }
2732
2733 /*** Observe button. ***/
2734 if (row_selected && NULL != selected_plr) {
2735 fc_snprintf(buf, sizeof(buf), _("_Observe %s"),
2737 text = buf;
2739 } else if (!client_is_global_observer()) {
2740 text = _("_Observe");
2741 sensitive = TRUE;
2742 } else {
2743 text = _("Do not _observe");
2744 sensitive = TRUE;
2745 }
2748}
2749
2750/**********************************************************************/
2756 GtkTreeIter *start,
2757 const struct player *pplayer)
2758{
2759 const int search_id = player_number(pplayer);
2760 int id;
2761
2762 if (NULL != start) {
2763 *iter = *start;
2764 if (!gtk_tree_model_iter_next(model, iter)) {
2765 return FALSE;
2766 }
2767 } else if (!gtk_tree_model_get_iter_first(model, iter)) {
2768 return FALSE;
2769 }
2770
2771 do {
2773 if (id == search_id) {
2774 return TRUE;
2775 }
2776 } while (gtk_tree_model_iter_next(model, iter));
2777
2778 return FALSE;
2779}
2780
2781/**********************************************************************/
2787 const struct connection *pconn)
2788{
2789 const int search_id = pconn->id;
2790 int id;
2791
2792 if (NULL != start) {
2793 *iter = *start;
2794 if (!gtk_tree_model_iter_next(model, iter)) {
2795 return FALSE;
2796 }
2797 } else if (!gtk_tree_model_iter_children(model, iter, parent)) {
2798 return FALSE;
2799 }
2800
2801 do {
2802 gtk_tree_model_get(model, iter, CL_COL_CONN_ID, &id, -1);
2803 if (id == search_id) {
2804 return TRUE;
2805 }
2806 } while (gtk_tree_model_iter_next(model, iter));
2807
2808 return FALSE;
2809}
2810
2811/**********************************************************************/
2815{
2820 GtkTreeModel *model = GTK_TREE_MODEL(store);
2821 GtkTreePath *path;
2824 GdkPixbuf *flag, *color;
2826 struct player *pselected_player;
2827 struct connection *pselected_conn;
2828 bool is_ready;
2829 const char *nation, *plr_name, *team;
2830 char name[MAX_LEN_NAME + 8];
2832 int conn_id;
2833
2834 /* Refresh the AI skill level control */
2835 if (ai_lvl_combobox) {
2836 enum ai_level new_level = server_ai_level(), level;
2837 int i = 0;
2838
2839 for (level = 0; level < AI_LEVEL_COUNT; level++) {
2841 if (level == new_level) {
2843 break;
2844 }
2845 i++;
2846 }
2847 }
2848 if (level == AI_LEVEL_COUNT) {
2849 /* Probably ai_level_invalid() */
2851 }
2852 }
2853
2854 /* Save the selected connection. */
2856
2857 /* Insert players into the connection list. */
2858 players_iterate(pplayer) {
2859 if (!player_has_flag(pplayer, PLRF_SCENARIO_RESERVED)) {
2860 conn_id = -1;
2862 flag = pplayer->nation ? get_flag(pplayer->nation) : NULL;
2863 color = create_player_icon(pplayer);
2864
2865 conn_list_iterate(pplayer->connections, pconn) {
2866 if (pconn->playing == pplayer && !pconn->observer) {
2867 conn_id = pconn->id;
2868 access_level = pconn->access_level;
2869 break;
2870 }
2872
2873 if (is_ai(pplayer) && !pplayer->was_created
2874 && !pplayer->is_connected) {
2875 /* TRANS: "<Novice AI>" */
2876 fc_snprintf(name, sizeof(name), _("<%s AI>"),
2877 ai_level_translated_name(pplayer->ai_common.skill_level));
2878 } else {
2879 sz_strlcpy(name, pplayer->username);
2880 if (access_level > ALLOW_BASIC) {
2881 sz_strlcat(name, "*");
2882 }
2883 }
2884
2885 is_ready = !is_human(pplayer) ? TRUE : pplayer->is_ready;
2886
2887 if (pplayer->nation == NO_NATION_SELECTED) {
2888 nation = _("Random");
2889 if (pplayer->was_created) {
2890 plr_name = player_name(pplayer);
2891 } else {
2892 plr_name = "";
2893 }
2894 } else {
2895 nation = nation_adjective_for_player(pplayer);
2896 plr_name = player_name(pplayer);
2897 }
2898
2899 team = pplayer->team ? team_name_translation(pplayer->team) : "";
2900
2901 if (model_get_player_iter(model, &parent, pprev_parent, pplayer)) {
2903 } else {
2905 }
2906
2907 gtk_tree_store_set(store, &parent,
2910 CL_COL_READY_STATE, is_ready,
2912 CL_COL_FLAG, flag,
2914 CL_COL_NATION, nation,
2916 CL_COL_CONN_ID, conn_id,
2919 -1);
2920
2921 /* Insert observers of this player as child nodes. */
2922 pprev_child = NULL;
2923 conn_list_iterate(pplayer->connections, pconn) {
2924 if (pconn->id == conn_id) {
2925 continue;
2926 }
2927 if (model_get_conn_iter(model, &child, &parent,
2928 pprev_child, pconn)) {
2929 gtk_tree_store_move_after(store, &child, pprev_child);
2930 } else {
2932 }
2933
2934 gtk_tree_store_set(store, &child,
2936 CL_COL_USER_NAME, pconn->username,
2937 CL_COL_TEAM, _("Observer"),
2938 CL_COL_CONN_ID, pconn->id,
2941 -1);
2942
2943 prev_child = child;
2946
2947 /* Expand node? */
2948 if (NULL != pprev_child) {
2950 if (!collapsed) {
2951 path = gtk_tree_model_get_path(model, &parent);
2953 path, FALSE);
2954 gtk_tree_path_free(path);
2955 }
2956 }
2957
2958 /* Remove trailing rows. */
2959 if (NULL != pprev_child) {
2960 child = prev_child;
2961 if (gtk_tree_model_iter_next(model, &child)) {
2962 while (gtk_tree_store_remove(store, &child)) {
2963 /* Do nothing more. */
2964 }
2965 }
2966 } else if (gtk_tree_model_iter_children(model, &child, &parent)) {
2967 while (gtk_tree_store_remove(store, &child)) {
2968 /* Do nothing more. */
2969 }
2970 }
2971
2974 if (flag) {
2975 g_object_unref(flag);
2976 }
2977 if (color) {
2979 }
2980 }
2982
2983 /* Finally, insert global observers... */
2985 if (NULL != pconn->playing || !pconn->observer) {
2986 continue;
2987 }
2988
2991 } else {
2993 }
2994
2995 gtk_tree_store_set(store, &parent,
2997 CL_COL_USER_NAME, pconn->username,
2998 CL_COL_TEAM, _("Observer"),
2999 CL_COL_CONN_ID, pconn->id,
3002 -1);
3003
3007
3008 /* ...and detached connections. */
3010 if (NULL != pconn->playing || pconn->observer) {
3011 continue;
3012 }
3013
3016 } else {
3018 }
3019
3020 gtk_tree_store_set(store, &parent,
3022 CL_COL_USER_NAME, pconn->username,
3023 CL_COL_TEAM, _("Detached"),
3024 CL_COL_CONN_ID, pconn->id,
3027 -1);
3028
3032
3033 /* Remove trailing rows. */
3034 if (NULL != pprev_parent) {
3036 if (gtk_tree_model_iter_next(model, &parent)) {
3037 while (gtk_tree_store_remove(store, &parent)) {
3038 /* Do nothing more. */
3039 }
3040 }
3041 } else {
3042 gtk_tree_store_clear(store);
3043 }
3044
3045 /* If we were selecting a single connection, let's try to reselect it. */
3048 }
3049 }
3050
3052}
3053
3054/**********************************************************************/
3060 const char *title, int colnum, const char *key)
3061{
3064
3065 if (gtype == G_TYPE_BOOLEAN) {
3068 "active", colnum, NULL);
3069 } else if (gtype == GDK_TYPE_PIXBUF) {
3072 "pixbuf", colnum, NULL);
3073 } else {
3076 "text", colnum,
3077 "style", CL_COL_STYLE,
3078 "weight", CL_COL_WEIGHT,
3079 NULL);
3080 }
3081
3084
3085 if (key != NULL) {
3087 }
3088}
3089
3090/**********************************************************************/
3094{
3095 GtkWidget *box, *sbox, *table, *vgrid;
3096 GtkWidget *view, *sw, *text, *toolkit_view, *button, *spin;
3097 GtkWidget *label;
3098 GtkTreeSelection *selection;
3099 enum ai_level level;
3100 /* There's less than AI_LEVEL_COUNT entries as not all levels have
3101 entries (that's the whole point of this array: index != value),
3102 but this is set safely to the max */
3103 static enum ai_level levels[AI_LEVEL_COUNT];
3104 int i = 0;
3105 int box_row = 0;
3106 int sbox_col = 0;
3107 int grid_row = 0;
3110
3111 box = gtk_grid_new();
3119
3120 sbox = gtk_grid_new();
3122 gtk_grid_attach(GTK_GRID(box), sbox, 0, box_row++, 1, 1);
3123
3124 vgrid = gtk_grid_new();
3135
3136 table = gtk_grid_new();
3141
3147 if (server_optset != NULL) {
3149
3150 if (paifill) {
3153 } /* else it'll be updated later */
3154 }
3155 g_signal_connect_after(spin, "value_changed",
3157
3158 gtk_grid_attach(GTK_GRID(table), spin, 1, 0, 1, 1);
3159
3161 "use-underline", TRUE,
3162 "mnemonic-widget", spin,
3163 /* TRANS: Keep individual lines short */
3164 "label", _("Number of _Players\n(including AI):"),
3165 "xalign", 0.0,
3166 "yalign", 0.5,
3167 NULL);
3168 gtk_grid_attach(GTK_GRID(table), label, 0, 0, 1, 1);
3169
3171
3172 for (level = 0; level < AI_LEVEL_COUNT; level++) {
3175
3177 levels[i] = level;
3178 i++;
3179 }
3180 }
3183 G_CALLBACK(ai_skill_callback), levels);
3184
3186
3188 "use-underline", TRUE,
3189 "mnemonic-widget", ai_lvl_combobox,
3190 "label", _("AI Skill _Level:"),
3191 "xalign", 0.0,
3192 "yalign", 0.5,
3193 NULL);
3194 gtk_grid_attach(GTK_GRID(table), label, 0, 1, 1, 1);
3195
3199
3201
3203 "use-underline", TRUE,
3204 "mnemonic-widget", GTK_COMBO_BOX_TEXT(ruleset_combo),
3205 "label", _("Ruleset:"),
3206 "xalign", 0.0,
3207 "yalign", 0.5,
3208 NULL);
3209 gtk_grid_attach(GTK_GRID(table), label, 0, 2, 1, 1);
3210
3211 button = icon_label_button_new("preferences-system",
3212 _("_More Game Options..."));
3214 gtk_widget_set_margin_end(button, 8);
3215 gtk_widget_set_margin_start(button, 8);
3216 gtk_widget_set_margin_top(button, 8);
3219 g_signal_connect(button, "clicked",
3221 gtk_grid_attach(GTK_GRID(vgrid), button, 0, grid_row++, 1, 1);
3222
3229
3232 g_signal_connect(selection, "changed",
3234
3235 add_tree_col(view, G_TYPE_STRING, _("Name"),
3237 add_tree_col(view, G_TYPE_BOOLEAN, _("Ready"),
3239 add_tree_col(view, G_TYPE_STRING, Q_("?player:Leader"),
3242 CL_COL_FLAG, NULL);
3243 add_tree_col(view, GDK_TYPE_PIXBUF, _("Border"),
3245 add_tree_col(view, G_TYPE_STRING, _("Nation"),
3247 add_tree_col(view, G_TYPE_STRING, _("Team"),
3248 CL_COL_TEAM, NULL);
3249
3251 g_signal_connect(controller, "pressed",
3254
3255 g_signal_connect(view, "row-collapsed",
3258 g_signal_connect(view, "row-expanded",
3261
3269
3270 /* This is for a workaround against gtk bug that we can't parent
3271 * popup to the tree view - we have to parent it all the way to sw */
3275 g_signal_connect(controller, "pressed",
3278
3279 gtk_grid_attach(GTK_GRID(sbox), sw, sbox_col++, 0, 1, 1);
3280
3286 gtk_grid_attach(GTK_GRID(box), sw, 0, box_row++, 1, 1);
3287
3291 start_message_area = text;
3292 gtk_widget_set_name(text, "chatline");
3297
3298
3299 /* Vote widgets. */
3300 if (pregame_votebar == NULL) {
3302 }
3304
3306 gtk_grid_attach(GTK_GRID(box), toolkit_view, 0, box_row++, 1, 1);
3307
3308 button = gtk_button_new_with_mnemonic(_("_Cancel"));
3310 g_signal_connect(button, "clicked", G_CALLBACK(main_callback), NULL);
3311
3312 nation_button = icon_label_button_new("document-properties",
3313 _("Pick _Nation"));
3317
3318 observe_button = icon_label_button_new("zoom-in", _("_Observe"));
3322
3323 ready_button = icon_label_button_new("system-run", _("_Ready"));
3325 g_signal_connect(ready_button, "clicked",
3327
3328 return box;
3329}
3330
3331
3332/**********************************************************************/
3335void handle_game_load(bool load_successful, const char *filename)
3336{
3337 if (load_successful) {
3339
3340 if (game.info.is_new_game) {
3341 /* It's pregame. Create a player and connect to it */
3342 send_chat("/take -");
3343 }
3344 }
3345}
3346
3347/**********************************************************************/
3350static void load_filename(const char *filename)
3351{
3352 send_chat_printf("/load %s", filename);
3353}
3354
3355/**********************************************************************/
3358static void load_callback(void)
3359{
3360 GtkTreeIter it;
3361 const gchar *filename;
3362
3364 return;
3365 }
3366
3368 SD_COL_FULL_PATH, &filename, -1);
3369 load_filename(filename);
3370}
3371
3372/**********************************************************************/
3376{
3377 save_dialog_file_chooser_popup(_("Choose Saved Game to Load"),
3380}
3381
3382/**********************************************************************/
3385static void update_load_page(void)
3386{
3387 /* Search for user saved games. */
3389 ".sav", FALSE);
3390
3392 fileinfo_list_destroy(files);
3393}
3394
3395/**********************************************************************/
3399{
3400 GtkWidget *box, *sbox, *bbox;
3401
3402 GtkWidget *button, *label, *view, *sw;
3404 int box_row = 0;
3405 int sbox_row = 0;
3406
3407 box = gtk_grid_new();
3415
3420
3423 -1, NULL, rend, "text", 0, NULL);
3424
3427
3429
3430 g_signal_connect(view, "row-activated",
3432
3433 sbox = gtk_grid_new();
3438 gtk_grid_attach(GTK_GRID(box), sbox, 0, box_row++, 1, 1);
3439
3441 "use-underline", TRUE,
3442 "mnemonic-widget", view,
3443 "label", _("Choose Saved Game to _Load:"),
3444 "xalign", 0.0,
3445 "yalign", 0.5,
3446 NULL);
3447 gtk_grid_attach(GTK_GRID(sbox), label, 0, sbox_row++, 1, 1);
3448
3455 gtk_grid_attach(GTK_GRID(sbox), sw, 0, sbox_row++, 1, 1);
3456
3460 gtk_grid_attach(GTK_GRID(box), bbox, 0, box_row++, 1, 1);
3461
3462 button = gtk_button_new_with_mnemonic(_("_Browse..."));
3463 gtk_box_append(GTK_BOX(bbox), button);
3464 g_signal_connect(button, "clicked",
3466
3467 button = gtk_button_new_with_mnemonic(_("_Cancel"));
3468 gtk_box_append(GTK_BOX(bbox), button);
3469 g_signal_connect(button, "clicked",
3471
3472 button = gtk_button_new_with_mnemonic(_("_OK"));
3473 gtk_box_append(GTK_BOX(bbox), button);
3474 g_signal_connect(button, "clicked",
3476
3477 return box;
3478}
3479
3480/**********************************************************************/
3483static void scenario_list_callback(void)
3484{
3485 GtkTreeIter it;
3486 GtkTextBuffer *buffer;
3487 char *description;
3488 char *authors;
3489 char *filename;
3490 int ver;
3491 char vername[50];
3492
3495 2, &description, -1);
3497 3, &authors, -1);
3499 1, &filename, -1);
3501 4, &ver, -1);
3502 filename = skip_to_basename(filename);
3503 if (ver > 0) {
3504 int maj;
3505 int min;
3506
3507 maj = ver / 1000000;
3508 ver %= 1000000;
3509 min = ver / 10000;
3510 ver %= 10000;
3511 if (ver >= 9000) {
3512 /* Development version, have '+' */
3513 fc_snprintf(vername, sizeof(vername), "%d.%d+", maj, min);
3514 } else {
3515 fc_snprintf(vername, sizeof(vername), "%d.%d", maj, min);
3516 }
3517 } else {
3518 /* TRANS: Old scenario format version */
3519 fc_snprintf(vername, sizeof(vername), _("pre-2.6"));
3520 }
3521 } else {
3522 description = "";
3523 authors = "";
3524 filename = "";
3525 vername[0] = '\0';
3526 }
3527
3529 gtk_text_buffer_set_text(buffer, description, -1);
3531 gtk_text_buffer_set_text(buffer, authors, -1);
3534}
3535
3536/**********************************************************************/
3539static void scenario_callback(void)
3540{
3541 GtkTreeIter it;
3542 char *filename;
3543
3545 return;
3546 }
3547
3548 gtk_tree_model_get(GTK_TREE_MODEL(scenario_store), &it, 1, &filename, -1);
3549 load_filename(filename);
3550}
3551
3552/**********************************************************************/
3556{
3557 save_dialog_file_chooser_popup(_("Choose a Scenario"),
3560}
3561
3562/**********************************************************************/
3565static void update_scenario_page(void)
3566{
3567 struct fileinfo_list *files;
3568
3570
3571 /* search for scenario files. */
3572 files = fileinfolist_infix(get_scenario_dirs(), ".sav", TRUE);
3574 struct section_file *sf;
3575
3576 if ((sf = secfile_load_section(pfile->fullname, "scenario", TRUE))
3577 && secfile_lookup_bool_default(sf, TRUE, "scenario.is_scenario")) {
3578 const char *sname, *sdescription, *sauthors;
3579 int fcver;
3580 int fcdev;
3581 int current_ver = MAJOR_VERSION * 1000000 + MINOR_VERSION * 10000;
3582 int current_dev;
3583
3585 if (PATCH_VERSION >= 90) {
3586 /* Patch level matters on development versions */
3587 current_dev += PATCH_VERSION * 100;
3588 }
3589
3590 fcver = secfile_lookup_int_default(sf, 0, "scenario.game_version");
3591 if (fcver < 30000) {
3592 /* Pre-3.0 versions stored version number without emergency version
3593 * part in the end. To get comparable version number stored,
3594 * multiply by 100. */
3595 fcver *= 100;
3596 }
3597 if (fcver % 10000 >= 9000) {
3598 fcdev = fcver - (fcver % 100); /* Emergency version does not count. */
3599 } else {
3600 fcdev = fcver - (fcver % 10000); /* Patch version does not count. */
3601 }
3602 sname = secfile_lookup_str_default(sf, NULL, "scenario.name");
3604 "scenario.description");
3605 sauthors = secfile_lookup_str_default(sf, NULL, "scenario.authors");
3606 log_debug("scenario file: %s from %s", sname, pfile->fullname);
3607
3608 /* Ignore scenarios for newer freeciv versions than we are. */
3609 if (fcdev <= current_dev) {
3610 bool add_new = TRUE;
3611
3612 if (sname != NULL) {
3613 GtkTreeIter it;
3614 bool valid;
3615
3617 while (valid) {
3618 char *oname;
3619
3621 0, &oname, -1);
3622
3623 if (!strcmp(sname, oname)) {
3624 /* Already listed scenario has the same name as the one we just found */
3625 int existing;
3626
3628 4, &existing, -1);
3629 log_debug("Duplicate %s (%d vs %d)", sname, existing, fcver);
3630
3631 if (existing > fcver) {
3632 /* Already listed one has higher version number */
3633 add_new = FALSE;
3634 } else if (existing < fcver) {
3635 /* New one has higher version number */
3636 add_new = FALSE;
3637
3639 0, sname && strlen(sname) ? Q_(sname) : pfile->name,
3640 1, pfile->fullname,
3641 2, (NULL != sdescription && '\0' != sdescription[0]
3642 ? Q_(sdescription) : ""),
3643 3, (NULL != sauthors && sauthors[0] != '\0'
3644 ? Q_(sauthors) : ""),
3645 4, fcver,
3646 -1);
3647 } else {
3648 /* Same version number -> list both */
3649 }
3650 }
3652 }
3653 }
3654
3655 if (add_new) {
3656 GtkTreeIter it;
3657
3660 0, sname && strlen(sname) ? Q_(sname) : pfile->name,
3661 1, pfile->fullname,
3662 2, (NULL != sdescription && '\0' != sdescription[0]
3663 ? Q_(sdescription) : ""),
3664 3, (NULL != sauthors && sauthors[0] != '\0'
3665 ? Q_(sauthors) : ""),
3666 4, fcver,
3667 -1);
3668 }
3669 }
3670
3671 secfile_destroy(sf);
3672 }
3674
3675 fileinfo_list_destroy(files);
3676}
3677
3678/**********************************************************************/
3692
3693/**********************************************************************/
3702
3703/**********************************************************************/
3707{
3710 GtkWidget *button, *label, *view, *sw, *swa, *text;
3713 int grid_row = 0;
3714 int filenamecol = 0;
3715 int vercol = 0;
3716 int descrow = 0;
3717
3718 vgrid = gtk_grid_new();
3726
3731 G_TYPE_INT);
3732
3735 nullptr);
3737 nullptr);
3738
3743
3746 -1, NULL, rend, "text", 0, NULL);
3747
3752
3754
3755 g_signal_connect(view, "row-activated",
3757
3759 "use-underline", TRUE,
3760 "mnemonic-widget", view,
3761 "label", _("Choose a _Scenario:"),
3762 "xalign", 0.0,
3763 "yalign", 0.5,
3764 NULL);
3765 gtk_grid_attach(GTK_GRID(vgrid), label, 0, grid_row++, 1, 1);
3766
3767 sbox = gtk_grid_new();
3774
3775 hbox = gtk_grid_new();
3778
3784 gtk_grid_attach(GTK_GRID(sbox), sw, 0, 0, 1, 2);
3785
3786 text = gtk_text_view_new();
3792 scenario_description = text;
3793
3799
3800 text = gtk_text_view_new();
3806 scenario_authors = text;
3807
3813
3814 text = gtk_label_new(_("Filename:"));
3819
3826
3827 gtk_grid_attach(GTK_GRID(filenamebox), text, filenamecol++, 0, 1, 1);
3829 filenamecol++, 0, 1, 1);
3830
3831 /* TRANS: Scenario format version */
3832 vertext = gtk_label_new(_("Format:"));
3837
3844
3847 vercol++, 0, 1, 1);
3848
3853 gtk_grid_attach(GTK_GRID(descbox), sw, 0, descrow++, 1, 1);
3856 0, descrow++, 1, 1);
3858 0, descrow++, 1, 1);
3859 gtk_grid_attach(GTK_GRID(sbox), descbox, 1, 0, 1, 2);
3860
3864
3865 button = gtk_button_new_with_mnemonic(_("_Browse..."));
3866 gtk_box_append(GTK_BOX(bbox), button);
3867 g_signal_connect(button, "clicked",
3869
3870 button = gtk_button_new_with_mnemonic(_("_Cancel"));
3871 gtk_box_append(GTK_BOX(bbox), button);
3872 g_signal_connect(button, "clicked",
3874
3875 button = gtk_button_new_with_mnemonic(_("_OK"));
3876 gtk_box_append(GTK_BOX(bbox), button);
3877 g_signal_connect(button, "clicked",
3879
3880 return vgrid;
3881}
3882
3883/**********************************************************************/
3887{
3888 return current_page;
3889}
3890
3891/**********************************************************************/
3895{
3896 /* Don't use current_page directly here because maybe it could be modified
3897 * before we reach the end of this function. */
3899
3900 /* If the page remains the same, don't do anything. */
3901 if (old_page == new_page) {
3902 return;
3903 }
3904
3905 log_debug("Switching client page from %s to %s.",
3906 -1 == old_page ? "(no page)" : client_pages_name(old_page),
3908
3910
3911 switch (old_page) {
3912 case PAGE_SCENARIO:
3913 case PAGE_LOAD:
3914 break;
3915 case PAGE_GAME:
3916 {
3918
3920 if (vmode == NULL) {
3922 }
3923 }
3924 break;
3925 default:
3926 break;
3927 }
3928
3929 switch (new_page) {
3930 case PAGE_MAIN:
3931 case PAGE_START:
3932 if (is_server_running()) {
3935 } else {
3937 }
3941 break;
3942 case PAGE_GAME:
3943 {
3945
3948 if (vmode == NULL) {
3950 }
3953 }
3954 break;
3955 case PAGE_LOAD:
3957 break;
3958 case PAGE_SCENARIO:
3960 break;
3961 case PAGE_NETWORK:
3963 break;
3964 }
3965
3966 /* Hide/show statusbar. */
3967 if (new_page == PAGE_START || new_page == PAGE_GAME) {
3970 } else {
3972 }
3973
3975
3976 /* Update the GUI. */
3977 while (g_main_context_pending(NULL)) {
3979 }
3980
3981 switch (new_page) {
3982 case PAGE_MAIN:
3983 break;
3984 case PAGE_START:
3987 break;
3988 case PAGE_LOAD:
3990 break;
3991 case PAGE_SCENARIO:
3993 break;
3994 case PAGE_GAME:
3998 mapview_thaw();
4001 break;
4002 case PAGE_NETWORK:
4007 break;
4008 }
4009}
4010
4011/****************************************************************************
4012 SAVE GAME DIALOGs
4013****************************************************************************/
4014
4015/**********************************************************************/
4019{
4020 return fileinfolist_infix(get_save_dirs(), ".sav", FALSE);
4021}
4022
4023/**********************************************************************/
4027{
4028 static GtkWidget *shell = NULL;
4029
4030 if (NULL != shell) {
4031 return;
4032 }
4033
4034 shell = save_dialog_new(_("Save Game"), _("Saved _Games:"),
4035 _("Save _Filename:"), send_save_game,
4038 &shell);
4040}
4041
4042/**********************************************************************/
4045static void save_dialog_save_scenario(const char *filename)
4046{
4048}
4049
4050/**********************************************************************/
4054{
4055 return fileinfolist_infix(get_scenario_dirs(), ".sav", FALSE);
4056}
4057
4058/**********************************************************************/
4062{
4063 static GtkWidget *shell = NULL;
4064
4065 if (NULL != shell) {
4066 return;
4067 }
4068
4069 shell = save_dialog_new(_("Save Scenario"), _("Saved Sce_narios:"),
4070 _("Save Sc_enario:"), save_dialog_save_scenario,
4073 &shell);
4075}
4076
4077/**********************************************************************/
4083{
4084 return fileinfolist_infix(get_save_dirs(), ".map", FALSE);
4085}
4086
4087/**********************************************************************/
4091{
4092 static GtkWidget *shell = NULL;
4093
4094 if (NULL != shell) {
4095 return;
4096 }
4097
4098 shell = save_dialog_new(_("Save Map Image"), _("Saved Map _Images:"),
4099 _("Save _Map Images:"), mapimg_client_save,
4102 &shell);
4104}
4105
4106/**********************************************************************/
4109void mapimg_client_save(const char *filename)
4110{
4111 if (!mapimg_client_createmap(filename)) {
4112 char msg[512];
4113
4114 fc_snprintf(msg, sizeof(msg), "(%s)", mapimg_error());
4115 popup_notify_dialog(_("Error"),
4116 _("Error Creating the Map Image!"), msg);
4117 }
4118}
4119
4120/**********************************************************************/
4125void set_rulesets(int num_rulesets, char **rulesets)
4126{
4127 int i;
4128 int def_idx = -1;
4129
4131 for (i = 0; i < num_rulesets; i++) {
4132
4134 if (!strcmp("default", rulesets[i])) {
4135 def_idx = i;
4136 }
4137 }
4138
4140
4141 /* HACK: Server should tell us the current ruleset. */
4143
4145}
#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)
static struct ai_type * self
Definition classicai.c:46
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
static void scenario_factory_bind(GtkSignalListItemFactory *self, GtkListItem *list_item, gpointer user_data)
Definition pages.c:3681
static void fc_save_row_init(FcSaveRow *self)
Definition pages.c:311
static void save_factory_setup(GtkSignalListItemFactory *self, GtkListItem *list_item, gpointer user_data)
Definition pages.c:833
static void fc_save_row_class_init(FcSaveRowClass *klass)
Definition pages.c:303
static void plr_factory_bind(GtkSignalListItemFactory *self, GtkListItem *list_item, gpointer user_data)
Definition pages.c:1527
static void fc_scen_row_class_init(FcScenRowClass *klass)
Definition pages.c:273
static void host_factory_setup(GtkSignalListItemFactory *self, GtkListItem *list_item, gpointer user_data)
Definition pages.c:1517
#define FC_TYPE_SAVE_ROW
Definition pages.c:190
#define FC_TYPE_SCEN_ROW
Definition pages.c:167
void(* save_dialog_action_fn_t)(const char *filename)
Definition pages.c:607
static void plr_factory_setup(GtkSignalListItemFactory *self, GtkListItem *list_item, gpointer user_data)
Definition pages.c:1555
host_rows
Definition pages.c:127
@ host_row_host
Definition pages.c:128
@ host_row_nplayers
Definition pages.c:132
@ host_row_humans
Definition pages.c:133
@ host_row_port
Definition pages.c:129
@ host_row_version
Definition pages.c:130
@ host_row_state
Definition pages.c:131
@ host_row_message
Definition pages.c:134
static void fc_scen_row_init(FcScenRow *self)
Definition pages.c:281
struct fileinfo_list *(* save_dialog_files_fn_t)(void)
Definition pages.c:608
static void save_factory_bind(GtkSignalListItemFactory *self, GtkListItem *list_item, gpointer user_data)
Definition pages.c:818
static void scenario_factory_setup(GtkSignalListItemFactory *self, GtkListItem *list_item, gpointer user_data)
Definition pages.c:3696
plr_rows
Definition pages.c:159
@ plr_row_name
Definition pages.c:160
@ plr_row_nation
Definition pages.c:163
@ plr_row_type
Definition pages.c:161
@ plr_row_host
Definition pages.c:162
static void fc_host_row_class_init(FcHostRowClass *klass)
Definition pages.c:213
static void fc_plr_row_class_init(FcPlrRowClass *klass)
Definition pages.c:243
#define FC_TYPE_HOST_ROW
Definition pages.c:103
static void host_factory_bind(GtkSignalListItemFactory *self, GtkListItem *list_item, gpointer user_data)
Definition pages.c:1477
#define FC_TYPE_PLR_ROW
Definition pages.c:138
static void fc_host_row_init(FcHostRow *self)
Definition pages.c:221
static void fc_plr_row_init(FcPlrRow *self)
Definition pages.c:251
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
GObjectClass parent_class
Definition pages.c:122
char * version
Definition pages.c:113
char * humans
Definition pages.c:116
GObject parent_instance
Definition pages.c:109
int port
Definition pages.c:112
int nplayers
Definition pages.c:115
char * message
Definition pages.c:117
char * state
Definition pages.c:114
char * host
Definition pages.c:111
GObjectClass parent_class
Definition pages.c:154
char * host
Definition pages.c:148
char * name
Definition pages.c:146
char * type
Definition pages.c:147
GObject parent_instance
Definition pages.c:144
char * nation
Definition pages.c:149
GObjectClass parent_class
Definition pages.c:204
char * pretty_name
Definition pages.c:198
GObject parent_instance
Definition pages.c:196
char * full_path
Definition pages.c:199
GObjectClass parent_class
Definition pages.c:184
char * name
Definition pages.c:175
char * filename
Definition pages.c:178
char * desc
Definition pages.c:176
int ver
Definition pages.c:179
GObject parent_instance
Definition pages.c:173
char * authors
Definition pages.c:177
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