Freeciv-3.2
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
72
75
76/* This is the current page. Invalid value at start, to be sure that it won't
77 * be caught through a switch() statement. */
78static enum client_pages current_page = -1;
79
85
86static struct server_scan_timer_data meta_scan = { NULL, 0 };
87static struct server_scan_timer_data lan_scan = { NULL, 0 };
88
92
94
96
97static void connection_state_reset(void);
98
99/**********************************************************************/
103{
104 if (!is_server_running()) {
106
107 /* Saved settings are sent in client/options.c
108 * resend_desired_settable_options() */
109 }
110}
111
112/**********************************************************************/
116{
117 output_window_append(ftc_client, _("Compiling scenario list."));
119}
120
121/**********************************************************************/
128
129/**********************************************************************/
137
138/**********************************************************************/
141static void open_settings(void)
142{
143 option_dialog_popup(_("Set local options"), client_optset);
144}
145
146/**********************************************************************/
149static void main_callback(GtkWidget *w, gpointer data)
150{
151 enum client_pages page = PAGE_MAIN;
152
153 if (client.conn.used) {
155 }
156 if (page != get_client_page()) {
157 set_client_page(page);
158 }
159}
160
161/**********************************************************************/
165{
166 static PangoLayout *layout;
168 static int width, height;
169 static bool left = FALSE;
171 struct sprite *intro = (struct sprite *)data;
172
173 cairo_set_source_surface(cr, intro->surface, 0, 0);
174 cairo_paint(cr);
175
176 if (!layout) {
177 char msgbuf[128];
178 const char *rev_ver;
179
181 desc = pango_font_description_from_string("Sans Bold 10");
184
186
187 if (rev_ver == NULL) {
188 /* TRANS: "version 2.6.0, gui-gtk-3.22 client" */
189 fc_snprintf(msgbuf, sizeof(msgbuf), _("%s%s, %s client"),
191 } else {
192 /* TRANS: "version 2.6.0
193 * commit: [modified] <git commit id>
194 * gui-gtk-3.22 client" */
195 fc_snprintf(msgbuf, sizeof(msgbuf), _("%s%s\ncommit: %s\n%s client"),
197 left = TRUE;
198 }
200
202 }
204
205 cairo_set_source_rgb(cr, 0, 0, 0);
206 cairo_move_to(cr, left ? 4 : allocation.width - width - 3,
207 allocation.height - height - 3);
209
210 cairo_set_source_rgb(cr, 1, 1, 1);
211 cairo_move_to(cr, left ? 3 : allocation.width - width - 4,
212 allocation.height - height - 4);
214
215 return TRUE;
216}
217
218/**********************************************************************/
221static void intro_free(GtkWidget *w, gpointer *data)
222{
223 struct sprite *intro = (struct sprite *)data;
224
226}
227
228/**********************************************************************/
232{
233 GtkWidget *widget, *vbox, *frame, *darea, *button, *table;
235 struct sprite *intro_in, *intro;
236 int width, height;
237 int sh;
238 int space_needed;
239
241
242 vbox = gtk_grid_new();
245 widget = vbox;
246
247 frame = gtk_frame_new(NULL);
248 g_object_set(frame, "margin", 18, NULL);
251 gtk_container_add(GTK_CONTAINER(vbox), frame);
252
255 sh = screen_height();
256
257 if (sh <= 0) {
258 /* Assume some minimum height */
259 sh = 600;
260 }
261
262 space_needed = 250;
263#if IS_BETA_VERSION || IS_DEVEL_VERSION
264 /* Alpha or Beta notice takes extra space */
265 space_needed += 50;
266#endif
267
268 if (sh - height < space_needed) {
269 float scale;
270
271 if (sh < (space_needed + 0.2 * height)) {
272 /* Screen is simply too small, use minimum scale */
273 scale = 0.2;
274 } else {
275 scale = (double)(sh - space_needed) / height;
276 }
277 height *= scale;
278 width *= scale;
281 } else {
282 intro = intro_in;
283 }
284 darea = gtk_drawing_area_new();
286 g_signal_connect(darea, "draw",
288 g_signal_connect(widget, "destroy",
290 gtk_container_add(GTK_CONTAINER(frame), darea);
291
292#if IS_BETA_VERSION || IS_DEVEL_VERSION
293 {
294 GtkWidget *label;
295
297 gtk_widget_set_name(label, "beta_label");
301 gtk_container_add(GTK_CONTAINER(vbox), label);
302 }
303#endif /* IS_BETA_VERSION || IS_DEVEL_VERSION */
304
306 g_object_set(table, "margin", 12, NULL);
311
315
316 button = gtk_button_new_with_mnemonic(_("Start _New Game"));
318 gtk_grid_attach(GTK_GRID(table), button, 0, 0, 1, 1);
320 _("Launches local server, and connects to it for a single-player game."));
321 g_signal_connect(button, "clicked",
323
324 button = gtk_button_new_with_mnemonic(_("Start _Scenario Game"));
326 gtk_grid_attach(GTK_GRID(table), button, 0, 1, 1, 1);
328 _("Loads one of the scenarios for a single-player game. "
329 "Tutorial is one of the scenarios."));
330 g_signal_connect(button, "clicked",
332
333 button = gtk_button_new_with_mnemonic(_("_Load Saved Game"));
335 gtk_grid_attach(GTK_GRID(table), button, 0, 2, 1, 1);
337 _("Continues previously saved single-player game."));
338 g_signal_connect(button, "clicked",
340
341 button = gtk_button_new_with_mnemonic(_("C_onnect to Network Game"));
343 gtk_grid_attach(GTK_GRID(table), button, 1, 0, 1, 1);
345 _("Connects to outside server. "
346 "Sometimes you want to launch a separate server even for local games."));
347 g_signal_connect(button, "clicked",
349
350 button = gtk_button_new_with_mnemonic(_("Client Settings"));
352 gtk_grid_attach(GTK_GRID(table), button, 1, 1, 1, 1);
354 _("Adjusting client-side options."));
355 g_signal_connect(button, "clicked", open_settings, NULL);
356
357 button = icon_label_button_new("application-exit", _("E_xit"));
360 gtk_grid_attach(GTK_GRID(table), button, 1, 2, 1, 1);
362 _("Gives you a break from playing freeciv."));
363 g_signal_connect(button, "clicked",
365
366 return widget;
367}
368
369/****************************************************************************
370 GENERIC SAVE DIALOG
371****************************************************************************/
372typedef void (*save_dialog_action_fn_t) (const char *filename);
373typedef struct fileinfo_list * (*save_dialog_files_fn_t) (void);
374
382
389
395
396/**********************************************************************/
400{
402 G_TYPE_STRING, /* SD_COL_PRETTY_NAME */
403 G_TYPE_STRING); /* SD_COL_FULL_PATH */
404}
405
406/**********************************************************************/
410 const struct fileinfo_list *files)
411{
413
417 gtk_list_store_set(store, &iter,
419 SD_COL_FULL_PATH, pfile->fullname,
420 -1);
422}
423
424/**********************************************************************/
427static void save_dialog_update(struct save_dialog *pdialog)
428{
429 struct fileinfo_list *files;
430
431 fc_assert_ret(NULL != pdialog);
432
433 /* Update the store. */
434 files = pdialog->files();
437 files);
439}
440
441/**********************************************************************/
445 gint response, gpointer data)
446{
447 if (response == GTK_RESPONSE_OK) {
451 -1, NULL, NULL, NULL);
452
453 if (NULL != filename) {
454 action(filename);
455 g_free(filename);
456 }
457 }
459}
460
461/**********************************************************************/
485
486/**********************************************************************/
490 gpointer data)
491{
492 struct save_dialog *pdialog = data;
493
494 switch (response) {
495 case SD_RES_BROWSE:
496 save_dialog_file_chooser_popup(_("Select Location to Save"),
498 pdialog->action);
499 break;
500 case SD_RES_DELETE:
501 {
502 GtkTreeSelection *selection;
503 GtkTreeModel *model;
505 const gchar *full_path;
506
507 selection = gtk_tree_view_get_selection(pdialog->tree_view);
508 if (!gtk_tree_selection_get_selected(selection, &model, &iter)) {
509 return;
510 }
511
514 save_dialog_update(pdialog);
515 }
516 return;
517 case SD_RES_SAVE:
518 {
519 const char *text = gtk_entry_get_text(pdialog->entry);
520 gchar *filename = g_filename_from_utf8(text, -1, NULL, NULL, NULL);
521
522 if (NULL == filename) {
523 return;
524 }
525 pdialog->action(filename);
526 g_free(filename);
527 }
528 break;
529 default:
530 break;
531 }
533}
534
535/**********************************************************************/
545
546/**********************************************************************/
553
554/**********************************************************************/
558 gpointer data)
559{
560 struct save_dialog *pdialog = data;
561 GtkTreeModel *model;
563 const gchar *filename;
564
565 if (!gtk_tree_selection_get_selected(selection, &model, &iter)) {
567 return;
568 }
569
571 gtk_tree_model_get(model, &iter, SD_COL_PRETTY_NAME, &filename, -1);
572 gtk_entry_set_text(pdialog->entry, filename);
573}
574
575/**********************************************************************/
578static GtkWidget *save_dialog_new(const char *title, const char *savelabel,
579 const char *savefilelabel,
582{
583 GtkWidget *shell, *sbox, *sw, *label, *view, *entry;
584 GtkContainer *vbox;
585 GtkListStore *store;
587 GtkTreeSelection *selection;
588 struct save_dialog *pdialog;
589
592
593 /* Save dialog structure. */
594 pdialog = fc_malloc(sizeof(*pdialog));
595 pdialog->action = action;
596 pdialog->files = files;
597
598 /* Shell. */
600 _("_Browse..."), SD_RES_BROWSE,
601 _("_Delete"), SD_RES_DELETE,
602 _("_Cancel"), GTK_RESPONSE_CANCEL,
603 _("_Save"), SD_RES_SAVE,
604 NULL);
605 g_object_set_data_full(G_OBJECT(shell), "save_dialog", pdialog,
610 g_signal_connect(shell, "response",
612 pdialog->shell = GTK_DIALOG(shell);
614
615 /* Tree view. */
616 store = save_dialog_store_new();
620 g_object_unref(store);
622 g_signal_connect(view, "row-activated",
624 pdialog->tree_view = GTK_TREE_VIEW(view);
625
626 sbox = gtk_grid_new();
630 gtk_container_add(vbox, sbox);
631
633 "use-underline", TRUE,
634 "mnemonic-widget", view,
635 "label", savelabel,
636 "xalign", 0.0,
637 "yalign", 0.5,
638 NULL);
640
650
653 g_signal_connect(selection, "changed",
655
658 -1, NULL, rend, "text",
660
661 /* Entry. */
664 g_signal_connect(entry, "activate",
666 pdialog->entry = GTK_ENTRY(entry);
667
668 sbox = gtk_grid_new();
669 g_object_set(sbox, "margin", 12, NULL);
673
675 "use-underline", TRUE,
676 "mnemonic-widget", entry,
677 "label", savefilelabel,
678 "xalign", 0.0,
679 "yalign", 0.5,
680 NULL);
682
684 gtk_container_add(vbox, sbox);
685
686 save_dialog_update(pdialog);
689 return shell;
690}
691
692/****************************************************************************
693 NETWORK PAGE
694****************************************************************************/
700
701/**********************************************************************/
705 const struct server_list *list)
706{
709 GtkTreeIter it;
710 GtkListStore *store;
711 const gchar *host, *portstr;
712 int port;
713
714 switch (sstype) {
717 break;
720 break;
721 default:
722 break;
723 }
724
725 if (!sel) {
726 return;
727 }
728
732
733 if (!list) {
734 return;
735 }
736
739 port = atoi(portstr);
740
742 char buf[35];
743
744 if (pserver->humans >= 0) {
745 fc_snprintf(buf, sizeof(buf), "%d", pserver->humans);
746 } else {
747 sz_strlcpy(buf, _("Unknown"));
748 }
749 gtk_list_store_append(store, &it);
750 gtk_list_store_set(store, &it,
751 0, pserver->host,
752 1, pserver->port,
753 2, pserver->version,
754 3, _(pserver->state),
755 4, pserver->nplayers,
756 5, buf,
757 6, pserver->message,
758 -1);
759 if (strcmp(host, pserver->host) == 0 && port == pserver->port) {
761 }
763}
764
765/**********************************************************************/
769{
770 if (meta_scan.scan) {
773 }
774 if (meta_scan.timer != 0) {
776 meta_scan.timer = 0;
777 }
778 if (lan_scan.scan) {
781 }
782 if (lan_scan.timer != 0) {
784 lan_scan.timer = 0;
785 }
786}
787
788/**********************************************************************/
792{
793 struct server_scan_timer_data *scan_data = data;
794 struct server_scan *scan = scan_data->scan;
796
797 if (!scan) {
798 return FALSE;
799 }
800
801 stat = server_scan_poll(scan);
802 if (stat >= SCAN_STATUS_PARTIAL) {
804 struct srv_list *srvrs;
805
807 srvrs = server_scan_get_list(scan);
808 fc_mutex_allocate(&srvrs->mutex);
812 fc_mutex_release(&srvrs->mutex);
813 }
814
816 scan_data->timer = 0;
817 return FALSE;
818 }
819 return TRUE;
820}
821
822/**********************************************************************/
825static void server_scan_error(struct server_scan *scan,
826 const char *message)
827{
829 log_error("%s", message);
830
831 /* Main thread will finalize the scan later (or even concurrently) -
832 * do not do anything here to cause double free or raze condition. */
833}
834
835/**********************************************************************/
848
849/**************************************************************************
850 Network connection state defines.
851**************************************************************************/
858
860
861/**********************************************************************/
865{
867 char *txt;
868
871 free(txt);
872 }
873
874 return TRUE;
875}
876
877/**********************************************************************/
880static void clear_network_statusbar(void)
881{
883 char *txt;
884
886 free(txt);
887 }
889}
890
891/**********************************************************************/
894void append_network_statusbar(const char *text, bool force)
895{
897 if (force) {
900 } else {
902 }
903 }
904}
905
906/**********************************************************************/
926
927/**********************************************************************/
931{
932 switch (state) {
933 case LOGIN_TYPE:
935
938
947 break;
952
961
963 break;
968
977
979 break;
980 case WAITING_TYPE:
982
989 break;
990 }
991
992 connection_status = state;
993}
994
995/**********************************************************************/
998static void connection_state_reset(void)
999{
1001}
1002
1003/**********************************************************************/
1008 const char *message)
1009{
1011
1012 switch (type) {
1013 case AUTH_NEWUSER_FIRST:
1014 case AUTH_NEWUSER_RETRY:
1016 return;
1017 case AUTH_LOGIN_FIRST:
1018 /* if we magically have a password already present in 'fc_password'
1019 * then, use that and skip the password entry dialog */
1020 if (fc_password[0] != '\0') {
1022
1023 sz_strlcpy(reply.password, fc_password);
1025 return;
1026 } else {
1028 }
1029 return;
1030 case AUTH_LOGIN_RETRY:
1032 return;
1033 }
1034
1035 log_error("Unsupported authentication type %d: %s.", type, message);
1036}
1037
1038/**********************************************************************/
1044{
1045 char errbuf [512];
1047
1048 switch (connection_status) {
1049 case LOGIN_TYPE:
1053
1055 errbuf, sizeof(errbuf)) != -1) {
1056 } else {
1058
1060 }
1061 return;
1062 case NEW_PASSWORD_TYPE:
1063 if (w != network_password) {
1066 sz_strlcpy(reply.password,
1068 if (!fc_strncmp(reply.password, fc_password, MAX_LEN_NAME)) {
1069 fc_password[0] = '\0';
1071
1073 } else {
1074 append_network_statusbar(_("Passwords don't match, enter password."),
1075 TRUE);
1076
1078 }
1079 }
1080 return;
1082 sz_strlcpy(reply.password,
1085
1087 return;
1088 case WAITING_TYPE:
1089 return;
1090 }
1091
1092 log_error("Unsupported connection status: %d", connection_status);
1093}
1094
1095/**********************************************************************/
1101 gpointer data)
1102{
1103 connect_callback(NULL, data);
1104}
1105
1106/**********************************************************************/
1110static void update_server_playerlist(const struct server *pserver)
1111{
1112 GtkListStore *store;
1114 int n, i;
1115
1117 fc_assert_ret(store != NULL);
1118
1119 gtk_list_store_clear(store);
1120 if (!pserver || !pserver->players) {
1121 return;
1122 }
1123
1124 n = pserver->nplayers;
1125 for (i = 0; i < n; i++) {
1126 gtk_list_store_append(store, &iter);
1127 gtk_list_store_set(store, &iter,
1128 0, pserver->players[i].name,
1129 1, pserver->players[i].type,
1130 2, pserver->players[i].host,
1131 3, pserver->players[i].nation,
1132 -1);
1133 }
1134}
1135
1136/**********************************************************************/
1140{
1141 GtkTreeModel *model;
1142 GtkTreeIter it;
1143 const char *host;
1144 int port;
1145 char portstr[32];
1146 const struct server *pserver = NULL;
1147
1148 if (!gtk_tree_selection_get_selected(select, &model, &it)) {
1149 return;
1150 }
1151
1152 if (select == meta_selection) {
1153 GtkTreePath *path;
1154 struct srv_list *srvrs;
1155
1157 path = gtk_tree_model_get_path(model, &it);
1159 /* We are not yet inside mutex protected block */
1160 fc_mutex_allocate(&srvrs->mutex);
1161 }
1162 if (srvrs->servers && path) {
1164
1166 }
1168 /* We are not yet inside mutex protected block */
1169 fc_mutex_release(&srvrs->mutex);
1170 }
1171 gtk_tree_path_free(path);
1172 }
1174
1175 gtk_tree_model_get(model, &it, 0, &host, 1, &port, -1);
1176
1178 fc_snprintf(portstr, sizeof(portstr), "%d", port);
1180}
1181
1182/**********************************************************************/
1197
1198/**********************************************************************/
1202{
1203 GtkWidget *box, *sbox, *bbox, *hbox, *notebook;
1204 GtkWidget *button, *label, *view, *sw, *table;
1205 GtkTreeSelection *selection;
1206 GtkListStore *store;
1207
1208 box = gtk_grid_new();
1212
1213 notebook = gtk_notebook_new();
1214 gtk_container_add(GTK_CONTAINER(box), notebook);
1215
1216 /* LAN pane. */
1218 G_TYPE_INT, /* port */
1219 G_TYPE_STRING, /* version */
1220 G_TYPE_STRING, /* state */
1221 G_TYPE_INT, /* nplayers */
1222 G_TYPE_STRING, /* humans */
1223 G_TYPE_STRING); /* message */
1224
1230
1232 lan_selection = selection;
1234 g_signal_connect(view, "focus",
1236 g_signal_connect(view, "row-activated",
1238 g_signal_connect(selection, "changed",
1240
1241 add_treeview_column(view, _("Server Name"), G_TYPE_STRING, 0);
1242 add_treeview_column(view, _("Port"), G_TYPE_INT, 1);
1243 add_treeview_column(view, _("Version"), G_TYPE_STRING, 2);
1244 add_treeview_column(view, _("Status"), G_TYPE_STRING, 3);
1245 add_treeview_column(view, _("Players"), G_TYPE_INT, 4);
1246 add_treeview_column(view, _("Humans"), G_TYPE_STRING, 5);
1247 add_treeview_column(view, _("Comment"), G_TYPE_STRING, 6);
1248
1249 label = gtk_label_new_with_mnemonic(_("Local _Area Network"));
1250
1258 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), sw, label);
1259
1260
1261 /* Metaserver pane. */
1263 G_TYPE_INT, /* port */
1264 G_TYPE_STRING, /* version */
1265 G_TYPE_STRING, /* state */
1266 G_TYPE_INT, /* nplayers */
1267 G_TYPE_STRING, /* humans */
1268 G_TYPE_STRING); /* message */
1269
1275
1277 meta_selection = selection;
1279 g_signal_connect(view, "focus",
1281 g_signal_connect(view, "row-activated",
1283 g_signal_connect(selection, "changed",
1285
1286 add_treeview_column(view, _("Server Name"), G_TYPE_STRING, 0);
1287 add_treeview_column(view, _("Port"), G_TYPE_INT, 1);
1288 add_treeview_column(view, _("Version"), G_TYPE_STRING, 2);
1289 add_treeview_column(view, _("Status"), G_TYPE_STRING, 3);
1290 add_treeview_column(view, _("Players"), G_TYPE_INT, 4);
1291 add_treeview_column(view, _("Humans"), G_TYPE_STRING, 5);
1292 add_treeview_column(view, _("Comment"), G_TYPE_STRING, 6);
1293
1294 label = gtk_label_new_with_mnemonic(_("Internet _Metaserver"));
1295
1304 gtk_notebook_prepend_page(GTK_NOTEBOOK(notebook), sw, label);
1305 } else {
1306 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), sw, label);
1307 }
1308
1309 /* Bottom part of the page, outside the inner notebook. */
1310 sbox = gtk_grid_new();
1314
1315 hbox = gtk_grid_new();
1317 g_object_set(hbox, "margin", 8, NULL);
1319
1320 table = gtk_grid_new();
1324
1326 g_signal_connect(network_host, "activate",
1329
1331 "use-underline", TRUE,
1332 "mnemonic-widget", network_host,
1333 "label", _("_Host:"),
1334 "xalign", 0.0,
1335 "yalign", 0.5,
1336 NULL);
1337 network_host_label = label;
1338 gtk_grid_attach(GTK_GRID(table), label, 0, 0, 1, 1);
1339
1341 g_signal_connect(network_port, "activate",
1344
1346 "use-underline", TRUE,
1347 "mnemonic-widget", network_port,
1348 "label", _("_Port:"),
1349 "xalign", 0.0,
1350 "yalign", 0.5,
1351 NULL);
1352 network_port_label = label;
1353 gtk_grid_attach(GTK_GRID(table), label, 0, 1, 1, 1);
1354
1357 g_signal_connect(network_login, "activate",
1360
1362 "use-underline", TRUE,
1363 "mnemonic-widget", network_login,
1364 "label", _("_Login:"),
1365 "xalign", 0.0,
1366 "yalign", 0.5,
1367 NULL);
1368 gtk_widget_set_margin_top(label, 10);
1369 network_login_label = label;
1370 gtk_grid_attach(GTK_GRID(table), label, 0, 3, 1, 1);
1371
1377
1379 "use-underline", TRUE,
1380 "mnemonic-widget", network_password,
1381 "label", _("Pass_word:"),
1382 "xalign", 0.0,
1383 "yalign", 0.5,
1384 NULL);
1385 network_password_label = label;
1386 gtk_grid_attach(GTK_GRID(table), label, 0, 4, 1, 1);
1387
1393
1395 "use-underline", TRUE,
1396 "mnemonic-widget", network_confirm_password,
1397 "label", _("Conf_irm Password:"),
1398 "xalign", 0.0,
1399 "yalign", 0.5,
1400 NULL);
1402 gtk_grid_attach(GTK_GRID(table), label, 0, 5, 1, 1);
1403
1404 /* Server player list. */
1410
1416 add_treeview_column(view, _("Nation"), G_TYPE_STRING, 3);
1418
1426
1427
1429 g_object_set(bbox, "margin", 2, NULL);
1433
1434 button = gtk_button_new_from_icon_name("view-refresh", GTK_ICON_SIZE_BUTTON);
1437 g_signal_connect(button, "clicked",
1439
1440 button = gtk_button_new_with_mnemonic(_("_Cancel"));
1442 g_signal_connect(button, "clicked",
1444
1445 button = gtk_button_new_with_mnemonic(_("C_onnect"));
1447 g_signal_connect(button, "clicked",
1449
1450 return box;
1451}
1452
1453
1454/****************************************************************************
1455 START PAGE
1456****************************************************************************/
1458
1465
1466
1467/* NB: Must match creation arguments in connection_list_store_new(). */
1484
1485/**********************************************************************/
1489{
1491 G_TYPE_INT, /* CL_COL_PLAYER_NUMBER */
1492 G_TYPE_STRING, /* CL_COL_USER_NAME */
1493 G_TYPE_BOOLEAN, /* CL_COL_READY_STATE */
1494 G_TYPE_STRING, /* CL_COL_PLAYER_NAME */
1495 GDK_TYPE_PIXBUF, /* CL_COL_FLAG */
1496 GDK_TYPE_PIXBUF, /* CL_COL_COLOR */
1497 G_TYPE_STRING, /* CL_COL_NATION */
1498 G_TYPE_STRING, /* CL_COL_TEAM */
1499 G_TYPE_INT, /* CL_COL_CONN_ID */
1500 G_TYPE_INT, /* CL_COL_STYLE */
1501 G_TYPE_INT, /* CL_COL_WEIGHT */
1502 G_TYPE_BOOLEAN); /* CL_COL_COLLAPSED */
1503}
1504
1505/**********************************************************************/
1509static void client_aitoggle_player(void *data)
1510{
1511 struct player *pplayer = player_by_number(FC_PTR_TO_INT(data));
1512
1513 if (NULL != pplayer
1514 && pplayer == client_player()
1515 && !is_human(pplayer)) {
1516 send_chat("/away");
1517 }
1518}
1519
1520/**********************************************************************/
1523static void client_take_player(struct player *pplayer)
1524{
1525 int request_id = send_chat_printf("/take \"%s\"", player_name(pplayer));
1526 void *data = FC_INT_TO_PTR(player_number(pplayer));
1527
1530}
1531
1532/**********************************************************************/
1535static void object_put(GObject *object, struct player *pplayer,
1536 struct connection *pconn)
1537{
1538 /* Note that passing -1 to GINT_TO_POINTER() is buggy with some versions
1539 * of gcc. player_slot_count() is not a valid player number. 0 is not
1540 * a valid connection id (see comment in server/sernet.c:
1541 * makeup_connection_name()). */
1542 g_object_set_data(object, "player_id",
1543 GINT_TO_POINTER(NULL != pplayer
1544 ? player_number(pplayer)
1545 : player_slot_count()));
1546 g_object_set_data(object, "connection_id",
1547 GINT_TO_POINTER(NULL != pconn ? pconn->id : 0));
1548}
1549
1550/**********************************************************************/
1554static bool object_extract(GObject *object, struct player **ppplayer,
1555 struct connection **ppconn)
1556{
1557 bool ret = FALSE;
1558 int id;
1559
1560 if (NULL != ppplayer) {
1561 id = GPOINTER_TO_INT(g_object_get_data(object, "player_id"));
1563 if (NULL != *ppplayer) {
1564 ret = TRUE;
1565 }
1566 }
1567 if (NULL != ppconn) {
1568 id = GPOINTER_TO_INT(g_object_get_data(object, "connection_id"));
1569 *ppconn = conn_by_number(id);
1570 if (NULL != *ppconn) {
1571 ret = TRUE;
1572 }
1573 }
1574
1575 return ret;
1576}
1577
1578/**********************************************************************/
1582{
1583 option_dialog_popup(_("Game Settings"), server_optset);
1584}
1585
1586/**********************************************************************/
1590{
1591 enum ai_level *levels = (enum ai_level *)data;
1592 const char *name;
1593 int i;
1594
1596
1597 if (i != -1) {
1598 enum ai_level level = levels[i];
1599
1600 /* Suppress changes provoked by server rather than local user */
1601 if (server_ai_level() != level) {
1603 send_chat_printf("/%s", name);
1604 }
1605 }
1606}
1607
1608/* HACK: sometimes when creating the ruleset combo the value is set without
1609 * the user's control. In this case we don't want to do a /read. */
1611
1612/**********************************************************************/
1615static void ruleset_selected(const char *name)
1616{
1617 if (name && name[0] != '\0' && !no_ruleset_callback) {
1619 }
1620}
1621
1622/**********************************************************************/
1628{
1629 const char *name = NULL;
1630
1632
1633 if (name != NULL) {
1635 }
1636}
1637
1638/**********************************************************************/
1649
1650/**********************************************************************/
1654{
1655 if (start_aifill_spin) {
1656 bool old = send_new_aifill_to_server;
1657
1658 /* Suppress callback from this change to avoid a loop. */
1660 /* HACK: this GUI control doesn't have quite the same semantics as the
1661 * server 'aifill' option, in that it claims to represent the minimum
1662 * number of players _including humans_. The GUI control has a minimum
1663 * value of 1, so aifill == 0 will not be represented correctly.
1664 * But there's generally exactly one human player because the control
1665 * only shows up for a locally spawned server, so we more or less
1666 * get away with this. */
1669 }
1670}
1671
1672/**********************************************************************/
1676{
1678}
1679
1680/**********************************************************************/
1683static void conn_menu_team_chosen(GObject *object, gpointer data)
1684{
1685 struct player *pplayer;
1686 struct team_slot *tslot = data;
1687
1688 if (object_extract(object, &pplayer, NULL)
1689 && NULL != tslot
1690 && team_slot_index(tslot) != team_number(pplayer->team)) {
1691 send_chat_printf("/team \"%s\" \"%s\"",
1692 player_name(pplayer),
1694 }
1695}
1696
1697/**********************************************************************/
1700static void conn_menu_ready_chosen(GObject *object, gpointer data)
1701{
1702 struct player *pplayer;
1703
1704 if (object_extract(object, &pplayer, NULL)) {
1706 player_number(pplayer), !pplayer->is_ready);
1707 }
1708}
1709
1710/**********************************************************************/
1713static void conn_menu_nation_chosen(GObject *object, gpointer data)
1714{
1715 struct player *pplayer;
1716
1717 if (object_extract(object, &pplayer, NULL)) {
1718 popup_races_dialog(pplayer);
1719 }
1720}
1721
1722/**********************************************************************/
1727{
1728 struct player *pplayer;
1729
1730 if (object_extract(object, &pplayer, NULL)) {
1731 send_chat_printf("/%s \"%s\"",
1732 (char *) g_object_get_data(G_OBJECT(data), "command"),
1733 player_name(pplayer));
1734 }
1735}
1736
1737/**********************************************************************/
1740static void conn_menu_player_take(GObject *object, gpointer data)
1741{
1742 struct player *pplayer;
1743
1744 if (object_extract(object, &pplayer, NULL)) {
1745 client_take_player(pplayer);
1746 }
1747}
1748
1749/**********************************************************************/
1754{
1755 struct connection *pconn;
1756
1757 if (object_extract(object, NULL, &pconn)) {
1758 send_chat_printf("/%s \"%s\"",
1759 (char *) g_object_get_data(G_OBJECT(data), "command"),
1760 pconn->username);
1761 }
1762}
1763
1764/**********************************************************************/
1767static void show_conn_popup(struct player *pplayer, struct connection *pconn)
1768{
1770 char buf[4096] = "";
1771
1772 if (pconn) {
1773 cat_snprintf(buf, sizeof(buf), _("Connection name: %s"),
1774 pconn->username);
1775 } else {
1776 cat_snprintf(buf, sizeof(buf), _("Player name: %s"),
1777 player_name(pplayer));
1778 }
1779 cat_snprintf(buf, sizeof(buf), "\n");
1780 if (pconn) {
1781 cat_snprintf(buf, sizeof(buf), _("Host: %s"), pconn->addr);
1782 }
1783 cat_snprintf(buf, sizeof(buf), "\n");
1784
1785 /* Show popup. */
1788 "%s", buf);
1789 gtk_window_set_title(GTK_WINDOW(popup), _("Player/conn info"));
1793}
1794
1795/**********************************************************************/
1798static void conn_menu_info_chosen(GObject *object, gpointer data)
1799{
1800 struct player *pplayer;
1801 struct connection *pconn;
1802
1803 if (object_extract(object, &pplayer, &pconn)) {
1804 show_conn_popup(pplayer, pconn);
1805 }
1806}
1807
1808/**********************************************************************/
1812static GtkWidget *create_conn_menu(struct player *pplayer,
1813 struct connection *pconn)
1814{
1815 GtkWidget *menu;
1816 GtkWidget *item;
1817 gchar *buf;
1818
1819 menu = gtk_menu_new();
1820 object_put(G_OBJECT(menu), pplayer, pconn);
1821
1822 buf = g_strdup_printf(_("%s info"),
1823 pconn ? pconn->username : player_name(pplayer));
1825 g_free(buf);
1827 g_signal_connect_swapped(item, "activate",
1829
1830 if (NULL != pplayer) {
1831 item = gtk_menu_item_new_with_label(_("Toggle player ready"));
1834 g_signal_connect_swapped(item, "activate",
1836
1837 item = gtk_menu_item_new_with_label(_("Pick nation"));
1840 pplayer));
1842 g_signal_connect_swapped(item, "activate",
1844
1845 item = gtk_menu_item_new_with_label(_("Observe this player"));
1847 g_object_set_data_full(G_OBJECT(item), "command", g_strdup("observe"),
1849 g_signal_connect_swapped(item, "activate",
1851
1852 item = gtk_menu_item_new_with_label(_("Take this player"));
1854 g_signal_connect_swapped(item, "activate",
1856 }
1857
1859 && (pconn->id != client.conn.id || NULL != pplayer)) {
1862
1863 if (pconn->id != client.conn.id) {
1864 item = gtk_menu_item_new_with_label(_("Cut connection"));
1866 g_object_set_data_full(G_OBJECT(item), "command", g_strdup("cut"),
1868 g_signal_connect_swapped(item, "activate",
1870 menu);
1871 }
1872 }
1873
1874 if (ALLOW_CTRL <= client.conn.access_level && NULL != pplayer) {
1875 item = gtk_menu_item_new_with_label(_("Aitoggle player"));
1877 g_object_set_data_full(G_OBJECT(item), "command", g_strdup("aitoggle"),
1879 g_signal_connect_swapped(item, "activate",
1881
1882 if (pplayer != client.conn.playing && game.info.is_new_game) {
1883 item = gtk_menu_item_new_with_label(_("Remove player"));
1885 g_object_set_data_full(G_OBJECT(item), "command", g_strdup("remove"),
1887 g_signal_connect_swapped(item, "activate",
1889 }
1890 }
1891
1893 && pconn->id != client.conn.id) {
1894 enum cmdlevel level;
1895
1896 /* No item for hack access; that would be a serious security hole. */
1898 /* TRANS: Give access level to a connection. */
1899 buf = g_strdup_printf(_("Give %s access"),
1902 g_free(buf);
1905 g_strdup_printf("cmdlevel %s",
1908 g_signal_connect_swapped(item, "activate",
1910 menu);
1911 }
1912 }
1913
1915 && NULL != pplayer && is_ai(pplayer)) {
1916 enum ai_level level;
1917
1920
1921 for (level = 0; level < AI_LEVEL_COUNT; level++) {
1924 const char *level_cmd = ai_level_cmd(level);
1925
1930 g_signal_connect_swapped(item, "activate",
1932 }
1933 }
1934 }
1935
1936 if (pplayer && game.info.is_new_game) {
1937 const int count = pplayer->team
1938 ? player_list_size(team_members(pplayer->team)) : 0;
1939 bool need_empty_team = (count != 1);
1940
1943
1944 /* Can't use team_iterate here since it skips empty teams. */
1946 if (!team_slot_is_used(tslot)) {
1947 if (!need_empty_team) {
1948 continue;
1949 }
1951 }
1952
1953 /* TRANS: e.g., "Put on Team 5" */
1954 buf = g_strdup_printf(_("Put on %s"),
1957 g_free(buf);
1959 object_put(G_OBJECT(item), pplayer, NULL);
1961 tslot);
1963 }
1964
1965 gtk_widget_show_all(menu);
1966
1967 return menu;
1968}
1969
1970/**********************************************************************/
1974{
1975 if (NULL != connection_list_view) {
1976 GtkTreeSelection *selection =
1978 GtkTreePath *path = data;
1979
1980 gtk_tree_selection_unselect_path(selection, path);
1981 gtk_tree_path_free(path);
1982 }
1983 return FALSE;
1984}
1985
1986/**********************************************************************/
1991 gpointer data)
1992{
1994 GtkTreePath *path = NULL;
1996 gboolean ret = FALSE;
1997
1998 if ((1 != event->button && 3 != event->button)
1999 || GDK_BUTTON_PRESS != event->type
2001 event->x, event->y,
2002 &path, NULL, NULL, NULL)) {
2003 return FALSE;
2004 }
2005
2006 if (1 == event->button) {
2007 if (gtk_tree_selection_path_is_selected(selection, path)) {
2008 /* Need to delay to avoid problem with the expander. */
2010 return FALSE; /* Return now, don't free the path. */
2011 }
2012 } else if (3 == event->button) {
2015 GtkWidget *menu;
2016 int player_no, conn_id;
2017 struct player *pplayer;
2018 struct connection *pconn;
2019
2020 if (!gtk_tree_selection_path_is_selected(selection, path)) {
2021 gtk_tree_selection_select_path(selection, path);
2022 }
2023 gtk_tree_model_get_iter(model, &iter, path);
2024
2025 gtk_tree_model_get(model, &iter, CL_COL_PLAYER_NUMBER, &player_no, -1);
2026 pplayer = player_by_number(player_no);
2027
2028 gtk_tree_model_get(model, &iter, CL_COL_CONN_ID, &conn_id, -1);
2029 pconn = conn_by_number(conn_id);
2030
2031 menu = create_conn_menu(pplayer, pconn);
2033 ret = TRUE;
2034 }
2035
2036 gtk_tree_path_free(path);
2037 return ret;
2038}
2039
2040/**********************************************************************/
2045 GtkTreePath *path,
2046 gpointer data)
2047{
2049
2050 gtk_tree_store_set(store, iter,
2052}
2053
2054/**********************************************************************/
2059 struct connection **ppconn)
2060{
2061 if (NULL != connection_list_view) {
2063 GtkTreeModel *model;
2064 GtkTreeSelection *selection =
2066
2067 if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
2068 int id;
2069
2070 if (NULL != ppplayer) {
2071 gtk_tree_model_get(model, &iter, CL_COL_PLAYER_NUMBER, &id, -1);
2073 }
2074 if (NULL != ppconn) {
2075 gtk_tree_model_get(model, &iter, CL_COL_CONN_ID, &id, -1);
2076 *ppconn = conn_by_number(id);
2077 }
2078 return TRUE;
2079 }
2080 }
2081
2082 if (NULL != ppplayer) {
2083 *ppplayer = NULL;
2084 }
2085 if (NULL != ppconn) {
2086 *ppconn = NULL;
2087 }
2088 return FALSE;
2089}
2090
2091/**********************************************************************/
2095{
2096 GtkTreeModel *model;
2097 GtkTreeIter parent, child, *iter = NULL;
2098 GtkTreeSelection *selection;
2099 gboolean valid;
2100 const int search_id = pconn->id;
2101 int id;
2102
2103 if (NULL == connection_list_view) {
2104 return;
2105 }
2106
2109
2110 /* Main iteration. */
2111 valid = gtk_tree_model_get_iter_first(model, &parent);
2112 while (valid && NULL == iter) {
2113 gtk_tree_model_get(model, &parent, CL_COL_CONN_ID, &id, -1);
2114 if (search_id == id) {
2115 iter = &parent;
2116 break;
2117 }
2118
2119 /* Node children iteration. */
2120 valid = gtk_tree_model_iter_children(model, &child, &parent);
2121 while (valid && NULL == iter) {
2122 gtk_tree_model_get(model, &child, CL_COL_CONN_ID, &id, -1);
2123 if (search_id == id) {
2124 iter = &child;
2125 break;
2126 }
2127 valid = gtk_tree_model_iter_next(model, &child);
2128 }
2129
2130 valid = gtk_tree_model_iter_next(model, &parent);
2131 }
2132
2133 /* Select iterator. */
2134 if (NULL != iter) {
2136 } else {
2137 log_error("%s(): connection %s not found.",
2139 }
2140}
2141
2142/**********************************************************************/
2146{
2147 if (can_client_control()) {
2150 !client_player()->is_ready);
2151 } else {
2153 }
2154}
2155
2156/**********************************************************************/
2160{
2161 struct player *selected_plr;
2162 bool row_selected = conn_list_selection(&selected_plr, NULL);
2163
2164 if (row_selected && NULL != selected_plr) {
2165 /* "Take <player_name>" */
2167 } else if (can_client_control()) {
2168 /* "Pick Nation" */
2170 } else {
2171 /* "Take a Player" */
2172 send_chat("/take -");
2173 }
2174}
2175
2176/**********************************************************************/
2180{
2181 struct player *selected_plr;
2182 bool row_selected = conn_list_selection(&selected_plr, NULL);
2183
2184 if (row_selected && NULL != selected_plr) {
2185 /* "Observe <player_name>" */
2186 send_chat_printf("/observe \"%s\"", player_name(selected_plr));
2187 } else if (!client_is_global_observer()) {
2188 /* "Observe" */
2189 send_chat("/observe");
2190 } else {
2191 /* "Do not observe" */
2192 send_chat("/detach");
2193 }
2194}
2195
2196/**********************************************************************/
2200{
2201 char buf[2 * MAX_LEN_NAME];
2202 const char *text;
2203 struct player *selected_plr;
2204 bool row_selected = conn_list_selection(&selected_plr, NULL);
2205 bool sensitive;
2206
2207 /*** Ready button. ***/
2208 if (can_client_control()) {
2209 sensitive = client_player()->is_alive;
2210 if (client_player()->is_ready) {
2211 text = _("Not _ready");
2212 } else {
2213 int num_unready = 0;
2214
2215 players_iterate_alive(pplayer) {
2216 if (is_human(pplayer) && !pplayer->is_ready) {
2217 num_unready++;
2218 }
2220
2221 if (num_unready > 1) {
2222 text = _("_Ready");
2223 } else {
2224 /* We are the last unready player so clicking here will
2225 * immediately start the game. */
2226 text = _("_Start");
2227 }
2228 }
2229 } else {
2230 text = _("_Start");
2231 if (can_client_access_hack()) {
2232 sensitive = TRUE;
2234 if (is_human(plr)) {
2235 /* There's human controlled player(s) in game, so it's their
2236 * job to start the game. */
2237 sensitive = FALSE;
2238 break;
2239 }
2241 } else {
2242 sensitive = FALSE;
2243 }
2244 }
2247
2248 /*** Nation button. ***/
2249 if (row_selected && NULL != selected_plr) {
2250 fc_snprintf(buf, sizeof(buf), _("_Take %s"), player_name(selected_plr));
2251 text = buf;
2253 } else if (can_client_control()) {
2254 text = _("Pick _Nation");
2256 } else {
2257 text = _("_Take a Player");
2259 }
2262
2263 /*** Observe button. ***/
2264 if (row_selected && NULL != selected_plr) {
2265 fc_snprintf(buf, sizeof(buf), _("_Observe %s"),
2267 text = buf;
2269 } else if (!client_is_global_observer()) {
2270 text = _("_Observe");
2271 sensitive = TRUE;
2272 } else {
2273 text = _("Do not _observe");
2274 sensitive = TRUE;
2275 }
2278}
2279
2280/**********************************************************************/
2286 GtkTreeIter *start,
2287 const struct player *pplayer)
2288{
2289 const int search_id = player_number(pplayer);
2290 int id;
2291
2292 if (NULL != start) {
2293 *iter = *start;
2294 if (!gtk_tree_model_iter_next(model, iter)) {
2295 return FALSE;
2296 }
2297 } else if (!gtk_tree_model_get_iter_first(model, iter)) {
2298 return FALSE;
2299 }
2300
2301 do {
2303 if (id == search_id) {
2304 return TRUE;
2305 }
2306 } while (gtk_tree_model_iter_next(model, iter));
2307
2308 return FALSE;
2309}
2310
2311/**********************************************************************/
2317 const struct connection *pconn)
2318{
2319 const int search_id = pconn->id;
2320 int id;
2321
2322 if (NULL != start) {
2323 *iter = *start;
2324 if (!gtk_tree_model_iter_next(model, iter)) {
2325 return FALSE;
2326 }
2327 } else if (!gtk_tree_model_iter_children(model, iter, parent)) {
2328 return FALSE;
2329 }
2330
2331 do {
2332 gtk_tree_model_get(model, iter, CL_COL_CONN_ID, &id, -1);
2333 if (id == search_id) {
2334 return TRUE;
2335 }
2336 } while (gtk_tree_model_iter_next(model, iter));
2337
2338 return FALSE;
2339}
2340
2341/**********************************************************************/
2345{
2350 GtkTreeModel *model = GTK_TREE_MODEL(store);
2351 GtkTreePath *path;
2354 GdkPixbuf *flag, *color;
2356 struct player *pselected_player;
2357 struct connection *pselected_conn;
2358 bool is_ready;
2359 const char *nation, *plr_name, *team;
2360 char name[MAX_LEN_NAME + 8];
2362 int conn_id;
2363
2364 /* Refresh the AI skill level control */
2365 if (ai_lvl_combobox) {
2366 enum ai_level new_level = server_ai_level(), level;
2367 int i = 0;
2368
2369 for (level = 0; level < AI_LEVEL_COUNT; level++) {
2371 if (level == new_level) {
2373 break;
2374 }
2375 i++;
2376 }
2377 }
2378 if (level == AI_LEVEL_COUNT) {
2379 /* Probably ai_level_invalid() */
2381 }
2382 }
2383
2384 /* Save the selected connection. */
2386
2387 /* Insert players into the connection list. */
2388 players_iterate(pplayer) {
2389 if (!player_has_flag(pplayer, PLRF_SCENARIO_RESERVED)) {
2390 conn_id = -1;
2392 flag = pplayer->nation ? get_flag(pplayer->nation) : NULL;
2393 color = create_player_icon(pplayer);
2394
2395 conn_list_iterate(pplayer->connections, pconn) {
2396 if (pconn->playing == pplayer && !pconn->observer) {
2397 conn_id = pconn->id;
2398 access_level = pconn->access_level;
2399 break;
2400 }
2402
2403 if (is_ai(pplayer) && !pplayer->was_created
2404 && !pplayer->is_connected) {
2405 /* TRANS: "<Novice AI>" */
2406 fc_snprintf(name, sizeof(name), _("<%s AI>"),
2407 ai_level_translated_name(pplayer->ai_common.skill_level));
2408 } else {
2409 sz_strlcpy(name, pplayer->username);
2410 if (access_level > ALLOW_BASIC) {
2411 sz_strlcat(name, "*");
2412 }
2413 }
2414
2415 is_ready = !is_human(pplayer) ? TRUE : pplayer->is_ready;
2416
2417 if (pplayer->nation == NO_NATION_SELECTED) {
2418 nation = _("Random");
2419 if (pplayer->was_created) {
2420 plr_name = player_name(pplayer);
2421 } else {
2422 plr_name = "";
2423 }
2424 } else {
2425 nation = nation_adjective_for_player(pplayer);
2426 plr_name = player_name(pplayer);
2427 }
2428
2429 team = pplayer->team ? team_name_translation(pplayer->team) : "";
2430
2431 if (model_get_player_iter(model, &parent, pprev_parent, pplayer)) {
2433 } else {
2435 }
2436
2437 gtk_tree_store_set(store, &parent,
2440 CL_COL_READY_STATE, is_ready,
2442 CL_COL_FLAG, flag,
2444 CL_COL_NATION, nation,
2446 CL_COL_CONN_ID, conn_id,
2449 -1);
2450
2451 /* Insert observers of this player as child nodes. */
2452 pprev_child = NULL;
2453 conn_list_iterate(pplayer->connections, pconn) {
2454 if (pconn->id == conn_id) {
2455 continue;
2456 }
2457 if (model_get_conn_iter(model, &child, &parent,
2458 pprev_child, pconn)) {
2459 gtk_tree_store_move_after(store, &child, pprev_child);
2460 } else {
2462 }
2463
2464 gtk_tree_store_set(store, &child,
2466 CL_COL_USER_NAME, pconn->username,
2467 CL_COL_TEAM, _("Observer"),
2468 CL_COL_CONN_ID, pconn->id,
2471 -1);
2472
2473 prev_child = child;
2476
2477 /* Expand node? */
2478 if (NULL != pprev_child) {
2480 if (!collapsed) {
2481 path = gtk_tree_model_get_path(model, &parent);
2483 path, FALSE);
2484 gtk_tree_path_free(path);
2485 }
2486 }
2487
2488 /* Remove trailing rows. */
2489 if (NULL != pprev_child) {
2490 child = prev_child;
2491 if (gtk_tree_model_iter_next(model, &child)) {
2492 while (gtk_tree_store_remove(store, &child)) {
2493 /* Do nothing more. */
2494 }
2495 }
2496 } else if (gtk_tree_model_iter_children(model, &child, &parent)) {
2497 while (gtk_tree_store_remove(store, &child)) {
2498 /* Do nothing more. */
2499 }
2500 }
2501
2504 if (flag) {
2505 g_object_unref(flag);
2506 }
2507 if (color) {
2509 }
2510 }
2512
2513 /* Finally, insert global observers... */
2515 if (NULL != pconn->playing || !pconn->observer) {
2516 continue;
2517 }
2518
2521 } else {
2523 }
2524
2525 gtk_tree_store_set(store, &parent,
2527 CL_COL_USER_NAME, pconn->username,
2528 CL_COL_TEAM, _("Observer"),
2529 CL_COL_CONN_ID, pconn->id,
2532 -1);
2533
2537
2538 /* ...and detached connections. */
2540 if (NULL != pconn->playing || pconn->observer) {
2541 continue;
2542 }
2543
2546 } else {
2548 }
2549
2550 gtk_tree_store_set(store, &parent,
2552 CL_COL_USER_NAME, pconn->username,
2553 CL_COL_TEAM, _("Detached"),
2554 CL_COL_CONN_ID, pconn->id,
2557 -1);
2558
2562
2563 /* Remove trailing rows. */
2564 if (NULL != pprev_parent) {
2566 if (gtk_tree_model_iter_next(model, &parent)) {
2567 while (gtk_tree_store_remove(store, &parent)) {
2568 /* Do nothing more. */
2569 }
2570 }
2571 } else {
2572 gtk_tree_store_clear(store);
2573 }
2574
2575 /* If we were selecting a single connection, let's try to reselect it. */
2578 }
2579 }
2580
2582}
2583
2584/**********************************************************************/
2590 const char *title, int colnum, const char *key)
2591{
2594
2595 if (gtype == G_TYPE_BOOLEAN) {
2598 "active", colnum, NULL);
2599 } else if (gtype == GDK_TYPE_PIXBUF) {
2602 "pixbuf", colnum, NULL);
2603 } else {
2606 "text", colnum,
2607 "style", CL_COL_STYLE,
2608 "weight", CL_COL_WEIGHT,
2609 NULL);
2610 }
2611
2614
2615 if (key != NULL) {
2617 }
2618}
2619
2620/**********************************************************************/
2624{
2625 GtkWidget *box, *sbox, *table, *vbox;
2626 GtkWidget *view, *sw, *text, *toolkit_view, *button, *spin;
2627 GtkWidget *label;
2628 GtkTreeSelection *selection;
2629 enum ai_level level;
2630 /* There's less than AI_LEVEL_COUNT entries as not all levels have
2631 entries (that's the whole point of this array: index != value),
2632 but this is set safely to the max */
2633 static enum ai_level levels[AI_LEVEL_COUNT];
2634 int i = 0;
2635
2636 box = gtk_grid_new();
2641
2642 sbox = gtk_grid_new();
2645
2646 vbox = gtk_grid_new();
2647 g_object_set(vbox, "margin", 12, NULL);
2654
2655 table = gtk_grid_new();
2660
2666 if (server_optset != NULL) {
2668 if (paifill) {
2671 } /* else it'll be updated later */
2672 }
2673 g_signal_connect_after(spin, "value_changed",
2675
2676 gtk_grid_attach(GTK_GRID(table), spin, 1, 0, 1, 1);
2677
2679 "use-underline", TRUE,
2680 "mnemonic-widget", spin,
2681 /* TRANS: Keep individual lines short */
2682 "label", _("Number of _Players\n(including AI):"),
2683 "xalign", 0.0,
2684 "yalign", 0.5,
2685 NULL);
2686 gtk_grid_attach(GTK_GRID(table), label, 0, 0, 1, 1);
2687
2689
2690 for (level = 0; level < AI_LEVEL_COUNT; level++) {
2693
2695 levels[i] = level;
2696 i++;
2697 }
2698 }
2701 G_CALLBACK(ai_skill_callback), levels);
2702
2704
2706 "use-underline", TRUE,
2707 "mnemonic-widget", ai_lvl_combobox,
2708 "label", _("AI Skill _Level:"),
2709 "xalign", 0.0,
2710 "yalign", 0.5,
2711 NULL);
2712 gtk_grid_attach(GTK_GRID(table), label, 0, 1, 1, 1);
2713
2717
2719
2721 "use-underline", TRUE,
2722 "mnemonic-widget", GTK_COMBO_BOX_TEXT(ruleset_combo),
2723 "label", _("Ruleset:"),
2724 "xalign", 0.0,
2725 "yalign", 0.5,
2726 NULL);
2727 gtk_grid_attach(GTK_GRID(table), label, 0, 2, 1, 1);
2728
2729 button = icon_label_button_new("preferences-system",
2730 _("_More Game Options..."));
2731 g_object_set(button, "margin", 8, NULL);
2734 g_signal_connect(button, "clicked",
2736 gtk_container_add(GTK_CONTAINER(vbox), button);
2737
2744
2747 g_signal_connect(selection, "changed",
2749
2750 add_tree_col(view, G_TYPE_STRING, _("Name"),
2752 add_tree_col(view, G_TYPE_BOOLEAN, _("Ready"),
2754 add_tree_col(view, G_TYPE_STRING, Q_("?player:Leader"),
2757 CL_COL_FLAG, NULL);
2758 add_tree_col(view, GDK_TYPE_PIXBUF, _("Border"),
2760 add_tree_col(view, G_TYPE_STRING, _("Nation"),
2762 add_tree_col(view, G_TYPE_STRING, _("Team"),
2763 CL_COL_TEAM, NULL);
2764
2765 g_signal_connect(view, "button-press-event",
2767 g_signal_connect(view, "row-collapsed",
2770 g_signal_connect(view, "row-expanded",
2773
2783
2784
2792
2796 start_message_area = text;
2797 gtk_widget_set_name(text, "chatline");
2802
2803
2804 /* Vote widgets. */
2805 if (pregame_votebar == NULL) {
2807 }
2809
2810
2813
2814 button = gtk_button_new_with_mnemonic(_("_Cancel"));
2816 g_signal_connect(button, "clicked", G_CALLBACK(main_callback), NULL);
2817
2818 nation_button = icon_label_button_new("document-properties",
2819 _("Pick _Nation"));
2823
2824 observe_button = icon_label_button_new("zoom-in", _("_Observe"));
2828
2829 ready_button = icon_label_button_new("system-run", _("_Ready"));
2831 g_signal_connect(ready_button, "clicked",
2833
2834 return box;
2835}
2836
2837
2838/**********************************************************************/
2841void handle_game_load(bool load_successful, const char *filename)
2842{
2843 if (load_successful) {
2845
2846 if (game.info.is_new_game) {
2847 /* It's pregame. Create a player and connect to it */
2848 send_chat("/take -");
2849 }
2850 }
2851}
2852
2853/**********************************************************************/
2856static void load_filename(const char *filename)
2857{
2858 send_chat_printf("/load %s", filename);
2859}
2860
2861/**********************************************************************/
2864static void load_callback(void)
2865{
2866 GtkTreeIter it;
2867 const gchar *filename;
2868
2870 return;
2871 }
2872
2874 SD_COL_FULL_PATH, &filename, -1);
2875 load_filename(filename);
2876}
2877
2878/**********************************************************************/
2882{
2883 save_dialog_file_chooser_popup(_("Choose Saved Game to Load"),
2886}
2887
2888/**********************************************************************/
2891static void update_load_page(void)
2892{
2893 /* Search for user saved games. */
2895 ".sav", FALSE);
2896
2898 fileinfo_list_destroy(files);
2899}
2900
2901/**********************************************************************/
2905{
2906 GtkWidget *box, *sbox, *bbox;
2907
2908 GtkWidget *button, *label, *view, *sw;
2910
2911 box = gtk_grid_new();
2916
2921
2924 -1, NULL, rend, "text", 0, NULL);
2925
2928
2930
2931 g_signal_connect(view, "row-activated",
2933
2934 sbox = gtk_grid_new();
2940
2942 "use-underline", TRUE,
2943 "mnemonic-widget", view,
2944 "label", _("Choose Saved Game to _Load:"),
2945 "xalign", 0.0,
2946 "yalign", 0.5,
2947 NULL);
2949
2958
2964
2965 button = gtk_button_new_with_mnemonic(_("_Browse..."));
2968 g_signal_connect(button, "clicked",
2970
2971 button = gtk_button_new_with_mnemonic(_("_Cancel"));
2973 g_signal_connect(button, "clicked",
2975
2976 button = gtk_button_new_with_mnemonic(_("_OK"));
2978 g_signal_connect(button, "clicked",
2980
2981 return box;
2982}
2983
2984/**********************************************************************/
2987static void scenario_list_callback(void)
2988{
2989 GtkTreeIter it;
2990 GtkTextBuffer *buffer;
2991 char *description;
2992 char *authors;
2993 char *filename;
2994 int ver;
2995 char vername[50];
2996
2999 2, &description, -1);
3001 3, &authors, -1);
3003 1, &filename, -1);
3005 4, &ver, -1);
3006 filename = skip_to_basename(filename);
3007 if (ver > 0) {
3008 int maj;
3009 int min;
3010
3011 maj = ver / 1000000;
3012 ver %= 1000000;
3013 min = ver / 10000;
3014 ver %= 10000;
3015 if (ver >= 9000) {
3016 /* Development version, have '+' */
3017 fc_snprintf(vername, sizeof(vername), "%d.%d+", maj, min);
3018 } else {
3019 fc_snprintf(vername, sizeof(vername), "%d.%d", maj, min);
3020 }
3021 } else {
3022 /* TRANS: Old scenario format version */
3023 fc_snprintf(vername, sizeof(vername), _("pre-2.6"));
3024 }
3025 } else {
3026 description = "";
3027 authors = "";
3028 filename = "";
3029 vername[0] = '\0';
3030 }
3031
3033 gtk_text_buffer_set_text(buffer, description, -1);
3035 gtk_text_buffer_set_text(buffer, authors, -1);
3038}
3039
3040/**********************************************************************/
3043static void scenario_callback(void)
3044{
3045 GtkTreeIter it;
3046 char *filename;
3047
3049 return;
3050 }
3051
3052 gtk_tree_model_get(GTK_TREE_MODEL(scenario_store), &it, 1, &filename, -1);
3053 load_filename(filename);
3054}
3055
3056/**********************************************************************/
3060{
3061 save_dialog_file_chooser_popup(_("Choose a Scenario"),
3064}
3065
3066/**********************************************************************/
3069static void update_scenario_page(void)
3070{
3071 struct fileinfo_list *files;
3072
3074
3075 /* search for scenario files. */
3076 files = fileinfolist_infix(get_scenario_dirs(), ".sav", TRUE);
3078 struct section_file *sf;
3079
3080 if ((sf = secfile_load_section(pfile->fullname, "scenario", TRUE))
3081 && secfile_lookup_bool_default(sf, TRUE, "scenario.is_scenario")) {
3082 const char *sname, *sdescription, *sauthors;
3083 int fcver;
3084 int fcdev;
3085 int current_ver = MAJOR_VERSION * 1000000 + MINOR_VERSION * 10000;
3086 int current_dev;
3087
3089 if (PATCH_VERSION >= 90) {
3090 /* Patch level matters on development versions */
3091 current_dev += PATCH_VERSION * 100;
3092 }
3093
3094 fcver = secfile_lookup_int_default(sf, 0, "scenario.game_version");
3095 if (fcver < 30000) {
3096 /* Pre-3.0 versions stored version number without emergency version
3097 * part in the end. To get comparable version number stored,
3098 * multiply by 100. */
3099 fcver *= 100;
3100 }
3101 if (fcver % 10000 >= 9000) {
3102 fcdev = fcver - (fcver % 100); /* Emergency version does not count. */
3103 } else {
3104 fcdev = fcver - (fcver % 10000); /* Patch version does not count. */
3105 }
3106 sname = secfile_lookup_str_default(sf, NULL, "scenario.name");
3108 "scenario.description");
3109 sauthors = secfile_lookup_str_default(sf, NULL, "scenario.authors");
3110 log_debug("scenario file: %s from %s", sname, pfile->fullname);
3111
3112 /* Ignore scenarios for newer freeciv versions than we are. */
3113 if (fcdev <= current_dev) {
3114 bool add_new = TRUE;
3115
3116 if (sname != NULL) {
3117 GtkTreeIter it;
3118 bool valid;
3119
3121 while (valid) {
3122 char *oname;
3123
3125 0, &oname, -1);
3126
3127 if (!strcmp(sname, oname)) {
3128 /* Already listed scenario has the same name as the one we just found */
3129 int existing;
3130
3132 4, &existing, -1);
3133 log_debug("Duplicate %s (%d vs %d)", sname, existing, fcver);
3134
3135 if (existing > fcver) {
3136 /* Already listed one has higher version number */
3137 add_new = FALSE;
3138 } else if (existing < fcver) {
3139 /* New one has higher version number */
3140 add_new = FALSE;
3141
3143 0, sname && strlen(sname) ? Q_(sname) : pfile->name,
3144 1, pfile->fullname,
3145 2, (NULL != sdescription && '\0' != sdescription[0]
3146 ? Q_(sdescription) : ""),
3147 3, (NULL != sauthors && sauthors[0] != '\0'
3148 ? Q_(sauthors) : ""),
3149 4, fcver,
3150 -1);
3151 } else {
3152 /* Same version number -> list both */
3153 }
3154 }
3156 }
3157 }
3158
3159 if (add_new) {
3160 GtkTreeIter it;
3161
3164 0, sname && strlen(sname) ? Q_(sname) : pfile->name,
3165 1, pfile->fullname,
3166 2, (NULL != sdescription && '\0' != sdescription[0]
3167 ? Q_(sdescription) : ""),
3168 3, (NULL != sauthors && sauthors[0] != '\0'
3169 ? Q_(sauthors) : ""),
3170 4, fcver,
3171 -1);
3172 }
3173 }
3174
3175 secfile_destroy(sf);
3176 }
3178
3179 fileinfo_list_destroy(files);
3180}
3181
3182/**********************************************************************/
3186{
3187 GtkWidget *vbox, *hbox, *sbox, *bbox, *filenamebox, *descbox;
3189 GtkWidget *button, *label, *view, *sw, *swa, *text;
3191
3192 vbox = gtk_grid_new();
3197
3202 G_TYPE_INT);
3207
3210 -1, NULL, rend, "text", 0, NULL);
3211
3216
3218
3219 g_signal_connect(view, "row-activated",
3221
3223 "use-underline", TRUE,
3224 "mnemonic-widget", view,
3225 "label", _("Choose a _Scenario:"),
3226 "xalign", 0.0,
3227 "yalign", 0.5,
3228 NULL);
3229 gtk_container_add(GTK_CONTAINER(vbox), label);
3230
3231 sbox = gtk_grid_new();
3238
3239 hbox = gtk_grid_new();
3242
3249 gtk_grid_attach(GTK_GRID(sbox), sw, 0, 0, 1, 2);
3250
3251 text = gtk_text_view_new();
3257 scenario_description = text;
3258
3265
3266 text = gtk_text_view_new();
3272 scenario_authors = text;
3273
3280
3281 text = gtk_label_new(_("Filename:"));
3286
3289 g_object_set(filenamebox, "margin", 5, NULL);
3290
3293
3294 /* TRANS: Scenario format version */
3295 vertext = gtk_label_new(_("Format:"));
3300
3303 g_object_set(versionbox, "margin", 5, NULL);
3304
3307
3316 gtk_grid_attach(GTK_GRID(sbox), descbox, 1, 0, 1, 2);
3317
3322
3323 button = gtk_button_new_with_mnemonic(_("_Browse..."));
3326 g_signal_connect(button, "clicked",
3328
3329 button = gtk_button_new_with_mnemonic(_("_Cancel"));
3331 g_signal_connect(button, "clicked",
3333
3334 button = gtk_button_new_with_mnemonic(_("_OK"));
3336 g_signal_connect(button, "clicked",
3338
3339 return vbox;
3340}
3341
3342/**********************************************************************/
3346{
3347 return current_page;
3348}
3349
3350/**********************************************************************/
3354{
3355 /* Don't use current_page directly here because maybe it could be modified
3356 * before we reach the end of this function. */
3358
3359 /* If the page remains the same, don't do anything. */
3360 if (old_page == new_page) {
3361 return;
3362 }
3363
3364 log_debug("Switching client page from %s to %s.",
3365 -1 == old_page ? "(no page)" : client_pages_name(old_page),
3367
3369
3370 switch (old_page) {
3371 case PAGE_SCENARIO:
3372 case PAGE_LOAD:
3373 break;
3374 case PAGE_GAME:
3375 {
3377
3379 if (vmode == NULL) {
3381 }
3382 }
3383 break;
3384 default:
3385 break;
3386 }
3387
3388 switch (new_page) {
3389 case PAGE_MAIN:
3390 case PAGE_START:
3391 if (is_server_running()) {
3392 if (game.info.is_new_game) {
3394 } else {
3396 }
3398 } else {
3400 }
3404 break;
3405 case PAGE_GAME:
3406 {
3408
3411 if (vmode == NULL) {
3413 }
3416 }
3417 break;
3418 case PAGE_LOAD:
3420 break;
3421 case PAGE_SCENARIO:
3423 break;
3424 case PAGE_NETWORK:
3426 break;
3427 }
3428
3429 /* hide/show statusbar. */
3430 if (new_page == PAGE_START || new_page == PAGE_GAME) {
3433 } else {
3435 }
3436
3438
3439 /* Update the GUI. */
3440 while (gtk_events_pending()) {
3442 }
3443
3444 switch (new_page) {
3445 case PAGE_MAIN:
3446 break;
3447 case PAGE_START:
3450 break;
3451 case PAGE_LOAD:
3453 break;
3454 case PAGE_SCENARIO:
3456 break;
3457 case PAGE_GAME:
3461 mapview_thaw();
3462 break;
3463 case PAGE_NETWORK:
3468 break;
3469 }
3470}
3471
3472/****************************************************************************
3473 SAVE GAME DIALOGs
3474****************************************************************************/
3475
3476/**********************************************************************/
3480{
3481 return fileinfolist_infix(get_save_dirs(), ".sav", FALSE);
3482}
3483
3484/**********************************************************************/
3488{
3489 static GtkWidget *shell = NULL;
3490
3491 if (NULL != shell) {
3492 return;
3493 }
3494
3495 shell = save_dialog_new(_("Save Game"), _("Saved _Games:"),
3496 _("Save _Filename:"), send_save_game,
3499 &shell);
3501}
3502
3503/**********************************************************************/
3506static void save_dialog_save_scenario(const char *filename)
3507{
3509}
3510
3511/**********************************************************************/
3515{
3516 return fileinfolist_infix(get_scenario_dirs(), ".sav", FALSE);
3517}
3518
3519/**********************************************************************/
3523{
3524 static GtkWidget *shell = NULL;
3525
3526 if (NULL != shell) {
3527 return;
3528 }
3529
3530 shell = save_dialog_new(_("Save Scenario"), _("Saved Sce_narios:"),
3531 _("Save Sc_enario:"), save_dialog_save_scenario,
3534 &shell);
3536}
3537
3538/**********************************************************************/
3544{
3545 return fileinfolist_infix(get_save_dirs(), ".map", FALSE);
3546}
3547
3548/**********************************************************************/
3552{
3553 static GtkWidget *shell = NULL;
3554
3555 if (NULL != shell) {
3556 return;
3557 }
3558
3559 shell = save_dialog_new(_("Save Map Image"), _("Saved Map _Images:"),
3560 _("Save _Map Images:"), mapimg_client_save,
3563 &shell);
3565}
3566
3567/**********************************************************************/
3570void mapimg_client_save(const char *filename)
3571{
3572 if (!mapimg_client_createmap(filename)) {
3573 char msg[512];
3574
3575 fc_snprintf(msg, sizeof(msg), "(%s)", mapimg_error());
3576 popup_notify_dialog(_("Error"),
3577 _("Error Creating the Map Image!"), msg);
3578 }
3579}
3580
3581/**********************************************************************/
3586void set_rulesets(int num_rulesets, char **rulesets)
3587{
3588 int i;
3589 int def_idx = -1;
3590
3592 for (i = 0; i < num_rulesets; i++) {
3593
3595 if (!strcmp("default", rulesets[i])) {
3596 def_idx = i;
3597 }
3598 }
3599
3601
3602 /* HACK: server should tell us the current ruleset. */
3604
3606}
#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:1518
bool mapimg_client_createmap(const char *filename)
Definition climisc.c:1465
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:75
authentication_type
Definition conn_types.h:41
@ AUTH_NEWUSER_RETRY
Definition conn_types.h:45
@ AUTH_NEWUSER_FIRST
Definition conn_types.h:43
@ AUTH_LOGIN_RETRY
Definition conn_types.h:44
@ AUTH_LOGIN_FIRST
Definition conn_types.h:42
void send_save_game(const char *filename)
void set_ruleset(const char *ruleset)
bool is_server_running(void)
bool client_start_server(void)
bool can_client_access_hack(void)
const char * conn_description(const struct connection *pconn)
Definition connection.c:474
struct connection * conn_by_number(int id)
Definition connection.c:421
#define conn_list_iterate(connlist, pconn)
Definition connection.h:108
#define conn_list_iterate_end
Definition connection.h:110
popup_notify_dialog
Definition dialogs_g.h:37
int int id
Definition editgui_g.h:28
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:66
#define Q_(String)
Definition fcintl.h:70
#define _(String)
Definition fcintl.h:67
void fc_mutex_allocate(fc_mutex *mutex)
void fc_mutex_release(fc_mutex *mutex)
const struct ft_color ftc_client
struct civ_game game
Definition game.c:62
static PangoLayout * layout
Definition canvas.c:325
void inputline_toolkit_view_append_button(GtkWidget *toolkit_view, GtkWidget *button)
Definition chatline.c:1292
GtkWidget * inputline_toolkit_view_new(void)
Definition chatline.c:1270
void inputline_grab_focus(void)
Definition chatline.c:79
void chatline_scroll_to_bottom(bool delayed)
Definition chatline.c:1006
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:105
GtkTextBuffer * message_buffer
Definition gui_main.c:178
struct video_mode * resolution_request_get(void)
Definition gui_main.c:2611
void enable_menus(bool enable)
Definition gui_main.c:1052
void refresh_chat_buttons(void)
Definition gui_main.c:2509
void reset_unit_table(void)
Definition gui_main.c:1023
GtkWidget * toplevel
Definition gui_main.c:125
void quit_gtk_main(void)
Definition gui_main.c:2337
static struct video_mode vmode
Definition gui_main.c:191
GtkWidget * toplevel_tabs
Definition gui_main.c:127
int screen_height(void)
Definition gui_main.c:2593
#define GUI_GTK_OPTION(optname)
Definition gui_main.h:25
void gtk_tree_view_focus(GtkTreeView *view)
Definition gui_stuff.c:236
void gtk_stockbutton_set_label(GtkWidget *button, const gchar *label_text)
Definition gui_stuff.c:96
GtkWidget * icon_label_button_new(const gchar *icon_name, const gchar *label_text)
Definition gui_stuff.c:76
GtkTreeViewColumn * add_treeview_column(GtkWidget *view, const char *title, GType gtype, int model_index)
Definition gui_stuff.c:1123
void setup_dialog(GtkWidget *shell, GtkWidget *parent)
Definition gui_stuff.c:287
void mapview_freeze(void)
Definition mapview.c:373
void overview_size_changed(void)
Definition mapview.c:326
void mapview_thaw(void)
Definition mapview.c:381
static struct gui_dialog * shell
Definition messagedlg.c:39
void option_dialog_popup(const char *name, const struct option_set *poptset)
Definition optiondlg.c:972
static GtkListStore * load_store
Definition pages.c:68
static void update_network_page(void)
Definition pages.c:1185
void handle_game_load(bool load_successful, const char *filename)
Definition pages.c:2841
GtkWidget * create_start_page(void)
Definition pages.c:2623
GtkWidget * create_network_page(void)
Definition pages.c:1201
static void client_aitoggle_player(void *data)
Definition pages.c:1509
static GtkWidget * nation_button
Definition pages.c:1460
static void update_server_list(enum server_scan_type sstype, const struct server_list *list)
Definition pages.c:704
static void start_scenario_callback(GtkWidget *w, gpointer data)
Definition pages.c:115
static GtkTreeSelection * scenario_selection
Definition pages.c:73
static void update_start_page_buttons(void)
Definition pages.c:2199
static void save_dialog_response_callback(GtkWidget *w, gint response, gpointer data)
Definition pages.c:489
GtkWidget * create_scenario_page(void)
Definition pages.c:3185
static void show_conn_popup(struct player *pplayer, struct connection *pconn)
Definition pages.c:1767
static GtkWidget * network_confirm_password_label
Definition pages.c:699
void save_mapimg_dialog_popup(void)
Definition pages.c:3551
static void ruleset_selected(const char *name)
Definition pages.c:1615
static void ready_button_callback(GtkWidget *w, gpointer data)
Definition pages.c:2145
static bool conn_list_selection(struct player **ppplayer, struct connection **ppconn)
Definition pages.c:2058
static struct server_scan_timer_data meta_scan
Definition pages.c:86
static void update_network_lists(void)
Definition pages.c:838
static GtkWidget * statusbar
Definition pages.c:89
static GtkWidget * server_playerlist_view
Definition pages.c:71
static GtkListStore * save_dialog_store_new(void)
Definition pages.c:399
void append_network_statusbar(const char *text, bool force)
Definition pages.c:894
static gboolean update_network_statusbar(gpointer data)
Definition pages.c:864
void set_rulesets(int num_rulesets, char **rulesets)
Definition pages.c:3586
void mapimg_client_save(const char *filename)
Definition pages.c:3570
static void conn_menu_player_command(GObject *object, gpointer data)
Definition pages.c:1726
static void load_filename(const char *filename)
Definition pages.c:2856
static void conn_menu_nation_chosen(GObject *object, gpointer data)
Definition pages.c:1713
static GtkWidget * scenario_description
Definition pages.c:63
void save_game_dialog_popup(void)
Definition pages.c:3487
enum client_pages get_current_client_page(void)
Definition pages.c:3345
static GtkListStore * lan_store
Definition pages.c:68
static enum connection_state connection_status
Definition pages.c:859
save_dialog_columns
Definition pages.c:383
@ SD_COL_NUM
Definition pages.c:387
@ SD_COL_FULL_PATH
Definition pages.c:385
@ SD_COL_PRETTY_NAME
Definition pages.c:384
static struct server_scan_timer_data lan_scan
Definition pages.c:87
static void save_dialog_list_callback(GtkTreeSelection *selection, gpointer data)
Definition pages.c:557
static void connect_network_game_callback(GtkWidget *w, gpointer data)
Definition pages.c:132
static GtkTreeView * connection_list_view
Definition pages.c:1462
static GtkWidget * network_login
Definition pages.c:695
static GtkWidget * network_login_label
Definition pages.c:695
connection_state
Definition pages.c:852
@ LOGIN_TYPE
Definition pages.c:853
@ NEW_PASSWORD_TYPE
Definition pages.c:854
@ WAITING_TYPE
Definition pages.c:856
@ ENTER_PASSWORD_TYPE
Definition pages.c:855
static void connect_callback(GtkWidget *w, gpointer data)
Definition pages.c:1043
static void scenario_browse_callback(GtkWidget *w, gpointer data)
Definition pages.c:3059
static GtkListStore * meta_store
Definition pages.c:68
connection_list_columns
Definition pages.c:1468
@ CL_COL_STYLE
Definition pages.c:1478
@ CL_COL_USER_NAME
Definition pages.c:1470
@ CL_COL_READY_STATE
Definition pages.c:1471
@ CL_COL_WEIGHT
Definition pages.c:1479
@ CL_COL_PLAYER_NAME
Definition pages.c:1472
@ CL_COL_NATION
Definition pages.c:1475
@ CL_COL_CONN_ID
Definition pages.c:1477
@ CL_COL_PLAYER_NUMBER
Definition pages.c:1469
@ CL_NUM_COLUMNS
Definition pages.c:1482
@ CL_COL_TEAM
Definition pages.c:1476
@ CL_COL_COLOR
Definition pages.c:1474
@ CL_COL_COLLAPSED
Definition pages.c:1480
@ CL_COL_FLAG
Definition pages.c:1473
static void update_load_page(void)
Definition pages.c:2891
static void save_dialog_update(struct save_dialog *pdialog)
Definition pages.c:427
static GtkWidget * scenario_authors
Definition pages.c:64
static GtkWidget * start_aifill_spin
Definition pages.c:1463
static void ruleset_entry_changed(GtkWidget *w, gpointer data)
Definition pages.c:1627
void(* save_dialog_action_fn_t)(const char *filename)
Definition pages.c:372
static void open_settings(void)
Definition pages.c:141
static void set_connection_state(enum connection_state state)
Definition pages.c:930
static GtkWidget * ruleset_combo
Definition pages.c:93
static void observe_button_callback(GtkWidget *w, gpointer data)
Definition pages.c:2179
static void conn_menu_ready_chosen(GObject *object, gpointer data)
Definition pages.c:1700
static void server_scan_error(struct server_scan *scan, const char *message)
Definition pages.c:825
static void load_callback(void)
Definition pages.c:2864
static void save_dialog_file_chooser_callback(GtkWidget *widget, gint response, gpointer data)
Definition pages.c:444
static void network_list_callback(GtkTreeSelection *select, gpointer data)
Definition pages.c:1139
static GtkListStore * server_playerlist_store
Definition pages.c:70
static void nation_button_callback(GtkWidget *w, gpointer data)
Definition pages.c:2159
void real_set_client_page(enum client_pages new_page)
Definition pages.c:3353
static void conn_menu_connection_command(GObject *object, gpointer data)
Definition pages.c:1753
static void scenario_list_callback(void)
Definition pages.c:2987
static gboolean intro_expose(GtkWidget *w, cairo_t *cr, gpointer *data)
Definition pages.c:164
static void load_browse_callback(GtkWidget *w, gpointer data)
Definition pages.c:2881
static void network_activate_callback(GtkTreeView *view, GtkTreePath *arg1, GtkTreeViewColumn *arg2, gpointer data)
Definition pages.c:1098
static struct fileinfo_list * save_dialog_scenario_list(void)
Definition pages.c:3514
static void connection_state_reset(void)
Definition pages.c:998
void real_conn_list_dialog_update(void *unused)
Definition pages.c:2344
static gboolean connection_list_event(GtkWidget *widget, GdkEventButton *event, gpointer data)
Definition pages.c:1989
static bool holding_srv_list_mutex
Definition pages.c:95
static GtkTreeStore * connection_list_store
Definition pages.c:1461
static struct fileinfo_list * save_dialog_savegame_list(void)
Definition pages.c:3479
static void start_new_game_callback(GtkWidget *w, gpointer data)
Definition pages.c:102
void destroy_server_scans(void)
Definition pages.c:768
void save_scenario_dialog_popup(void)
Definition pages.c:3522
static GtkTreeSelection * lan_selection
Definition pages.c:74
static void save_dialog_save_scenario(const char *filename)
Definition pages.c:3506
struct fileinfo_list *(* save_dialog_files_fn_t)(void)
Definition pages.c:373
static gboolean check_server_scan(gpointer data)
Definition pages.c:791
static void save_dialog_store_update(GtkListStore *store, const struct fileinfo_list *files)
Definition pages.c:409
static void ai_fill_changed_by_user(GtkWidget *w, gpointer data)
Definition pages.c:1642
static gboolean delayed_unselect_path(gpointer data)
Definition pages.c:1973
static void conn_menu_player_take(GObject *object, gpointer data)
Definition pages.c:1740
static void conn_menu_info_chosen(GObject *object, gpointer data)
Definition pages.c:1798
static bool model_get_player_iter(GtkTreeModel *model, GtkTreeIter *iter, GtkTreeIter *start, const struct player *pplayer)
Definition pages.c:2284
static GtkTreeSelection * load_selection
Definition pages.c:73
static void ai_skill_callback(GtkWidget *w, gpointer data)
Definition pages.c:1589
static enum client_pages current_page
Definition pages.c:78
static GtkWidget * statusbar_frame
Definition pages.c:89
static GtkWidget * network_confirm_password
Definition pages.c:699
static void client_take_player(struct player *pplayer)
Definition pages.c:1523
static void clear_network_statusbar(void)
Definition pages.c:880
static GtkTreeSelection * meta_selection
Definition pages.c:74
static void save_dialog_row_callback(GtkTreeView *tree_view, GtkTreePath *path, GtkTreeViewColumn *column, gpointer data)
Definition pages.c:538
static void connection_list_row_callback(GtkTreeView *tree_view, GtkTreeIter *iter, GtkTreePath *path, gpointer data)
Definition pages.c:2043
save_dialog_response
Definition pages.c:390
@ SD_RES_DELETE
Definition pages.c:392
@ SD_RES_SAVE
Definition pages.c:393
@ SD_RES_BROWSE
Definition pages.c:391
GtkWidget * create_load_page(void)
Definition pages.c:2904
static GtkWidget * ai_lvl_combobox
Definition pages.c:1464
static GtkWidget * network_password_label
Definition pages.c:698
static GtkWidget * save_dialog_new(const char *title, const char *savelabel, const char *savefilelabel, save_dialog_action_fn_t action, save_dialog_files_fn_t files)
Definition pages.c:578
static void intro_free(GtkWidget *w, gpointer *data)
Definition pages.c:221
static GtkWidget * network_password
Definition pages.c:698
static GtkWidget * network_host
Definition pages.c:696
void handle_authentication_req(enum authentication_type type, const char *message)
Definition pages.c:1007
static GtkTreeStore * connection_list_store_new(void)
Definition pages.c:1488
static bool send_new_aifill_to_server
Definition pages.c:1641
static void save_dialog_file_chooser_popup(const char *title, GtkFileChooserAction action, save_dialog_action_fn_t cb)
Definition pages.c:464
static GtkWidget * network_port
Definition pages.c:697
static void add_tree_col(GtkWidget *treeview, GType gtype, const char *title, int colnum, const char *key)
Definition pages.c:2589
static void save_dialog_entry_callback(GtkEntry *entry, gpointer data)
Definition pages.c:549
static void main_callback(GtkWidget *w, gpointer data)
Definition pages.c:149
void update_start_page(void)
Definition pages.c:1675
static void scenario_callback(void)
Definition pages.c:3043
static GtkWidget * start_options_table
Definition pages.c:1459
static bool no_ruleset_callback
Definition pages.c:1610
void ai_fill_changed_by_server(int aifill)
Definition pages.c:1653
static void update_server_playerlist(const struct server *pserver)
Definition pages.c:1110
static GtkWidget * observe_button
Definition pages.c:1460
static GtkWidget * scenario_version
Definition pages.c:66
GtkWidget * create_statusbar(void)
Definition pages.c:909
static void game_options_callback(GtkWidget *w, gpointer data)
Definition pages.c:1581
static GtkListStore * scenario_store
Definition pages.c:68
static GtkWidget * network_host_label
Definition pages.c:696
static bool model_get_conn_iter(GtkTreeModel *model, GtkTreeIter *iter, GtkTreeIter *parent, GtkTreeIter *start, const struct connection *pconn)
Definition pages.c:2315
static GQueue * statusbar_queue
Definition pages.c:90
GtkWidget * start_message_area
Definition pages.c:1457
static GtkWidget * network_port_label
Definition pages.c:697
static void update_scenario_page(void)
Definition pages.c:3069
static GtkWidget * scenario_filename
Definition pages.c:65
static void conn_menu_team_chosen(GObject *object, gpointer data)
Definition pages.c:1683
static GtkWidget * create_conn_menu(struct player *pplayer, struct connection *pconn)
Definition pages.c:1812
static void load_saved_game_callback(GtkWidget *w, gpointer data)
Definition pages.c:124
static guint statusbar_timer
Definition pages.c:91
static bool object_extract(GObject *object, struct player **ppplayer, struct connection **ppconn)
Definition pages.c:1554
static void object_put(GObject *object, struct player *pplayer, struct connection *pconn)
Definition pages.c:1535
static struct fileinfo_list * save_dialog_mapimg_list(void)
Definition pages.c:3543
GtkWidget * create_main_page(void)
Definition pages.c:231
static void conn_list_select_conn(struct connection *pconn)
Definition pages.c:2094
static GtkWidget * ready_button
Definition pages.c:1460
GdkPixbuf * create_player_icon(const struct player *plr)
Definition plrdlg.c:117
GdkPixbuf * get_flag(const struct nation_type *nation)
Definition plrdlg.c:607
const char * title
Definition repodlgs.c:1314
GType type
Definition repodlgs.c:1313
void free_sprite(struct sprite *s)
Definition sprite.c:278
struct sprite * sprite_scale(struct sprite *src, int new_w, int new_h)
Definition sprite.c:291
struct sprite * load_gfxfile(const char *filename, bool svgflag)
Definition sprite.c:170
void voteinfo_gui_update(void)
GtkWidget * voteinfo_bar_new(bool split_bar)
GtkWidget * pregame_votebar
void(* save_dialog_action_fn_t)(const char *filename)
Definition pages.c:381
struct fileinfo_list *(* save_dialog_files_fn_t)(void)
Definition pages.c:382
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:191
#define fc_assert_ret_val(condition, val)
Definition log.h:194
#define log_debug(message,...)
Definition log.h:115
#define log_error(message,...)
Definition log.h:103
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:4016
const struct option_set * client_optset
Definition options.c:1280
int option_int_get(const struct option *poption)
Definition options.c:834
struct option * optset_option_by_name(const struct option_set *poptset, const char *name)
Definition options.c:431
bool option_int_set(struct option *poption, int val)
Definition options.c:878
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)
void client_start_server_and_set_page(enum client_pages page)
void set_client_page(enum client_pages page)
enum client_pages get_client_page(void)
bool is_settable_ai_level(enum ai_level level)
Definition player.c:1919
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:1990
#define ai_level_cmd(_level_)
Definition player.h:567
#define players_iterate_end
Definition player.h:537
#define players_iterate(_pplayer)
Definition player.h:532
#define is_ai(plr)
Definition player.h:230
#define players_iterate_alive_end
Definition player.h:547
#define is_human(plr)
Definition player.h:229
#define players_iterate_alive(_pplayer)
Definition player.h:542
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:978
const struct strvec * get_save_dirs(void)
Definition shared.c:941
char * skip_to_basename(char *filepath)
Definition shared.c:1760
struct fileinfo_list * fileinfolist_infix(const struct strvec *dirs, const char *infix, bool nodups)
Definition shared.c:1211
#define fileinfo_list_iterate(list, pnode)
Definition shared.h:176
#define FC_PTR_TO_INT(p)
Definition shared.h:95
#define fileinfo_list_iterate_end
Definition shared.h:178
#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:2465
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:259
bool is_ready
Definition player.h:260
save_dialog_action_fn_t action
Definition pages.c:379
GtkEntry * entry
Definition pages.c:378
GtkTreeView * tree_view
Definition pages.c:377
GtkDialog * shell
Definition pages.c:376
save_dialog_files_fn_t files
Definition pages.c:380
struct server_scan * scan
Definition pages.c:82
fc_mutex mutex
Definition servers.h:64
struct server_list * servers
Definition servers.h:63
Definition team.c:40
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:974
int cat_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:1000
int fc_remove(const char *filename)
Definition support.c:557
#define sz_strlcpy(dest, src)
Definition support.h:195
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
#define sz_strlcat(dest, src)
Definition support.h:196
#define fc_strncmp(_s1_, _s2_, _len_)
Definition support.h:160
const char * team_name_translation(const struct team *pteam)
Definition team.c:420
const char * team_slot_name_translation(const struct team_slot *tslot)
Definition team.c:253
int team_number(const struct team *pteam)
Definition team.c:391
int team_slot_index(const struct team_slot *tslot)
Definition team.c:138
const struct player_list * team_members(const struct team *pteam)
Definition team.c:456
bool team_slot_is_used(const struct team_slot *tslot)
Definition team.c:162
const char * team_slot_rule_name(const struct team_slot *tslot)
Definition team.c:233
#define team_slots_iterate_end
Definition team.h:77
#define team_slots_iterate(_tslot)
Definition team.h:72
const char * tileset_main_intro_filename(const struct tileset *t)
Definition tilespec.c:947
void update_queue_connect_processing_finished(int request_id, uq_callback_t callback, void *data)
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