Freeciv-3.4
Loading...
Searching...
No Matches
pages.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18#include <stdio.h>
19#include <time.h>
20
21#include <sys/stat.h>
22
23#include <gtk/gtk.h>
24
25/* utility */
26#include "fcintl.h"
27#include "log.h"
28#include "mem.h"
29#include "shared.h"
30#include "support.h"
31
32/* common */
33#include "chat.h"
34#include "dataio.h"
35#include "game.h"
36#include "mapimg.h"
37#include "version.h"
38
39/* client */
40#include "client_main.h"
41#include "climisc.h"
42#include "clinet.h"
43#include "connectdlg_common.h"
44#include "packhand.h"
45#include "servers.h"
46#include "update_queue.h"
47
48/* client/gui-gtk-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
73
76
77/* This is the current page. Invalid value at start, to be sure that it won't
78 * be caught through a switch() statement. */
79static enum client_pages current_page = -1;
80
82{
83 struct server_scan *scan;
85};
86
87static struct server_scan_timer_data meta_scan = { NULL, 0 };
88static struct server_scan_timer_data lan_scan = { NULL, 0 };
89
92
94
96
98
99static void connection_state_reset(void);
100
101#define FC_TYPE_HOST_ROW (fc_host_row_get_type())
102
104
117
122
124
134
135
136#define FC_TYPE_PLR_ROW (fc_plr_row_get_type())
137
139
149
154
156
163
164
165#define FC_TYPE_SCEN_ROW (fc_scen_row_get_type())
166
168
179
184
186
187
188#define FC_TYPE_SAVE_ROW (fc_save_row_get_type())
189
191
199
204
206
207/**********************************************************************/
210static void
214
215/**********************************************************************/
218static void
222
223/**********************************************************************/
226#if 0
227static FcHostRow *fc_host_row_new(void)
228{
229 FcHostRow *result;
230
231 result = g_object_new(FC_TYPE_HOST_ROW, nullptr);
232
233 return result;
234}
235#endif
236
237/**********************************************************************/
240static void
244
245/**********************************************************************/
248static void
252
253/**********************************************************************/
256#if 0
257static FcPlrRow *fc_plr_row_new(void)
258{
259 FcPlrRow *result;
260
261 result = g_object_new(FC_TYPE_PLR_ROW, nullptr);
262
263 return result;
264}
265#endif
266
267/**********************************************************************/
270static void
274
275/**********************************************************************/
278static void
282
283/**********************************************************************/
286#if 0
287static FcScenRow *fc_scen_row_new(void)
288{
289 FcScenRow *result;
290
291 result = g_object_new(FC_TYPE_SCEN_ROW, nullptr);
292
293 return result;
294}
295#endif
296
297/**********************************************************************/
300static void
304
305/**********************************************************************/
308static void
312
313/**********************************************************************/
316#if 0
317static FcSaveRow *fc_save_row_new(void)
318{
319 FcSaveRow *result;
320
321 result = g_object_new(FC_TYPE_SAVE_ROW, nullptr);
322
323 return result;
324}
325#endif
326
327/**********************************************************************/
331{
332 if (!is_server_running()) {
334
335 /* Saved settings are sent in client/options.c
336 * resend_desired_settable_options() */
337 }
338}
339
340/**********************************************************************/
344{
345 output_window_append(ftc_client, _("Compiling scenario list."));
347}
348
349/**********************************************************************/
356
357/**********************************************************************/
365
366/**********************************************************************/
369static void open_settings(void)
370{
371 option_dialog_popup(_("Set local options"), client_optset);
372}
373
374/**********************************************************************/
377static void main_callback(GtkWidget *w, gpointer data)
378{
379 enum client_pages page = PAGE_MAIN;
380
381 if (client.conn.used) {
383 }
384 if (page != get_client_page()) {
385 set_client_page(page);
386 }
387}
388
389/**********************************************************************/
393 int width, int height, gpointer data)
394{
395 static PangoLayout *layout;
397 static int pwidth, pheight;
398 static bool left = FALSE;
400 struct sprite *intro = (struct sprite *)data;
401
402 cairo_set_source_surface(cr, intro->surface, 0, 0);
403 cairo_paint(cr);
404
405 if (!layout) {
406 char msgbuf[128];
407 const char *rev_ver;
408
410 desc = pango_font_description_from_string("Sans Bold 10");
413
415
416 if (rev_ver == NULL) {
417 /* TRANS: "version 2.6.0, gui-gtk-3.22 client" */
418 fc_snprintf(msgbuf, sizeof(msgbuf), _("%s%s, %s client"),
420 } else {
421 /* TRANS: "version 2.6.0
422 * commit: [modified] <git commit id>
423 * gui-gtk-3.22 client" */
424 fc_snprintf(msgbuf, sizeof(msgbuf), _("%s%s\ncommit: %s\n%s client"),
426 left = TRUE;
427 }
429
431 }
433
434 cairo_set_source_rgb(cr, 0, 0, 0);
435 cairo_move_to(cr, left ? 4 : allocation.width - pwidth - 3,
436 allocation.height - pheight - 3);
438
439 cairo_set_source_rgb(cr, 1, 1, 1);
440 cairo_move_to(cr, left ? 3 : allocation.width - pwidth - 4,
441 allocation.height - pheight - 4);
443}
444
445/**********************************************************************/
448static void intro_free(GtkWidget *w, gpointer *data)
449{
450 struct sprite *intro = (struct sprite *)data;
451
453}
454
455/**********************************************************************/
459{
460 GtkWidget *widget, *vgrid, *frame, *darea, *button, *table;
462 struct sprite *intro_in, *intro;
463 int width, height;
464 int sh;
465 int space_needed;
466 int grid_row = 0;
467
469
473 widget = vgrid;
474
475 frame = gtk_frame_new(NULL);
477 gtk_widget_set_margin_end(frame, 18);
479 gtk_widget_set_margin_top(frame, 18);
481 gtk_grid_attach(GTK_GRID(vgrid), frame, 0, grid_row++, 1, 1);
482
485 sh = screen_height();
486
487 if (sh <= 0) {
488 /* Assume some minimum height */
489 sh = 600;
490 }
491
492 space_needed = 250;
493#if IS_BETA_VERSION || IS_DEVEL_VERSION
494 /* Alpha or Beta notice takes extra space */
495 space_needed += 50;
496#endif
497
498 if (sh - height < space_needed) {
499 float scale;
500
501 if (sh < (space_needed + 0.2 * height)) {
502 /* Screen is simply too small, use minimum scale */
503 scale = 0.2;
504 } else {
505 scale = (double)(sh - space_needed) / height;
506 }
507 height *= scale;
508 width *= scale;
511 } else {
512 intro = intro_in;
513 }
514 darea = gtk_drawing_area_new();
518 g_signal_connect(widget, "destroy",
520 gtk_frame_set_child(GTK_FRAME(frame), darea);
521
522#if IS_BETA_VERSION || IS_DEVEL_VERSION
523 {
524 GtkWidget *label;
525
527 gtk_widget_set_name(label, "beta_label");
531 gtk_grid_attach(GTK_GRID(vgrid), label, 0, grid_row++, 1, 1);
532 }
533#endif /* IS_BETA_VERSION || IS_DEVEL_VERSION */
534
544
548
549 button = gtk_button_new_with_mnemonic(_("Start _New Game"));
551 gtk_grid_attach(GTK_GRID(table), button, 0, 0, 1, 1);
553 _("Launches local server, and connects to it for a single-player game."));
554 g_signal_connect(button, "clicked",
556
557 button = gtk_button_new_with_mnemonic(_("Start _Scenario Game"));
559 gtk_grid_attach(GTK_GRID(table), button, 0, 1, 1, 1);
561 _("Loads one of the scenarios for a single-player game. "
562 "Tutorial is one of the scenarios."));
563 g_signal_connect(button, "clicked",
565
566 button = gtk_button_new_with_mnemonic(_("_Load Saved Game"));
568 gtk_grid_attach(GTK_GRID(table), button, 0, 2, 1, 1);
570 _("Continues previously saved single-player game."));
571 g_signal_connect(button, "clicked",
573
574 button = gtk_button_new_with_mnemonic(_("C_onnect to Network Game"));
576 gtk_grid_attach(GTK_GRID(table), button, 1, 0, 1, 1);
578 _("Connects to outside server. "
579 "Sometimes you want to launch a separate server even for local games."));
580 g_signal_connect(button, "clicked",
582
583 button = gtk_button_new_with_mnemonic(_("Client Settings"));
585 gtk_grid_attach(GTK_GRID(table), button, 1, 1, 1, 1);
587 _("Adjusting client-side options."));
588 g_signal_connect(button, "clicked", open_settings, NULL);
589
590 button = icon_label_button_new("application-exit", _("E_xit"));
593 gtk_grid_attach(GTK_GRID(table), button, 1, 2, 1, 1);
595 _("Gives you a break from playing freeciv."));
596 g_signal_connect(button, "clicked",
598
599 return widget;
600}
601
602/****************************************************************************
603 GENERIC SAVE DIALOG
604****************************************************************************/
605typedef void (*save_dialog_action_fn_t) (const char *filename);
606typedef struct fileinfo_list * (*save_dialog_files_fn_t) (void);
607
608struct save_dialog {
614};
615
622
628
629/**********************************************************************/
633{
635 G_TYPE_STRING, /* SD_COL_PRETTY_NAME */
636 G_TYPE_STRING); /* SD_COL_FULL_PATH */
637}
638
639/**********************************************************************/
643 const struct fileinfo_list *files)
644{
646
650 gtk_list_store_set(store, &iter,
652 SD_COL_FULL_PATH, pfile->fullname,
653 -1);
655}
656
657/**********************************************************************/
660static void save_dialog_update(struct save_dialog *pdialog)
661{
662 struct fileinfo_list *files;
663
664 fc_assert_ret(NULL != pdialog);
665
666 /* Update the store. */
667 files = pdialog->files();
670 files);
672}
673
674/**********************************************************************/
678 gint response, gpointer data)
679{
680 if (response == GTK_RESPONSE_OK) {
683
684 if (file != NULL) {
685 gchar *filename = g_file_get_parse_name(file);
686
687 if (NULL != filename) {
688 action(filename);
689 g_free(filename);
690 }
691
692 g_object_unref(file);
693 }
694 }
695
697}
698
699/**********************************************************************/
702static void save_dialog_file_chooser_popup(const char *title,
705{
707
708 /* Create the chooser */
710 _("_Cancel"), GTK_RESPONSE_CANCEL,
712 _("_Save") : _("_Open"),
715
716 g_signal_connect(filechoose, "response",
718
719 /* Display that dialog */
721}
722
723/**********************************************************************/
727 gpointer data)
728{
729 struct save_dialog *pdialog = data;
730
731 switch (response) {
732 case SD_RES_BROWSE:
733 save_dialog_file_chooser_popup(_("Select Location to Save"),
735 pdialog->action);
736 break;
737 case SD_RES_DELETE:
738 {
739 GtkTreeSelection *selection;
740 GtkTreeModel *model;
742 const gchar *full_path;
743
744 selection = gtk_tree_view_get_selection(pdialog->tree_view);
745 if (!gtk_tree_selection_get_selected(selection, &model, &iter)) {
746 return;
747 }
748
749 gtk_tree_model_get(model, &iter, SD_COL_FULL_PATH, &full_path, -1);
750 fc_remove(full_path);
751 save_dialog_update(pdialog);
752 }
753 return;
754 case SD_RES_SAVE:
755 {
756 const char *text = gtk_entry_buffer_get_text(gtk_entry_get_buffer(pdialog->entry));
757 gchar *filename = g_filename_from_utf8(text, -1, NULL, NULL, NULL);
758
759 if (NULL == filename) {
760 return;
761 }
762 pdialog->action(filename);
763 g_free(filename);
764 }
765 break;
766 default:
767 break;
768 }
769
771}
772
773/**********************************************************************/
783
784/**********************************************************************/
791
792/**********************************************************************/
796 gpointer data)
797{
798 struct save_dialog *pdialog = data;
799 GtkTreeModel *model;
801 const gchar *filename;
802
803 if (!gtk_tree_selection_get_selected(selection, &model, &iter)) {
805 return;
806 }
807
809 gtk_tree_model_get(model, &iter, SD_COL_PRETTY_NAME, &filename, -1);
811}
812
813/**********************************************************************/
827
828/**********************************************************************/
837
838/**********************************************************************/
841static GtkWidget *save_dialog_new(const char *title, const char *savelabel,
842 const char *savefilelabel,
845{
846 GtkWidget *shell, *sbox, *sw, *label, *view, *entry;
847 GtkBox *vbox;
848 GtkListStore *store;
851 GtkTreeSelection *selection;
852 struct save_dialog *pdialog;
853
856
857 /* Save dialog structure. */
858 pdialog = fc_malloc(sizeof(*pdialog));
859 pdialog->action = action;
860 pdialog->files = files;
861
862 /* Shell. */
864 _("_Browse..."), SD_RES_BROWSE,
865 _("_Delete"), SD_RES_DELETE,
866 _("_Cancel"), GTK_RESPONSE_CANCEL,
867 _("_Save"), SD_RES_SAVE,
868 NULL);
869 g_object_set_data_full(G_OBJECT(shell), "save_dialog", pdialog,
874 g_signal_connect(shell, "response",
876 pdialog->shell = GTK_DIALOG(shell);
878
879 /* Tree view. */
880 store = save_dialog_store_new();
881
884 nullptr);
886 nullptr);
887
891 g_object_unref(store);
893 g_signal_connect(view, "row-activated",
895 pdialog->tree_view = GTK_TREE_VIEW(view);
896
898 gtk_box_append(vbox, sbox);
899
901 "use-underline", TRUE,
902 "mnemonic-widget", view,
903 "label", savelabel,
904 "xalign", 0.0,
905 "yalign", 0.5,
906 NULL);
907 gtk_box_append(GTK_BOX(sbox), label);
908
917
920 g_signal_connect(selection, "changed",
922
925 -1, NULL, rend, "text",
927
928 /* Entry. */
931 g_signal_connect(entry, "activate",
933 pdialog->entry = GTK_ENTRY(entry);
934
940
942 "use-underline", TRUE,
943 "mnemonic-widget", entry,
944 "label", savefilelabel,
945 "xalign", 0.0,
946 "yalign", 0.5,
947 NULL);
948 gtk_box_append(GTK_BOX(sbox), label);
949
951 gtk_box_append(vbox, sbox);
952
953 save_dialog_update(pdialog);
956
957 return shell;
958}
959
960/****************************************************************************
961 NETWORK PAGE
962****************************************************************************/
968
969/**********************************************************************/
973 const struct server_list *list)
974{
977 GtkTreeIter it;
978 GtkListStore *store;
979 const gchar *host, *portstr;
980 int port;
981
982 switch (sstype) {
985 break;
988 break;
989 default:
990 break;
991 }
992
993 if (!sel) {
994 return;
995 }
996
1000
1001 if (!list) {
1002 return;
1003 }
1004
1007 port = atoi(portstr);
1008
1010 char buf[35];
1011
1012 if (pserver->humans >= 0) {
1013 fc_snprintf(buf, sizeof(buf), "%d", pserver->humans);
1014 } else {
1015 sz_strlcpy(buf, _("Unknown"));
1016 }
1017 gtk_list_store_append(store, &it);
1018 gtk_list_store_set(store, &it,
1019 0, pserver->host,
1020 1, pserver->port,
1021 2, pserver->version,
1022 3, _(pserver->state),
1023 4, pserver->nplayers,
1024 5, buf,
1025 6, pserver->message,
1026 -1);
1027 if (strcmp(host, pserver->host) == 0 && port == pserver->port) {
1029 }
1031}
1032
1033/**********************************************************************/
1037{
1038 if (meta_scan.scan) {
1041 }
1042 if (meta_scan.timer != 0) {
1044 meta_scan.timer = 0;
1045 }
1046 if (lan_scan.scan) {
1048 lan_scan.scan = NULL;
1049 }
1050 if (lan_scan.timer != 0) {
1052 lan_scan.timer = 0;
1053 }
1054}
1055
1056/**********************************************************************/
1060{
1061 struct server_scan_timer_data *scan_data = data;
1062 struct server_scan *scan = scan_data->scan;
1064
1065 if (!scan) {
1066 return FALSE;
1067 }
1068
1069 stat = server_scan_poll(scan);
1070 if (stat >= SCAN_STATUS_PARTIAL) {
1072 struct srv_list *srvrs;
1073
1074 type = server_scan_get_type(scan);
1075 srvrs = server_scan_get_list(scan);
1076 fc_mutex_allocate(&srvrs->mutex);
1080 fc_mutex_release(&srvrs->mutex);
1081 }
1082
1084 scan_data->timer = 0;
1085 return FALSE;
1086 }
1087 return TRUE;
1088}
1089
1090/**********************************************************************/
1093static void server_scan_error(struct server_scan *scan,
1094 const char *message)
1095{
1097 log_error("%s", message);
1098
1099 /* Main thread will finalize the scan later (or even concurrently) -
1100 * do not do anything here to cause double free or raze condition. */
1101}
1102
1103/**********************************************************************/
1116
1117/**************************************************************************
1118 Network connection state defines.
1119**************************************************************************/
1126
1128
1129/**********************************************************************/
1133{
1135 char *txt;
1136
1139 free(txt);
1140 }
1141
1142 return TRUE;
1143}
1144
1145/**********************************************************************/
1149{
1151 char *txt;
1152
1154 free(txt);
1155 }
1156
1158}
1159
1160/**********************************************************************/
1163void append_network_statusbar(const char *text, bool force)
1164{
1166 if (force) {
1169 } else {
1171 }
1172 }
1173}
1174
1175/**********************************************************************/
1194
1195/**********************************************************************/
1199{
1200 switch (state) {
1201 case LOGIN_TYPE:
1203
1205 "", -1);
1207 "", -1);
1208
1217 break;
1218 case NEW_PASSWORD_TYPE:
1222 "", -1);
1223
1232
1234 break;
1239 "", -1);
1240
1249
1251 break;
1252 case WAITING_TYPE:
1254
1261 break;
1262 }
1263
1264 connection_status = state;
1265}
1266
1267/**********************************************************************/
1270static void connection_state_reset(void)
1271{
1273}
1274
1275/**********************************************************************/
1280 const char *message)
1281{
1283
1284 switch (type) {
1285 case AUTH_NEWUSER_FIRST:
1286 case AUTH_NEWUSER_RETRY:
1288 return;
1289 case AUTH_LOGIN_FIRST:
1290 /* if we magically have a password already present in 'fc_password'
1291 * then, use that and skip the password entry dialog */
1292 if (fc_password[0] != '\0') {
1294
1295 sz_strlcpy(reply.password, fc_password);
1297 return;
1298 } else {
1300 }
1301 return;
1302 case AUTH_LOGIN_RETRY:
1304 return;
1305 }
1306
1307 log_error("Unsupported authentication type %d: %s.", type, message);
1308}
1309
1310/**********************************************************************/
1316{
1317 char errbuf [512];
1319
1320 switch (connection_status) {
1321 case LOGIN_TYPE:
1327
1329 errbuf, sizeof(errbuf)) != -1) {
1330 } else {
1332
1334 }
1335 return;
1336 case NEW_PASSWORD_TYPE:
1337 if (w != network_password) {
1340 sz_strlcpy(reply.password,
1342 if (!fc_strncmp(reply.password, fc_password, MAX_LEN_NAME)) {
1343 fc_password[0] = '\0';
1345
1347 } else {
1348 append_network_statusbar(_("Passwords don't match, enter password."),
1349 TRUE);
1350
1352 }
1353 }
1354 return;
1356 sz_strlcpy(reply.password,
1359
1361 return;
1362 case WAITING_TYPE:
1363 return;
1364 }
1365
1366 log_error("Unsupported connection status: %d", connection_status);
1367}
1368
1369/**********************************************************************/
1375 gpointer data)
1376{
1377 connect_callback(NULL, data);
1378}
1379
1380/**********************************************************************/
1384static void update_server_playerlist(const struct server *pserver)
1385{
1386 GtkListStore *store;
1388 int n, i;
1389
1391 fc_assert_ret(store != NULL);
1392
1393 gtk_list_store_clear(store);
1394 if (!pserver || !pserver->players) {
1395 return;
1396 }
1397
1398 n = pserver->nplayers;
1399 for (i = 0; i < n; i++) {
1400 gtk_list_store_append(store, &iter);
1401 gtk_list_store_set(store, &iter,
1402 0, pserver->players[i].name,
1403 1, pserver->players[i].type,
1404 2, pserver->players[i].host,
1405 3, pserver->players[i].nation,
1406 -1);
1407 }
1408}
1409
1410/**********************************************************************/
1414{
1415 GtkTreeModel *model;
1416 GtkTreeIter it;
1417 const char *host;
1418 int port;
1419 char portstr[32];
1420 const struct server *pserver = NULL;
1421
1422 if (!gtk_tree_selection_get_selected(select, &model, &it)) {
1423 return;
1424 }
1425
1426 if (select == meta_selection) {
1427 GtkTreePath *path;
1428 struct srv_list *srvrs;
1429
1431 path = gtk_tree_model_get_path(model, &it);
1433 /* We are not yet inside mutex protected block */
1434 fc_mutex_allocate(&srvrs->mutex);
1435 }
1436 if (srvrs->servers && path) {
1438
1440 }
1442 /* We are not yet inside mutex protected block */
1443 fc_mutex_release(&srvrs->mutex);
1444 }
1445 gtk_tree_path_free(path);
1446 }
1448
1449 gtk_tree_model_get(model, &it, 0, &host, 1, &port, -1);
1450
1452 fc_snprintf(portstr, sizeof(portstr), "%d", port);
1454}
1455
1456/**********************************************************************/
1471
1472/**********************************************************************/
1477 gpointer user_data)
1478{
1479 FcHostRow *row;
1481 char buf[512];
1482
1484
1485 switch (GPOINTER_TO_INT(user_data)) {
1486 case host_row_host:
1487 gtk_label_set_text(GTK_LABEL(child), row->host);
1488 break;
1489 case host_row_port:
1490 fc_snprintf(buf, sizeof(buf), "%d", row->port);
1492 break;
1493 case host_row_version:
1494 gtk_label_set_text(GTK_LABEL(child), row->version);
1495 break;
1496 case host_row_state:
1497 gtk_label_set_text(GTK_LABEL(child), row->state);
1498 break;
1499 case host_row_nplayers:
1500 fc_snprintf(buf, sizeof(buf), "%d", row->nplayers);
1502 break;
1503 case host_row_humans:
1504 gtk_label_set_text(GTK_LABEL(child), row->humans);
1505 break;
1506 case host_row_message:
1507 gtk_label_set_text(GTK_LABEL(child), row->message);
1508 break;
1509 }
1510}
1511
1512/**********************************************************************/
1521
1522/**********************************************************************/
1527 gpointer user_data)
1528{
1529 FcPlrRow *row;
1531
1533
1534 switch (GPOINTER_TO_INT(user_data)) {
1535 case plr_row_name:
1536 gtk_label_set_text(GTK_LABEL(child), row->name);
1537 break;
1538 case plr_row_type:
1539 gtk_label_set_text(GTK_LABEL(child), row->type);
1540 break;
1541 case plr_row_host:
1542 gtk_label_set_text(GTK_LABEL(child), row->host);
1543 break;
1544 case plr_row_nation:
1545 gtk_label_set_text(GTK_LABEL(child), row->nation);
1546 break;
1547 }
1548}
1549
1550/**********************************************************************/
1559
1560/**********************************************************************/
1564{
1565 GtkWidget *box, *sbox, *bbox, *hbox, *notebook;
1566 GtkWidget *button, *label, *view, *sw, *table;
1567 GtkTreeSelection *selection;
1568 GtkListStore *store;
1571
1577
1578 notebook = gtk_notebook_new();
1579 gtk_box_append(GTK_BOX(box), notebook);
1580
1581 /* LAN pane. */
1583 G_TYPE_INT, /* port */
1584 G_TYPE_STRING, /* version */
1585 G_TYPE_STRING, /* state */
1586 G_TYPE_INT, /* nplayers */
1587 G_TYPE_STRING, /* humans */
1588 G_TYPE_STRING); /* message */
1589
1594 nullptr);
1595
1601
1603 lan_selection = selection;
1605
1610
1611 g_signal_connect(view, "row-activated",
1613 g_signal_connect(selection, "changed",
1615
1616 add_treeview_column(view, _("Server Name"), G_TYPE_STRING, 0);
1617 add_treeview_column(view, _("Port"), G_TYPE_INT, 1);
1618 add_treeview_column(view, _("Version"), G_TYPE_STRING, 2);
1619 add_treeview_column(view, _("Status"), G_TYPE_STRING, 3);
1620 add_treeview_column(view, _("Players"), G_TYPE_INT, 4);
1621 add_treeview_column(view, _("Humans"), G_TYPE_STRING, 5);
1622 add_treeview_column(view, _("Comment"), G_TYPE_STRING, 6);
1623
1624 label = gtk_label_new_with_mnemonic(_("Local _Area Network"));
1625
1635 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), sw, label);
1636
1637
1638 /* Metaserver pane. */
1640 G_TYPE_INT, /* port */
1641 G_TYPE_STRING, /* version */
1642 G_TYPE_STRING, /* state */
1643 G_TYPE_INT, /* nplayers */
1644 G_TYPE_STRING, /* humans */
1645 G_TYPE_STRING); /* message */
1646
1652
1654 meta_selection = selection;
1656
1661
1662 g_signal_connect(view, "row-activated",
1664 g_signal_connect(selection, "changed",
1666
1667 add_treeview_column(view, _("Server Name"), G_TYPE_STRING, 0);
1668 add_treeview_column(view, _("Port"), G_TYPE_INT, 1);
1669 add_treeview_column(view, _("Version"), G_TYPE_STRING, 2);
1670 add_treeview_column(view, _("Status"), G_TYPE_STRING, 3);
1671 add_treeview_column(view, _("Players"), G_TYPE_INT, 4);
1672 add_treeview_column(view, _("Humans"), G_TYPE_STRING, 5);
1673 add_treeview_column(view, _("Comment"), G_TYPE_STRING, 6);
1674
1675 label = gtk_label_new_with_mnemonic(_("Internet _Metaserver"));
1676
1687 gtk_notebook_prepend_page(GTK_NOTEBOOK(notebook), sw, label);
1688 } else {
1689 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), sw, label);
1690 }
1691
1692 /* Bottom part of the page, outside the inner notebook. */
1695
1702
1703 table = gtk_grid_new();
1707
1709 g_signal_connect(network_host, "activate",
1712
1714 "use-underline", TRUE,
1715 "mnemonic-widget", network_host,
1716 "label", _("_Host:"),
1717 "xalign", 0.0,
1718 "yalign", 0.5,
1719 NULL);
1720 gtk_grid_attach(GTK_GRID(table), label, 0, 0, 1, 1);
1721
1723 g_signal_connect(network_port, "activate",
1726
1728 "use-underline", TRUE,
1729 "mnemonic-widget", network_port,
1730 "label", _("_Port:"),
1731 "xalign", 0.0,
1732 "yalign", 0.5,
1733 NULL);
1734 gtk_grid_attach(GTK_GRID(table), label, 0, 1, 1, 1);
1735
1738 g_signal_connect(network_login, "activate",
1741
1743 "use-underline", TRUE,
1744 "mnemonic-widget", network_login,
1745 "label", _("_Login:"),
1746 "xalign", 0.0,
1747 "yalign", 0.5,
1748 NULL);
1749 gtk_widget_set_margin_top(label, 10);
1750 gtk_grid_attach(GTK_GRID(table), label, 0, 3, 1, 1);
1751
1757
1759 "use-underline", TRUE,
1760 "mnemonic-widget", network_password,
1761 "label", _("Pass_word:"),
1762 "xalign", 0.0,
1763 "yalign", 0.5,
1764 NULL);
1765 network_password_label = label;
1766 gtk_grid_attach(GTK_GRID(table), label, 0, 4, 1, 1);
1767
1773
1775 "use-underline", TRUE,
1776 "mnemonic-widget", network_confirm_password,
1777 "label", _("Conf_irm Password:"),
1778 "xalign", 0.0,
1779 "yalign", 0.5,
1780 NULL);
1782 gtk_grid_attach(GTK_GRID(table), label, 0, 5, 1, 1);
1783
1784 /* Server player list. */
1790
1795 nullptr);
1796
1802 add_treeview_column(view, _("Nation"), G_TYPE_STRING, 3);
1803
1810
1818
1819 button = gtk_button_new_from_icon_name("view-refresh");
1820 gtk_box_append(GTK_BOX(bbox), button);
1821 g_signal_connect(button, "clicked",
1823
1824 button = gtk_button_new_with_mnemonic(_("_Cancel"));
1825 gtk_box_append(GTK_BOX(bbox), button);
1826 g_signal_connect(button, "clicked",
1828
1829 button = gtk_button_new_with_mnemonic(_("C_onnect"));
1830 gtk_box_append(GTK_BOX(bbox), button);
1831 g_signal_connect(button, "clicked",
1833
1834 return box;
1835}
1836
1837/****************************************************************************
1838 START PAGE
1839****************************************************************************/
1841
1848
1849
1850/* NB: Must match creation arguments in connection_list_store_new(). */
1867
1868/**********************************************************************/
1872{
1874 G_TYPE_INT, /* CL_COL_PLAYER_NUMBER */
1875 G_TYPE_STRING, /* CL_COL_USER_NAME */
1876 G_TYPE_BOOLEAN, /* CL_COL_READY_STATE */
1877 G_TYPE_STRING, /* CL_COL_PLAYER_NAME */
1878 GDK_TYPE_PIXBUF, /* CL_COL_FLAG */
1879 GDK_TYPE_PIXBUF, /* CL_COL_COLOR */
1880 G_TYPE_STRING, /* CL_COL_NATION */
1881 G_TYPE_STRING, /* CL_COL_TEAM */
1882 G_TYPE_INT, /* CL_COL_CONN_ID */
1883 G_TYPE_INT, /* CL_COL_STYLE */
1884 G_TYPE_INT, /* CL_COL_WEIGHT */
1885 G_TYPE_BOOLEAN); /* CL_COL_COLLAPSED */
1886}
1887
1888/**********************************************************************/
1892static void client_aitoggle_player(void *data)
1893{
1894 struct player *pplayer = player_by_number(FC_PTR_TO_INT(data));
1895
1896 if (NULL != pplayer
1897 && pplayer == client_player()
1898 && !is_human(pplayer)) {
1899 send_chat("/away");
1900 }
1901}
1902
1903/**********************************************************************/
1906static void client_take_player(struct player *pplayer)
1907{
1908 int request_id = send_chat_printf("/take \"%s\"", player_name(pplayer));
1909 void *data = FC_INT_TO_PTR(player_number(pplayer));
1910
1913}
1914
1915/**********************************************************************/
1918static void object_put(GObject *object, struct player *pplayer,
1919 struct connection *pconn)
1920{
1921 /* Note that passing -1 to GINT_TO_POINTER() is buggy with some versions
1922 * of gcc. player_slot_count() is not a valid player number. 0 is not
1923 * a valid connection id (see comment in server/sernet.c:
1924 * makeup_connection_name()). */
1925 g_object_set_data(object, "player_id",
1926 GINT_TO_POINTER(NULL != pplayer
1927 ? player_number(pplayer)
1928 : player_slot_count()));
1929 g_object_set_data(object, "connection_id",
1930 GINT_TO_POINTER(NULL != pconn ? pconn->id : 0));
1931}
1932
1933/**********************************************************************/
1937static bool object_extract(GObject *object, struct player **ppplayer,
1938 struct connection **ppconn)
1939{
1940 bool ret = FALSE;
1941 int id;
1942
1943 if (NULL != ppplayer) {
1944 id = GPOINTER_TO_INT(g_object_get_data(object, "player_id"));
1946 if (NULL != *ppplayer) {
1947 ret = TRUE;
1948 }
1949 }
1950 if (NULL != ppconn) {
1951 id = GPOINTER_TO_INT(g_object_get_data(object, "connection_id"));
1952 *ppconn = conn_by_number(id);
1953 if (NULL != *ppconn) {
1954 ret = TRUE;
1955 }
1956 }
1957
1958 return ret;
1959}
1960
1961/**********************************************************************/
1965{
1966 option_dialog_popup(_("Game Settings"), server_optset);
1967}
1968
1969/**********************************************************************/
1973{
1974 enum ai_level *levels = (enum ai_level *)data;
1975 const char *name;
1976 int i;
1977
1979
1980 if (i != -1) {
1981 enum ai_level level = levels[i];
1982
1983 /* Suppress changes provoked by server rather than local user */
1984 if (server_ai_level() != level) {
1986 send_chat_printf("/%s", name);
1987 }
1988 }
1989}
1990
1991/* HACK: sometimes when creating the ruleset combo the value is set without
1992 * the user's control. In this case we don't want to do a /read. */
1994
1995/**********************************************************************/
1998static void ruleset_selected(const char *name)
1999{
2000 if (name && name[0] != '\0' && !no_ruleset_callback) {
2002 }
2003}
2004
2005/**********************************************************************/
2011{
2012 const char *name = NULL;
2013
2015
2016 if (name != NULL) {
2018 }
2019}
2020
2021/**********************************************************************/
2032
2033/**********************************************************************/
2037{
2038 if (start_aifill_spin) {
2040 /* Suppress callback from this change to avoid a loop. */
2042 /* HACK: this GUI control doesn't have quite the same semantics as the
2043 * server 'aifill' option, in that it claims to represent the minimum
2044 * number of players _including humans_. The GUI control has a minimum
2045 * value of 1, so aifill == 0 will not be represented correctly.
2046 * But there's generally exactly one human player because the control
2047 * only shows up for a locally spawned server, so we more or less
2048 * get away with this. */
2051 }
2052}
2053
2054/**********************************************************************/
2058{
2060}
2061
2062/**********************************************************************/
2066{
2067 if (conn_popover != NULL){
2070
2072 }
2073}
2074
2075/**********************************************************************/
2079 gpointer data)
2080{
2081 struct player *pplayer;
2082 struct team_slot *tslot = g_object_get_data(G_OBJECT(action), "slot");
2083 GMenu *menu = data;
2084
2085 if (object_extract(G_OBJECT(menu), &pplayer, NULL)
2086 && NULL != tslot
2087 && team_slot_index(tslot) != team_number(pplayer->team)) {
2088 send_chat_printf("/team \"%s\" \"%s\"",
2089 player_name(pplayer),
2091 }
2092
2094}
2095
2096/**********************************************************************/
2100 gpointer data)
2101{
2102 struct player *pplayer;
2103 GMenu *menu = data;
2104
2105 if (object_extract(G_OBJECT(menu), &pplayer, NULL)) {
2107 player_number(pplayer), !pplayer->is_ready);
2108 }
2109
2111}
2112
2113/**********************************************************************/
2117 gpointer data)
2118{
2119 struct player *pplayer;
2120 GMenu *menu = data;
2121
2122 if (object_extract(G_OBJECT(menu), &pplayer, NULL)) {
2123 popup_races_dialog(pplayer);
2124 }
2125
2127}
2128
2129/**********************************************************************/
2134 gpointer data)
2135{
2136 struct player *pplayer;
2137 GMenu *menu = data;
2138
2139 if (object_extract(G_OBJECT(menu), &pplayer, NULL)) {
2140 send_chat_printf("/%s \"%s\"",
2141 (char *) g_object_get_data(G_OBJECT(action), "command"),
2142 player_name(pplayer));
2143 }
2144
2146}
2147
2148/**********************************************************************/
2152 gpointer data)
2153{
2154 struct player *pplayer;
2155 GMenu *menu = data;
2156
2157 if (object_extract(G_OBJECT(menu), &pplayer, NULL)) {
2158 client_take_player(pplayer);
2159 }
2160
2162}
2163
2164/**********************************************************************/
2169 GVariant *parameter, gpointer data)
2170{
2171 struct connection *pconn;
2172 GMenu *menu = data;
2173
2174 if (object_extract(G_OBJECT(menu), NULL, &pconn)) {
2176 (char *) g_object_get_data(G_OBJECT(action), "command"),
2177 pconn->username);
2178 }
2179
2181}
2182
2183/**********************************************************************/
2186static void show_conn_popup(struct player *pplayer, struct connection *pconn)
2187{
2189 char buf[4096] = "";
2190
2191 if (pconn) {
2192 cat_snprintf(buf, sizeof(buf), _("Connection name: %s"),
2193 pconn->username);
2194 } else {
2195 cat_snprintf(buf, sizeof(buf), _("Player name: %s"),
2196 player_name(pplayer));
2197 }
2198 cat_snprintf(buf, sizeof(buf), "\n");
2199 if (pconn) {
2200 cat_snprintf(buf, sizeof(buf), _("Host: %s"), pconn->addr);
2201 }
2202 cat_snprintf(buf, sizeof(buf), "\n");
2203
2204 /* Show popup. */
2207 "%s", buf);
2208 gtk_window_set_title(GTK_WINDOW(popup), _("Player/conn info"));
2212}
2213
2214/**********************************************************************/
2218 gpointer data)
2219{
2220 struct player *pplayer;
2221 struct connection *pconn;
2222 GMenu *menu = data;
2223
2224 if (object_extract(G_OBJECT(menu), &pplayer, &pconn)) {
2225 show_conn_popup(pplayer, pconn);
2226 }
2227
2229}
2230
2231/**********************************************************************/
2235static GtkWidget *create_conn_menu(struct player *pplayer,
2236 struct connection *pconn)
2237{
2238 GMenu *menu;
2239 gchar *buf;
2240 GSimpleAction *act;
2241 GActionGroup *group;
2242
2244
2245 menu = g_menu_new();
2246
2247 object_put(G_OBJECT(menu), pplayer, pconn);
2248
2249 buf = g_strdup_printf(_("%s info"),
2250 pconn ? pconn->username : player_name(pplayer));
2251
2252 act = g_simple_action_new("info", NULL);
2254 g_signal_connect(act, "activate", G_CALLBACK(conn_menu_info_chosen), menu);
2255 menu_item_append_unref(menu, g_menu_item_new(buf, "win.info"));
2256
2257 if (NULL != pplayer) {
2258 act = g_simple_action_new("toggle_ready", NULL);
2260 g_signal_connect(act, "activate", G_CALLBACK(conn_menu_ready_chosen), menu);
2262 menu_item_append_unref(menu, g_menu_item_new(_("Toggle player ready"),
2263 "win.toggle_ready"));
2264
2265 act = g_simple_action_new("pick_nation", NULL);
2267 g_signal_connect(act, "activate", G_CALLBACK(conn_menu_nation_chosen), menu);
2270 pplayer));
2271 menu_item_append_unref(menu, g_menu_item_new(_("Pick nation"), "win.pick_nation"));
2272
2273 act = g_simple_action_new("observe", NULL);
2274 g_object_set_data_full(G_OBJECT(act), "command", g_strdup("observe"),
2277 g_signal_connect(act, "activate", G_CALLBACK(conn_menu_player_command), menu);
2278 menu_item_append_unref(menu, g_menu_item_new(_("Observe this player"),
2279 "win.observe"));
2280
2281 act = g_simple_action_new("take_plr", NULL);
2283 g_signal_connect(act, "activate", G_CALLBACK(conn_menu_player_take), menu);
2284 menu_item_append_unref(menu, g_menu_item_new(_("Take this player"),
2285 "win.take_plr"));
2286 }
2287
2289 && pconn->id != client.conn.id) {
2290 act = g_simple_action_new("cut_conn", NULL);
2291 g_object_set_data_full(G_OBJECT(act), "command", g_strdup("cut"),
2295 menu_item_append_unref(menu, g_menu_item_new(_("Cut connection"), "win.cut_conn"));
2296 }
2297
2298 if (ALLOW_CTRL <= client.conn.access_level && NULL != pplayer) {
2299 act = g_simple_action_new("aitoggle", NULL);
2300 g_object_set_data_full(G_OBJECT(act), "command", g_strdup("aitoggle"),
2304 menu_item_append_unref(menu, g_menu_item_new(_("Aitoggle player"), "win.aitoggle"));
2305
2306 if (pplayer != client.conn.playing && game.info.is_new_game) {
2307 act = g_simple_action_new("remove", NULL);
2308 g_object_set_data_full(G_OBJECT(act), "command", g_strdup("remove"),
2312 menu_item_append_unref(menu, g_menu_item_new(_("Remove player"), "win.remove"));
2313 }
2314 }
2315
2317 && pconn->id != client.conn.id) {
2318 enum cmdlevel level;
2319
2320 /* No item for hack access; that would be a serious security hole. */
2322 char actbuf[128];
2323
2324 buf = g_strdup_printf(_("Give %s access"), cmdlevel_name(level));
2325 fc_snprintf(actbuf, sizeof(actbuf), "cmdlevel_%d", level);
2326
2328 g_object_set_data_full(G_OBJECT(act), "command",
2329 g_strdup_printf("cmdlevel %s",
2334 fc_snprintf(actbuf, sizeof(actbuf), "win.cmdlevel_%d", level);
2336 g_free(buf);
2337 }
2338 }
2339
2341 && NULL != pplayer && is_ai(pplayer)) {
2342 enum ai_level level;
2343
2344 for (level = 0; level < AI_LEVEL_COUNT; level++) {
2346 char actbuf[128];
2347
2348 buf = g_strdup_printf(_("Difficulty: %s"), ai_level_translated_name(level));
2349 fc_snprintf(actbuf, sizeof(actbuf), "ailevel_%d", level);
2350
2352 g_object_set_data_full(G_OBJECT(act), "command",
2356 g_signal_connect(act, "activate", G_CALLBACK(conn_menu_player_command), menu);
2357 fc_snprintf(actbuf, sizeof(actbuf), "win.ailevel_%d", level);
2359 g_free(buf);
2360 }
2361 }
2362 }
2363
2364 if (pplayer != NULL /* && game.info.is_new_game */) {
2365 const int count = pplayer->team
2366 ? player_list_size(team_members(pplayer->team)) : 0;
2367 bool need_empty_team = (count != 1);
2368
2369 /* Can't use team_iterate here since it skips empty teams. */
2371 char actbuf[128];
2372 int id;
2373
2374 if (!team_slot_is_used(tslot)) {
2375 if (!need_empty_team) {
2376 continue;
2377 }
2379 }
2380
2382
2383 /* TRANS: e.g., "Put on Team 5" */
2384 buf = g_strdup_printf(_("Put on %s"),
2386 fc_snprintf(actbuf, sizeof(actbuf), "team_%d", id);
2387
2389 g_object_set_data(G_OBJECT(act), "slot", tslot);
2391 g_signal_connect(act, "activate", G_CALLBACK(conn_menu_team_chosen), menu);
2392 fc_snprintf(actbuf, sizeof(actbuf), "win.team_%d", id);
2394 g_free(buf);
2396 }
2397
2402
2403 return conn_popover;
2404}
2405
2406/**********************************************************************/
2410{
2411 if (NULL != connection_list_view) {
2412 GtkTreeSelection *selection =
2414 GtkTreePath *path = data;
2415
2416 gtk_tree_selection_unselect_path(selection, path);
2417 gtk_tree_path_free(path);
2418 }
2419 return FALSE;
2420}
2421
2422/**********************************************************************/
2426 int n_press,
2427 double x, double y, gpointer data)
2428{
2431 GtkTreePath *path = NULL;
2433
2435 x, y,
2436 &path, NULL, NULL, NULL)) {
2437 return FALSE;
2438 }
2439
2440 if (gtk_tree_selection_path_is_selected(selection, path)) {
2441 /* Need to delay to avoid problem with the expander. */
2443 return FALSE; /* Return now, don't free the path. */
2444 }
2445
2446 gtk_tree_path_free(path);
2447
2448 return FALSE;
2449}
2450
2451/**********************************************************************/
2455 int n_press,
2456 double x, double y, gpointer data)
2457{
2460 GtkWidget *parent = data;
2461 GtkTreePath *path = NULL;
2462 GtkWidget *menu;
2463 GtkTreeSelection *selection;
2464 GtkTreeModel *model;
2466 int player_no, conn_id;
2467 struct player *pplayer;
2468 struct connection *pconn;
2469 int bx, by;
2470 GdkRectangle rect = { .x = x, .y = y, .width = 1, .height = 1};
2471
2473
2475 &path, NULL, NULL, NULL)) {
2476 return FALSE;
2477 }
2478
2481
2482 if (!gtk_tree_selection_path_is_selected(selection, path)) {
2483 gtk_tree_selection_select_path(selection, path);
2484 }
2485 gtk_tree_model_get_iter(model, &iter, path);
2486
2487 gtk_tree_model_get(model, &iter, CL_COL_PLAYER_NUMBER, &player_no, -1);
2488 pplayer = player_by_number(player_no);
2489
2490 gtk_tree_model_get(model, &iter, CL_COL_CONN_ID, &conn_id, -1);
2491 pconn = conn_by_number(conn_id);
2492
2493 menu = create_conn_menu(pplayer, pconn);
2494 gtk_widget_set_parent(menu, parent); /* Gtk bug prevents tree view parenting */
2496
2498
2499 gtk_tree_path_free(path);
2500
2501 return TRUE;
2502}
2503
2504/**********************************************************************/
2509 GtkTreePath *path,
2510 gpointer data)
2511{
2513
2514 gtk_tree_store_set(store, iter,
2516}
2517
2518/**********************************************************************/
2523 struct connection **ppconn)
2524{
2525 if (NULL != connection_list_view) {
2527 GtkTreeModel *model;
2528 GtkTreeSelection *selection =
2530
2531 if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
2532 int id;
2533
2534 if (NULL != ppplayer) {
2535 gtk_tree_model_get(model, &iter, CL_COL_PLAYER_NUMBER, &id, -1);
2537 }
2538 if (NULL != ppconn) {
2539 gtk_tree_model_get(model, &iter, CL_COL_CONN_ID, &id, -1);
2540 *ppconn = conn_by_number(id);
2541 }
2542 return TRUE;
2543 }
2544 }
2545
2546 if (NULL != ppplayer) {
2547 *ppplayer = NULL;
2548 }
2549 if (NULL != ppconn) {
2550 *ppconn = NULL;
2551 }
2552 return FALSE;
2553}
2554
2555/**********************************************************************/
2559{
2560 GtkTreeModel *model;
2561 GtkTreeIter parent, child, *iter = NULL;
2562 GtkTreeSelection *selection;
2563 gboolean valid;
2564 const int search_id = pconn->id;
2565 int id;
2566
2567 if (NULL == connection_list_view) {
2568 return;
2569 }
2570
2573
2574 /* Main iteration. */
2575 valid = gtk_tree_model_get_iter_first(model, &parent);
2576 while (valid && NULL == iter) {
2577 gtk_tree_model_get(model, &parent, CL_COL_CONN_ID, &id, -1);
2578 if (search_id == id) {
2579 iter = &parent;
2580 break;
2581 }
2582
2583 /* Node children iteration. */
2584 valid = gtk_tree_model_iter_children(model, &child, &parent);
2585 while (valid && NULL == iter) {
2586 gtk_tree_model_get(model, &child, CL_COL_CONN_ID, &id, -1);
2587 if (search_id == id) {
2588 iter = &child;
2589 break;
2590 }
2591 valid = gtk_tree_model_iter_next(model, &child);
2592 }
2593
2594 valid = gtk_tree_model_iter_next(model, &parent);
2595 }
2596
2597 /* Select iterator. */
2598 if (NULL != iter) {
2600 } else {
2601 log_error("%s(): connection %s not found.",
2603 }
2604}
2605
2606/**********************************************************************/
2610{
2611 if (can_client_control()) {
2614 !client_player()->is_ready);
2615 } else {
2617 }
2618}
2619
2620/**********************************************************************/
2624{
2625 struct player *selected_plr;
2626 bool row_selected = conn_list_selection(&selected_plr, NULL);
2627
2628 if (row_selected && NULL != selected_plr) {
2629 /* "Take <player_name>" */
2631 } else if (can_client_control()) {
2632 /* "Pick Nation" */
2634 } else {
2635 /* "Take a Player" */
2636 send_chat("/take -");
2637 }
2638}
2639
2640/**********************************************************************/
2644{
2645 struct player *selected_plr;
2646 bool row_selected = conn_list_selection(&selected_plr, NULL);
2647
2648 if (row_selected && NULL != selected_plr) {
2649 /* "Observe <player_name>" */
2650 send_chat_printf("/observe \"%s\"", player_name(selected_plr));
2651 } else if (!client_is_global_observer()) {
2652 /* "Observe" */
2653 send_chat("/observe");
2654 } else {
2655 /* "Do not observe" */
2656 send_chat("/detach");
2657 }
2658}
2659
2660/**********************************************************************/
2664{
2665 char buf[2 * MAX_LEN_NAME];
2666 const char *text;
2667 struct player *selected_plr;
2668 bool row_selected = conn_list_selection(&selected_plr, NULL);
2669 bool sensitive;
2670
2671 /*** Ready button. ***/
2672 if (can_client_control()) {
2673 sensitive = client_player()->is_alive;
2674 if (client_player()->is_ready) {
2675 text = _("Not _ready");
2676 } else {
2677 int num_unready = 0;
2678
2679 players_iterate_alive(pplayer) {
2680 if (is_human(pplayer) && !pplayer->is_ready) {
2681 num_unready++;
2682 }
2684
2685 if (num_unready > 1) {
2686 text = _("_Ready");
2687 } else {
2688 /* We are the last unready player so clicking here will
2689 * immediately start the game. */
2690 text = _("_Start");
2691 }
2692 }
2693 } else {
2694 text = _("_Start");
2695 if (can_client_access_hack()) {
2696 sensitive = TRUE;
2698 if (is_human(plr)) {
2699 /* There's human controlled player(s) in game, so it's their
2700 * job to start the game. */
2701 sensitive = FALSE;
2702 break;
2703 }
2705 } else {
2706 sensitive = FALSE;
2707 }
2708 }
2711
2712 /*** Nation button. ***/
2713 if (row_selected && NULL != selected_plr) {
2714 fc_snprintf(buf, sizeof(buf), _("_Take %s"), player_name(selected_plr));
2715 text = buf;
2717 } else if (can_client_control()) {
2718 text = _("Pick _Nation");
2720 } else {
2721 text = _("_Take a Player");
2723 }
2726
2727 /*** Observe button. ***/
2728 if (row_selected && NULL != selected_plr) {
2729 fc_snprintf(buf, sizeof(buf), _("_Observe %s"),
2731 text = buf;
2733 } else if (!client_is_global_observer()) {
2734 text = _("_Observe");
2735 sensitive = TRUE;
2736 } else {
2737 text = _("Do not _observe");
2738 sensitive = TRUE;
2739 }
2742}
2743
2744/**********************************************************************/
2750 GtkTreeIter *start,
2751 const struct player *pplayer)
2752{
2753 const int search_id = player_number(pplayer);
2754 int id;
2755
2756 if (NULL != start) {
2757 *iter = *start;
2758 if (!gtk_tree_model_iter_next(model, iter)) {
2759 return FALSE;
2760 }
2761 } else if (!gtk_tree_model_get_iter_first(model, iter)) {
2762 return FALSE;
2763 }
2764
2765 do {
2767 if (id == search_id) {
2768 return TRUE;
2769 }
2770 } while (gtk_tree_model_iter_next(model, iter));
2771
2772 return FALSE;
2773}
2774
2775/**********************************************************************/
2781 const struct connection *pconn)
2782{
2783 const int search_id = pconn->id;
2784 int id;
2785
2786 if (NULL != start) {
2787 *iter = *start;
2788 if (!gtk_tree_model_iter_next(model, iter)) {
2789 return FALSE;
2790 }
2791 } else if (!gtk_tree_model_iter_children(model, iter, parent)) {
2792 return FALSE;
2793 }
2794
2795 do {
2796 gtk_tree_model_get(model, iter, CL_COL_CONN_ID, &id, -1);
2797 if (id == search_id) {
2798 return TRUE;
2799 }
2800 } while (gtk_tree_model_iter_next(model, iter));
2801
2802 return FALSE;
2803}
2804
2805/**********************************************************************/
2809{
2814 GtkTreeModel *model = GTK_TREE_MODEL(store);
2815 GtkTreePath *path;
2818 GdkPixbuf *flag, *color;
2820 struct player *pselected_player;
2821 struct connection *pselected_conn;
2822 bool is_ready;
2823 const char *nation, *plr_name, *team;
2824 char name[MAX_LEN_NAME + 8];
2826 int conn_id;
2827
2828 /* Refresh the AI skill level control */
2829 if (ai_lvl_combobox) {
2830 enum ai_level new_level = server_ai_level(), level;
2831 int i = 0;
2832
2833 for (level = 0; level < AI_LEVEL_COUNT; level++) {
2835 if (level == new_level) {
2837 break;
2838 }
2839 i++;
2840 }
2841 }
2842 if (level == AI_LEVEL_COUNT) {
2843 /* Probably ai_level_invalid() */
2845 }
2846 }
2847
2848 /* Save the selected connection. */
2850
2851 /* Insert players into the connection list. */
2852 players_iterate(pplayer) {
2853 if (!player_has_flag(pplayer, PLRF_SCENARIO_RESERVED)) {
2854 conn_id = -1;
2856 flag = pplayer->nation ? get_flag(pplayer->nation) : NULL;
2857 color = create_player_icon(pplayer);
2858
2859 conn_list_iterate(pplayer->connections, pconn) {
2860 if (pconn->playing == pplayer && !pconn->observer) {
2861 conn_id = pconn->id;
2862 access_level = pconn->access_level;
2863 break;
2864 }
2866
2867 if (is_ai(pplayer) && !pplayer->was_created
2868 && !pplayer->is_connected) {
2869 /* TRANS: "<Novice AI>" */
2870 fc_snprintf(name, sizeof(name), _("<%s AI>"),
2871 ai_level_translated_name(pplayer->ai_common.skill_level));
2872 } else {
2873 sz_strlcpy(name, pplayer->username);
2874 if (access_level > ALLOW_BASIC) {
2875 sz_strlcat(name, "*");
2876 }
2877 }
2878
2879 is_ready = !is_human(pplayer) ? TRUE : pplayer->is_ready;
2880
2881 if (pplayer->nation == NO_NATION_SELECTED) {
2882 nation = _("Random");
2883 if (pplayer->was_created) {
2884 plr_name = player_name(pplayer);
2885 } else {
2886 plr_name = "";
2887 }
2888 } else {
2889 nation = nation_adjective_for_player(pplayer);
2890 plr_name = player_name(pplayer);
2891 }
2892
2893 team = pplayer->team ? team_name_translation(pplayer->team) : "";
2894
2895 if (model_get_player_iter(model, &parent, pprev_parent, pplayer)) {
2897 } else {
2899 }
2900
2901 gtk_tree_store_set(store, &parent,
2904 CL_COL_READY_STATE, is_ready,
2906 CL_COL_FLAG, flag,
2908 CL_COL_NATION, nation,
2910 CL_COL_CONN_ID, conn_id,
2913 -1);
2914
2915 /* Insert observers of this player as child nodes. */
2916 pprev_child = NULL;
2917 conn_list_iterate(pplayer->connections, pconn) {
2918 if (pconn->id == conn_id) {
2919 continue;
2920 }
2921 if (model_get_conn_iter(model, &child, &parent,
2922 pprev_child, pconn)) {
2923 gtk_tree_store_move_after(store, &child, pprev_child);
2924 } else {
2926 }
2927
2928 gtk_tree_store_set(store, &child,
2930 CL_COL_USER_NAME, pconn->username,
2931 CL_COL_TEAM, _("Observer"),
2932 CL_COL_CONN_ID, pconn->id,
2935 -1);
2936
2937 prev_child = child;
2940
2941 /* Expand node? */
2942 if (NULL != pprev_child) {
2944 if (!collapsed) {
2945 path = gtk_tree_model_get_path(model, &parent);
2947 path, FALSE);
2948 gtk_tree_path_free(path);
2949 }
2950 }
2951
2952 /* Remove trailing rows. */
2953 if (NULL != pprev_child) {
2954 child = prev_child;
2955 if (gtk_tree_model_iter_next(model, &child)) {
2956 while (gtk_tree_store_remove(store, &child)) {
2957 /* Do nothing more. */
2958 }
2959 }
2960 } else if (gtk_tree_model_iter_children(model, &child, &parent)) {
2961 while (gtk_tree_store_remove(store, &child)) {
2962 /* Do nothing more. */
2963 }
2964 }
2965
2968 if (flag) {
2969 g_object_unref(flag);
2970 }
2971 if (color) {
2973 }
2974 }
2976
2977 /* Finally, insert global observers... */
2979 if (NULL != pconn->playing || !pconn->observer) {
2980 continue;
2981 }
2982
2985 } else {
2987 }
2988
2989 gtk_tree_store_set(store, &parent,
2991 CL_COL_USER_NAME, pconn->username,
2992 CL_COL_TEAM, _("Observer"),
2993 CL_COL_CONN_ID, pconn->id,
2996 -1);
2997
3001
3002 /* ...and detached connections. */
3004 if (NULL != pconn->playing || pconn->observer) {
3005 continue;
3006 }
3007
3010 } else {
3012 }
3013
3014 gtk_tree_store_set(store, &parent,
3016 CL_COL_USER_NAME, pconn->username,
3017 CL_COL_TEAM, _("Detached"),
3018 CL_COL_CONN_ID, pconn->id,
3021 -1);
3022
3026
3027 /* Remove trailing rows. */
3028 if (NULL != pprev_parent) {
3030 if (gtk_tree_model_iter_next(model, &parent)) {
3031 while (gtk_tree_store_remove(store, &parent)) {
3032 /* Do nothing more. */
3033 }
3034 }
3035 } else {
3036 gtk_tree_store_clear(store);
3037 }
3038
3039 /* If we were selecting a single connection, let's try to reselect it. */
3042 }
3043 }
3044
3046}
3047
3048/**********************************************************************/
3054 const char *title, int colnum, const char *key)
3055{
3058
3059 if (gtype == G_TYPE_BOOLEAN) {
3062 "active", colnum, NULL);
3063 } else if (gtype == GDK_TYPE_PIXBUF) {
3066 "pixbuf", colnum, NULL);
3067 } else {
3070 "text", colnum,
3071 "style", CL_COL_STYLE,
3072 "weight", CL_COL_WEIGHT,
3073 NULL);
3074 }
3075
3078
3079 if (key != NULL) {
3081 }
3082}
3083
3084/**********************************************************************/
3088{
3089 GtkWidget *box, *sbox, *table, *vgrid;
3090 GtkWidget *view, *sw, *text, *toolkit_view, *button, *spin;
3091 GtkWidget *label;
3092 GtkTreeSelection *selection;
3093 enum ai_level level;
3094 /* There's less than AI_LEVEL_COUNT entries as not all levels have
3095 entries (that's the whole point of this array: index != value),
3096 but this is set safely to the max */
3097 static enum ai_level levels[AI_LEVEL_COUNT];
3098 int i = 0;
3099 int box_row = 0;
3100 int sbox_col = 0;
3101 int grid_row = 0;
3104
3105 box = gtk_grid_new();
3113
3114 sbox = gtk_grid_new();
3116 gtk_grid_attach(GTK_GRID(box), sbox, 0, box_row++, 1, 1);
3117
3118 vgrid = gtk_grid_new();
3129
3130 table = gtk_grid_new();
3135
3141 if (server_optset != NULL) {
3143
3144 if (paifill) {
3147 } /* else it'll be updated later */
3148 }
3149 g_signal_connect_after(spin, "value_changed",
3151
3152 gtk_grid_attach(GTK_GRID(table), spin, 1, 0, 1, 1);
3153
3155 "use-underline", TRUE,
3156 "mnemonic-widget", spin,
3157 /* TRANS: Keep individual lines short */
3158 "label", _("Number of _Players\n(including AI):"),
3159 "xalign", 0.0,
3160 "yalign", 0.5,
3161 NULL);
3162 gtk_grid_attach(GTK_GRID(table), label, 0, 0, 1, 1);
3163
3165
3166 for (level = 0; level < AI_LEVEL_COUNT; level++) {
3169
3171 levels[i] = level;
3172 i++;
3173 }
3174 }
3177 G_CALLBACK(ai_skill_callback), levels);
3178
3180
3182 "use-underline", TRUE,
3183 "mnemonic-widget", ai_lvl_combobox,
3184 "label", _("AI Skill _Level:"),
3185 "xalign", 0.0,
3186 "yalign", 0.5,
3187 NULL);
3188 gtk_grid_attach(GTK_GRID(table), label, 0, 1, 1, 1);
3189
3193
3195
3197 "use-underline", TRUE,
3198 "mnemonic-widget", GTK_COMBO_BOX_TEXT(ruleset_combo),
3199 "label", _("Ruleset:"),
3200 "xalign", 0.0,
3201 "yalign", 0.5,
3202 NULL);
3203 gtk_grid_attach(GTK_GRID(table), label, 0, 2, 1, 1);
3204
3205 button = icon_label_button_new("preferences-system",
3206 _("_More Game Options..."));
3208 gtk_widget_set_margin_end(button, 8);
3209 gtk_widget_set_margin_start(button, 8);
3210 gtk_widget_set_margin_top(button, 8);
3213 g_signal_connect(button, "clicked",
3215 gtk_grid_attach(GTK_GRID(vgrid), button, 0, grid_row++, 1, 1);
3216
3220 gtk_widget_add_css_class(GTK_WIDGET(view), "large-pixbufs");
3224
3227 g_signal_connect(selection, "changed",
3229
3230 add_tree_col(view, G_TYPE_STRING, _("Name"),
3232 add_tree_col(view, G_TYPE_BOOLEAN, _("Ready"),
3234 add_tree_col(view, G_TYPE_STRING, Q_("?player:Leader"),
3237 CL_COL_FLAG, NULL);
3238 add_tree_col(view, GDK_TYPE_PIXBUF, _("Border"),
3240 add_tree_col(view, G_TYPE_STRING, _("Nation"),
3242 add_tree_col(view, G_TYPE_STRING, _("Team"),
3243 CL_COL_TEAM, NULL);
3244
3246 g_signal_connect(controller, "pressed",
3249
3250 g_signal_connect(view, "row-collapsed",
3253 g_signal_connect(view, "row-expanded",
3256
3264
3265 /* This is for a workaround against gtk bug that we can't parent
3266 * popup to the tree view - we have to parent it all the way to sw */
3270 g_signal_connect(controller, "pressed",
3273
3274 gtk_grid_attach(GTK_GRID(sbox), sw, sbox_col++, 0, 1, 1);
3275
3281 gtk_grid_attach(GTK_GRID(box), sw, 0, box_row++, 1, 1);
3282
3286 start_message_area = text;
3287 gtk_widget_set_name(text, "chatline");
3292
3293
3294 /* Vote widgets. */
3295 if (pregame_votebar == NULL) {
3297 }
3299
3301 gtk_grid_attach(GTK_GRID(box), toolkit_view, 0, box_row++, 1, 1);
3302
3303 button = gtk_button_new_with_mnemonic(_("_Cancel"));
3305 g_signal_connect(button, "clicked", G_CALLBACK(main_callback), NULL);
3306
3307 nation_button = icon_label_button_new("document-properties",
3308 _("Pick _Nation"));
3312
3313 observe_button = icon_label_button_new("zoom-in", _("_Observe"));
3317
3318 ready_button = icon_label_button_new("system-run", _("_Ready"));
3320 g_signal_connect(ready_button, "clicked",
3322
3323 return box;
3324}
3325
3326
3327/**********************************************************************/
3330void handle_game_load(bool load_successful, const char *filename)
3331{
3332 if (load_successful) {
3334
3335 if (game.info.is_new_game) {
3336 /* It's pregame. Create a player and connect to it */
3337 send_chat("/take -");
3338 }
3339 }
3340}
3341
3342/**********************************************************************/
3345static void load_filename(const char *filename)
3346{
3347 send_chat_printf("/load %s", filename);
3348}
3349
3350/**********************************************************************/
3353static void load_callback(void)
3354{
3355 GtkTreeIter it;
3356 const gchar *filename;
3357
3359 return;
3360 }
3361
3363 SD_COL_FULL_PATH, &filename, -1);
3364 load_filename(filename);
3365}
3366
3367/**********************************************************************/
3371{
3372 save_dialog_file_chooser_popup(_("Choose Saved Game to Load"),
3375}
3376
3377/**********************************************************************/
3380static void update_load_page(void)
3381{
3382 /* Search for user saved games. */
3384 ".sav", FALSE);
3385
3387 fileinfo_list_destroy(files);
3388}
3389
3390/**********************************************************************/
3394{
3395 GtkWidget *box, *sbox, *bbox;
3396
3397 GtkWidget *button, *label, *view, *sw;
3399 int box_row = 0;
3400 int sbox_row = 0;
3401
3402 box = gtk_grid_new();
3410
3415
3418 -1, NULL, rend, "text", 0, NULL);
3419
3422
3424
3425 g_signal_connect(view, "row-activated",
3427
3428 sbox = gtk_grid_new();
3433 gtk_grid_attach(GTK_GRID(box), sbox, 0, box_row++, 1, 1);
3434
3436 "use-underline", TRUE,
3437 "mnemonic-widget", view,
3438 "label", _("Choose Saved Game to _Load:"),
3439 "xalign", 0.0,
3440 "yalign", 0.5,
3441 NULL);
3442 gtk_grid_attach(GTK_GRID(sbox), label, 0, sbox_row++, 1, 1);
3443
3450 gtk_grid_attach(GTK_GRID(sbox), sw, 0, sbox_row++, 1, 1);
3451
3455 gtk_grid_attach(GTK_GRID(box), bbox, 0, box_row++, 1, 1);
3456
3457 button = gtk_button_new_with_mnemonic(_("_Browse..."));
3458 gtk_box_append(GTK_BOX(bbox), button);
3459 g_signal_connect(button, "clicked",
3461
3462 button = gtk_button_new_with_mnemonic(_("_Cancel"));
3463 gtk_box_append(GTK_BOX(bbox), button);
3464 g_signal_connect(button, "clicked",
3466
3467 button = gtk_button_new_with_mnemonic(_("_OK"));
3468 gtk_box_append(GTK_BOX(bbox), button);
3469 g_signal_connect(button, "clicked",
3471
3472 return box;
3473}
3474
3475/**********************************************************************/
3478static void scenario_list_callback(void)
3479{
3480 GtkTreeIter it;
3481 GtkTextBuffer *buffer;
3482 char *description;
3483 char *authors;
3484 char *filename;
3485 int ver;
3486 char vername[50];
3487
3490 2, &description, -1);
3492 3, &authors, -1);
3494 1, &filename, -1);
3496 4, &ver, -1);
3497 filename = skip_to_basename(filename);
3498 if (ver > 0) {
3499 int maj;
3500 int min;
3501
3502 maj = ver / 1000000;
3503 ver %= 1000000;
3504 min = ver / 10000;
3505 ver %= 10000;
3506 if (ver >= 9000) {
3507 /* Development version, have '+' */
3508 fc_snprintf(vername, sizeof(vername), "%d.%d+", maj, min);
3509 } else {
3510 fc_snprintf(vername, sizeof(vername), "%d.%d", maj, min);
3511 }
3512 } else {
3513 /* TRANS: Old scenario format version */
3514 fc_snprintf(vername, sizeof(vername), _("pre-2.6"));
3515 }
3516 } else {
3517 description = "";
3518 authors = "";
3519 filename = "";
3520 vername[0] = '\0';
3521 }
3522
3524 gtk_text_buffer_set_text(buffer, description, -1);
3526 gtk_text_buffer_set_text(buffer, authors, -1);
3529}
3530
3531/**********************************************************************/
3534static void scenario_callback(void)
3535{
3536 GtkTreeIter it;
3537 char *filename;
3538
3540 return;
3541 }
3542
3543 gtk_tree_model_get(GTK_TREE_MODEL(scenario_store), &it, 1, &filename, -1);
3544 load_filename(filename);
3545}
3546
3547/**********************************************************************/
3551{
3552 save_dialog_file_chooser_popup(_("Choose a Scenario"),
3555}
3556
3557/**********************************************************************/
3560static void update_scenario_page(void)
3561{
3562 struct fileinfo_list *files;
3563
3565
3566 /* search for scenario files. */
3567 files = fileinfolist_infix(get_scenario_dirs(), ".sav", TRUE);
3569 struct section_file *sf;
3570
3571 if ((sf = secfile_load_section(pfile->fullname, "scenario", TRUE))
3572 && secfile_lookup_bool_default(sf, TRUE, "scenario.is_scenario")) {
3573 const char *sname, *sdescription, *sauthors;
3574 int fcver;
3575 int fcdev;
3576 int current_ver = MAJOR_VERSION * 1000000 + MINOR_VERSION * 10000;
3577 int current_dev;
3578
3580 if (PATCH_VERSION >= 90) {
3581 /* Patch level matters on development versions */
3582 current_dev += PATCH_VERSION * 100;
3583 }
3584
3585 fcver = secfile_lookup_int_default(sf, 0, "scenario.game_version");
3586 if (fcver < 30000) {
3587 /* Pre-3.0 versions stored version number without emergency version
3588 * part in the end. To get comparable version number stored,
3589 * multiply by 100. */
3590 fcver *= 100;
3591 }
3592 if (fcver % 10000 >= 9000) {
3593 fcdev = fcver - (fcver % 100); /* Emergency version does not count. */
3594 } else {
3595 fcdev = fcver - (fcver % 10000); /* Patch version does not count. */
3596 }
3597 sname = secfile_lookup_str_default(sf, NULL, "scenario.name");
3599 "scenario.description");
3600 sauthors = secfile_lookup_str_default(sf, NULL, "scenario.authors");
3601 log_debug("scenario file: %s from %s", sname, pfile->fullname);
3602
3603 /* Ignore scenarios for newer freeciv versions than we are. */
3604 if (fcdev <= current_dev) {
3605 bool add_new = TRUE;
3606
3607 if (sname != NULL) {
3608 GtkTreeIter it;
3609 bool valid;
3610
3612 while (valid) {
3613 char *oname;
3614
3616 0, &oname, -1);
3617
3618 if (!strcmp(sname, oname)) {
3619 /* Already listed scenario has the same name as the one we just found */
3620 int existing;
3621
3623 4, &existing, -1);
3624 log_debug("Duplicate %s (%d vs %d)", sname, existing, fcver);
3625
3626 if (existing > fcver) {
3627 /* Already listed one has higher version number */
3628 add_new = FALSE;
3629 } else if (existing < fcver) {
3630 /* New one has higher version number */
3631 add_new = FALSE;
3632
3634 0, sname && strlen(sname) ? Q_(sname) : pfile->name,
3635 1, pfile->fullname,
3636 2, (NULL != sdescription && '\0' != sdescription[0]
3637 ? Q_(sdescription) : ""),
3638 3, (NULL != sauthors && sauthors[0] != '\0'
3639 ? Q_(sauthors) : ""),
3640 4, fcver,
3641 -1);
3642 } else {
3643 /* Same version number -> list both */
3644 }
3645 }
3647 }
3648 }
3649
3650 if (add_new) {
3651 GtkTreeIter it;
3652
3655 0, sname && strlen(sname) ? Q_(sname) : pfile->name,
3656 1, pfile->fullname,
3657 2, (NULL != sdescription && '\0' != sdescription[0]
3658 ? Q_(sdescription) : ""),
3659 3, (NULL != sauthors && sauthors[0] != '\0'
3660 ? Q_(sauthors) : ""),
3661 4, fcver,
3662 -1);
3663 }
3664 }
3665
3666 secfile_destroy(sf);
3667 }
3669
3670 fileinfo_list_destroy(files);
3671}
3672
3673/**********************************************************************/
3687
3688/**********************************************************************/
3697
3698/**********************************************************************/
3702{
3705 GtkWidget *button, *label, *view, *sw, *swa, *text;
3708 int grid_row = 0;
3709 int filenamecol = 0;
3710 int vercol = 0;
3711 int descrow = 0;
3712
3713 vgrid = gtk_grid_new();
3721
3726 G_TYPE_INT);
3727
3730 nullptr);
3732 nullptr);
3733
3738
3741 -1, NULL, rend, "text", 0, NULL);
3742
3747
3749
3750 g_signal_connect(view, "row-activated",
3752
3754 "use-underline", TRUE,
3755 "mnemonic-widget", view,
3756 "label", _("Choose a _Scenario:"),
3757 "xalign", 0.0,
3758 "yalign", 0.5,
3759 NULL);
3760 gtk_grid_attach(GTK_GRID(vgrid), label, 0, grid_row++, 1, 1);
3761
3762 sbox = gtk_grid_new();
3769
3770 hbox = gtk_grid_new();
3773
3779 gtk_grid_attach(GTK_GRID(sbox), sw, 0, 0, 1, 2);
3780
3781 text = gtk_text_view_new();
3787 scenario_description = text;
3788
3794
3795 text = gtk_text_view_new();
3801 scenario_authors = text;
3802
3808
3809 text = gtk_label_new(_("Filename:"));
3814
3821
3822 gtk_grid_attach(GTK_GRID(filenamebox), text, filenamecol++, 0, 1, 1);
3824 filenamecol++, 0, 1, 1);
3825
3826 /* TRANS: Scenario format version */
3827 vertext = gtk_label_new(_("Format:"));
3832
3839
3842 vercol++, 0, 1, 1);
3843
3848 gtk_grid_attach(GTK_GRID(descbox), sw, 0, descrow++, 1, 1);
3851 0, descrow++, 1, 1);
3853 0, descrow++, 1, 1);
3854 gtk_grid_attach(GTK_GRID(sbox), descbox, 1, 0, 1, 2);
3855
3859
3860 button = gtk_button_new_with_mnemonic(_("_Browse..."));
3861 gtk_box_append(GTK_BOX(bbox), button);
3862 g_signal_connect(button, "clicked",
3864
3865 button = gtk_button_new_with_mnemonic(_("_Cancel"));
3866 gtk_box_append(GTK_BOX(bbox), button);
3867 g_signal_connect(button, "clicked",
3869
3870 button = gtk_button_new_with_mnemonic(_("_OK"));
3871 gtk_box_append(GTK_BOX(bbox), button);
3872 g_signal_connect(button, "clicked",
3874
3875 return vgrid;
3876}
3877
3878/**********************************************************************/
3882{
3883 return current_page;
3884}
3885
3886/**********************************************************************/
3890{
3891 /* Don't use current_page directly here because maybe it could be modified
3892 * before we reach the end of this function. */
3894
3895 /* If the page remains the same, don't do anything. */
3896 if (old_page == new_page) {
3897 return;
3898 }
3899
3900 log_debug("Switching client page from %s to %s.",
3901 -1 == old_page ? "(no page)" : client_pages_name(old_page),
3903
3905
3906 switch (old_page) {
3907 case PAGE_SCENARIO:
3908 case PAGE_LOAD:
3909 break;
3910 case PAGE_GAME:
3911 {
3913
3915 if (vmode == NULL) {
3917 }
3918 }
3919 break;
3920 default:
3921 break;
3922 }
3923
3924 switch (new_page) {
3925 case PAGE_MAIN:
3926 case PAGE_START:
3927 if (is_server_running()) {
3930 } else {
3932 }
3936 break;
3937 case PAGE_GAME:
3938 {
3940
3943 if (vmode == NULL) {
3945 }
3948 }
3949 break;
3950 case PAGE_LOAD:
3952 break;
3953 case PAGE_SCENARIO:
3955 break;
3956 case PAGE_NETWORK:
3958 break;
3959 }
3960
3961 /* Hide/show statusbar. */
3962 if (new_page == PAGE_START || new_page == PAGE_GAME) {
3965 } else {
3967 }
3968
3970
3971 /* Update the GUI. */
3972 while (g_main_context_pending(NULL)) {
3974 }
3975
3976 switch (new_page) {
3977 case PAGE_MAIN:
3978 break;
3979 case PAGE_START:
3982 break;
3983 case PAGE_LOAD:
3985 break;
3986 case PAGE_SCENARIO:
3988 break;
3989 case PAGE_GAME:
3993 mapview_thaw();
3994 /* Force a resize "just in case" */
3995 /* this is probably a no-op most of the time */
3997 break;
3998 case PAGE_NETWORK:
4003 break;
4004 }
4005}
4006
4007/****************************************************************************
4008 SAVE GAME DIALOGs
4009****************************************************************************/
4010
4011/**********************************************************************/
4015{
4016 return fileinfolist_infix(get_save_dirs(), ".sav", FALSE);
4017}
4018
4019/**********************************************************************/
4023{
4024 static GtkWidget *shell = NULL;
4025
4026 if (NULL != shell) {
4027 return;
4028 }
4029
4030 shell = save_dialog_new(_("Save Game"), _("Saved _Games:"),
4031 _("Save _Filename:"), send_save_game,
4034 &shell);
4036}
4037
4038/**********************************************************************/
4041static void save_dialog_save_scenario(const char *filename)
4042{
4044}
4045
4046/**********************************************************************/
4050{
4051 return fileinfolist_infix(get_scenario_dirs(), ".sav", FALSE);
4052}
4053
4054/**********************************************************************/
4058{
4059 static GtkWidget *shell = NULL;
4060
4061 if (NULL != shell) {
4062 return;
4063 }
4064
4065 shell = save_dialog_new(_("Save Scenario"), _("Saved Sce_narios:"),
4066 _("Save Sc_enario:"), save_dialog_save_scenario,
4069 &shell);
4071}
4072
4073/**********************************************************************/
4079{
4080 return fileinfolist_infix(get_save_dirs(), ".map", FALSE);
4081}
4082
4083/**********************************************************************/
4087{
4088 static GtkWidget *shell = NULL;
4089
4090 if (NULL != shell) {
4091 return;
4092 }
4093
4094 shell = save_dialog_new(_("Save Map Image"), _("Saved Map _Images:"),
4095 _("Save _Map Images:"), mapimg_client_save,
4098 &shell);
4100}
4101
4102/**********************************************************************/
4105void mapimg_client_save(const char *filename)
4106{
4107 if (!mapimg_client_createmap(filename)) {
4108 char msg[512];
4109
4110 fc_snprintf(msg, sizeof(msg), "(%s)", mapimg_error());
4111 popup_notify_dialog(_("Error"),
4112 _("Error Creating the Map Image!"), msg);
4113 }
4114}
4115
4116/**********************************************************************/
4121void set_rulesets(int num_rulesets, char **rulesets)
4122{
4123 int i;
4124 int def_idx = -1;
4125
4127 for (i = 0; i < num_rulesets; i++) {
4128
4130 if (!strcmp("default", rulesets[i])) {
4131 def_idx = i;
4132 }
4133 }
4134
4136
4137 /* HACK: Server should tell us the current ruleset. */
4139
4141}
#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:47
bool can_client_control(void)
bool client_is_global_observer(void)
bool client_is_observer(void)
char user_name[512]
char server_host[512]
struct civclient client
enum client_states client_state(void)
char fc_password[MAX_LEN_PASSWORD]
int server_port
#define client_player()
@ C_S_PREPARING
Definition client_main.h:46
enum ai_level server_ai_level(void)
Definition climisc.c:1524
bool mapimg_client_createmap(const char *filename)
Definition climisc.c:1471
void center_on_something(void)
Definition climisc.c:430
static struct fc_sockaddr_list * list
Definition clinet.c:102
int connect_to_server(const char *username, const char *hostname, int port, char *errbuf, int errbufsize)
Definition clinet.c:249
void disconnect_from_server(bool leaving_sound)
Definition clinet.c:306
char * incite_cost
Definition comments.c:77
authentication_type
Definition conn_types.h:41
@ AUTH_NEWUSER_RETRY
Definition conn_types.h:45
@ AUTH_NEWUSER_FIRST
Definition conn_types.h:43
@ AUTH_LOGIN_RETRY
Definition conn_types.h:44
@ AUTH_LOGIN_FIRST
Definition conn_types.h:42
void send_save_game(const char *filename)
void set_ruleset(const char *ruleset)
bool is_server_running(void)
bool client_start_server(void)
bool can_client_access_hack(void)
const char * conn_description(const struct connection *pconn)
Definition connection.c:476
struct connection * conn_by_number(int id)
Definition connection.c:423
#define conn_list_iterate(connlist, pconn)
Definition connection.h:108
#define conn_list_iterate_end
Definition connection.h:110
popup_notify_dialog
Definition dialogs_g.h:36
int int id
Definition editgui_g.h:28
#define MAX_NUM_PLAYERS
Definition fc_types.h:36
#define MAX_LEN_NAME
Definition fc_types.h:68
#define Q_(String)
Definition fcintl.h:70
#define _(String)
Definition fcintl.h:67
void fc_mutex_allocate(fc_mutex *mutex)
Definition fcthread.c:144
void fc_mutex_release(fc_mutex *mutex)
Definition fcthread.c:152
const struct ft_color ftc_client
struct civ_game game
Definition game.c:62
static PangoLayout * layout
Definition canvas.c:325
void inputline_toolkit_view_append_button(GtkWidget *toolkit_view, GtkWidget *button)
Definition chatline.c:1293
GtkWidget * inputline_toolkit_view_new(void)
Definition chatline.c:1271
void inputline_grab_focus(void)
Definition chatline.c:80
void chatline_scroll_to_bottom(bool delayed)
Definition chatline.c:1007
void popup_races_dialog(struct player *pplayer)
Definition dialogs.c:1215
static struct tile * pos
Definition finddlg.c:53
const char * client_string
Definition gui_main.c:106
GtkTextBuffer * message_buffer
Definition gui_main.c:178
struct video_mode * resolution_request_get(void)
Definition gui_main.c:2580
void enable_menus(bool enable)
Definition gui_main.c:1021
void refresh_chat_buttons(void)
Definition gui_main.c:2478
void reset_unit_table(void)
Definition gui_main.c:992
GtkWidget * toplevel
Definition gui_main.c:126
void quit_gtk_main(void)
Definition gui_main.c:2306
static struct video_mode vmode
Definition gui_main.c:190
GtkWidget * toplevel_tabs
Definition gui_main.c:128
int screen_height(void)
Definition gui_main.c:2562
#define GUI_GTK_OPTION(optname)
Definition gui_main.h:32
void gtk_tree_view_focus(GtkTreeView *view)
Definition gui_stuff.c:236
void gtk_stockbutton_set_label(GtkWidget *button, const gchar *label_text)
Definition gui_stuff.c:96
GtkWidget * icon_label_button_new(const gchar *icon_name, const gchar *label_text)
Definition gui_stuff.c:76
GtkTreeViewColumn * add_treeview_column(GtkWidget *view, const char *title, GType gtype, int model_index)
Definition gui_stuff.c:1123
void setup_dialog(GtkWidget *shell, GtkWidget *parent)
Definition gui_stuff.c:287
void mapview_freeze(void)
Definition mapview.c:373
void overview_size_changed(void)
Definition mapview.c:326
void mapview_thaw(void)
Definition mapview.c:381
static struct gui_dialog * shell
Definition messagedlg.c:39
void option_dialog_popup(const char *name, const struct option_set *poptset)
Definition optiondlg.c:984
static GtkListStore * load_store
Definition pages.c:68
static void update_network_page(void)
Definition pages.c:1183
void handle_game_load(bool load_successful, const char *filename)
Definition pages.c:2835
GtkWidget * create_start_page(void)
Definition pages.c:2617
GtkWidget * create_network_page(void)
Definition pages.c:1199
static void client_aitoggle_player(void *data)
Definition pages.c:1503
static GtkWidget * nation_button
Definition pages.c:1454
static void update_server_list(enum server_scan_type sstype, const struct server_list *list)
Definition pages.c:702
static void start_scenario_callback(GtkWidget *w, gpointer data)
Definition pages.c:113
static GtkTreeSelection * scenario_selection
Definition pages.c:72
static void update_start_page_buttons(void)
Definition pages.c:2193
static void save_dialog_response_callback(GtkWidget *w, gint response, gpointer data)
Definition pages.c:487
GtkWidget * create_scenario_page(void)
Definition pages.c:3179
static void show_conn_popup(struct player *pplayer, struct connection *pconn)
Definition pages.c:1761
static GtkWidget * network_confirm_password_label
Definition pages.c:697
void save_mapimg_dialog_popup(void)
Definition pages.c:3545
static void ruleset_selected(const char *name)
Definition pages.c:1609
static void ready_button_callback(GtkWidget *w, gpointer data)
Definition pages.c:2139
static bool conn_list_selection(struct player **ppplayer, struct connection **ppconn)
Definition pages.c:2052
static struct server_scan_timer_data meta_scan
Definition pages.c:85
static void update_network_lists(void)
Definition pages.c:836
static GtkWidget * statusbar
Definition pages.c:88
static GtkListStore * save_dialog_store_new(void)
Definition pages.c:397
void append_network_statusbar(const char *text, bool force)
Definition pages.c:892
static gboolean update_network_statusbar(gpointer data)
Definition pages.c:862
void set_rulesets(int num_rulesets, char **rulesets)
Definition pages.c:3580
void mapimg_client_save(const char *filename)
Definition pages.c:3564
static void conn_menu_player_command(GObject *object, gpointer data)
Definition pages.c:1720
static void load_filename(const char *filename)
Definition pages.c:2850
static GtkWidget * network_login
Definition pages.c:693
static void conn_menu_nation_chosen(GObject *object, gpointer data)
Definition pages.c:1707
static GtkWidget * scenario_description
Definition pages.c:63
void save_game_dialog_popup(void)
Definition pages.c:3481
enum client_pages get_current_client_page(void)
Definition pages.c:3339
static GtkListStore * lan_store
Definition pages.c:68
static enum connection_state connection_status
Definition pages.c:857
save_dialog_columns
Definition pages.c:381
@ SD_COL_NUM
Definition pages.c:385
@ SD_COL_FULL_PATH
Definition pages.c:383
@ SD_COL_PRETTY_NAME
Definition pages.c:382
static struct server_scan_timer_data lan_scan
Definition pages.c:86
static void save_dialog_list_callback(GtkTreeSelection *selection, gpointer data)
Definition pages.c:555
static void connect_network_game_callback(GtkWidget *w, gpointer data)
Definition pages.c:130
static GtkTreeView * connection_list_view
Definition pages.c:1456
connection_state
Definition pages.c:850
@ LOGIN_TYPE
Definition pages.c:851
@ NEW_PASSWORD_TYPE
Definition pages.c:852
@ WAITING_TYPE
Definition pages.c:854
@ ENTER_PASSWORD_TYPE
Definition pages.c:853
static void connect_callback(GtkWidget *w, gpointer data)
Definition pages.c:1041
static void scenario_browse_callback(GtkWidget *w, gpointer data)
Definition pages.c:3053
static GtkListStore * meta_store
Definition pages.c:68
connection_list_columns
Definition pages.c:1462
@ CL_COL_STYLE
Definition pages.c:1472
@ CL_COL_USER_NAME
Definition pages.c:1464
@ CL_COL_READY_STATE
Definition pages.c:1465
@ CL_COL_WEIGHT
Definition pages.c:1473
@ CL_COL_PLAYER_NAME
Definition pages.c:1466
@ CL_COL_NATION
Definition pages.c:1469
@ CL_COL_CONN_ID
Definition pages.c:1471
@ CL_COL_PLAYER_NUMBER
Definition pages.c:1463
@ CL_NUM_COLUMNS
Definition pages.c:1476
@ CL_COL_TEAM
Definition pages.c:1470
@ CL_COL_COLOR
Definition pages.c:1468
@ CL_COL_COLLAPSED
Definition pages.c:1474
@ CL_COL_FLAG
Definition pages.c:1467
static void update_load_page(void)
Definition pages.c:2885
static void save_dialog_update(struct save_dialog *pdialog)
Definition pages.c:425
static GtkWidget * scenario_authors
Definition pages.c:64
static GtkWidget * start_aifill_spin
Definition pages.c:1457
static void ruleset_entry_changed(GtkWidget *w, gpointer data)
Definition pages.c:1621
void(* save_dialog_action_fn_t)(const char *filename)
Definition pages.c:370
static void open_settings(void)
Definition pages.c:139
static void set_connection_state(enum connection_state state)
Definition pages.c:928
static GtkWidget * ruleset_combo
Definition pages.c:91
static void observe_button_callback(GtkWidget *w, gpointer data)
Definition pages.c:2173
static void conn_menu_ready_chosen(GObject *object, gpointer data)
Definition pages.c:1694
static void server_scan_error(struct server_scan *scan, const char *message)
Definition pages.c:823
static void load_callback(void)
Definition pages.c:2858
static void save_dialog_file_chooser_callback(GtkWidget *widget, gint response, gpointer data)
Definition pages.c:442
static void network_list_callback(GtkTreeSelection *select, gpointer data)
Definition pages.c:1137
static GtkListStore * server_playerlist_store
Definition pages.c:70
static void nation_button_callback(GtkWidget *w, gpointer data)
Definition pages.c:2153
void real_set_client_page(enum client_pages new_page)
Definition pages.c:3347
static void conn_menu_connection_command(GObject *object, gpointer data)
Definition pages.c:1747
static void scenario_list_callback(void)
Definition pages.c:2981
static gboolean intro_expose(GtkWidget *w, cairo_t *cr, gpointer *data)
Definition pages.c:162
static void load_browse_callback(GtkWidget *w, gpointer data)
Definition pages.c:2875
static void network_activate_callback(GtkTreeView *view, GtkTreePath *arg1, GtkTreeViewColumn *arg2, gpointer data)
Definition pages.c:1096
static struct fileinfo_list * save_dialog_scenario_list(void)
Definition pages.c:3508
static void connection_state_reset(void)
Definition pages.c:996
void real_conn_list_dialog_update(void *unused)
Definition pages.c:2338
static bool holding_srv_list_mutex
Definition pages.c:93
static GtkTreeStore * connection_list_store
Definition pages.c:1455
static struct fileinfo_list * save_dialog_savegame_list(void)
Definition pages.c:3473
static void start_new_game_callback(GtkWidget *w, gpointer data)
Definition pages.c:100
void destroy_server_scans(void)
Definition pages.c:766
void save_scenario_dialog_popup(void)
Definition pages.c:3516
static GtkTreeSelection * lan_selection
Definition pages.c:73
static void save_dialog_save_scenario(const char *filename)
Definition pages.c:3500
struct fileinfo_list *(* save_dialog_files_fn_t)(void)
Definition pages.c:371
static gboolean check_server_scan(gpointer data)
Definition pages.c:789
static void save_dialog_store_update(GtkListStore *store, const struct fileinfo_list *files)
Definition pages.c:407
static void ai_fill_changed_by_user(GtkWidget *w, gpointer data)
Definition pages.c:1636
static gboolean delayed_unselect_path(gpointer data)
Definition pages.c:1967
static void conn_menu_player_take(GObject *object, gpointer data)
Definition pages.c:1734
static void conn_menu_info_chosen(GObject *object, gpointer data)
Definition pages.c:1792
static bool model_get_player_iter(GtkTreeModel *model, GtkTreeIter *iter, GtkTreeIter *start, const struct player *pplayer)
Definition pages.c:2278
static GtkTreeSelection * load_selection
Definition pages.c:72
static void ai_skill_callback(GtkWidget *w, gpointer data)
Definition pages.c:1583
static enum client_pages current_page
Definition pages.c:77
static GtkWidget * statusbar_frame
Definition pages.c:88
static GtkWidget * network_confirm_password
Definition pages.c:697
static void client_take_player(struct player *pplayer)
Definition pages.c:1517
static void clear_network_statusbar(void)
Definition pages.c:878
static GtkTreeSelection * meta_selection
Definition pages.c:73
static void save_dialog_row_callback(GtkTreeView *tree_view, GtkTreePath *path, GtkTreeViewColumn *column, gpointer data)
Definition pages.c:536
static void connection_list_row_callback(GtkTreeView *tree_view, GtkTreeIter *iter, GtkTreePath *path, gpointer data)
Definition pages.c:2037
save_dialog_response
Definition pages.c:388
@ SD_RES_DELETE
Definition pages.c:390
@ SD_RES_SAVE
Definition pages.c:391
@ SD_RES_BROWSE
Definition pages.c:389
GtkWidget * create_load_page(void)
Definition pages.c:2898
static GtkWidget * ai_lvl_combobox
Definition pages.c:1458
static GtkWidget * network_password_label
Definition pages.c:696
static GtkWidget * save_dialog_new(const char *title, const char *savelabel, const char *savefilelabel, save_dialog_action_fn_t action, save_dialog_files_fn_t files)
Definition pages.c:576
static GtkWidget * network_host
Definition pages.c:694
static void intro_free(GtkWidget *w, gpointer *data)
Definition pages.c:219
static GtkWidget * network_password
Definition pages.c:696
void handle_authentication_req(enum authentication_type type, const char *message)
Definition pages.c:1005
static GtkTreeStore * connection_list_store_new(void)
Definition pages.c:1482
static bool send_new_aifill_to_server
Definition pages.c:1635
static void save_dialog_file_chooser_popup(const char *title, GtkFileChooserAction action, save_dialog_action_fn_t cb)
Definition pages.c:462
static void add_tree_col(GtkWidget *treeview, GType gtype, const char *title, int colnum, const char *key)
Definition pages.c:2583
static void save_dialog_entry_callback(GtkEntry *entry, gpointer data)
Definition pages.c:547
static void main_callback(GtkWidget *w, gpointer data)
Definition pages.c:147
void update_start_page(void)
Definition pages.c:1669
static void scenario_callback(void)
Definition pages.c:3037
static GtkWidget * start_options_table
Definition pages.c:1453
static bool no_ruleset_callback
Definition pages.c:1604
void ai_fill_changed_by_server(int aifill)
Definition pages.c:1647
static void update_server_playerlist(const struct server *pserver)
Definition pages.c:1108
static GtkWidget * observe_button
Definition pages.c:1454
static GtkWidget * scenario_version
Definition pages.c:66
GtkWidget * create_statusbar(void)
Definition pages.c:907
static void game_options_callback(GtkWidget *w, gpointer data)
Definition pages.c:1575
static GtkListStore * scenario_store
Definition pages.c:68
static bool model_get_conn_iter(GtkTreeModel *model, GtkTreeIter *iter, GtkTreeIter *parent, GtkTreeIter *start, const struct connection *pconn)
Definition pages.c:2309
static GQueue * statusbar_queue
Definition pages.c:89
GtkWidget * start_message_area
Definition pages.c:1451
static void update_scenario_page(void)
Definition pages.c:3063
static GtkWidget * scenario_filename
Definition pages.c:65
static void conn_menu_team_chosen(GObject *object, gpointer data)
Definition pages.c:1677
static GtkWidget * create_conn_menu(struct player *pplayer, struct connection *pconn)
Definition pages.c:1806
static void load_saved_game_callback(GtkWidget *w, gpointer data)
Definition pages.c:122
static bool object_extract(GObject *object, struct player **ppplayer, struct connection **ppconn)
Definition pages.c:1548
static void object_put(GObject *object, struct player *pplayer, struct connection *pconn)
Definition pages.c:1529
static GtkWidget * network_port
Definition pages.c:695
static struct fileinfo_list * save_dialog_mapimg_list(void)
Definition pages.c:3537
GtkWidget * create_main_page(void)
Definition pages.c:229
static void conn_list_select_conn(struct connection *pconn)
Definition pages.c:2088
static GtkWidget * ready_button
Definition pages.c:1454
GdkPixbuf * create_player_icon(const struct player *plr)
Definition plrdlg.c:117
GdkPixbuf * get_flag(const struct nation_type *nation)
Definition plrdlg.c:607
const char * title
Definition repodlgs.c:1314
GType type
Definition repodlgs.c:1313
void free_sprite(struct sprite *s)
Definition sprite.c:278
struct sprite * sprite_scale(struct sprite *src, int new_w, int new_h)
Definition sprite.c:291
struct sprite * load_gfxfile(const char *filename, bool svgflag)
Definition sprite.c:170
void voteinfo_gui_update(void)
GtkWidget * voteinfo_bar_new(bool split_bar)
GtkWidget * pregame_votebar
gboolean terminate_signal_processing(GtkEventControllerFocus *controller, gpointer data)
Definition gui_main.c:1015
void main_message_area_resize(void *data)
Definition gui_main.c:362
void widget_destroyed(GtkWidget *wdg, void *data)
Definition gui_stuff.c:1158
#define menu_item_append_unref(menu, item)
Definition gui_stuff.h:149
static gboolean connect_list_right_button(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data)
Definition pages.c:2094
static void close_conn_menu_popover(void)
Definition pages.c:1705
static gboolean connect_list_left_button(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data)
Definition pages.c:2065
static GtkWidget * conn_popover
Definition pages.c:95
static void scenario_factory_bind(GtkSignalListItemFactory *self, GtkListItem *list_item, gpointer user_data)
Definition pages.c:3676
static void fc_save_row_init(FcSaveRow *self)
Definition pages.c:309
static void save_factory_setup(GtkSignalListItemFactory *self, GtkListItem *list_item, gpointer user_data)
Definition pages.c:831
static void fc_save_row_class_init(FcSaveRowClass *klass)
Definition pages.c:301
static void plr_factory_bind(GtkSignalListItemFactory *self, GtkListItem *list_item, gpointer user_data)
Definition pages.c:1525
static void fc_scen_row_class_init(FcScenRowClass *klass)
Definition pages.c:271
static void host_factory_setup(GtkSignalListItemFactory *self, GtkListItem *list_item, gpointer user_data)
Definition pages.c:1515
#define FC_TYPE_SAVE_ROW
Definition pages.c:188
#define FC_TYPE_SCEN_ROW
Definition pages.c:165
void(* save_dialog_action_fn_t)(const char *filename)
Definition pages.c:605
static void plr_factory_setup(GtkSignalListItemFactory *self, GtkListItem *list_item, gpointer user_data)
Definition pages.c:1553
host_rows
Definition pages.c:125
@ host_row_host
Definition pages.c:126
@ host_row_nplayers
Definition pages.c:130
@ host_row_humans
Definition pages.c:131
@ host_row_port
Definition pages.c:127
@ host_row_version
Definition pages.c:128
@ host_row_state
Definition pages.c:129
@ host_row_message
Definition pages.c:132
static void fc_scen_row_init(FcScenRow *self)
Definition pages.c:279
struct fileinfo_list *(* save_dialog_files_fn_t)(void)
Definition pages.c:606
static void save_factory_bind(GtkSignalListItemFactory *self, GtkListItem *list_item, gpointer user_data)
Definition pages.c:816
static void scenario_factory_setup(GtkSignalListItemFactory *self, GtkListItem *list_item, gpointer user_data)
Definition pages.c:3691
plr_rows
Definition pages.c:157
@ plr_row_name
Definition pages.c:158
@ plr_row_nation
Definition pages.c:161
@ plr_row_type
Definition pages.c:159
@ plr_row_host
Definition pages.c:160
static void fc_host_row_class_init(FcHostRowClass *klass)
Definition pages.c:211
static void fc_plr_row_class_init(FcPlrRowClass *klass)
Definition pages.c:241
#define FC_TYPE_HOST_ROW
Definition pages.c:101
static void host_factory_bind(GtkSignalListItemFactory *self, GtkListItem *list_item, gpointer user_data)
Definition pages.c:1475
#define FC_TYPE_PLR_ROW
Definition pages.c:136
static void fc_host_row_init(FcHostRow *self)
Definition pages.c:219
static void fc_plr_row_init(FcPlrRow *self)
Definition pages.c:249
static struct server_list * server_list
Definition connectdlg.c:61
static enum client_pages old_page
Definition pages.c:46
void conn_list_dialog_update(void)
const char * name
Definition inputfile.c:127
#define fc_assert_ret(condition)
Definition log.h:192
#define fc_assert_ret_val(condition, val)
Definition log.h:195
#define log_debug(message,...)
Definition log.h:116
#define log_error(message,...)
Definition log.h:104
int send_packet_authentication_reply(struct connection *pc, const struct packet_authentication_reply *packet)
int dsend_packet_save_scenario(struct connection *pc, const char *name)
int dsend_packet_player_ready(struct connection *pc, int player_no, bool is_ready)
const char * mapimg_error(void)
Definition mapimg.c:759
#define fc_strdup(str)
Definition mem.h:43
#define fc_malloc(sz)
Definition mem.h:34
const char * nation_adjective_for_player(const struct player *pplayer)
Definition nation.c:169
bool can_conn_edit_players_nation(const struct connection *pconn, const struct player *pplayer)
Definition nation.c:1174
#define NO_NATION_SELECTED
Definition nation.h:30
const struct option_set * server_optset
Definition options.c:4369
const struct option_set * client_optset
Definition options.c:1331
int option_int_get(const struct option *poption)
Definition options.c:885
struct option * optset_option_by_name(const struct option_set *poptset, const char *name)
Definition options.c:482
bool option_int_set(struct option *poption, int val)
Definition options.c:929
bool is_settable_ai_level(enum ai_level level)
Definition player.c:1908
struct player * player_by_number(const int player_id)
Definition player.c:837
int player_slot_count(void)
Definition player.c:415
int player_number(const struct player *pplayer)
Definition player.c:826
const char * player_name(const struct player *pplayer)
Definition player.c:885
bool player_has_flag(const struct player *pplayer, enum plr_flag_id flag)
Definition player.c:1979
#define ai_level_cmd(_level_)
Definition player.h:582
#define players_iterate_end
Definition player.h:552
#define players_iterate(_pplayer)
Definition player.h:547
#define is_ai(plr)
Definition player.h:232
#define players_iterate_alive_end
Definition player.h:562
#define is_human(plr)
Definition player.h:231
#define players_iterate_alive(_pplayer)
Definition player.h:557
void secfile_destroy(struct section_file *secfile)
struct section_file * secfile_load_section(const char *filename, const char *section, bool allow_duplicates)
bool secfile_lookup_bool_default(const struct section_file *secfile, bool def, const char *path,...)
int secfile_lookup_int_default(const struct section_file *secfile, int def, const char *path,...)
const char * secfile_lookup_str_default(const struct section_file *secfile, const char *def, const char *path,...)
struct srv_list * server_scan_get_list(struct server_scan *scan)
Definition servers.c:865
void server_scan_finish(struct server_scan *scan)
Definition servers.c:878
struct server_scan * server_scan_begin(enum server_scan_type type, ServerScanErrorFunc error_func)
Definition servers.c:754
enum server_scan_type server_scan_get_type(const struct server_scan *scan)
Definition servers.c:808
enum server_scan_status server_scan_poll(struct server_scan *scan)
Definition servers.c:831
#define server_list_iterate_end
Definition servers.h:57
server_scan_status
Definition servers.h:79
@ SCAN_STATUS_PARTIAL
Definition servers.h:82
@ SCAN_STATUS_ERROR
Definition servers.h:80
@ SCAN_STATUS_DONE
Definition servers.h:83
#define server_list_iterate(serverlist, pserver)
Definition servers.h:55
server_scan_type
Definition servers.h:67
@ SERVER_SCAN_LOCAL
Definition servers.h:68
@ SERVER_SCAN_GLOBAL
Definition servers.h:69
struct setting_list * level[OLEVELS_NUM]
Definition settings.c:190
const struct strvec * get_scenario_dirs(void)
Definition shared.c:971
const struct strvec * get_save_dirs(void)
Definition shared.c:934
char * skip_to_basename(char *filepath)
Definition shared.c:1753
struct fileinfo_list * fileinfolist_infix(const struct strvec *dirs, const char *infix, bool nodups)
Definition shared.c:1204
#define fileinfo_list_iterate(list, pnode)
Definition shared.h:182
#define FC_PTR_TO_INT(p)
Definition shared.h:95
#define fileinfo_list_iterate_end
Definition shared.h:184
#define FC_INT_TO_PTR(i)
Definition shared.h:94
size_t size
Definition specvec.h:72
struct sprite int int y
Definition sprite_g.h:31
struct sprite int int int int struct sprite int int float scale
Definition sprite_g.h:33
struct sprite int x
Definition sprite_g.h:31
struct sprite int int int int struct sprite int int float bool smooth get_sprite_dimensions
Definition sprite_g.h:36
const char * aifill(int amount)
Definition srv_main.c:2556
GObjectClass parent_class
Definition pages.c:120
char * version
Definition pages.c:111
char * humans
Definition pages.c:114
GObject parent_instance
Definition pages.c:107
int port
Definition pages.c:110
int nplayers
Definition pages.c:113
char * message
Definition pages.c:115
char * state
Definition pages.c:112
char * host
Definition pages.c:109
GObjectClass parent_class
Definition pages.c:152
char * host
Definition pages.c:146
char * name
Definition pages.c:144
char * type
Definition pages.c:145
GObject parent_instance
Definition pages.c:142
char * nation
Definition pages.c:147
GObjectClass parent_class
Definition pages.c:202
char * pretty_name
Definition pages.c:196
GObject parent_instance
Definition pages.c:194
char * full_path
Definition pages.c:197
GObjectClass parent_class
Definition pages.c:182
char * name
Definition pages.c:173
char * filename
Definition pages.c:176
char * desc
Definition pages.c:174
int ver
Definition pages.c:177
GObject parent_instance
Definition pages.c:171
char * authors
Definition pages.c:175
struct conn_list * est_connections
Definition game.h:97
struct packet_game_info info
Definition game.h:89
struct connection conn
Definition client_main.h:96
Definition colors.h:21
struct player * playing
Definition connection.h:151
enum cmdlevel access_level
Definition connection.h:177
struct team * team
Definition player.h:261
bool is_ready
Definition player.h:262
save_dialog_action_fn_t action
Definition pages.c:377
GtkEntry * entry
Definition pages.c:376
GtkTreeView * tree_view
Definition pages.c:375
GtkDialog * shell
Definition pages.c:374
save_dialog_files_fn_t files
Definition pages.c:378
struct server_scan * scan
Definition pages.c:81
fc_mutex mutex
Definition servers.h:64
struct server_list * servers
Definition servers.h:63
Definition team.c:40
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:925
int cat_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:951
int fc_remove(const char *filename)
Definition support.c:520
#define sz_strlcpy(dest, src)
Definition support.h:195
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
#define sz_strlcat(dest, src)
Definition support.h:196
#define fc_strncmp(_s1_, _s2_, _len_)
Definition support.h:160
const char * team_name_translation(const struct team *pteam)
Definition team.c:409
struct team * team_slot_get_team(const struct team_slot *tslot)
Definition team.c:149
const char * team_slot_name_translation(const struct team_slot *tslot)
Definition team.c:248
int team_number(const struct team *pteam)
Definition team.c:383
int team_slot_index(const struct team_slot *tslot)
Definition team.c:138
const struct player_list * team_members(const struct team *pteam)
Definition team.c:443
bool team_slot_is_used(const struct team_slot *tslot)
Definition team.c:160
const char * team_slot_rule_name(const struct team_slot *tslot)
Definition team.c:229
#define team_slots_iterate_end
Definition team.h:89
#define team_slots_iterate(_tslot)
Definition team.h:84
const char * tileset_main_intro_filename(const struct tileset *t)
Definition tilespec.c:973
void client_start_server_and_set_page(enum client_pages page)
void set_client_page(enum client_pages page)
void update_queue_connect_processing_finished(int request_id, uq_callback_t callback, void *data)
enum client_pages get_client_page(void)
const char * fc_git_revision(void)
Definition version.c:75
const char * unstable_message(void)
Definition version.c:160
const char * word_version(void)
Definition version.c:62
#define MINOR_VERSION
Definition version_gen.h:7
#define VERSION_STRING
Definition version_gen.h:14
#define MAJOR_VERSION
Definition version_gen.h:6
#define PATCH_VERSION
Definition version_gen.h:8