Freeciv-3.3
Loading...
Searching...
No Matches
pages.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18#include <stdio.h>
19#include <time.h>
20
21#include <sys/stat.h>
22
23#include <gtk/gtk.h>
24
25/* utility */
26#include "fcintl.h"
27#include "log.h"
28#include "mem.h"
29#include "shared.h"
30#include "support.h"
31
32/* common */
33#include "dataio.h"
34#include "game.h"
35#include "mapimg.h"
36#include "version.h"
37
38/* client */
39#include "client_main.h"
40#include "climisc.h"
41#include "clinet.h"
42#include "connectdlg_common.h"
43#include "packhand.h"
44#include "servers.h"
45#include "update_queue.h"
46
47/* client/gui-gtk-3.22 */
48#include "chatline.h"
49#include "connectdlg.h"
50#include "dialogs.h"
51#include "graphics.h"
52#include "gui_main.h"
53#include "gui_stuff.h"
54#include "mapview.h"
55#include "optiondlg.h"
56#include "plrdlg.h" /* get_flag() */
57#include "repodlgs.h"
58#include "voteinfo_bar.h"
59
60#include "pages.h"
61
62
67
69
71
74
75/* This is the current page. Invalid value at start, to be sure that it won't
76 * be caught through a switch() statement. */
77static enum client_pages current_page = -1;
78
84
85static struct server_scan_timer_data meta_scan = { NULL, 0 };
86static struct server_scan_timer_data lan_scan = { NULL, 0 };
87
90
92
94
95static void connection_state_reset(void);
96
97/**********************************************************************/
101{
102 if (!is_server_running()) {
104
105 /* Saved settings are sent in client/options.c
106 * resend_desired_settable_options() */
107 }
108}
109
110/**********************************************************************/
114{
115 output_window_append(ftc_client, _("Compiling scenario list."));
117}
118
119/**********************************************************************/
126
127/**********************************************************************/
135
136/**********************************************************************/
139static void open_settings(void)
140{
141 option_dialog_popup(_("Set local options"), client_optset);
142}
143
144/**********************************************************************/
147static void main_callback(GtkWidget *w, gpointer data)
148{
149 enum client_pages page = PAGE_MAIN;
150
151 if (client.conn.used) {
153 }
154 if (page != get_client_page()) {
155 set_client_page(page);
156 }
157}
158
159/**********************************************************************/
163{
164 static PangoLayout *layout;
166 static int width, height;
167 static bool left = FALSE;
169 struct sprite *intro = (struct sprite *)data;
170
171 cairo_set_source_surface(cr, intro->surface, 0, 0);
172 cairo_paint(cr);
173
174 if (!layout) {
175 char msgbuf[128];
176 const char *rev_ver;
177
179 desc = pango_font_description_from_string("Sans Bold 10");
182
184
185 if (rev_ver == NULL) {
186 /* TRANS: "version 2.6.0, gui-gtk-3.22 client" */
187 fc_snprintf(msgbuf, sizeof(msgbuf), _("%s%s, %s client"),
189 } else {
190 /* TRANS: "version 2.6.0
191 * commit: [modified] <git commit id>
192 * gui-gtk-3.22 client" */
193 fc_snprintf(msgbuf, sizeof(msgbuf), _("%s%s\ncommit: %s\n%s client"),
195 left = TRUE;
196 }
198
200 }
202
203 cairo_set_source_rgb(cr, 0, 0, 0);
204 cairo_move_to(cr, left ? 4 : allocation.width - width - 3,
205 allocation.height - height - 3);
207
208 cairo_set_source_rgb(cr, 1, 1, 1);
209 cairo_move_to(cr, left ? 3 : allocation.width - width - 4,
210 allocation.height - height - 4);
212
213 return TRUE;
214}
215
216/**********************************************************************/
219static void intro_free(GtkWidget *w, gpointer *data)
220{
221 struct sprite *intro = (struct sprite *)data;
222
224}
225
226/**********************************************************************/
230{
231 GtkWidget *widget, *vbox, *frame, *darea, *button, *table;
233 struct sprite *intro_in, *intro;
234 int width, height;
235 int sh;
236 int space_needed;
237
239
240 vbox = gtk_grid_new();
243 widget = vbox;
244
245 frame = gtk_frame_new(NULL);
246 g_object_set(frame, "margin", 18, NULL);
249 gtk_container_add(GTK_CONTAINER(vbox), frame);
250
253 sh = screen_height();
254
255 if (sh <= 0) {
256 /* Assume some minimum height */
257 sh = 600;
258 }
259
260 space_needed = 250;
261#if IS_BETA_VERSION || IS_DEVEL_VERSION
262 /* Alpha or Beta notice takes extra space */
263 space_needed += 50;
264#endif
265
266 if (sh - height < space_needed) {
267 float scale;
268
269 if (sh < (space_needed + 0.2 * height)) {
270 /* Screen is simply too small, use minimum scale */
271 scale = 0.2;
272 } else {
273 scale = (double)(sh - space_needed) / height;
274 }
275 height *= scale;
276 width *= scale;
279 } else {
280 intro = intro_in;
281 }
282 darea = gtk_drawing_area_new();
284 g_signal_connect(darea, "draw",
286 g_signal_connect(widget, "destroy",
288 gtk_container_add(GTK_CONTAINER(frame), darea);
289
290#if IS_BETA_VERSION || IS_DEVEL_VERSION
291 {
292 GtkWidget *label;
293
295 gtk_widget_set_name(label, "beta_label");
299 gtk_container_add(GTK_CONTAINER(vbox), label);
300 }
301#endif /* IS_BETA_VERSION || IS_DEVEL_VERSION */
302
304 g_object_set(table, "margin", 12, NULL);
309
313
314 button = gtk_button_new_with_mnemonic(_("Start _New Game"));
316 gtk_grid_attach(GTK_GRID(table), button, 0, 0, 1, 1);
318 _("Launches local server, and connects to it for a single-player game."));
319 g_signal_connect(button, "clicked",
321
322 button = gtk_button_new_with_mnemonic(_("Start _Scenario Game"));
324 gtk_grid_attach(GTK_GRID(table), button, 0, 1, 1, 1);
326 _("Loads one of the scenarios for a single-player game. "
327 "Tutorial is one of the scenarios."));
328 g_signal_connect(button, "clicked",
330
331 button = gtk_button_new_with_mnemonic(_("_Load Saved Game"));
333 gtk_grid_attach(GTK_GRID(table), button, 0, 2, 1, 1);
335 _("Continues previously saved single-player game."));
336 g_signal_connect(button, "clicked",
338
339 button = gtk_button_new_with_mnemonic(_("C_onnect to Network Game"));
341 gtk_grid_attach(GTK_GRID(table), button, 1, 0, 1, 1);
343 _("Connects to outside server. "
344 "Sometimes you want to launch a separate server even for local games."));
345 g_signal_connect(button, "clicked",
347
348 button = gtk_button_new_with_mnemonic(_("Client Settings"));
350 gtk_grid_attach(GTK_GRID(table), button, 1, 1, 1, 1);
352 _("Adjusting client-side options."));
353 g_signal_connect(button, "clicked", open_settings, NULL);
354
355 button = icon_label_button_new("application-exit", _("E_xit"));
358 gtk_grid_attach(GTK_GRID(table), button, 1, 2, 1, 1);
360 _("Gives you a break from playing freeciv."));
361 g_signal_connect(button, "clicked",
363
364 return widget;
365}
366
367/****************************************************************************
368 GENERIC SAVE DIALOG
369****************************************************************************/
370typedef void (*save_dialog_action_fn_t) (const char *filename);
371typedef struct fileinfo_list * (*save_dialog_files_fn_t) (void);
372
380
387
393
394/**********************************************************************/
398{
400 G_TYPE_STRING, /* SD_COL_PRETTY_NAME */
401 G_TYPE_STRING); /* SD_COL_FULL_PATH */
402}
403
404/**********************************************************************/
408 const struct fileinfo_list *files)
409{
411
415 gtk_list_store_set(store, &iter,
417 SD_COL_FULL_PATH, pfile->fullname,
418 -1);
420}
421
422/**********************************************************************/
425static void save_dialog_update(struct save_dialog *pdialog)
426{
427 struct fileinfo_list *files;
428
429 fc_assert_ret(NULL != pdialog);
430
431 /* Update the store. */
432 files = pdialog->files();
435 files);
437}
438
439/**********************************************************************/
443 gint response, gpointer data)
444{
445 if (response == GTK_RESPONSE_OK) {
449 -1, NULL, NULL, NULL);
450
451 if (NULL != filename) {
452 action(filename);
453 g_free(filename);
454 }
455 }
457}
458
459/**********************************************************************/
483
484/**********************************************************************/
488 gpointer data)
489{
490 struct save_dialog *pdialog = data;
491
492 switch (response) {
493 case SD_RES_BROWSE:
494 save_dialog_file_chooser_popup(_("Select Location to Save"),
496 pdialog->action);
497 break;
498 case SD_RES_DELETE:
499 {
500 GtkTreeSelection *selection;
501 GtkTreeModel *model;
503 const gchar *full_path;
504
505 selection = gtk_tree_view_get_selection(pdialog->tree_view);
506 if (!gtk_tree_selection_get_selected(selection, &model, &iter)) {
507 return;
508 }
509
512 save_dialog_update(pdialog);
513 }
514 return;
515 case SD_RES_SAVE:
516 {
517 const char *text = gtk_entry_get_text(pdialog->entry);
518 gchar *filename = g_filename_from_utf8(text, -1, NULL, NULL, NULL);
519
520 if (NULL == filename) {
521 return;
522 }
523 pdialog->action(filename);
524 g_free(filename);
525 }
526 break;
527 default:
528 break;
529 }
531}
532
533/**********************************************************************/
543
544/**********************************************************************/
551
552/**********************************************************************/
556 gpointer data)
557{
558 struct save_dialog *pdialog = data;
559 GtkTreeModel *model;
561 const gchar *filename;
562
563 if (!gtk_tree_selection_get_selected(selection, &model, &iter)) {
565 return;
566 }
567
569 gtk_tree_model_get(model, &iter, SD_COL_PRETTY_NAME, &filename, -1);
570 gtk_entry_set_text(pdialog->entry, filename);
571}
572
573/**********************************************************************/
576static GtkWidget *save_dialog_new(const char *title, const char *savelabel,
577 const char *savefilelabel,
580{
581 GtkWidget *shell, *sbox, *sw, *label, *view, *entry;
582 GtkContainer *vbox;
583 GtkListStore *store;
585 GtkTreeSelection *selection;
586 struct save_dialog *pdialog;
587
590
591 /* Save dialog structure. */
592 pdialog = fc_malloc(sizeof(*pdialog));
593 pdialog->action = action;
594 pdialog->files = files;
595
596 /* Shell. */
598 _("_Browse..."), SD_RES_BROWSE,
599 _("_Delete"), SD_RES_DELETE,
600 _("_Cancel"), GTK_RESPONSE_CANCEL,
601 _("_Save"), SD_RES_SAVE,
602 NULL);
603 g_object_set_data_full(G_OBJECT(shell), "save_dialog", pdialog,
608 g_signal_connect(shell, "response",
610 pdialog->shell = GTK_DIALOG(shell);
612
613 /* Tree view. */
614 store = save_dialog_store_new();
618 g_object_unref(store);
620 g_signal_connect(view, "row-activated",
622 pdialog->tree_view = GTK_TREE_VIEW(view);
623
624 sbox = gtk_grid_new();
628 gtk_container_add(vbox, sbox);
629
631 "use-underline", TRUE,
632 "mnemonic-widget", view,
633 "label", savelabel,
634 "xalign", 0.0,
635 "yalign", 0.5,
636 NULL);
638
648
651 g_signal_connect(selection, "changed",
653
656 -1, NULL, rend, "text",
658
659 /* Entry. */
662 g_signal_connect(entry, "activate",
664 pdialog->entry = GTK_ENTRY(entry);
665
666 sbox = gtk_grid_new();
667 g_object_set(sbox, "margin", 12, NULL);
671
673 "use-underline", TRUE,
674 "mnemonic-widget", entry,
675 "label", savefilelabel,
676 "xalign", 0.0,
677 "yalign", 0.5,
678 NULL);
680
682 gtk_container_add(vbox, sbox);
683
684 save_dialog_update(pdialog);
687 return shell;
688}
689
690/****************************************************************************
691 NETWORK PAGE
692****************************************************************************/
698
699/**********************************************************************/
703 const struct server_list *list)
704{
707 GtkTreeIter it;
708 GtkListStore *store;
709 const gchar *host, *portstr;
710 int port;
711
712 switch (sstype) {
715 break;
718 break;
719 default:
720 break;
721 }
722
723 if (!sel) {
724 return;
725 }
726
730
731 if (!list) {
732 return;
733 }
734
737 port = atoi(portstr);
738
740 char buf[35];
741
742 if (pserver->humans >= 0) {
743 fc_snprintf(buf, sizeof(buf), "%d", pserver->humans);
744 } else {
745 sz_strlcpy(buf, _("Unknown"));
746 }
747 gtk_list_store_append(store, &it);
748 gtk_list_store_set(store, &it,
749 0, pserver->host,
750 1, pserver->port,
751 2, pserver->version,
752 3, _(pserver->state),
753 4, pserver->nplayers,
754 5, buf,
755 6, pserver->message,
756 -1);
757 if (strcmp(host, pserver->host) == 0 && port == pserver->port) {
759 }
761}
762
763/**********************************************************************/
767{
768 if (meta_scan.scan) {
771 }
772 if (meta_scan.timer != 0) {
774 meta_scan.timer = 0;
775 }
776 if (lan_scan.scan) {
779 }
780 if (lan_scan.timer != 0) {
782 lan_scan.timer = 0;
783 }
784}
785
786/**********************************************************************/
790{
791 struct server_scan_timer_data *scan_data = data;
792 struct server_scan *scan = scan_data->scan;
794
795 if (!scan) {
796 return FALSE;
797 }
798
799 stat = server_scan_poll(scan);
800 if (stat >= SCAN_STATUS_PARTIAL) {
802 struct srv_list *srvrs;
803
805 srvrs = server_scan_get_list(scan);
806 fc_mutex_allocate(&srvrs->mutex);
810 fc_mutex_release(&srvrs->mutex);
811 }
812
814 scan_data->timer = 0;
815 return FALSE;
816 }
817 return TRUE;
818}
819
820/**********************************************************************/
823static void server_scan_error(struct server_scan *scan,
824 const char *message)
825{
827 log_error("%s", message);
828
829 /* Main thread will finalize the scan later (or even concurrently) -
830 * do not do anything here to cause double free or raze condition. */
831}
832
833/**********************************************************************/
846
847/**************************************************************************
848 Network connection state defines.
849**************************************************************************/
856
858
859/**********************************************************************/
863{
865 char *txt;
866
869 free(txt);
870 }
871
872 return TRUE;
873}
874
875/**********************************************************************/
878static void clear_network_statusbar(void)
879{
881 char *txt;
882
884 free(txt);
885 }
887}
888
889/**********************************************************************/
892void append_network_statusbar(const char *text, bool force)
893{
895 if (force) {
898 } else {
900 }
901 }
902}
903
904/**********************************************************************/
924
925/**********************************************************************/
929{
930 switch (state) {
931 case LOGIN_TYPE:
933
936
945 break;
950
959
961 break;
966
975
977 break;
978 case WAITING_TYPE:
980
987 break;
988 }
989
990 connection_status = state;
991}
992
993/**********************************************************************/
1000
1001/**********************************************************************/
1006 const char *message)
1007{
1009
1010 switch (type) {
1011 case AUTH_NEWUSER_FIRST:
1012 case AUTH_NEWUSER_RETRY:
1014 return;
1015 case AUTH_LOGIN_FIRST:
1016 /* if we magically have a password already present in 'fc_password'
1017 * then, use that and skip the password entry dialog */
1018 if (fc_password[0] != '\0') {
1020
1021 sz_strlcpy(reply.password, fc_password);
1023 return;
1024 } else {
1026 }
1027 return;
1028 case AUTH_LOGIN_RETRY:
1030 return;
1031 }
1032
1033 log_error("Unsupported authentication type %d: %s.", type, message);
1034}
1035
1036/**********************************************************************/
1042{
1043 char errbuf [512];
1045
1046 switch (connection_status) {
1047 case LOGIN_TYPE:
1051
1053 errbuf, sizeof(errbuf)) != -1) {
1054 } else {
1056
1058 }
1059 return;
1060 case NEW_PASSWORD_TYPE:
1061 if (w != network_password) {
1064 sz_strlcpy(reply.password,
1066 if (!fc_strncmp(reply.password, fc_password, MAX_LEN_NAME)) {
1067 fc_password[0] = '\0';
1069
1071 } else {
1072 append_network_statusbar(_("Passwords don't match, enter password."),
1073 TRUE);
1074
1076 }
1077 }
1078 return;
1080 sz_strlcpy(reply.password,
1083
1085 return;
1086 case WAITING_TYPE:
1087 return;
1088 }
1089
1090 log_error("Unsupported connection status: %d", connection_status);
1091}
1092
1093/**********************************************************************/
1099 gpointer data)
1100{
1101 connect_callback(NULL, data);
1102}
1103
1104/**********************************************************************/
1108static void update_server_playerlist(const struct server *pserver)
1109{
1110 GtkListStore *store;
1112 int n, i;
1113
1115 fc_assert_ret(store != NULL);
1116
1117 gtk_list_store_clear(store);
1118 if (!pserver || !pserver->players) {
1119 return;
1120 }
1121
1122 n = pserver->nplayers;
1123 for (i = 0; i < n; i++) {
1124 gtk_list_store_append(store, &iter);
1125 gtk_list_store_set(store, &iter,
1126 0, pserver->players[i].name,
1127 1, pserver->players[i].type,
1128 2, pserver->players[i].host,
1129 3, pserver->players[i].nation,
1130 -1);
1131 }
1132}
1133
1134/**********************************************************************/
1138{
1139 GtkTreeModel *model;
1140 GtkTreeIter it;
1141 const char *host;
1142 int port;
1143 char portstr[32];
1144 const struct server *pserver = NULL;
1145
1146 if (!gtk_tree_selection_get_selected(select, &model, &it)) {
1147 return;
1148 }
1149
1150 if (select == meta_selection) {
1151 GtkTreePath *path;
1152 struct srv_list *srvrs;
1153
1155 path = gtk_tree_model_get_path(model, &it);
1157 /* We are not yet inside mutex protected block */
1158 fc_mutex_allocate(&srvrs->mutex);
1159 }
1160 if (srvrs->servers && path) {
1162
1164 }
1166 /* We are not yet inside mutex protected block */
1167 fc_mutex_release(&srvrs->mutex);
1168 }
1169 gtk_tree_path_free(path);
1170 }
1172
1173 gtk_tree_model_get(model, &it, 0, &host, 1, &port, -1);
1174
1176 fc_snprintf(portstr, sizeof(portstr), "%d", port);
1178}
1179
1180/**********************************************************************/
1195
1196/**********************************************************************/
1200{
1201 GtkWidget *box, *sbox, *bbox, *hbox, *notebook;
1202 GtkWidget *button, *label, *view, *sw, *table;
1203 GtkTreeSelection *selection;
1204 GtkListStore *store;
1205
1206 box = gtk_grid_new();
1210
1211 notebook = gtk_notebook_new();
1212 gtk_container_add(GTK_CONTAINER(box), notebook);
1213
1214 /* LAN pane. */
1216 G_TYPE_INT, /* port */
1217 G_TYPE_STRING, /* version */
1218 G_TYPE_STRING, /* state */
1219 G_TYPE_INT, /* nplayers */
1220 G_TYPE_STRING, /* humans */
1221 G_TYPE_STRING); /* message */
1222
1228
1230 lan_selection = selection;
1232 g_signal_connect(view, "focus",
1234 g_signal_connect(view, "row-activated",
1236 g_signal_connect(selection, "changed",
1238
1239 add_treeview_column(view, _("Server Name"), G_TYPE_STRING, 0);
1240 add_treeview_column(view, _("Port"), G_TYPE_INT, 1);
1241 add_treeview_column(view, _("Version"), G_TYPE_STRING, 2);
1242 add_treeview_column(view, _("Status"), G_TYPE_STRING, 3);
1243 add_treeview_column(view, _("Players"), G_TYPE_INT, 4);
1244 add_treeview_column(view, _("Humans"), G_TYPE_STRING, 5);
1245 add_treeview_column(view, _("Comment"), G_TYPE_STRING, 6);
1246
1247 label = gtk_label_new_with_mnemonic(_("Local _Area Network"));
1248
1256 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), sw, label);
1257
1258
1259 /* Metaserver pane. */
1261 G_TYPE_INT, /* port */
1262 G_TYPE_STRING, /* version */
1263 G_TYPE_STRING, /* state */
1264 G_TYPE_INT, /* nplayers */
1265 G_TYPE_STRING, /* humans */
1266 G_TYPE_STRING); /* message */
1267
1273
1275 meta_selection = selection;
1277 g_signal_connect(view, "focus",
1279 g_signal_connect(view, "row-activated",
1281 g_signal_connect(selection, "changed",
1283
1284 add_treeview_column(view, _("Server Name"), G_TYPE_STRING, 0);
1285 add_treeview_column(view, _("Port"), G_TYPE_INT, 1);
1286 add_treeview_column(view, _("Version"), G_TYPE_STRING, 2);
1287 add_treeview_column(view, _("Status"), G_TYPE_STRING, 3);
1288 add_treeview_column(view, _("Players"), G_TYPE_INT, 4);
1289 add_treeview_column(view, _("Humans"), G_TYPE_STRING, 5);
1290 add_treeview_column(view, _("Comment"), G_TYPE_STRING, 6);
1291
1292 label = gtk_label_new_with_mnemonic(_("Internet _Metaserver"));
1293
1302 gtk_notebook_prepend_page(GTK_NOTEBOOK(notebook), sw, label);
1303 } else {
1304 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), sw, label);
1305 }
1306
1307 /* Bottom part of the page, outside the inner notebook. */
1308 sbox = gtk_grid_new();
1312
1313 hbox = gtk_grid_new();
1315 g_object_set(hbox, "margin", 8, NULL);
1317
1318 table = gtk_grid_new();
1322
1324 g_signal_connect(network_host, "activate",
1327
1329 "use-underline", TRUE,
1330 "mnemonic-widget", network_host,
1331 "label", _("_Host:"),
1332 "xalign", 0.0,
1333 "yalign", 0.5,
1334 NULL);
1335 gtk_grid_attach(GTK_GRID(table), label, 0, 0, 1, 1);
1336
1338 g_signal_connect(network_port, "activate",
1341
1343 "use-underline", TRUE,
1344 "mnemonic-widget", network_port,
1345 "label", _("_Port:"),
1346 "xalign", 0.0,
1347 "yalign", 0.5,
1348 NULL);
1349 gtk_grid_attach(GTK_GRID(table), label, 0, 1, 1, 1);
1350
1353 g_signal_connect(network_login, "activate",
1356
1358 "use-underline", TRUE,
1359 "mnemonic-widget", network_login,
1360 "label", _("_Login:"),
1361 "xalign", 0.0,
1362 "yalign", 0.5,
1363 NULL);
1364 gtk_widget_set_margin_top(label, 10);
1365 gtk_grid_attach(GTK_GRID(table), label, 0, 3, 1, 1);
1366
1372
1374 "use-underline", TRUE,
1375 "mnemonic-widget", network_password,
1376 "label", _("Pass_word:"),
1377 "xalign", 0.0,
1378 "yalign", 0.5,
1379 NULL);
1380 network_password_label = label;
1381 gtk_grid_attach(GTK_GRID(table), label, 0, 4, 1, 1);
1382
1388
1390 "use-underline", TRUE,
1391 "mnemonic-widget", network_confirm_password,
1392 "label", _("Conf_irm Password:"),
1393 "xalign", 0.0,
1394 "yalign", 0.5,
1395 NULL);
1397 gtk_grid_attach(GTK_GRID(table), label, 0, 5, 1, 1);
1398
1399 /* Server player list. */
1405
1411 add_treeview_column(view, _("Nation"), G_TYPE_STRING, 3);
1412
1420
1421
1423 g_object_set(bbox, "margin", 2, NULL);
1427
1428 button = gtk_button_new_from_icon_name("view-refresh", GTK_ICON_SIZE_BUTTON);
1431 g_signal_connect(button, "clicked",
1433
1434 button = gtk_button_new_with_mnemonic(_("_Cancel"));
1436 g_signal_connect(button, "clicked",
1438
1439 button = gtk_button_new_with_mnemonic(_("C_onnect"));
1441 g_signal_connect(button, "clicked",
1443
1444 return box;
1445}
1446
1447
1448/****************************************************************************
1449 START PAGE
1450****************************************************************************/
1452
1459
1460
1461/* NB: Must match creation arguments in connection_list_store_new(). */
1478
1479/**********************************************************************/
1483{
1485 G_TYPE_INT, /* CL_COL_PLAYER_NUMBER */
1486 G_TYPE_STRING, /* CL_COL_USER_NAME */
1487 G_TYPE_BOOLEAN, /* CL_COL_READY_STATE */
1488 G_TYPE_STRING, /* CL_COL_PLAYER_NAME */
1489 GDK_TYPE_PIXBUF, /* CL_COL_FLAG */
1490 GDK_TYPE_PIXBUF, /* CL_COL_COLOR */
1491 G_TYPE_STRING, /* CL_COL_NATION */
1492 G_TYPE_STRING, /* CL_COL_TEAM */
1493 G_TYPE_INT, /* CL_COL_CONN_ID */
1494 G_TYPE_INT, /* CL_COL_STYLE */
1495 G_TYPE_INT, /* CL_COL_WEIGHT */
1496 G_TYPE_BOOLEAN); /* CL_COL_COLLAPSED */
1497}
1498
1499/**********************************************************************/
1503static void client_aitoggle_player(void *data)
1504{
1505 struct player *pplayer = player_by_number(FC_PTR_TO_INT(data));
1506
1507 if (NULL != pplayer
1508 && pplayer == client_player()
1509 && !is_human(pplayer)) {
1510 send_chat("/away");
1511 }
1512}
1513
1514/**********************************************************************/
1517static void client_take_player(struct player *pplayer)
1518{
1519 int request_id = send_chat_printf("/take \"%s\"", player_name(pplayer));
1520 void *data = FC_INT_TO_PTR(player_number(pplayer));
1521
1524}
1525
1526/**********************************************************************/
1529static void object_put(GObject *object, struct player *pplayer,
1530 struct connection *pconn)
1531{
1532 /* Note that passing -1 to GINT_TO_POINTER() is buggy with some versions
1533 * of gcc. player_slot_count() is not a valid player number. 0 is not
1534 * a valid connection id (see comment in server/sernet.c:
1535 * makeup_connection_name()). */
1536 g_object_set_data(object, "player_id",
1537 GINT_TO_POINTER(NULL != pplayer
1538 ? player_number(pplayer)
1539 : player_slot_count()));
1540 g_object_set_data(object, "connection_id",
1541 GINT_TO_POINTER(NULL != pconn ? pconn->id : 0));
1542}
1543
1544/**********************************************************************/
1548static bool object_extract(GObject *object, struct player **ppplayer,
1549 struct connection **ppconn)
1550{
1551 bool ret = FALSE;
1552 int id;
1553
1554 if (NULL != ppplayer) {
1555 id = GPOINTER_TO_INT(g_object_get_data(object, "player_id"));
1557 if (NULL != *ppplayer) {
1558 ret = TRUE;
1559 }
1560 }
1561 if (NULL != ppconn) {
1562 id = GPOINTER_TO_INT(g_object_get_data(object, "connection_id"));
1563 *ppconn = conn_by_number(id);
1564 if (NULL != *ppconn) {
1565 ret = TRUE;
1566 }
1567 }
1568
1569 return ret;
1570}
1571
1572/**********************************************************************/
1576{
1577 option_dialog_popup(_("Game Settings"), server_optset);
1578}
1579
1580/**********************************************************************/
1584{
1585 enum ai_level *levels = (enum ai_level *)data;
1586 const char *name;
1587 int i;
1588
1590
1591 if (i != -1) {
1592 enum ai_level level = levels[i];
1593
1594 /* Suppress changes provoked by server rather than local user */
1595 if (server_ai_level() != level) {
1597 send_chat_printf("/%s", name);
1598 }
1599 }
1600}
1601
1602/* HACK: sometimes when creating the ruleset combo the value is set without
1603 * the user's control. In this case we don't want to do a /read. */
1605
1606/**********************************************************************/
1609static void ruleset_selected(const char *name)
1610{
1611 if (name && name[0] != '\0' && !no_ruleset_callback) {
1613 }
1614}
1615
1616/**********************************************************************/
1622{
1623 const char *name = NULL;
1624
1626
1627 if (name != NULL) {
1629 }
1630}
1631
1632/**********************************************************************/
1643
1644/**********************************************************************/
1648{
1649 if (start_aifill_spin) {
1651
1652 /* Suppress callback from this change to avoid a loop. */
1654 /* HACK: this GUI control doesn't have quite the same semantics as the
1655 * server 'aifill' option, in that it claims to represent the minimum
1656 * number of players _including humans_. The GUI control has a minimum
1657 * value of 1, so aifill == 0 will not be represented correctly.
1658 * But there's generally exactly one human player because the control
1659 * only shows up for a locally spawned server, so we more or less
1660 * get away with this. */
1663 }
1664}
1665
1666/**********************************************************************/
1670{
1672}
1673
1674/**********************************************************************/
1677static void conn_menu_team_chosen(GObject *object, gpointer data)
1678{
1679 struct player *pplayer;
1680 struct team_slot *tslot = data;
1681
1682 if (object_extract(object, &pplayer, NULL)
1683 && NULL != tslot
1684 && team_slot_index(tslot) != team_number(pplayer->team)) {
1685 send_chat_printf("/team \"%s\" \"%s\"",
1686 player_name(pplayer),
1688 }
1689}
1690
1691/**********************************************************************/
1694static void conn_menu_ready_chosen(GObject *object, gpointer data)
1695{
1696 struct player *pplayer;
1697
1698 if (object_extract(object, &pplayer, NULL)) {
1700 player_number(pplayer), !pplayer->is_ready);
1701 }
1702}
1703
1704/**********************************************************************/
1707static void conn_menu_nation_chosen(GObject *object, gpointer data)
1708{
1709 struct player *pplayer;
1710
1711 if (object_extract(object, &pplayer, NULL)) {
1712 popup_races_dialog(pplayer);
1713 }
1714}
1715
1716/**********************************************************************/
1721{
1722 struct player *pplayer;
1723
1724 if (object_extract(object, &pplayer, NULL)) {
1725 send_chat_printf("/%s \"%s\"",
1726 (char *) g_object_get_data(G_OBJECT(data), "command"),
1727 player_name(pplayer));
1728 }
1729}
1730
1731/**********************************************************************/
1734static void conn_menu_player_take(GObject *object, gpointer data)
1735{
1736 struct player *pplayer;
1737
1738 if (object_extract(object, &pplayer, NULL)) {
1739 client_take_player(pplayer);
1740 }
1741}
1742
1743/**********************************************************************/
1748{
1749 struct connection *pconn;
1750
1751 if (object_extract(object, NULL, &pconn)) {
1752 send_chat_printf("/%s \"%s\"",
1753 (char *) g_object_get_data(G_OBJECT(data), "command"),
1754 pconn->username);
1755 }
1756}
1757
1758/**********************************************************************/
1761static void show_conn_popup(struct player *pplayer, struct connection *pconn)
1762{
1764 char buf[4096] = "";
1765
1766 if (pconn) {
1767 cat_snprintf(buf, sizeof(buf), _("Connection name: %s"),
1768 pconn->username);
1769 } else {
1770 cat_snprintf(buf, sizeof(buf), _("Player name: %s"),
1771 player_name(pplayer));
1772 }
1773 cat_snprintf(buf, sizeof(buf), "\n");
1774 if (pconn) {
1775 cat_snprintf(buf, sizeof(buf), _("Host: %s"), pconn->addr);
1776 }
1777 cat_snprintf(buf, sizeof(buf), "\n");
1778
1779 /* Show popup. */
1782 "%s", buf);
1783 gtk_window_set_title(GTK_WINDOW(popup), _("Player/conn info"));
1787}
1788
1789/**********************************************************************/
1792static void conn_menu_info_chosen(GObject *object, gpointer data)
1793{
1794 struct player *pplayer;
1795 struct connection *pconn;
1796
1797 if (object_extract(object, &pplayer, &pconn)) {
1798 show_conn_popup(pplayer, pconn);
1799 }
1800}
1801
1802/**********************************************************************/
1806static GtkWidget *create_conn_menu(struct player *pplayer,
1807 struct connection *pconn)
1808{
1809 GtkWidget *menu;
1810 GtkWidget *item;
1811 gchar *buf;
1812
1813 menu = gtk_menu_new();
1814 object_put(G_OBJECT(menu), pplayer, pconn);
1815
1816 buf = g_strdup_printf(_("%s info"),
1817 pconn ? pconn->username : player_name(pplayer));
1819 g_free(buf);
1821 g_signal_connect_swapped(item, "activate",
1823
1824 if (NULL != pplayer) {
1825 item = gtk_menu_item_new_with_label(_("Toggle player ready"));
1828 g_signal_connect_swapped(item, "activate",
1830
1831 item = gtk_menu_item_new_with_label(_("Pick nation"));
1834 pplayer));
1836 g_signal_connect_swapped(item, "activate",
1838
1839 item = gtk_menu_item_new_with_label(_("Observe this player"));
1841 g_object_set_data_full(G_OBJECT(item), "command", g_strdup("observe"),
1843 g_signal_connect_swapped(item, "activate",
1845
1846 item = gtk_menu_item_new_with_label(_("Take this player"));
1848 g_signal_connect_swapped(item, "activate",
1850 }
1851
1853 && (pconn->id != client.conn.id || NULL != pplayer)) {
1856
1857 if (pconn->id != client.conn.id) {
1858 item = gtk_menu_item_new_with_label(_("Cut connection"));
1860 g_object_set_data_full(G_OBJECT(item), "command", g_strdup("cut"),
1862 g_signal_connect_swapped(item, "activate",
1864 menu);
1865 }
1866 }
1867
1868 if (ALLOW_CTRL <= client.conn.access_level && NULL != pplayer) {
1869 item = gtk_menu_item_new_with_label(_("Aitoggle player"));
1871 g_object_set_data_full(G_OBJECT(item), "command", g_strdup("aitoggle"),
1873 g_signal_connect_swapped(item, "activate",
1875
1876 if (pplayer != client.conn.playing && game.info.is_new_game) {
1877 item = gtk_menu_item_new_with_label(_("Remove player"));
1879 g_object_set_data_full(G_OBJECT(item), "command", g_strdup("remove"),
1881 g_signal_connect_swapped(item, "activate",
1883 }
1884 }
1885
1887 && pconn->id != client.conn.id) {
1888 enum cmdlevel level;
1889
1890 /* No item for hack access; that would be a serious security hole. */
1892 /* TRANS: Give access level to a connection. */
1893 buf = g_strdup_printf(_("Give %s access"),
1896 g_free(buf);
1899 g_strdup_printf("cmdlevel %s",
1902 g_signal_connect_swapped(item, "activate",
1904 menu);
1905 }
1906 }
1907
1909 && NULL != pplayer && is_ai(pplayer)) {
1910 enum ai_level level;
1911
1914
1915 for (level = 0; level < AI_LEVEL_COUNT; level++) {
1918 const char *level_cmd = ai_level_cmd(level);
1919
1924 g_signal_connect_swapped(item, "activate",
1926 }
1927 }
1928 }
1929
1930 if (pplayer && game.info.is_new_game) {
1931 const int count = pplayer->team
1932 ? player_list_size(team_members(pplayer->team)) : 0;
1933 bool need_empty_team = (count != 1);
1934
1937
1938 /* Can't use team_iterate here since it skips empty teams. */
1940 if (!team_slot_is_used(tslot)) {
1941 if (!need_empty_team) {
1942 continue;
1943 }
1945 }
1946
1947 /* TRANS: e.g., "Put on Team 5" */
1948 buf = g_strdup_printf(_("Put on %s"),
1951 g_free(buf);
1953 object_put(G_OBJECT(item), pplayer, NULL);
1955 tslot);
1957 }
1958
1959 gtk_widget_show_all(menu);
1960
1961 return menu;
1962}
1963
1964/**********************************************************************/
1968{
1969 if (NULL != connection_list_view) {
1970 GtkTreeSelection *selection =
1972 GtkTreePath *path = data;
1973
1974 gtk_tree_selection_unselect_path(selection, path);
1975 gtk_tree_path_free(path);
1976 }
1977 return FALSE;
1978}
1979
1980/**********************************************************************/
1985 gpointer data)
1986{
1988 GtkTreePath *path = NULL;
1990 gboolean ret = FALSE;
1991
1992 if ((1 != event->button && 3 != event->button)
1993 || GDK_BUTTON_PRESS != event->type
1995 event->x, event->y,
1996 &path, NULL, NULL, NULL)) {
1997 return FALSE;
1998 }
1999
2000 if (1 == event->button) {
2001 if (gtk_tree_selection_path_is_selected(selection, path)) {
2002 /* Need to delay to avoid problem with the expander. */
2004 return FALSE; /* Return now, don't free the path. */
2005 }
2006 } else if (3 == event->button) {
2009 GtkWidget *menu;
2010 int player_no, conn_id;
2011 struct player *pplayer;
2012 struct connection *pconn;
2013
2014 if (!gtk_tree_selection_path_is_selected(selection, path)) {
2015 gtk_tree_selection_select_path(selection, path);
2016 }
2017 gtk_tree_model_get_iter(model, &iter, path);
2018
2019 gtk_tree_model_get(model, &iter, CL_COL_PLAYER_NUMBER, &player_no, -1);
2020 pplayer = player_by_number(player_no);
2021
2022 gtk_tree_model_get(model, &iter, CL_COL_CONN_ID, &conn_id, -1);
2023 pconn = conn_by_number(conn_id);
2024
2025 menu = create_conn_menu(pplayer, pconn);
2027 ret = TRUE;
2028 }
2029
2030 gtk_tree_path_free(path);
2031 return ret;
2032}
2033
2034/**********************************************************************/
2039 GtkTreePath *path,
2040 gpointer data)
2041{
2043
2044 gtk_tree_store_set(store, iter,
2046}
2047
2048/**********************************************************************/
2053 struct connection **ppconn)
2054{
2055 if (NULL != connection_list_view) {
2057 GtkTreeModel *model;
2058 GtkTreeSelection *selection =
2060
2061 if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
2062 int id;
2063
2064 if (NULL != ppplayer) {
2065 gtk_tree_model_get(model, &iter, CL_COL_PLAYER_NUMBER, &id, -1);
2067 }
2068 if (NULL != ppconn) {
2069 gtk_tree_model_get(model, &iter, CL_COL_CONN_ID, &id, -1);
2070 *ppconn = conn_by_number(id);
2071 }
2072 return TRUE;
2073 }
2074 }
2075
2076 if (NULL != ppplayer) {
2077 *ppplayer = NULL;
2078 }
2079 if (NULL != ppconn) {
2080 *ppconn = NULL;
2081 }
2082 return FALSE;
2083}
2084
2085/**********************************************************************/
2089{
2090 GtkTreeModel *model;
2091 GtkTreeIter parent, child, *iter = NULL;
2092 GtkTreeSelection *selection;
2093 gboolean valid;
2094 const int search_id = pconn->id;
2095 int id;
2096
2097 if (NULL == connection_list_view) {
2098 return;
2099 }
2100
2103
2104 /* Main iteration. */
2105 valid = gtk_tree_model_get_iter_first(model, &parent);
2106 while (valid && NULL == iter) {
2107 gtk_tree_model_get(model, &parent, CL_COL_CONN_ID, &id, -1);
2108 if (search_id == id) {
2109 iter = &parent;
2110 break;
2111 }
2112
2113 /* Node children iteration. */
2114 valid = gtk_tree_model_iter_children(model, &child, &parent);
2115 while (valid && NULL == iter) {
2116 gtk_tree_model_get(model, &child, CL_COL_CONN_ID, &id, -1);
2117 if (search_id == id) {
2118 iter = &child;
2119 break;
2120 }
2121 valid = gtk_tree_model_iter_next(model, &child);
2122 }
2123
2124 valid = gtk_tree_model_iter_next(model, &parent);
2125 }
2126
2127 /* Select iterator. */
2128 if (NULL != iter) {
2130 } else {
2131 log_error("%s(): connection %s not found.",
2133 }
2134}
2135
2136/**********************************************************************/
2140{
2141 if (can_client_control()) {
2144 !client_player()->is_ready);
2145 } else {
2147 }
2148}
2149
2150/**********************************************************************/
2154{
2155 struct player *selected_plr;
2156 bool row_selected = conn_list_selection(&selected_plr, NULL);
2157
2158 if (row_selected && NULL != selected_plr) {
2159 /* "Take <player_name>" */
2161 } else if (can_client_control()) {
2162 /* "Pick Nation" */
2164 } else {
2165 /* "Take a Player" */
2166 send_chat("/take -");
2167 }
2168}
2169
2170/**********************************************************************/
2174{
2175 struct player *selected_plr;
2176 bool row_selected = conn_list_selection(&selected_plr, NULL);
2177
2178 if (row_selected && NULL != selected_plr) {
2179 /* "Observe <player_name>" */
2180 send_chat_printf("/observe \"%s\"", player_name(selected_plr));
2181 } else if (!client_is_global_observer()) {
2182 /* "Observe" */
2183 send_chat("/observe");
2184 } else {
2185 /* "Do not observe" */
2186 send_chat("/detach");
2187 }
2188}
2189
2190/**********************************************************************/
2194{
2195 char buf[2 * MAX_LEN_NAME];
2196 const char *text;
2197 struct player *selected_plr;
2198 bool row_selected = conn_list_selection(&selected_plr, NULL);
2199 bool sensitive;
2200
2201 /*** Ready button. ***/
2202 if (can_client_control()) {
2203 sensitive = client_player()->is_alive;
2204 if (client_player()->is_ready) {
2205 text = _("Not _ready");
2206 } else {
2207 int num_unready = 0;
2208
2209 players_iterate_alive(pplayer) {
2210 if (is_human(pplayer) && !pplayer->is_ready) {
2211 num_unready++;
2212 }
2214
2215 if (num_unready > 1) {
2216 text = _("_Ready");
2217 } else {
2218 /* We are the last unready player so clicking here will
2219 * immediately start the game. */
2220 text = _("_Start");
2221 }
2222 }
2223 } else {
2224 text = _("_Start");
2225 if (can_client_access_hack()) {
2226 sensitive = TRUE;
2228 if (is_human(plr)) {
2229 /* There's human controlled player(s) in game, so it's their
2230 * job to start the game. */
2231 sensitive = FALSE;
2232 break;
2233 }
2235 } else {
2236 sensitive = FALSE;
2237 }
2238 }
2241
2242 /*** Nation button. ***/
2243 if (row_selected && NULL != selected_plr) {
2244 fc_snprintf(buf, sizeof(buf), _("_Take %s"), player_name(selected_plr));
2245 text = buf;
2247 } else if (can_client_control()) {
2248 text = _("Pick _Nation");
2250 } else {
2251 text = _("_Take a Player");
2253 }
2256
2257 /*** Observe button. ***/
2258 if (row_selected && NULL != selected_plr) {
2259 fc_snprintf(buf, sizeof(buf), _("_Observe %s"),
2261 text = buf;
2263 } else if (!client_is_global_observer()) {
2264 text = _("_Observe");
2265 sensitive = TRUE;
2266 } else {
2267 text = _("Do not _observe");
2268 sensitive = TRUE;
2269 }
2272}
2273
2274/**********************************************************************/
2280 GtkTreeIter *start,
2281 const struct player *pplayer)
2282{
2283 const int search_id = player_number(pplayer);
2284 int id;
2285
2286 if (NULL != start) {
2287 *iter = *start;
2288 if (!gtk_tree_model_iter_next(model, iter)) {
2289 return FALSE;
2290 }
2291 } else if (!gtk_tree_model_get_iter_first(model, iter)) {
2292 return FALSE;
2293 }
2294
2295 do {
2297 if (id == search_id) {
2298 return TRUE;
2299 }
2300 } while (gtk_tree_model_iter_next(model, iter));
2301
2302 return FALSE;
2303}
2304
2305/**********************************************************************/
2311 const struct connection *pconn)
2312{
2313 const int search_id = pconn->id;
2314 int id;
2315
2316 if (NULL != start) {
2317 *iter = *start;
2318 if (!gtk_tree_model_iter_next(model, iter)) {
2319 return FALSE;
2320 }
2321 } else if (!gtk_tree_model_iter_children(model, iter, parent)) {
2322 return FALSE;
2323 }
2324
2325 do {
2326 gtk_tree_model_get(model, iter, CL_COL_CONN_ID, &id, -1);
2327 if (id == search_id) {
2328 return TRUE;
2329 }
2330 } while (gtk_tree_model_iter_next(model, iter));
2331
2332 return FALSE;
2333}
2334
2335/**********************************************************************/
2339{
2344 GtkTreeModel *model = GTK_TREE_MODEL(store);
2345 GtkTreePath *path;
2348 GdkPixbuf *flag, *color;
2350 struct player *pselected_player;
2351 struct connection *pselected_conn;
2352 bool is_ready;
2353 const char *nation, *plr_name, *team;
2354 char name[MAX_LEN_NAME + 8];
2356 int conn_id;
2357
2358 /* Refresh the AI skill level control */
2359 if (ai_lvl_combobox) {
2360 enum ai_level new_level = server_ai_level(), level;
2361 int i = 0;
2362
2363 for (level = 0; level < AI_LEVEL_COUNT; level++) {
2365 if (level == new_level) {
2367 break;
2368 }
2369 i++;
2370 }
2371 }
2372 if (level == AI_LEVEL_COUNT) {
2373 /* Probably ai_level_invalid() */
2375 }
2376 }
2377
2378 /* Save the selected connection. */
2380
2381 /* Insert players into the connection list. */
2382 players_iterate(pplayer) {
2383 if (!player_has_flag(pplayer, PLRF_SCENARIO_RESERVED)) {
2384 conn_id = -1;
2386 flag = pplayer->nation ? get_flag(pplayer->nation) : NULL;
2387 color = create_player_icon(pplayer);
2388
2389 conn_list_iterate(pplayer->connections, pconn) {
2390 if (pconn->playing == pplayer && !pconn->observer) {
2391 conn_id = pconn->id;
2392 access_level = pconn->access_level;
2393 break;
2394 }
2396
2397 if (is_ai(pplayer) && !pplayer->was_created
2398 && !pplayer->is_connected) {
2399 /* TRANS: "<Novice AI>" */
2400 fc_snprintf(name, sizeof(name), _("<%s AI>"),
2401 ai_level_translated_name(pplayer->ai_common.skill_level));
2402 } else {
2403 sz_strlcpy(name, pplayer->username);
2404 if (access_level > ALLOW_BASIC) {
2405 sz_strlcat(name, "*");
2406 }
2407 }
2408
2409 is_ready = !is_human(pplayer) ? TRUE : pplayer->is_ready;
2410
2411 if (pplayer->nation == NO_NATION_SELECTED) {
2412 nation = _("Random");
2413 if (pplayer->was_created) {
2414 plr_name = player_name(pplayer);
2415 } else {
2416 plr_name = "";
2417 }
2418 } else {
2419 nation = nation_adjective_for_player(pplayer);
2420 plr_name = player_name(pplayer);
2421 }
2422
2423 team = pplayer->team ? team_name_translation(pplayer->team) : "";
2424
2425 if (model_get_player_iter(model, &parent, pprev_parent, pplayer)) {
2427 } else {
2429 }
2430
2431 gtk_tree_store_set(store, &parent,
2434 CL_COL_READY_STATE, is_ready,
2436 CL_COL_FLAG, flag,
2438 CL_COL_NATION, nation,
2440 CL_COL_CONN_ID, conn_id,
2443 -1);
2444
2445 /* Insert observers of this player as child nodes. */
2446 pprev_child = NULL;
2447 conn_list_iterate(pplayer->connections, pconn) {
2448 if (pconn->id == conn_id) {
2449 continue;
2450 }
2451 if (model_get_conn_iter(model, &child, &parent,
2452 pprev_child, pconn)) {
2453 gtk_tree_store_move_after(store, &child, pprev_child);
2454 } else {
2456 }
2457
2458 gtk_tree_store_set(store, &child,
2460 CL_COL_USER_NAME, pconn->username,
2461 CL_COL_TEAM, _("Observer"),
2462 CL_COL_CONN_ID, pconn->id,
2465 -1);
2466
2467 prev_child = child;
2470
2471 /* Expand node? */
2472 if (NULL != pprev_child) {
2474 if (!collapsed) {
2475 path = gtk_tree_model_get_path(model, &parent);
2477 path, FALSE);
2478 gtk_tree_path_free(path);
2479 }
2480 }
2481
2482 /* Remove trailing rows. */
2483 if (NULL != pprev_child) {
2484 child = prev_child;
2485 if (gtk_tree_model_iter_next(model, &child)) {
2486 while (gtk_tree_store_remove(store, &child)) {
2487 /* Do nothing more. */
2488 }
2489 }
2490 } else if (gtk_tree_model_iter_children(model, &child, &parent)) {
2491 while (gtk_tree_store_remove(store, &child)) {
2492 /* Do nothing more. */
2493 }
2494 }
2495
2498 if (flag) {
2499 g_object_unref(flag);
2500 }
2501 if (color) {
2503 }
2504 }
2506
2507 /* Finally, insert global observers... */
2509 if (NULL != pconn->playing || !pconn->observer) {
2510 continue;
2511 }
2512
2515 } else {
2517 }
2518
2519 gtk_tree_store_set(store, &parent,
2521 CL_COL_USER_NAME, pconn->username,
2522 CL_COL_TEAM, _("Observer"),
2523 CL_COL_CONN_ID, pconn->id,
2526 -1);
2527
2531
2532 /* ...and detached connections. */
2534 if (NULL != pconn->playing || pconn->observer) {
2535 continue;
2536 }
2537
2540 } else {
2542 }
2543
2544 gtk_tree_store_set(store, &parent,
2546 CL_COL_USER_NAME, pconn->username,
2547 CL_COL_TEAM, _("Detached"),
2548 CL_COL_CONN_ID, pconn->id,
2551 -1);
2552
2556
2557 /* Remove trailing rows. */
2558 if (NULL != pprev_parent) {
2560 if (gtk_tree_model_iter_next(model, &parent)) {
2561 while (gtk_tree_store_remove(store, &parent)) {
2562 /* Do nothing more. */
2563 }
2564 }
2565 } else {
2566 gtk_tree_store_clear(store);
2567 }
2568
2569 /* If we were selecting a single connection, let's try to reselect it. */
2572 }
2573 }
2574
2576}
2577
2578/**********************************************************************/
2584 const char *title, int colnum, const char *key)
2585{
2588
2589 if (gtype == G_TYPE_BOOLEAN) {
2592 "active", colnum, NULL);
2593 } else if (gtype == GDK_TYPE_PIXBUF) {
2596 "pixbuf", colnum, NULL);
2597 } else {
2600 "text", colnum,
2601 "style", CL_COL_STYLE,
2602 "weight", CL_COL_WEIGHT,
2603 NULL);
2604 }
2605
2608
2609 if (key != NULL) {
2611 }
2612}
2613
2614/**********************************************************************/
2618{
2619 GtkWidget *box, *sbox, *table, *vbox;
2620 GtkWidget *view, *sw, *text, *toolkit_view, *button, *spin;
2621 GtkWidget *label;
2622 GtkTreeSelection *selection;
2623 enum ai_level level;
2624 /* There's less than AI_LEVEL_COUNT entries as not all levels have
2625 entries (that's the whole point of this array: index != value),
2626 but this is set safely to the max */
2627 static enum ai_level levels[AI_LEVEL_COUNT];
2628 int i = 0;
2629
2630 box = gtk_grid_new();
2635
2636 sbox = gtk_grid_new();
2639
2640 vbox = gtk_grid_new();
2641 g_object_set(vbox, "margin", 12, NULL);
2648
2649 table = gtk_grid_new();
2654
2660 if (server_optset != NULL) {
2662 if (paifill) {
2665 } /* else it'll be updated later */
2666 }
2667 g_signal_connect_after(spin, "value_changed",
2669
2670 gtk_grid_attach(GTK_GRID(table), spin, 1, 0, 1, 1);
2671
2673 "use-underline", TRUE,
2674 "mnemonic-widget", spin,
2675 /* TRANS: Keep individual lines short */
2676 "label", _("Number of _Players\n(including AI):"),
2677 "xalign", 0.0,
2678 "yalign", 0.5,
2679 NULL);
2680 gtk_grid_attach(GTK_GRID(table), label, 0, 0, 1, 1);
2681
2683
2684 for (level = 0; level < AI_LEVEL_COUNT; level++) {
2687
2689 levels[i] = level;
2690 i++;
2691 }
2692 }
2695 G_CALLBACK(ai_skill_callback), levels);
2696
2698
2700 "use-underline", TRUE,
2701 "mnemonic-widget", ai_lvl_combobox,
2702 "label", _("AI Skill _Level:"),
2703 "xalign", 0.0,
2704 "yalign", 0.5,
2705 NULL);
2706 gtk_grid_attach(GTK_GRID(table), label, 0, 1, 1, 1);
2707
2711
2713
2715 "use-underline", TRUE,
2716 "mnemonic-widget", GTK_COMBO_BOX_TEXT(ruleset_combo),
2717 "label", _("Ruleset:"),
2718 "xalign", 0.0,
2719 "yalign", 0.5,
2720 NULL);
2721 gtk_grid_attach(GTK_GRID(table), label, 0, 2, 1, 1);
2722
2723 button = icon_label_button_new("preferences-system",
2724 _("_More Game Options..."));
2725 g_object_set(button, "margin", 8, NULL);
2728 g_signal_connect(button, "clicked",
2730 gtk_container_add(GTK_CONTAINER(vbox), button);
2731
2738
2741 g_signal_connect(selection, "changed",
2743
2744 add_tree_col(view, G_TYPE_STRING, _("Name"),
2746 add_tree_col(view, G_TYPE_BOOLEAN, _("Ready"),
2748 add_tree_col(view, G_TYPE_STRING, Q_("?player:Leader"),
2751 CL_COL_FLAG, NULL);
2752 add_tree_col(view, GDK_TYPE_PIXBUF, _("Border"),
2754 add_tree_col(view, G_TYPE_STRING, _("Nation"),
2756 add_tree_col(view, G_TYPE_STRING, _("Team"),
2757 CL_COL_TEAM, NULL);
2758
2759 g_signal_connect(view, "button-press-event",
2761 g_signal_connect(view, "row-collapsed",
2764 g_signal_connect(view, "row-expanded",
2767
2777
2778
2786
2790 start_message_area = text;
2791 gtk_widget_set_name(text, "chatline");
2796
2797
2798 /* Vote widgets. */
2799 if (pregame_votebar == NULL) {
2801 }
2803
2804
2807
2808 button = gtk_button_new_with_mnemonic(_("_Cancel"));
2810 g_signal_connect(button, "clicked", G_CALLBACK(main_callback), NULL);
2811
2812 nation_button = icon_label_button_new("document-properties",
2813 _("Pick _Nation"));
2817
2818 observe_button = icon_label_button_new("zoom-in", _("_Observe"));
2822
2823 ready_button = icon_label_button_new("system-run", _("_Ready"));
2825 g_signal_connect(ready_button, "clicked",
2827
2828 return box;
2829}
2830
2831
2832/**********************************************************************/
2835void handle_game_load(bool load_successful, const char *filename)
2836{
2837 if (load_successful) {
2839
2840 if (game.info.is_new_game) {
2841 /* It's pregame. Create a player and connect to it */
2842 send_chat("/take -");
2843 }
2844 }
2845}
2846
2847/**********************************************************************/
2850static void load_filename(const char *filename)
2851{
2852 send_chat_printf("/load %s", filename);
2853}
2854
2855/**********************************************************************/
2858static void load_callback(void)
2859{
2860 GtkTreeIter it;
2861 const gchar *filename;
2862
2864 return;
2865 }
2866
2868 SD_COL_FULL_PATH, &filename, -1);
2869 load_filename(filename);
2870}
2871
2872/**********************************************************************/
2876{
2877 save_dialog_file_chooser_popup(_("Choose Saved Game to Load"),
2880}
2881
2882/**********************************************************************/
2885static void update_load_page(void)
2886{
2887 /* Search for user saved games. */
2889 ".sav", FALSE);
2890
2892 fileinfo_list_destroy(files);
2893}
2894
2895/**********************************************************************/
2899{
2900 GtkWidget *box, *sbox, *bbox;
2901
2902 GtkWidget *button, *label, *view, *sw;
2904
2905 box = gtk_grid_new();
2910
2915
2918 -1, NULL, rend, "text", 0, NULL);
2919
2922
2924
2925 g_signal_connect(view, "row-activated",
2927
2928 sbox = gtk_grid_new();
2934
2936 "use-underline", TRUE,
2937 "mnemonic-widget", view,
2938 "label", _("Choose Saved Game to _Load:"),
2939 "xalign", 0.0,
2940 "yalign", 0.5,
2941 NULL);
2943
2952
2958
2959 button = gtk_button_new_with_mnemonic(_("_Browse..."));
2962 g_signal_connect(button, "clicked",
2964
2965 button = gtk_button_new_with_mnemonic(_("_Cancel"));
2967 g_signal_connect(button, "clicked",
2969
2970 button = gtk_button_new_with_mnemonic(_("_OK"));
2972 g_signal_connect(button, "clicked",
2974
2975 return box;
2976}
2977
2978/**********************************************************************/
2981static void scenario_list_callback(void)
2982{
2983 GtkTreeIter it;
2984 GtkTextBuffer *buffer;
2985 char *description;
2986 char *authors;
2987 char *filename;
2988 int ver;
2989 char vername[50];
2990
2993 2, &description, -1);
2995 3, &authors, -1);
2997 1, &filename, -1);
2999 4, &ver, -1);
3000 filename = skip_to_basename(filename);
3001 if (ver > 0) {
3002 int maj;
3003 int min;
3004
3005 maj = ver / 1000000;
3006 ver %= 1000000;
3007 min = ver / 10000;
3008 ver %= 10000;
3009 if (ver >= 9000) {
3010 /* Development version, have '+' */
3011 fc_snprintf(vername, sizeof(vername), "%d.%d+", maj, min);
3012 } else {
3013 fc_snprintf(vername, sizeof(vername), "%d.%d", maj, min);
3014 }
3015 } else {
3016 /* TRANS: Old scenario format version */
3017 fc_snprintf(vername, sizeof(vername), _("pre-2.6"));
3018 }
3019 } else {
3020 description = "";
3021 authors = "";
3022 filename = "";
3023 vername[0] = '\0';
3024 }
3025
3027 gtk_text_buffer_set_text(buffer, description, -1);
3029 gtk_text_buffer_set_text(buffer, authors, -1);
3032}
3033
3034/**********************************************************************/
3037static void scenario_callback(void)
3038{
3039 GtkTreeIter it;
3040 char *filename;
3041
3043 return;
3044 }
3045
3046 gtk_tree_model_get(GTK_TREE_MODEL(scenario_store), &it, 1, &filename, -1);
3047 load_filename(filename);
3048}
3049
3050/**********************************************************************/
3054{
3055 save_dialog_file_chooser_popup(_("Choose a Scenario"),
3058}
3059
3060/**********************************************************************/
3063static void update_scenario_page(void)
3064{
3065 struct fileinfo_list *files;
3066
3068
3069 /* search for scenario files. */
3070 files = fileinfolist_infix(get_scenario_dirs(), ".sav", TRUE);
3072 struct section_file *sf;
3073
3074 if ((sf = secfile_load_section(pfile->fullname, "scenario", TRUE))
3075 && secfile_lookup_bool_default(sf, TRUE, "scenario.is_scenario")) {
3076 const char *sname, *sdescription, *sauthors;
3077 int fcver;
3078 int fcdev;
3079 int current_ver = MAJOR_VERSION * 1000000 + MINOR_VERSION * 10000;
3080 int current_dev;
3081
3083 if (PATCH_VERSION >= 90) {
3084 /* Patch level matters on development versions */
3085 current_dev += PATCH_VERSION * 100;
3086 }
3087
3088 fcver = secfile_lookup_int_default(sf, 0, "scenario.game_version");
3089 if (fcver < 30000) {
3090 /* Pre-3.0 versions stored version number without emergency version
3091 * part in the end. To get comparable version number stored,
3092 * multiply by 100. */
3093 fcver *= 100;
3094 }
3095 if (fcver % 10000 >= 9000) {
3096 fcdev = fcver - (fcver % 100); /* Emergency version does not count. */
3097 } else {
3098 fcdev = fcver - (fcver % 10000); /* Patch version does not count. */
3099 }
3100 sname = secfile_lookup_str_default(sf, NULL, "scenario.name");
3102 "scenario.description");
3103 sauthors = secfile_lookup_str_default(sf, NULL, "scenario.authors");
3104 log_debug("scenario file: %s from %s", sname, pfile->fullname);
3105
3106 /* Ignore scenarios for newer freeciv versions than we are. */
3107 if (fcdev <= current_dev) {
3108 bool add_new = TRUE;
3109
3110 if (sname != NULL) {
3111 GtkTreeIter it;
3112 bool valid;
3113
3115 while (valid) {
3116 char *oname;
3117
3119 0, &oname, -1);
3120
3121 if (!strcmp(sname, oname)) {
3122 /* Already listed scenario has the same name as the one we just found */
3123 int existing;
3124
3126 4, &existing, -1);
3127 log_debug("Duplicate %s (%d vs %d)", sname, existing, fcver);
3128
3129 if (existing > fcver) {
3130 /* Already listed one has higher version number */
3131 add_new = FALSE;
3132 } else if (existing < fcver) {
3133 /* New one has higher version number */
3134 add_new = FALSE;
3135
3137 0, sname && strlen(sname) ? Q_(sname) : pfile->name,
3138 1, pfile->fullname,
3139 2, (NULL != sdescription && '\0' != sdescription[0]
3140 ? Q_(sdescription) : ""),
3141 3, (NULL != sauthors && sauthors[0] != '\0'
3142 ? Q_(sauthors) : ""),
3143 4, fcver,
3144 -1);
3145 } else {
3146 /* Same version number -> list both */
3147 }
3148 }
3150 }
3151 }
3152
3153 if (add_new) {
3154 GtkTreeIter it;
3155
3158 0, sname && strlen(sname) ? Q_(sname) : pfile->name,
3159 1, pfile->fullname,
3160 2, (NULL != sdescription && '\0' != sdescription[0]
3161 ? Q_(sdescription) : ""),
3162 3, (NULL != sauthors && sauthors[0] != '\0'
3163 ? Q_(sauthors) : ""),
3164 4, fcver,
3165 -1);
3166 }
3167 }
3168
3169 secfile_destroy(sf);
3170 }
3172
3173 fileinfo_list_destroy(files);
3174}
3175
3176/**********************************************************************/
3180{
3181 GtkWidget *vbox, *hbox, *sbox, *bbox, *filenamebox, *descbox;
3183 GtkWidget *button, *label, *view, *sw, *swa, *text;
3185
3186 vbox = gtk_grid_new();
3191
3196 G_TYPE_INT);
3201
3204 -1, NULL, rend, "text", 0, NULL);
3205
3210
3212
3213 g_signal_connect(view, "row-activated",
3215
3217 "use-underline", TRUE,
3218 "mnemonic-widget", view,
3219 "label", _("Choose a _Scenario:"),
3220 "xalign", 0.0,
3221 "yalign", 0.5,
3222 NULL);
3223 gtk_container_add(GTK_CONTAINER(vbox), label);
3224
3225 sbox = gtk_grid_new();
3232
3233 hbox = gtk_grid_new();
3236
3243 gtk_grid_attach(GTK_GRID(sbox), sw, 0, 0, 1, 2);
3244
3245 text = gtk_text_view_new();
3251 scenario_description = text;
3252
3259
3260 text = gtk_text_view_new();
3266 scenario_authors = text;
3267
3274
3275 text = gtk_label_new(_("Filename:"));
3280
3283 g_object_set(filenamebox, "margin", 5, NULL);
3284
3287
3288 /* TRANS: Scenario format version */
3289 vertext = gtk_label_new(_("Format:"));
3294
3297 g_object_set(versionbox, "margin", 5, NULL);
3298
3301
3310 gtk_grid_attach(GTK_GRID(sbox), descbox, 1, 0, 1, 2);
3311
3316
3317 button = gtk_button_new_with_mnemonic(_("_Browse..."));
3320 g_signal_connect(button, "clicked",
3322
3323 button = gtk_button_new_with_mnemonic(_("_Cancel"));
3325 g_signal_connect(button, "clicked",
3327
3328 button = gtk_button_new_with_mnemonic(_("_OK"));
3330 g_signal_connect(button, "clicked",
3332
3333 return vbox;
3334}
3335
3336/**********************************************************************/
3340{
3341 return current_page;
3342}
3343
3344/**********************************************************************/
3348{
3349 /* Don't use current_page directly here because maybe it could be modified
3350 * before we reach the end of this function. */
3352
3353 /* If the page remains the same, don't do anything. */
3354 if (old_page == new_page) {
3355 return;
3356 }
3357
3358 log_debug("Switching client page from %s to %s.",
3359 -1 == old_page ? "(no page)" : client_pages_name(old_page),
3361
3363
3364 switch (old_page) {
3365 case PAGE_SCENARIO:
3366 case PAGE_LOAD:
3367 break;
3368 case PAGE_GAME:
3369 {
3371
3373 if (vmode == NULL) {
3375 }
3376 }
3377 break;
3378 default:
3379 break;
3380 }
3381
3382 switch (new_page) {
3383 case PAGE_MAIN:
3384 case PAGE_START:
3385 if (is_server_running()) {
3386 if (game.info.is_new_game) {
3388 } else {
3390 }
3392 } else {
3394 }
3398 break;
3399 case PAGE_GAME:
3400 {
3402
3405 if (vmode == NULL) {
3407 }
3410 }
3411 break;
3412 case PAGE_LOAD:
3414 break;
3415 case PAGE_SCENARIO:
3417 break;
3418 case PAGE_NETWORK:
3420 break;
3421 }
3422
3423 /* hide/show statusbar. */
3424 if (new_page == PAGE_START || new_page == PAGE_GAME) {
3427 } else {
3429 }
3430
3432
3433 /* Update the GUI. */
3434 while (gtk_events_pending()) {
3436 }
3437
3438 switch (new_page) {
3439 case PAGE_MAIN:
3440 break;
3441 case PAGE_START:
3444 break;
3445 case PAGE_LOAD:
3447 break;
3448 case PAGE_SCENARIO:
3450 break;
3451 case PAGE_GAME:
3455 mapview_thaw();
3456 break;
3457 case PAGE_NETWORK:
3462 break;
3463 }
3464}
3465
3466/****************************************************************************
3467 SAVE GAME DIALOGs
3468****************************************************************************/
3469
3470/**********************************************************************/
3474{
3475 return fileinfolist_infix(get_save_dirs(), ".sav", FALSE);
3476}
3477
3478/**********************************************************************/
3482{
3483 static GtkWidget *shell = NULL;
3484
3485 if (NULL != shell) {
3486 return;
3487 }
3488
3489 shell = save_dialog_new(_("Save Game"), _("Saved _Games:"),
3490 _("Save _Filename:"), send_save_game,
3493 &shell);
3495}
3496
3497/**********************************************************************/
3500static void save_dialog_save_scenario(const char *filename)
3501{
3503}
3504
3505/**********************************************************************/
3509{
3510 return fileinfolist_infix(get_scenario_dirs(), ".sav", FALSE);
3511}
3512
3513/**********************************************************************/
3517{
3518 static GtkWidget *shell = NULL;
3519
3520 if (NULL != shell) {
3521 return;
3522 }
3523
3524 shell = save_dialog_new(_("Save Scenario"), _("Saved Sce_narios:"),
3525 _("Save Sc_enario:"), save_dialog_save_scenario,
3528 &shell);
3530}
3531
3532/**********************************************************************/
3538{
3539 return fileinfolist_infix(get_save_dirs(), ".map", FALSE);
3540}
3541
3542/**********************************************************************/
3546{
3547 static GtkWidget *shell = NULL;
3548
3549 if (NULL != shell) {
3550 return;
3551 }
3552
3553 shell = save_dialog_new(_("Save Map Image"), _("Saved Map _Images:"),
3554 _("Save _Map Images:"), mapimg_client_save,
3557 &shell);
3559}
3560
3561/**********************************************************************/
3564void mapimg_client_save(const char *filename)
3565{
3566 if (!mapimg_client_createmap(filename)) {
3567 char msg[512];
3568
3569 fc_snprintf(msg, sizeof(msg), "(%s)", mapimg_error());
3570 popup_notify_dialog(_("Error"),
3571 _("Error Creating the Map Image!"), msg);
3572 }
3573}
3574
3575/**********************************************************************/
3580void set_rulesets(int num_rulesets, char **rulesets)
3581{
3582 int i;
3583 int def_idx = -1;
3584
3586 for (i = 0; i < num_rulesets; i++) {
3587
3589 if (!strcmp("default", rulesets[i])) {
3590 def_idx = i;
3591 }
3592 }
3593
3595
3596 /* HACK: server should tell us the current ruleset. */
3598
3600}
#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
int send_chat_printf(const char *format,...)
int send_chat(const char *message)
void output_window_append(const struct ft_color color, const char *featured_text)
bool can_client_control(void)
bool client_is_global_observer(void)
bool client_is_observer(void)
char user_name[512]
char server_host[512]
struct civclient client
enum client_states client_state(void)
char fc_password[MAX_LEN_PASSWORD]
int server_port
#define client_player()
@ C_S_PREPARING
Definition client_main.h:46
enum ai_level server_ai_level(void)
Definition climisc.c:1519
bool mapimg_client_createmap(const char *filename)
Definition climisc.c:1466
void center_on_something(void)
Definition climisc.c:430
static struct fc_sockaddr_list * list
Definition clinet.c:102
int connect_to_server(const char *username, const char *hostname, int port, char *errbuf, int errbufsize)
Definition clinet.c:249
void disconnect_from_server(bool leaving_sound)
Definition clinet.c:306
char * incite_cost
Definition comments.c:76
authentication_type
Definition conn_types.h:41
@ AUTH_NEWUSER_RETRY
Definition conn_types.h:45
@ AUTH_NEWUSER_FIRST
Definition conn_types.h:43
@ AUTH_LOGIN_RETRY
Definition conn_types.h:44
@ AUTH_LOGIN_FIRST
Definition conn_types.h:42
void send_save_game(const char *filename)
void set_ruleset(const char *ruleset)
bool is_server_running(void)
bool client_start_server(void)
bool can_client_access_hack(void)
const char * conn_description(const struct connection *pconn)
Definition connection.c:474
struct connection * conn_by_number(int id)
Definition connection.c:421
#define conn_list_iterate(connlist, pconn)
Definition connection.h:108
#define conn_list_iterate_end
Definition connection.h:110
popup_notify_dialog
Definition dialogs_g.h:36
int int id
Definition editgui_g.h:28
enum event_type event
Definition events.c:81
#define MAX_NUM_PLAYERS
Definition fc_types.h:36
#define MAX_LEN_NAME
Definition fc_types.h:67
#define Q_(String)
Definition fcintl.h:70
#define _(String)
Definition fcintl.h:67
void fc_mutex_allocate(fc_mutex *mutex)
void fc_mutex_release(fc_mutex *mutex)
const struct ft_color ftc_client
struct civ_game game
Definition game.c:61
static PangoLayout * layout
Definition canvas.c:325
void inputline_toolkit_view_append_button(GtkWidget *toolkit_view, GtkWidget *button)
Definition chatline.c:1293
GtkWidget * inputline_toolkit_view_new(void)
Definition chatline.c:1271
void inputline_grab_focus(void)
Definition chatline.c:80
void chatline_scroll_to_bottom(bool delayed)
Definition chatline.c:1007
void popup_races_dialog(struct player *pplayer)
Definition dialogs.c:1215
static struct tile * pos
Definition finddlg.c:53
const char * client_string
Definition gui_main.c:106
GtkTextBuffer * message_buffer
Definition gui_main.c: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 gboolean connection_list_event(GtkWidget *widget, GdkEventButton *event, gpointer data)
Definition pages.c:1983
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
void(* save_dialog_action_fn_t)(const char *filename)
Definition pages.c:379
struct fileinfo_list *(* save_dialog_files_fn_t)(void)
Definition pages.c:380
static struct server_list * server_list
Definition connectdlg.c:61
static enum client_pages old_page
Definition pages.c:46
void conn_list_dialog_update(void)
const char * name
Definition inputfile.c:127
#define fc_assert_ret(condition)
Definition log.h:192
#define fc_assert_ret_val(condition, val)
Definition log.h:195
#define log_debug(message,...)
Definition log.h:116
#define log_error(message,...)
Definition log.h:104
const char * mapimg_error(void)
Definition mapimg.c:759
#define fc_strdup(str)
Definition mem.h:43
#define fc_malloc(sz)
Definition mem.h:34
const char * nation_adjective_for_player(const struct player *pplayer)
Definition nation.c:169
bool can_conn_edit_players_nation(const struct connection *pconn, const struct player *pplayer)
Definition nation.c:1187
#define NO_NATION_SELECTED
Definition nation.h:30
const struct option_set * server_optset
Definition options.c:4077
const struct option_set * client_optset
Definition options.c:1291
int option_int_get(const struct option *poption)
Definition options.c:845
struct option * optset_option_by_name(const struct option_set *poptset, const char *name)
Definition options.c:442
bool option_int_set(struct option *poption, int val)
Definition options.c:889
int send_packet_authentication_reply(struct connection *pc, const struct packet_authentication_reply *packet)
int dsend_packet_save_scenario(struct connection *pc, const char *name)
int dsend_packet_player_ready(struct connection *pc, int player_no, bool is_ready)
bool is_settable_ai_level(enum ai_level level)
Definition player.c:1925
struct player * player_by_number(const int player_id)
Definition player.c:849
int player_slot_count(void)
Definition player.c:418
int player_number(const struct player *pplayer)
Definition player.c:837
const char * player_name(const struct player *pplayer)
Definition player.c:895
bool player_has_flag(const struct player *pplayer, enum plr_flag_id flag)
Definition player.c:1996
#define ai_level_cmd(_level_)
Definition player.h:572
#define players_iterate_end
Definition player.h:542
#define players_iterate(_pplayer)
Definition player.h:537
#define is_ai(plr)
Definition player.h:232
#define players_iterate_alive_end
Definition player.h:552
#define is_human(plr)
Definition player.h:231
#define players_iterate_alive(_pplayer)
Definition player.h:547
void secfile_destroy(struct section_file *secfile)
struct section_file * secfile_load_section(const char *filename, const char *section, bool allow_duplicates)
bool secfile_lookup_bool_default(const struct section_file *secfile, bool def, const char *path,...)
int secfile_lookup_int_default(const struct section_file *secfile, int def, const char *path,...)
const char * secfile_lookup_str_default(const struct section_file *secfile, const char *def, const char *path,...)
struct srv_list * server_scan_get_list(struct server_scan *scan)
Definition servers.c:866
void server_scan_finish(struct server_scan *scan)
Definition servers.c:879
struct server_scan * server_scan_begin(enum server_scan_type type, ServerScanErrorFunc error_func)
Definition servers.c:755
enum server_scan_type server_scan_get_type(const struct server_scan *scan)
Definition servers.c:809
enum server_scan_status server_scan_poll(struct server_scan *scan)
Definition servers.c:832
#define server_list_iterate_end
Definition servers.h:57
server_scan_status
Definition servers.h:79
@ SCAN_STATUS_PARTIAL
Definition servers.h:82
@ SCAN_STATUS_ERROR
Definition servers.h:80
@ SCAN_STATUS_DONE
Definition servers.h:83
#define server_list_iterate(serverlist, pserver)
Definition servers.h:55
server_scan_type
Definition servers.h:67
@ SERVER_SCAN_LOCAL
Definition servers.h:68
@ SERVER_SCAN_GLOBAL
Definition servers.h:69
struct setting_list * level[OLEVELS_NUM]
Definition settings.c:190
const struct strvec * get_scenario_dirs(void)
Definition shared.c:971
const struct strvec * get_save_dirs(void)
Definition shared.c:934
char * skip_to_basename(char *filepath)
Definition shared.c:1753
struct fileinfo_list * fileinfolist_infix(const struct strvec *dirs, const char *infix, bool nodups)
Definition shared.c:1204
#define fileinfo_list_iterate(list, pnode)
Definition shared.h:182
#define FC_PTR_TO_INT(p)
Definition shared.h:95
#define fileinfo_list_iterate_end
Definition shared.h:184
#define FC_INT_TO_PTR(i)
Definition shared.h:94
size_t size
Definition specvec.h:72
struct sprite int int int int struct sprite int int float scale
Definition sprite_g.h:33
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:2552
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
Definition climisc.h:82
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:960
int cat_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:986
int fc_remove(const char *filename)
Definition support.c:555
#define sz_strlcpy(dest, src)
Definition support.h:195
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
#define sz_strlcat(dest, src)
Definition support.h:196
#define fc_strncmp(_s1_, _s2_, _len_)
Definition support.h:160
const char * team_name_translation(const struct team *pteam)
Definition team.c:421
const char * team_slot_name_translation(const struct team_slot *tslot)
Definition team.c:253
int team_number(const struct team *pteam)
Definition team.c:392
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:457
bool team_slot_is_used(const struct team_slot *tslot)
Definition team.c:162
const char * team_slot_rule_name(const struct team_slot *tslot)
Definition team.c:233
#define team_slots_iterate_end
Definition team.h:77
#define team_slots_iterate(_tslot)
Definition team.h:72
const char * tileset_main_intro_filename(const struct tileset *t)
Definition tilespec.c:973
void client_start_server_and_set_page(enum client_pages page)
void set_client_page(enum client_pages page)
void update_queue_connect_processing_finished(int request_id, uq_callback_t callback, void *data)
enum client_pages get_client_page(void)
const char * fc_git_revision(void)
Definition version.c:75
const char * unstable_message(void)
Definition version.c:160
const char * word_version(void)
Definition version.c:62